Compare commits

...

18 Commits

Author SHA1 Message Date
Olivier Gagnon
c9b5aaa2f7 v0.51.7 2021-05-03 12:17:05 -04:00
hydroflame
34a20802c9 Merge pull request #910 from danielyxie/lint-fix
The mega linting patch
2021-05-01 23:08:10 -04:00
hydroflame
6d53ff109b Merge pull request #914 from Pimvgd/patch-3
Typo fixes
2021-05-01 21:50:08 -04:00
Pimvgd
8eab9f3b59 Update Bladeburner.jsx 2021-05-02 00:09:13 +02:00
Pimvgd
f40faadcc4 Update augmentations.rst 2021-05-01 18:04:27 +02:00
Pimvgd
fb129198a6 Update AugmentationHelpers.jsx
more typos
2021-05-01 17:43:13 +02:00
Pimvgd
3eecff1de6 Update netscriptbladeburnerapi.rst
fix typos
2021-05-01 17:34:55 +02:00
Olivier Gagnon
d745150c45 all the lints 2021-05-01 03:17:31 -04:00
Olivier Gagnon
abe0330dc3 css --fix 2021-04-29 23:59:43 -04:00
Olivier Gagnon
3fad505096 run auto fix lint 2021-04-29 23:52:56 -04:00
Olivier Gagnon
77cb63e36a When you hotfix you need to build 2021-04-29 13:41:13 -04:00
Olivier Gagnon
50b490ba8d fix netscript access 2021-04-29 13:39:03 -04:00
hydroflame
15bd8a6233 Merge pull request #907 from danielyxie/dev
update patch notes
2021-04-28 20:26:38 -04:00
Olivier Gagnon
20c593b236 update patch notes 2021-04-28 20:25:51 -04:00
hydroflame
52a80ad236 v0.51.6 (#905)
* Make command `cd` without arguments an alias for `cd /` (#853)

In most shells `cd` without arguments takes you to the home directory
of the current user. I keep trying to do this due to muscle memory
from working in terminals, so I figured I'd make it do something useful.

There is no home directory in the game, but going to / is the closest
thing we have, since that is the starting point for the user in the
game.

* Add new `backdoor` terminal command (#852)

* Add the backdoor command to the terminal

This command will perform a manual hack without rewarding money. It will be used for the story, mainly for faction hacking tests

* Add tab completion for backdoor command

* Add help text for backdoor command

* Change condition syntax to be more consistent with others

* Extract reused code block so it is always called after actions

* Update documentation for new backdoor command

Modified references to manual hack as it isn't for factions anymore

* Remove extra parenthesis

* Rename manuallyHacked to backdoorInstalled

* Fix typo

* Change faction test messages to use backdoor instad of hack

* Rename more instances of manuallyHacked

* fixed typo in helptext of darkweb buy (#858)

* Fix typos and unify descriptions of augmentations (#859)

Made an attempt to...
- give all "+rep% company/faction" the same text
- make all augmentations with a single effect use a single line to describe the effect
- make all effects end with a period

* Made Cashroot starter kit display its tooltip with the money formatted properly and in gold

* fix typo in docs (#860)

* Initial code for Casino Card Deck implementation

* Casino Blackjack Implementation

* Update some tools (eslint, typescript)

* Blackjack code cleanup

* Update README_contribution

* Update ScriptHelpers.js (#861)

expand error message

* More augmentation typo fixes (#862)

* Add Netscript function getCurrentScript (#856)

Add netscript function that returns the current script.

* Added milestones menu to guide new players. (#865)

Milestone menu

* fix typos in milestones (#866)

Co-authored-by: sschmidTU <s.schmid@phonicscore.com>

* Corrupt location title when backdoor is installed (#864)

* Add corruptableText component

* Corrupt location title if backdoor is installed

* Formatting

* Add helper to check value of backdoorInstalled

Helper could be oneline but it would make it less readable

* Fix some formatting

* Add settings option to disable text effects

* Import useState

* getRunningScript (#867)

* Replaced getCurrentScript with getRunningScript

* Bunch of smaller fixes (#904)

Fix #884
Fix #879
Fix #878
Fix #876
Fix #874
Fix #873
Fix #887
Fix #891
Fix #895

* rework the early servers to be more noob friendly (#903)

* v0.51.6

Co-authored-by: Andreas Eriksson <2691182+AndreasTPC@users.noreply.github.com>
Co-authored-by: Jack <jackdewinter1@gmail.com>
Co-authored-by: Teun Pronk <5228255+Crownie88@users.noreply.github.com>
Co-authored-by: Pimvgd <Pimvgd@gmail.com>
Co-authored-by: Daniel Xie <daniel.xie@flockfreight.com>
Co-authored-by: Simon <33069673+sschmidTU@users.noreply.github.com>
Co-authored-by: sschmidTU <s.schmid@phonicscore.com>
2021-04-28 20:07:26 -04:00
hydroflame
b2aafea656 v0.51.5 (#848) 2021-04-21 08:20:26 -04:00
hydroflame
135df8703c V0.51.4 (#847)
* BladeBurner
    * nerfed int exp gained.

    Documentation
    * purchaseServer specifies what happens on failure.
    * Fixed typo in recommended bitnode page.
    * Removed misleading ram requirements for hacking factions.

    Netscript
    * growthAnalyze handles Infinity correctly.

    Misc.
    * Faction Augmentation will list how much reputation is required even after
      that goal has been reached.
    * Removed dollar sign in travel agency confirmation.
    * Fixed typo in alpha-omega.lit

* the game save text no longer obstruct the save game and options button

* the text editors now remember where your cursor was and restores it when loading the same script again.

* v0.51.4
2021-04-19 21:26:51 -04:00
hydroflame
4743801e86 hotfix (#846) 2021-04-18 11:33:46 -04:00
346 changed files with 13795 additions and 9210 deletions

View File

@@ -2,3 +2,7 @@ node_modules/
doc/build/ doc/build/
dist/ dist/
tests/*.bundle.* tests/*.bundle.*
src/ThirdParty/*
src/ScriptEditor/CodeMirrorNetscriptMode.js
src/ScriptEditor/CodeMirrorNetscriptLint.js
src/JSInterpreter.js

File diff suppressed because it is too large Load Diff

View File

@@ -7,4 +7,17 @@ Update the following
- `doc/source/conf.py` `version` and `release` - `doc/source/conf.py` `version` and `release`
- `doc/source/changelog.rst` - `doc/source/changelog.rst`
- post to discord - post to discord
- post to reddit.com/r/Bitburner - post to reddit.com/r/Bitburner
Deploying `dev` to the Beta Branch
----------------------------------
TODO
Development Workflow Best Practices
-----------------------------------
- Work in a new branch forked from the `dev` branch to isolate your new code
- Keep code-changes on a branch as small as possible. This makes it easier for code review. Each branch should be its own independent feature.
- Regularly rebase your branch against `dev` to make sure you have the latest updates pulled.
- When merging, always merge your branch into `dev`. When releasing a new update, then merge `dev` into `master`

24
css/casino.scss Normal file
View File

@@ -0,0 +1,24 @@
.casino-card {
padding: 10px;
border: solid 1px #808080;
background-color: white;
display: inline-block;
border-radius: 10px;
font-size: 14pt;
text-align: center;
margin: 3px;
font-weight: bold;
}
.casino-card .value {
font-size:15pt;
font-family: sans-serif;
}
.casino-card.red {
color: red;
}
.casino-card.black {
color: black;
}

View File

@@ -43,9 +43,9 @@
background-color: #444; background-color: #444;
} }
.character-stat-cell { .character-stat-cell {
text-align: right; text-align: right;
} }
#character-hack-wrapper td, #character-hack-wrapper td,
#character-agi-wrapper td { #character-agi-wrapper td {

View File

@@ -6,7 +6,7 @@
#codemirror-form-wrapper { #codemirror-form-wrapper {
height: 80%; height: 80%;
margin: 10px 0px 0px 6px; margin: 10px 0 0 6px;
} }
.CodeMirror { .CodeMirror {
@@ -22,11 +22,11 @@
* Highlight matches * Highlight matches
*/ */
.cm-matchhighlight { .cm-matchhighlight {
background-color: #8F908A; background-color: #8f908a;
} }
.CodeMirror-selection-highlight-scrollbar { .CodeMirror-selection-highlight-scrollbar {
background-color: #8F908A; background-color: #8f908a;
} }
/** /**
@@ -35,7 +35,7 @@
.cm-whitespace::before { .cm-whitespace::before {
position: absolute; position: absolute;
pointer-events: none; pointer-events: none;
color: #404F7D; color: #404f7d;
} }
/** /**

View File

@@ -1,36 +1,36 @@
.add-exp-button { .add-exp-button {
margin-right: 0px; margin-right: 0;
} }
.remove-exp-button { .remove-exp-button {
margin-left:0px; margin-left:0;
} }
.exp-input { .exp-input {
margin-right: 0px; margin-right: 0;
margin-left:0px; margin-left:0;
margin-top: 5px; margin-top: 5px;
margin-bottom: 5px; margin-bottom: 5px;
padding: 2px 5px; padding: 2px 5px;
} }
.text-center { .text-center {
margin: auto; margin: auto;
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;
} }
.touch-right { .touch-right {
margin-right: 0px; margin-right: 0;
} }
.touch-left { .touch-left {
margin-left: 0px; margin-left: 0;
} }
.touch-sides { .touch-sides {
margin-left: 0px; margin-left: 0;
margin-right: 0px; margin-right: 0;
} }

2
css/grid.min.css vendored

File diff suppressed because one or more lines are too long

5
css/milestones.scss Normal file
View File

@@ -0,0 +1,5 @@
#milestones-container {
position: fixed;
padding: 6px;
width: 60%;
}

View File

@@ -17,7 +17,7 @@
} }
&.level-2 { &.level-2 {
color: #48D1CC; color: #48d1cc;
} }
&.level-3 { &.level-3 {

View File

@@ -1,4 +1,4 @@
/** /**
* Styling for the Re-Sleeving Page * Styling for the Re-Sleeving Page
*/ */
@import "theme"; @import "theme";
@@ -15,7 +15,7 @@
.resleeve-panel { .resleeve-panel {
display: inline-block; display: inline-block;
margin: 0px; margin: 0;
padding: 2px; padding: 2px;
} }

View File

@@ -20,7 +20,7 @@
.sleeve-panel { .sleeve-panel {
display: inline-block; display: inline-block;
margin: 0px; margin: 0;
padding: 2px; padding: 2px;
select { select {

View File

@@ -228,14 +228,15 @@ a:visited {
} }
.status-text { .status-text {
display: inline-block;
position: fixed;
z-index: 2; z-index: 2;
-webkit-animation: status-text 3s 1; -webkit-animation: status-text 3s 1;
} }
#status-text-container { #status-text-container {
background-color: transparent; background-color: transparent;
position:absolute;
top:0;
left:50%;
} }
#status-text { #status-text {
@@ -374,7 +375,7 @@ a:visited {
} }
.noscrollbar::-webkit-scrollbar { .noscrollbar::-webkit-scrollbar {
display: none; display: none;
} }
input[type=checkbox] { input[type=checkbox] {
@@ -382,42 +383,42 @@ input[type=checkbox] {
} }
.optionCheckbox { .optionCheckbox {
margin: 5px; margin: 5px;
float: right; float: right;
} }
.optionRange { .optionRange {
-webkit-appearance: none; -webkit-appearance: none;
background: #777; background: #777;
outline: none; outline: none;
opacity: 0.7; opacity: 0.7;
height: 10px; height: 10px;
-webkit-transition: .2s; -webkit-transition: 0.2s;
transition: opacity .2s; transition: opacity 0.2s;
margin: 3px; margin: 3px;
} }
.optionRange::-webkit-slider-thumb { .optionRange::-webkit-slider-thumb {
-webkit-appearance: none; -webkit-appearance: none;
appearance: none; appearance: none;
width: 10px; width: 10px;
height: 10px; height: 10px;
background: var(--my-font-color); background: var(--my-font-color);
cursor: pointer; cursor: pointer;
} }
.optionRange::-moz-range-thumb { .optionRange::-moz-range-thumb {
width: 10px; width: 10px;
height: 10px; height: 10px;
background: var(--my-font-color); background: var(--my-font-color);
cursor: pointer; cursor: pointer;
} }
.noselect { .noselect {
-moz-user-select: -moz-none; -moz-user-select: -moz-none;
-khtml-user-select: none; -khtml-user-select: none;
-webkit-user-select: none; -webkit-user-select: none;
-ms-user-select: none; -ms-user-select: none;
user-select: none; user-select: none;
} }

View File

@@ -35,7 +35,7 @@
left: 50%; left: 50%;
transform: translate(-100%, -100%); transform: translate(-100%, -100%);
/* Backwards compatibility */ /* Backwards compatibility */
-webkit-transform: translate(-100%, -100%); -webkit-transform: translate(-100%, -100%);
-moz-transform: translate(-100%, -100%); -moz-transform: translate(-100%, -100%);
-o-transform: translate(-100%, -100%); -o-transform: translate(-100%, -100%);
@@ -126,4 +126,4 @@
visibility: visible; visibility: visible;
opacity: 1; opacity: 1;
transition: opacity 0.3s; transition: opacity 0.3s;
} }

View File

@@ -7,16 +7,16 @@
.Treant.Treant-loaded .pseudo { visibility: visible; } .Treant.Treant-loaded .pseudo { visibility: visible; }
.Treant > .pseudo { width: 0; height: 0; border: none; padding: 0; } .Treant > .pseudo { width: 0; height: 0; border: none; padding: 0; }
.Treant .collapse-switch { width: 3px; height: 3px; display: block; border: 1px solid black; position: absolute; top: 1px; right: 1px; cursor: pointer; } .Treant .collapse-switch { width: 3px; height: 3px; display: block; border: 1px solid black; position: absolute; top: 1px; right: 1px; cursor: pointer; }
.Treant .collapsed .collapse-switch { background-color: #868DEE; } .Treant .collapsed .collapse-switch { background-color: #868dee; }
.Treant > .node img { border: none; float: left; } .Treant > .node img { border: none; float: left; }
.Treant > .node { .Treant > .node {
cursor: pointer; cursor: pointer;
padding: 4px; padding: 4px;
min-width: 60px; min-width: 60px;
text-align: center; text-align: center;
border: 2px solid #E8E8E3; border: 2px solid #e8e8e3;
border-radius: 2px; border-radius: 2px;
box-shadow: 1px 1px 1px rgba(0,0,0,.5); box-shadow: 1px 1px 1px rgba(0,0,0,0.5);
font-size: 12px; font-size: 12px;
} }

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +1,2 @@
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([400,0]),o()}({343:function(n,t,o){},345:function(n,t,o){},347:function(n,t,o){},349:function(n,t,o){},351:function(n,t,o){},353:function(n,t,o){},355:function(n,t,o){},357:function(n,t,o){},359:function(n,t,o){},361:function(n,t,o){},363:function(n,t,o){},365:function(n,t,o){},367:function(n,t,o){},369:function(n,t,o){},371:function(n,t,o){},373:function(n,t,o){},375:function(n,t,o){},377:function(n,t,o){},379:function(n,t,o){},381:function(n,t,o){},383:function(n,t,o){},385:function(n,t,o){},387:function(n,t,o){},389:function(n,t,o){},391:function(n,t,o){},393:function(n,t,o){},395:function(n,t,o){},397:function(n,t,o){},400:function(n,t,o){"use strict";o.r(t);o(399),o(397),o(395),o(393),o(391),o(389),o(387),o(385),o(383),o(381),o(379),o(377),o(375),o(373),o(371),o(369),o(367),o(365),o(363),o(361),o(359),o(357),o(355),o(353),o(351),o(349),o(347),o(345),o(343)}}); !function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([840,0]),o()}({779:function(n,t,o){},781:function(n,t,o){},783:function(n,t,o){},785:function(n,t,o){},787:function(n,t,o){},789:function(n,t,o){},791:function(n,t,o){},793:function(n,t,o){},795:function(n,t,o){},797:function(n,t,o){},799:function(n,t,o){},801:function(n,t,o){},803:function(n,t,o){},805:function(n,t,o){},807:function(n,t,o){},809:function(n,t,o){},811:function(n,t,o){},813:function(n,t,o){},815:function(n,t,o){},817:function(n,t,o){},819:function(n,t,o){},821:function(n,t,o){},823:function(n,t,o){},825:function(n,t,o){},827:function(n,t,o){},829:function(n,t,o){},831:function(n,t,o){},833:function(n,t,o){},835:function(n,t,o){},837:function(n,t,o){},840:function(n,t,o){"use strict";o.r(t);o(839),o(837),o(835),o(833),o(831),o(829),o(827),o(825),o(823),o(821),o(819),o(817),o(815),o(813),o(811),o(809),o(807),o(805),o(803),o(801),o(799),o(797),o(795),o(793),o(791),o(789),o(787),o(785),o(783),o(781),o(779)}});
//# sourceMappingURL=engineStyle.bundle.js.map //# sourceMappingURL=engineStyle.bundle.js.map

271
dist/engineStyle.css vendored
View File

@@ -250,13 +250,14 @@ a:visited {
opacity: 0; } } opacity: 0; } }
.status-text { .status-text {
display: inline-block;
position: fixed;
z-index: 2; z-index: 2;
-webkit-animation: status-text 3s 1; } -webkit-animation: status-text 3s 1; }
#status-text-container { #status-text-container {
background-color: transparent; } background-color: transparent;
position: absolute;
top: 0;
left: 50%; }
#status-text { #status-text {
background-color: transparent; background-color: transparent;
@@ -384,8 +385,8 @@ input[type=checkbox] {
outline: none; outline: none;
opacity: 0.7; opacity: 0.7;
height: 10px; height: 10px;
-webkit-transition: .2s; -webkit-transition: 0.2s;
transition: opacity .2s; transition: opacity 0.2s;
margin: 3px; } margin: 3px; }
.optionRange::-webkit-slider-thumb { .optionRange::-webkit-slider-thumb {
@@ -1026,7 +1027,7 @@ button {
*/ */
#codemirror-form-wrapper { #codemirror-form-wrapper {
height: 80%; height: 80%;
margin: 10px 0px 0px 6px; } margin: 10px 0 0 6px; }
.CodeMirror { .CodeMirror {
height: 100%; height: 100%;
@@ -1040,10 +1041,10 @@ button {
* Highlight matches * Highlight matches
*/ */
.cm-matchhighlight { .cm-matchhighlight {
background-color: #8F908A; } background-color: #8f908a; }
.CodeMirror-selection-highlight-scrollbar { .CodeMirror-selection-highlight-scrollbar {
background-color: #8F908A; } background-color: #8f908a; }
/** /**
* Show Invisibles * Show Invisibles
@@ -1051,7 +1052,7 @@ button {
.cm-whitespace::before { .cm-whitespace::before {
position: absolute; position: absolute;
pointer-events: none; pointer-events: none;
color: #404F7D; } color: #404f7d; }
/** /**
* Vim command display * Vim command display
@@ -1414,7 +1415,7 @@ button {
color: yellow; } color: yellow; }
.bitnode.level-2 { .bitnode.level-2 {
color: #48D1CC; } color: #48d1cc; }
.bitnode.level-3 { .bitnode.level-3 {
color: blue; } color: blue; }
@@ -2416,7 +2417,7 @@ button {
.sleeve-panel { .sleeve-panel {
display: inline-block; display: inline-block;
margin: 0px; margin: 0;
padding: 2px; } padding: 2px; }
.sleeve-panel select { .sleeve-panel select {
display: block; } display: block; }
@@ -2435,7 +2436,7 @@ button {
.resleeve-panel { .resleeve-panel {
display: inline-block; display: inline-block;
margin: 0px; margin: 0;
padding: 2px; } padding: 2px; }
.resleeve-aug-selector { .resleeve-aug-selector {
@@ -2477,7 +2478,7 @@ button {
cursor: pointer; } cursor: pointer; }
.Treant .collapsed .collapse-switch { .Treant .collapsed .collapse-switch {
background-color: #868DEE; } background-color: #868dee; }
.Treant > .node img { .Treant > .node img {
border: none; border: none;
@@ -2488,7 +2489,7 @@ button {
padding: 4px; padding: 4px;
min-width: 60px; min-width: 60px;
text-align: center; text-align: center;
border: 2px solid #E8E8E3; border: 2px solid #e8e8e3;
border-radius: 2px; border-radius: 2px;
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5); box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
font-size: 12px; } font-size: 12px; }
@@ -4265,34 +4266,34 @@ html {
margin-left: 0 !important; } margin-left: 0 !important; }
.m-1 { .m-1 {
margin: .25rem !important; } margin: 0.25rem !important; }
.mt-1, .my-1 { .mt-1, .my-1 {
margin-top: .25rem !important; } margin-top: 0.25rem !important; }
.mr-1, .mx-1 { .mr-1, .mx-1 {
margin-right: .25rem !important; } margin-right: 0.25rem !important; }
.mb-1, .my-1 { .mb-1, .my-1 {
margin-bottom: .25rem !important; } margin-bottom: 0.25rem !important; }
.ml-1, .mx-1 { .ml-1, .mx-1 {
margin-left: .25rem !important; } margin-left: 0.25rem !important; }
.m-2 { .m-2 {
margin: .5rem !important; } margin: 0.5rem !important; }
.mt-2, .my-2 { .mt-2, .my-2 {
margin-top: .5rem !important; } margin-top: 0.5rem !important; }
.mr-2, .mx-2 { .mr-2, .mx-2 {
margin-right: .5rem !important; } margin-right: 0.5rem !important; }
.mb-2, .my-2 { .mb-2, .my-2 {
margin-bottom: .5rem !important; } margin-bottom: 0.5rem !important; }
.ml-2, .mx-2 { .ml-2, .mx-2 {
margin-left: .5rem !important; } margin-left: 0.5rem !important; }
.m-3 { .m-3 {
margin: 1rem !important; } margin: 1rem !important; }
@@ -4355,34 +4356,34 @@ html {
padding-left: 0 !important; } padding-left: 0 !important; }
.p-1 { .p-1 {
padding: .25rem !important; } padding: 0.25rem !important; }
.pt-1, .py-1 { .pt-1, .py-1 {
padding-top: .25rem !important; } padding-top: 0.25rem !important; }
.pr-1, .px-1 { .pr-1, .px-1 {
padding-right: .25rem !important; } padding-right: 0.25rem !important; }
.pb-1, .py-1 { .pb-1, .py-1 {
padding-bottom: .25rem !important; } padding-bottom: 0.25rem !important; }
.pl-1, .px-1 { .pl-1, .px-1 {
padding-left: .25rem !important; } padding-left: 0.25rem !important; }
.p-2 { .p-2 {
padding: .5rem !important; } padding: 0.5rem !important; }
.pt-2, .py-2 { .pt-2, .py-2 {
padding-top: .5rem !important; } padding-top: 0.5rem !important; }
.pr-2, .px-2 { .pr-2, .px-2 {
padding-right: .5rem !important; } padding-right: 0.5rem !important; }
.pb-2, .py-2 { .pb-2, .py-2 {
padding-bottom: .5rem !important; } padding-bottom: 0.5rem !important; }
.pl-2, .px-2 { .pl-2, .px-2 {
padding-left: .5rem !important; } padding-left: 0.5rem !important; }
.p-3 { .p-3 {
padding: 1rem !important; } padding: 1rem !important; }
@@ -4456,25 +4457,25 @@ html {
.ml-sm-0, .mx-sm-0 { .ml-sm-0, .mx-sm-0 {
margin-left: 0 !important; } margin-left: 0 !important; }
.m-sm-1 { .m-sm-1 {
margin: .25rem !important; } margin: 0.25rem !important; }
.mt-sm-1, .my-sm-1 { .mt-sm-1, .my-sm-1 {
margin-top: .25rem !important; } margin-top: 0.25rem !important; }
.mr-sm-1, .mx-sm-1 { .mr-sm-1, .mx-sm-1 {
margin-right: .25rem !important; } margin-right: 0.25rem !important; }
.mb-sm-1, .my-sm-1 { .mb-sm-1, .my-sm-1 {
margin-bottom: .25rem !important; } margin-bottom: 0.25rem !important; }
.ml-sm-1, .mx-sm-1 { .ml-sm-1, .mx-sm-1 {
margin-left: .25rem !important; } margin-left: 0.25rem !important; }
.m-sm-2 { .m-sm-2 {
margin: .5rem !important; } margin: 0.5rem !important; }
.mt-sm-2, .my-sm-2 { .mt-sm-2, .my-sm-2 {
margin-top: .5rem !important; } margin-top: 0.5rem !important; }
.mr-sm-2, .mx-sm-2 { .mr-sm-2, .mx-sm-2 {
margin-right: .5rem !important; } margin-right: 0.5rem !important; }
.mb-sm-2, .my-sm-2 { .mb-sm-2, .my-sm-2 {
margin-bottom: .5rem !important; } margin-bottom: 0.5rem !important; }
.ml-sm-2, .mx-sm-2 { .ml-sm-2, .mx-sm-2 {
margin-left: .5rem !important; } margin-left: 0.5rem !important; }
.m-sm-3 { .m-sm-3 {
margin: 1rem !important; } margin: 1rem !important; }
.mt-sm-3, .my-sm-3 { .mt-sm-3, .my-sm-3 {
@@ -4516,25 +4517,25 @@ html {
.pl-sm-0, .px-sm-0 { .pl-sm-0, .px-sm-0 {
padding-left: 0 !important; } padding-left: 0 !important; }
.p-sm-1 { .p-sm-1 {
padding: .25rem !important; } padding: 0.25rem !important; }
.pt-sm-1, .py-sm-1 { .pt-sm-1, .py-sm-1 {
padding-top: .25rem !important; } padding-top: 0.25rem !important; }
.pr-sm-1, .px-sm-1 { .pr-sm-1, .px-sm-1 {
padding-right: .25rem !important; } padding-right: 0.25rem !important; }
.pb-sm-1, .py-sm-1 { .pb-sm-1, .py-sm-1 {
padding-bottom: .25rem !important; } padding-bottom: 0.25rem !important; }
.pl-sm-1, .px-sm-1 { .pl-sm-1, .px-sm-1 {
padding-left: .25rem !important; } padding-left: 0.25rem !important; }
.p-sm-2 { .p-sm-2 {
padding: .5rem !important; } padding: 0.5rem !important; }
.pt-sm-2, .py-sm-2 { .pt-sm-2, .py-sm-2 {
padding-top: .5rem !important; } padding-top: 0.5rem !important; }
.pr-sm-2, .px-sm-2 { .pr-sm-2, .px-sm-2 {
padding-right: .5rem !important; } padding-right: 0.5rem !important; }
.pb-sm-2, .py-sm-2 { .pb-sm-2, .py-sm-2 {
padding-bottom: .5rem !important; } padding-bottom: 0.5rem !important; }
.pl-sm-2, .px-sm-2 { .pl-sm-2, .px-sm-2 {
padding-left: .5rem !important; } padding-left: 0.5rem !important; }
.p-sm-3 { .p-sm-3 {
padding: 1rem !important; } padding: 1rem !important; }
.pt-sm-3, .py-sm-3 { .pt-sm-3, .py-sm-3 {
@@ -4588,25 +4589,25 @@ html {
.ml-md-0, .mx-md-0 { .ml-md-0, .mx-md-0 {
margin-left: 0 !important; } margin-left: 0 !important; }
.m-md-1 { .m-md-1 {
margin: .25rem !important; } margin: 0.25rem !important; }
.mt-md-1, .my-md-1 { .mt-md-1, .my-md-1 {
margin-top: .25rem !important; } margin-top: 0.25rem !important; }
.mr-md-1, .mx-md-1 { .mr-md-1, .mx-md-1 {
margin-right: .25rem !important; } margin-right: 0.25rem !important; }
.mb-md-1, .my-md-1 { .mb-md-1, .my-md-1 {
margin-bottom: .25rem !important; } margin-bottom: 0.25rem !important; }
.ml-md-1, .mx-md-1 { .ml-md-1, .mx-md-1 {
margin-left: .25rem !important; } margin-left: 0.25rem !important; }
.m-md-2 { .m-md-2 {
margin: .5rem !important; } margin: 0.5rem !important; }
.mt-md-2, .my-md-2 { .mt-md-2, .my-md-2 {
margin-top: .5rem !important; } margin-top: 0.5rem !important; }
.mr-md-2, .mx-md-2 { .mr-md-2, .mx-md-2 {
margin-right: .5rem !important; } margin-right: 0.5rem !important; }
.mb-md-2, .my-md-2 { .mb-md-2, .my-md-2 {
margin-bottom: .5rem !important; } margin-bottom: 0.5rem !important; }
.ml-md-2, .mx-md-2 { .ml-md-2, .mx-md-2 {
margin-left: .5rem !important; } margin-left: 0.5rem !important; }
.m-md-3 { .m-md-3 {
margin: 1rem !important; } margin: 1rem !important; }
.mt-md-3, .my-md-3 { .mt-md-3, .my-md-3 {
@@ -4648,25 +4649,25 @@ html {
.pl-md-0, .px-md-0 { .pl-md-0, .px-md-0 {
padding-left: 0 !important; } padding-left: 0 !important; }
.p-md-1 { .p-md-1 {
padding: .25rem !important; } padding: 0.25rem !important; }
.pt-md-1, .py-md-1 { .pt-md-1, .py-md-1 {
padding-top: .25rem !important; } padding-top: 0.25rem !important; }
.pr-md-1, .px-md-1 { .pr-md-1, .px-md-1 {
padding-right: .25rem !important; } padding-right: 0.25rem !important; }
.pb-md-1, .py-md-1 { .pb-md-1, .py-md-1 {
padding-bottom: .25rem !important; } padding-bottom: 0.25rem !important; }
.pl-md-1, .px-md-1 { .pl-md-1, .px-md-1 {
padding-left: .25rem !important; } padding-left: 0.25rem !important; }
.p-md-2 { .p-md-2 {
padding: .5rem !important; } padding: 0.5rem !important; }
.pt-md-2, .py-md-2 { .pt-md-2, .py-md-2 {
padding-top: .5rem !important; } padding-top: 0.5rem !important; }
.pr-md-2, .px-md-2 { .pr-md-2, .px-md-2 {
padding-right: .5rem !important; } padding-right: 0.5rem !important; }
.pb-md-2, .py-md-2 { .pb-md-2, .py-md-2 {
padding-bottom: .5rem !important; } padding-bottom: 0.5rem !important; }
.pl-md-2, .px-md-2 { .pl-md-2, .px-md-2 {
padding-left: .5rem !important; } padding-left: 0.5rem !important; }
.p-md-3 { .p-md-3 {
padding: 1rem !important; } padding: 1rem !important; }
.pt-md-3, .py-md-3 { .pt-md-3, .py-md-3 {
@@ -4720,25 +4721,25 @@ html {
.ml-lg-0, .mx-lg-0 { .ml-lg-0, .mx-lg-0 {
margin-left: 0 !important; } margin-left: 0 !important; }
.m-lg-1 { .m-lg-1 {
margin: .25rem !important; } margin: 0.25rem !important; }
.mt-lg-1, .my-lg-1 { .mt-lg-1, .my-lg-1 {
margin-top: .25rem !important; } margin-top: 0.25rem !important; }
.mr-lg-1, .mx-lg-1 { .mr-lg-1, .mx-lg-1 {
margin-right: .25rem !important; } margin-right: 0.25rem !important; }
.mb-lg-1, .my-lg-1 { .mb-lg-1, .my-lg-1 {
margin-bottom: .25rem !important; } margin-bottom: 0.25rem !important; }
.ml-lg-1, .mx-lg-1 { .ml-lg-1, .mx-lg-1 {
margin-left: .25rem !important; } margin-left: 0.25rem !important; }
.m-lg-2 { .m-lg-2 {
margin: .5rem !important; } margin: 0.5rem !important; }
.mt-lg-2, .my-lg-2 { .mt-lg-2, .my-lg-2 {
margin-top: .5rem !important; } margin-top: 0.5rem !important; }
.mr-lg-2, .mx-lg-2 { .mr-lg-2, .mx-lg-2 {
margin-right: .5rem !important; } margin-right: 0.5rem !important; }
.mb-lg-2, .my-lg-2 { .mb-lg-2, .my-lg-2 {
margin-bottom: .5rem !important; } margin-bottom: 0.5rem !important; }
.ml-lg-2, .mx-lg-2 { .ml-lg-2, .mx-lg-2 {
margin-left: .5rem !important; } margin-left: 0.5rem !important; }
.m-lg-3 { .m-lg-3 {
margin: 1rem !important; } margin: 1rem !important; }
.mt-lg-3, .my-lg-3 { .mt-lg-3, .my-lg-3 {
@@ -4780,25 +4781,25 @@ html {
.pl-lg-0, .px-lg-0 { .pl-lg-0, .px-lg-0 {
padding-left: 0 !important; } padding-left: 0 !important; }
.p-lg-1 { .p-lg-1 {
padding: .25rem !important; } padding: 0.25rem !important; }
.pt-lg-1, .py-lg-1 { .pt-lg-1, .py-lg-1 {
padding-top: .25rem !important; } padding-top: 0.25rem !important; }
.pr-lg-1, .px-lg-1 { .pr-lg-1, .px-lg-1 {
padding-right: .25rem !important; } padding-right: 0.25rem !important; }
.pb-lg-1, .py-lg-1 { .pb-lg-1, .py-lg-1 {
padding-bottom: .25rem !important; } padding-bottom: 0.25rem !important; }
.pl-lg-1, .px-lg-1 { .pl-lg-1, .px-lg-1 {
padding-left: .25rem !important; } padding-left: 0.25rem !important; }
.p-lg-2 { .p-lg-2 {
padding: .5rem !important; } padding: 0.5rem !important; }
.pt-lg-2, .py-lg-2 { .pt-lg-2, .py-lg-2 {
padding-top: .5rem !important; } padding-top: 0.5rem !important; }
.pr-lg-2, .px-lg-2 { .pr-lg-2, .px-lg-2 {
padding-right: .5rem !important; } padding-right: 0.5rem !important; }
.pb-lg-2, .py-lg-2 { .pb-lg-2, .py-lg-2 {
padding-bottom: .5rem !important; } padding-bottom: 0.5rem !important; }
.pl-lg-2, .px-lg-2 { .pl-lg-2, .px-lg-2 {
padding-left: .5rem !important; } padding-left: 0.5rem !important; }
.p-lg-3 { .p-lg-3 {
padding: 1rem !important; } padding: 1rem !important; }
.pt-lg-3, .py-lg-3 { .pt-lg-3, .py-lg-3 {
@@ -4852,25 +4853,25 @@ html {
.ml-xl-0, .mx-xl-0 { .ml-xl-0, .mx-xl-0 {
margin-left: 0 !important; } margin-left: 0 !important; }
.m-xl-1 { .m-xl-1 {
margin: .25rem !important; } margin: 0.25rem !important; }
.mt-xl-1, .my-xl-1 { .mt-xl-1, .my-xl-1 {
margin-top: .25rem !important; } margin-top: 0.25rem !important; }
.mr-xl-1, .mx-xl-1 { .mr-xl-1, .mx-xl-1 {
margin-right: .25rem !important; } margin-right: 0.25rem !important; }
.mb-xl-1, .my-xl-1 { .mb-xl-1, .my-xl-1 {
margin-bottom: .25rem !important; } margin-bottom: 0.25rem !important; }
.ml-xl-1, .mx-xl-1 { .ml-xl-1, .mx-xl-1 {
margin-left: .25rem !important; } margin-left: 0.25rem !important; }
.m-xl-2 { .m-xl-2 {
margin: .5rem !important; } margin: 0.5rem !important; }
.mt-xl-2, .my-xl-2 { .mt-xl-2, .my-xl-2 {
margin-top: .5rem !important; } margin-top: 0.5rem !important; }
.mr-xl-2, .mx-xl-2 { .mr-xl-2, .mx-xl-2 {
margin-right: .5rem !important; } margin-right: 0.5rem !important; }
.mb-xl-2, .my-xl-2 { .mb-xl-2, .my-xl-2 {
margin-bottom: .5rem !important; } margin-bottom: 0.5rem !important; }
.ml-xl-2, .mx-xl-2 { .ml-xl-2, .mx-xl-2 {
margin-left: .5rem !important; } margin-left: 0.5rem !important; }
.m-xl-3 { .m-xl-3 {
margin: 1rem !important; } margin: 1rem !important; }
.mt-xl-3, .my-xl-3 { .mt-xl-3, .my-xl-3 {
@@ -4912,25 +4913,25 @@ html {
.pl-xl-0, .px-xl-0 { .pl-xl-0, .px-xl-0 {
padding-left: 0 !important; } padding-left: 0 !important; }
.p-xl-1 { .p-xl-1 {
padding: .25rem !important; } padding: 0.25rem !important; }
.pt-xl-1, .py-xl-1 { .pt-xl-1, .py-xl-1 {
padding-top: .25rem !important; } padding-top: 0.25rem !important; }
.pr-xl-1, .px-xl-1 { .pr-xl-1, .px-xl-1 {
padding-right: .25rem !important; } padding-right: 0.25rem !important; }
.pb-xl-1, .py-xl-1 { .pb-xl-1, .py-xl-1 {
padding-bottom: .25rem !important; } padding-bottom: 0.25rem !important; }
.pl-xl-1, .px-xl-1 { .pl-xl-1, .px-xl-1 {
padding-left: .25rem !important; } padding-left: 0.25rem !important; }
.p-xl-2 { .p-xl-2 {
padding: .5rem !important; } padding: 0.5rem !important; }
.pt-xl-2, .py-xl-2 { .pt-xl-2, .py-xl-2 {
padding-top: .5rem !important; } padding-top: 0.5rem !important; }
.pr-xl-2, .px-xl-2 { .pr-xl-2, .px-xl-2 {
padding-right: .5rem !important; } padding-right: 0.5rem !important; }
.pb-xl-2, .py-xl-2 { .pb-xl-2, .py-xl-2 {
padding-bottom: .5rem !important; } padding-bottom: 0.5rem !important; }
.pl-xl-2, .px-xl-2 { .pl-xl-2, .px-xl-2 {
padding-left: .5rem !important; } padding-left: 0.5rem !important; }
.p-xl-3 { .p-xl-3 {
padding: 1rem !important; } padding: 1rem !important; }
.pt-xl-3, .py-xl-3 { .pt-xl-3, .py-xl-3 {
@@ -4979,14 +4980,14 @@ html {
visibility: hidden !important; } visibility: hidden !important; }
.add-exp-button { .add-exp-button {
margin-right: 0px; } margin-right: 0; }
.remove-exp-button { .remove-exp-button {
margin-left: 0px; } margin-left: 0; }
.exp-input { .exp-input {
margin-right: 0px; margin-right: 0;
margin-left: 0px; margin-left: 0;
margin-top: 5px; margin-top: 5px;
margin-bottom: 5px; margin-bottom: 5px;
padding: 2px 5px; } padding: 2px 5px; }
@@ -4997,14 +4998,40 @@ html {
vertical-align: middle; } vertical-align: middle; }
.touch-right { .touch-right {
margin-right: 0px; } margin-right: 0; }
.touch-left { .touch-left {
margin-left: 0px; } margin-left: 0; }
.touch-sides { .touch-sides {
margin-left: 0px; margin-left: 0;
margin-right: 0px; } margin-right: 0; }
.casino-card {
padding: 10px;
border: solid 1px #808080;
background-color: white;
display: inline-block;
border-radius: 10px;
font-size: 14pt;
text-align: center;
margin: 3px;
font-weight: bold; }
.casino-card .value {
font-size: 15pt;
font-family: sans-serif; }
.casino-card.red {
color: red; }
.casino-card.black {
color: black; }
#milestones-container {
position: fixed;
padding: 6px;
width: 60%; }
/*# sourceMappingURL=engineStyle.css.map*/ /*# sourceMappingURL=engineStyle.css.map*/

78
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -11,7 +11,7 @@ user's physical and mental faculties.
Augmentations provide persistent upgrades in the form of multipliers. Augmentations provide persistent upgrades in the form of multipliers.
These multipliers apply to a wide variety of things such as stats, These multipliers apply to a wide variety of things such as stats,
experience gain, and hacking, just to name a few. Your multipliers experience gain, and hacking, just to name a few. Your multipliers
can be viewed in the 'Character' page (:ref:`keyboard shortcut <shortcuts>` Alt + c) can be viewed in the 'Character' page (:ref:`keyboard shortcut <shortcuts>` Alt + c).
How to acquire Augmentations How to acquire Augmentations
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -35,7 +35,7 @@ List of Factions and their Requirements
| Early Game | Faction Name | Requirements | Joining this Faction prevents | | Early Game | Faction Name | Requirements | Joining this Faction prevents |
| Factions | | | you from joining: | | Factions | | | you from joining: |
+ +----------------+-----------------------------------------+-------------------------------+ + +----------------+-----------------------------------------+-------------------------------+
| | CyberSec | * Hack CSEC Manually | | | | CyberSec | * Install a backdoor on the CSEC server | |
+ +----------------+-----------------------------------------+-------------------------------+ + +----------------+-----------------------------------------+-------------------------------+
| | Tian Di Hui | * $1m | | | | Tian Di Hui | * $1m | |
| | | * Hacking Level 50 | | | | | * Hacking Level 50 | |
@@ -74,13 +74,16 @@ List of Factions and their Requirements
| | | | * New Tokyo | | | | | * New Tokyo |
| | | | * Ishima | | | | | * Ishima |
+---------------------+----------------+-----------------------------------------+-------------------------------+ +---------------------+----------------+-----------------------------------------+-------------------------------+
| Hacking | NiteSec | * Hack avmnite-02h manually | | | Hacking | NiteSec | * Install a backdoor on the avmnite-02h | |
| Groups | | * Home Computer RAM of at least 32GB | | | Groups | | server | |
| | | * Home Computer RAM of at least 32GB | |
+ +----------------+-----------------------------------------+-------------------------------+ + +----------------+-----------------------------------------+-------------------------------+
| | The Black Hand | * Hack I.I.I.I manually | | | | The Black Hand | * Install a backdoor on the I.I.I.I | |
| | | server | |
| | | * Home Computer RAM of at least 64GB | | | | | * Home Computer RAM of at least 64GB | |
+ +----------------+-----------------------------------------+-------------------------------+ + +----------------+-----------------------------------------+-------------------------------+
| | Bitrunners | * Hack run4theh111z manually | | | | Bitrunners | * Install a backdoor on the run4theh111z| |
| | | server | |
| | | * Home Computer RAM of at least 128GB | | | | | * Home Computer RAM of at least 128GB | |
+---------------------+----------------+-----------------------------------------+-------------------------------+ +---------------------+----------------+-----------------------------------------+-------------------------------+
| Megacorporations | ECorp | * Have 200k reputation with | | | Megacorporations | ECorp | * Have 200k reputation with | |
@@ -112,7 +115,8 @@ List of Factions and their Requirements
+ +----------------+-----------------------------------------+-------------------------------+ + +----------------+-----------------------------------------+-------------------------------+
| | Fulcrum Secret | * Have 250k reputation with | | | | Fulcrum Secret | * Have 250k reputation with | |
| | Technologies | the Corporation | | | | Technologies | the Corporation | |
| | | * Hack fulcrumassets manually | | | | | * Install a backdoor on the | |
| | | fulcrumassets server | |
+---------------------+----------------+-----------------------------------------+-------------------------------+ +---------------------+----------------+-----------------------------------------+-------------------------------+
| Criminal | Slum Snakes | * All Combat Stats of 30 | | | Criminal | Slum Snakes | * All Combat Stats of 30 | |
| Organizations | | * -9 Karma | | | Organizations | | * -9 Karma | |

View File

@@ -148,6 +148,14 @@ has root access, what ports are opened/closed, and also hacking-related informat
such as an estimated chance to successfully hack, an estimate of how much money is such as an estimated chance to successfully hack, an estimate of how much money is
available on the server, etc. available on the server, etc.
backdoor
^^^^^^^^
Installs a backdoor on the current server. Root access is required to do this.
Servers will give different bonuses when you install a backdoor.
This can pass faction tests or give bonsues such as discounts from companies.
buy buy
^^^ ^^^

View File

@@ -3,6 +3,172 @@
Changelog Changelog
========= =========
v0.51.7 - 2021-04-28 n00dles
----------------------------
**Tutorial servers**
* All the tutorial servers have been reverted to their original value
* The new server n00dles has been added as tutorial server.
**Terminal**
* 'tail' now accepts Pid.
* 'analyze' now handles Hacknet Servers correctly.
* 'ServerProfiler.exe' now handles Hacknet Servers correctly.
**SF12**
* Now makes you start with Neuroflux Governor equal to the level of the SF.
**Netscript**
* Deprecated 'getServerRam'.
* 'getServerMaxRam' added to replace 'getServerRam'
* 'getServerUsedRam' added to replace 'getServerRam'
* 'getBitnodeMultipliers' is available inside BN5
* Time logged by hack/grow/weaken now displays in human time.
* thread count logged by hack/grow/weaken now displays with commas every
thousands place.
**Donation**
* Always visible but locked until favor requirements are reached.
**Augmentations**
* City factions has been rebalanced to give a reason to visit them all.
**Sleeves**
* Fix sleeves not being able to work at Volhavens gym.
**Lint**
* This shouldn't change anything but was like 10h of work. So I'm logging it.
**Misc.**
* Plethora of typo fixed (@Pimgd)
* ps documentation fix (@Dawe)
* The dev menu now has a quick bitflume option.
* Fix SF -1 not being as powerful as intended.
* Fix cashroot starter kit not displaying correctly.
* Fix DOM element 'character-overview-text' being nested twice.
* Hacknet documentation example fix.
* Money amount under 1000 dont display 3 decimal anymore.
* Fix nextSourceFile flag miscalculation on the bitverse (for Bn12)
* Faction invite text says "Decide later"/"Join!" instead of "No"/"Yes"
v0.51.6 - 2021-04-28 Backdoor! (Community)
------------------------------------------
**Backdoor**
* a new terminal command, backdoor, has been added to help differentiate
between the terminal hack command and the netscript hack function. (@dewint)
**Servers**
* foodnstuff, sigma-cosmetics, and joesguns have been rebalanced to help new players.
**Milestones**
* A new tab under the Help menu has been added to guide players through the
game.
**Casino**
* Blackjack has been added (@BigD)
**Netscript**
* 'prompt' now converts input to JSON.
* 'getRunningScript' is a new netscript function that returns a bunch of
data related to a running script.
**Coding contracts**
* trivial puzzles should no longer appear.
**Infiltration**
* All numbers are formatted like the rest of the game.
**Misc.**
* Server security is capped at 100.
* Added option to quit a job.
* 'cd' no longer works on unexistent folders.
* cd with no arguments brings you back to top level folder (@Andreas)
* 'softReset' documentation udpated.
* Money tracker now accounts for going to the hospital manually.
* codemirror is now the default editor (for new save files)
* fix typo in dark web help text (@Rodeth)
* so many documentation and typos fixes (@Pimgd)
* A corruption visual effect has been added to location with servers that
have backdoor installed. (@dewint)
v0.51.5 - 2021-04-20 Flags! (hydroflame)
----------------------------------------
**Netscript**
* 'flags' is a new function that helps script handle flags.
This is subject to change if it doesn't meet the need of the players.
* 'ps' now returns the pid.
* 'tail' now works with pid as first argument.
* 'tail' hostname defaults to current server. (like the documentation says)
* 'isRunning' hostname defaults to current server.
* 'isRunning' now works with pid as first argument.
**Gang**
* Nerfed ascension mechanic once again :(
**Misc.**
* Souce-File typo fix
* Fix 'while you were away' screen.
* Bladeburner team size can no longer be set to negative amounts.
v0.51.4 - 2021-04-19 Manual hacking is fun (hydroflame)
-------------------------------------------------------
**Manual hacking**
* These bonus require an install or a soft reset to take effect.
* Manual hacking gyms and university gives you a 10% discount.
* Manual hacking a corporation server decreases the penalty for leaving work
early.
**BladeBurner**
* nerfed int exp gained.
**Documentation**
* purchaseServer specifies what happens on failure.
* Fixed typo in recommended bitnode page.
* Removed misleading ram requirements for hacking factions.
**Netscript**
* growthAnalyze handles Infinity correctly.
**Misc.**
* Faction Augmentation will list how much reputation is required even after
that goal has been reached.
* Removed dollar sign in travel agency confirmation dialog box.
* Fixed typo in alpha-omega.lit
* the 'Game saved!' text no longer blocks the save game/options button.
* The text editor now remembers the location of your cursor and restores it.
* skills are recalculated instantly.
* Fix typo in Operation Zero description.
v0.51.3 - 2021-04-16 Y'all broke it on the first day (hydroflame) v0.51.3 - 2021-04-16 Y'all broke it on the first day (hydroflame)
----------------------------------------------------------------- -----------------------------------------------------------------

View File

@@ -66,7 +66,7 @@ documentation_title = '{0} Documentation'.format(project)
# The short X.Y version. # The short X.Y version.
version = '0.51' version = '0.51'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '0.51.3' release = '0.51.7'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

View File

@@ -634,7 +634,7 @@ This tells me that I can reach :code:`CSEC` by going through :code:`iron-gym`::
Make sure you notice the required hacking skill for the :code:`CSEC` server. Make sure you notice the required hacking skill for the :code:`CSEC` server.
This is a random value between 51 and 60. Although you receive the message This is a random value between 51 and 60. Although you receive the message
from CSEC once you hit 50 hacking, you cannot actually pass their test from CSEC once you hit 50 hacking, you cannot actually pass their test
until your hacking is high enough to hack their server. until your hacking is high enough to install a backdoor on their server.
After you are connected to the :code:`CSEC` server, you can hack it. Note that this After you are connected to the :code:`CSEC` server, you can hack it. Note that this
server requires one open port in order to gain root access. We can open the SSH port server requires one open port in order to gain root access. We can open the SSH port
@@ -642,10 +642,10 @@ using the :code:`BruteSSH.exe` program we created earlier. In |Terminal|::
$ run BruteSSH.exe $ run BruteSSH.exe
$ run NUKE.exe $ run NUKE.exe
$ hack $ backdoor
Keep hacking the server until you are successful. After you successfully hack it, you should After you successfully install the backdoor, you should receive a faction
receive a faction invitation from |CyberSec| shortly afterwards. Accept it. If you accidentally invitation from |CyberSec| shortly afterwards. Accept it. If you accidentally
reject the invitation, that's okay. Just go to the :code:`Factions` tab reject the invitation, that's okay. Just go to the :code:`Factions` tab
(|Keyboard shortcut| Alt + f) and you should see an option that lets you (|Keyboard shortcut| Alt + f) and you should see an option that lets you
accept the invitation. accept the invitation.

View File

@@ -278,6 +278,7 @@ Description
hashes, which can be spent on a variety of different upgrades. hashes, which can be spent on a variety of different upgrades.
In this BitNode: In this BitNode:
* Your stats are significantly decreased * Your stats are significantly decreased
* You cannnot purchase additional servers * You cannnot purchase additional servers
* Hacking is significantly less profitable * Hacking is significantly less profitable
@@ -292,7 +293,7 @@ Source-File
* Level 3: Grants a highly-upgraded Hacknet Server when entering a new BitNode * Level 3: Grants a highly-upgraded Hacknet Server when entering a new BitNode
(Note that the Level 3 effect of this Source-File only applies when entering a new BitNode, NOT (Note that the Level 3 effect of this Source-File only applies when entering a new BitNode, NOT
when installing Augmentation when installing Augmentations.)
Difficulty Difficulty
Hard Hard
@@ -312,6 +313,7 @@ Description
2. Duplicate Sleeves: Duplicate your consciousness into Synthoids, allowing you to perform different tasks synchronously 2. Duplicate Sleeves: Duplicate your consciousness into Synthoids, allowing you to perform different tasks synchronously
In this BitNode: In this BitNode:
* Your stats are significantly decreased * Your stats are significantly decreased
* All methods of gaining money are half as profitable (except Stock Market) * All methods of gaining money are half as profitable (except Stock Market)
* Purchased servers are more expensive, have less max RAM, and a lower maximum limit * Purchased servers are more expensive, have less max RAM, and a lower maximum limit

View File

@@ -27,7 +27,7 @@ getServer() Netscript Function
sshPortOpen sshPortOpen
baseDifficulty baseDifficulty
hackDifficulty hackDifficulty
manuallyHacked backdoorInstalled
minDifficulty minDifficulty
moneyAvailable moneyAvailable
moneyMax moneyMax

View File

@@ -0,0 +1,40 @@
flags() Netscript Function
============================
.. js:function:: flags(data)
:RAM cost: 0 GB
:param data array of pairs of strings: Flags definition.
:returns: Object containing all the flags that were parsed or default.
The flag definition is an array of pairs of values, the first value is the
name of the flag, the 2nd value is the default value for that flag.
The return object is a map containing flag names to the value. It also
contains the special field '_' which contains all arguments that were not flags.
Example:
.. code-block:: javascript
/* example.script
var data = flags([
['delay', 0], // a default number means this flag is a number
['server', 'foodnstuff'], // a default string means this flag is a string
['exclude', []], // a default array means this flag is a default array of string
['help', false], // a default boolean means this flag is a boolean
]);
tprint(data);
*/
[home ~/]> run example.script
{"_":[],"delay":0,"server":"foodnstuff"}
[home ~/]> run example.script --delay 3000
{"_":[],"server":"foodnstuff","delay":3000}
[home ~/]> run example.script --delay 3000 --server harakiri-sushi
{"_":[],"delay":3000,"server":"harakiri-sushi"}
[home ~/]> run example.script --delay 3000 --server harakiri-sushi hello world
{"_":["hello","world"],"delay":3000,"server":"harakiri-sushi"}
[home ~/]> run example.script --delay 3000 --server harakiri-sushi hello world --exclude a --exclude b
{"_":["hello","world"],"delay":3000,"server":"harakiri-sushi","exclude":["a","b"]}
[home ~/]> run example.script --help
{"_":[],"delay":0,"server":"foodnstuff","exclude":[],"help":true}

View File

@@ -0,0 +1,88 @@
getRunningScript() Netscript Function
=====================================
.. js:function:: getRunningScript()
:RAM cost: 0.3 GB
:returns: Script object or null if not found
The object has the following properties:
.. code-block:: javascript
{
// Script arguments
args
// Script filename
filename
// This script's logs. An array of log entries
logs
// Flag indicating whether the logs have been updated since
// the last time the UI was updated
logUpd
// Total amount of hacking experience earned from this script when offline
offlineExpGained
// Total amount of money made by this script when offline
offlineMoneyMade
// Number of seconds that the script has been running offline
offlineRunningTime
// Total amount of hacking experience earned from this script when online
onlineExpGained
// Total amount of money made by this script when online
onlineMoneyMade
// Number of seconds that this script has been running online
onlineRunningTime
// Process ID.
pid
// How much RAM this script uses for ONE thread
ramUsage
// IP of the server on which this script is running
server
// Number of threads that this script is running with
threads
}
Examples:
.. code-block:: javascript
getRunningScript(); // get the current script.
.. js:function:: getRunningScript(pid)
:RAM cost: 0.3 GB
:param number pid: PID of the script
:returns: Script object or null if not found
Examples:
.. code-block:: javascript
getRunningScript(42); // get the script with pid 42.
.. js:function:: getRunningScript(fn, hostname[, args])
:RAM cost: 0.3 GB
:param number fn: filename of the target script
:param number hostname: hostname of the server running the script
:param number args: arguments to the script.
:returns: Script object or null if not found
Examples:
.. code-block:: javascript
getRunningScript("example.script", "home", "foodnstuff"); // get the script called "example.script" on "home" with argument "foodnstuff"

View File

@@ -1,11 +1,11 @@
isRunning() Netscript Function isRunning() Netscript Function
============================== ==============================
.. js:function:: isRunning(filename, hostname, [args...]) .. js:function:: isRunning(filename[, hostname=current hostname[, args...]])
:RAM cost: 0.1 GB :RAM cost: 0.1 GB
:param string filename: Filename of script to check. case-sensitive. :param string filename: Filename of script to check. case-sensitive.
:param string hostname: Hostname of target server. :param string hostname: Hostname of target server. Defaults to current server
:param args...: Arguments to specify/identify which scripts to search for :param args...: Arguments to specify/identify which scripts to search for
:returns: ``true`` if that script with those args is running on that server. :returns: ``true`` if that script with those args is running on that server.
@@ -38,3 +38,17 @@ isRunning() Netscript Function
.. code-block:: javascript .. code-block:: javascript
isRunning("foo.script", "joesguns", 1, 5, "test"); isRunning("foo.script", "joesguns", 1, 5, "test");
.. js:function:: isRunning(scriptPid)
:RAM cost: 0.1 GB
:param number scriptPid: PID of the script to check.
Same as the above version but with pid.
Example:
.. code-block:: javascript
isRunning(39);

View File

@@ -7,7 +7,7 @@ purchaseServer() Netscript Function
:param string hostname: Hostname of the purchased server. :param string hostname: Hostname of the purchased server.
:param number ram: Amount of RAM of the purchased server. Must be a power of :param number ram: Amount of RAM of the purchased server. Must be a power of
2. Maximum value of :doc:`getPurchasedServerMaxRam<getPurchasedServerMaxRam>` 2. Maximum value of :doc:`getPurchasedServerMaxRam<getPurchasedServerMaxRam>`
:returns: The hostname of the newly purchased server. :returns: The hostname of the newly purchased server. Empty string on failure.
Purchased a server with the specified hostname and amount of RAM. Purchased a server with the specified hostname and amount of RAM.

View File

@@ -1,7 +1,7 @@
tail() Netscript Function tail() Netscript Function
================================== ==================================
.. js:function:: tail([fn[, hostname=current hostname[, [...args]]]) .. js:function:: tail([fn[, hostname=current hostname[, ...args]])
:RAM cost: 0 GB :RAM cost: 0 GB
:param string fn: Optional. Filename of script to get logs from. :param string fn: Optional. Filename of script to get logs from.
@@ -29,3 +29,33 @@ tail() Netscript Function
// Open logs from foo.script on the foodnstuff server that was run with the arguments [1, "test"] // Open logs from foo.script on the foodnstuff server that was run with the arguments [1, "test"]
tail("foo.script", "foodnstuff", 1, "test"); tail("foo.script", "foodnstuff", 1, "test");
.. js:function:: tail(scriptPid)
:RAM cost: 0 GB
:param number scriptPid: PID of the script to tail.
Opens a script's logs by pid
Example:
.. code-block:: javascript
// Open logs from process with id 42
tail(42);
// Open logs from process with id 42 on the foodnstuff server
tail(42, "foodnstuff");
.. js:function:: tail()
:RAM cost: 0 GB
Opens the current script logs.
Example:
.. code-block:: javascript
// Open the current script logs.
tail();

View File

@@ -5,13 +5,13 @@ Netscript Bladeburner API
Netscript provides the following API for interacting with the game's Bladeburner mechanic. Netscript provides the following API for interacting with the game's Bladeburner mechanic.
The Bladeburner API is **not** immediately available to the player and must be unlocked The Bladeburner API is **not** immediately available to the player and must be unlocked
later in the game 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 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 automatically gain access to this API. Otherwise, you must have Source-File 7 in
order to use this API in other BitNodes order to use this API in other BitNodes.
**Bladeburner API functions must be accessed through the 'bladeburner' namespace** **Bladeburner API functions must be accessed through the 'bladeburner' namespace**
@@ -157,7 +157,7 @@ identifier by attaching the Bladeburner API functions to an object::
} }
BladeburnerHandler.prototype.handle = function() { BladeburnerHandler.prototype.handle = function() {
//If we're doing something else manually (without Simlacrum), //If we're doing something else manually (without Simulacrum),
//it overrides Bladeburner stuff //it overrides Bladeburner stuff
if (!this.hasSimulacrum() && this.ns.isBusy()) { if (!this.hasSimulacrum() && this.ns.isBusy()) {
this.ns.print("Idling bc player is busy with some other action"); this.ns.print("Idling bc player is busy with some other action");

View File

@@ -75,6 +75,7 @@ This includes information such as function signatures, what they do, and their r
scriptKill() <basicfunctions/scriptKill> scriptKill() <basicfunctions/scriptKill>
getScriptName() <basicfunctions/getScriptName> getScriptName() <basicfunctions/getScriptName>
getScriptRam() <basicfunctions/getScriptRam> getScriptRam() <basicfunctions/getScriptRam>
getRunningScript() <basicfunctions/getRunningScript>
getHackTime() <basicfunctions/getHackTime> getHackTime() <basicfunctions/getHackTime>
getGrowTime() <basicfunctions/getGrowTime> getGrowTime() <basicfunctions/getGrowTime>
getWeakenTime() <basicfunctions/getWeakenTime> getWeakenTime() <basicfunctions/getWeakenTime>
@@ -88,3 +89,4 @@ This includes information such as function signatures, what they do, and their r
prompt() <basicfunctions/prompt> prompt() <basicfunctions/prompt>
wget() <basicfunctions/wget> wget() <basicfunctions/wget>
getFavorToDonate() <basicfunctions/getFavorToDonate> getFavorToDonate() <basicfunctions/getFavorToDonate>
flags() <basicfunctions/flags>

View File

@@ -9,13 +9,12 @@ manualHack() Netscript Function
If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to use this function. If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to use this function.
This function will perform a manual hack on the server you are currently connected to. This function will perform a manual hack on the server you are currently connected to.
This is typically required to join factions.
Examples: Examples:
.. code-block:: javascript .. code-block:: javascript
connect("CSEC"); connect("foodnstuff");
manualHack(); manualHack();
.. warning:: .. warning::

View File

@@ -1,9 +1,13 @@
softReset() Netscript Function softReset() Netscript Function
=================================== ===================================
.. js:function:: softReset() .. js:function:: softReset([callbackScript])
:RAM cost: 5 GB :RAM cost: 5 GB
:param string cbScript:
Optional callback script. This is a script that will automatically be
run after the soft reset. This script will be run with no arguments and
1 thread. It must be located on your home computer.
If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function. If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.

View File

@@ -100,9 +100,12 @@
<li id="help-menu-header-li"> <li id="help-menu-header-li">
<button id="help-menu-header" class="mainmenu-accordion-header"> Help </button> <button id="help-menu-header" class="mainmenu-accordion-header"> Help </button>
</li> </li>
<li id="tutorial-tab" class="mainmenu-accordion-panel"> <li id="milestones-tab" class="mainmenu-accordion-panel">
<button id="tutorial-menu-link"> Tutorial </button> <button id="milestones-menu-link"> Milestones </button>
</li> </li>
<li id="tutorial-tab" class="mainmenu-accordion-panel">
<button id="tutorial-menu-link"> Tutorial </button>
</li>
<li id="options-tab" class="mainmenu-accordion-panel"> <li id="options-tab" class="mainmenu-accordion-panel">
<button id="options-menu-link"> Options </button> <button id="options-menu-link"> Options </button>
</li> </li>
@@ -226,6 +229,10 @@
<!-- Augmentations --> <!-- Augmentations -->
<div id="augmentations-container" class="generic-menupage-container"></div> <div id="augmentations-container" class="generic-menupage-container"></div>
<!-- Milestones content -->
<div id="milestones-container" class="generic-menupage-container">
</div>
<!-- Tutorial content --> <!-- Tutorial content -->
<div id="tutorial-container" class="generic-menupage-container"> <div id="tutorial-container" class="generic-menupage-container">
<h1> Tutorial (AKA Links to Documentation) </h1> <h1> Tutorial (AKA Links to Documentation) </h1>
@@ -381,7 +388,7 @@
<!-- Status text --> <!-- Status text -->
<div id="status-text-container"> <div id="status-text-container">
<p id="status-text"> </p> <p id="status-text"></p>
</div> </div>
<!-- Game Options --> <!-- Game Options -->
@@ -521,6 +528,16 @@
<input class="optionCheckbox" type="checkbox" name="settingsDisableASCIIArt" id="settingsDisableASCIIArt"> <input class="optionCheckbox" type="checkbox" name="settingsDisableASCIIArt" id="settingsDisableASCIIArt">
</fieldset> </fieldset>
<!-- Disable text effects such as corruption. -->
<fieldset>
<label for="settingsDisableTextEffects" class="tooltip">Disable Text Effects:
<span class="tooltiptexthigh">
If this is set, text effects will not be displayed. This can help if text is difficult to read in certain areas.
</span>
</label>
<input class="optionCheckbox" type="checkbox" name="settingsDisableTextEffects" id="settingsDisableTextEffects">
</fieldset>
<!-- Locale for displaying numbers --> <!-- Locale for displaying numbers -->
<fieldset> <fieldset>
<label for="settingsLocale" class="tooltip">Locale: <label for="settingsLocale" class="tooltip">Locale:

13764
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,7 @@
"url": "https://github.com/danielyxie/bitburner/issues" "url": "https://github.com/danielyxie/bitburner/issues"
}, },
"dependencies": { "dependencies": {
"@material-ui/core": "^4.11.3",
"@types/numeral": "0.0.25", "@types/numeral": "0.0.25",
"@types/react": "^16.8.6", "@types/react": "^16.8.6",
"@types/react-dom": "^16.8.2", "@types/react-dom": "^16.8.2",
@@ -13,6 +14,7 @@
"acorn-walk": "^6.2.0", "acorn-walk": "^6.2.0",
"ajv": "^5.1.5", "ajv": "^5.1.5",
"ajv-keywords": "^2.0.0", "ajv-keywords": "^2.0.0",
"arg": "^5.0.0",
"async": "^2.6.1", "async": "^2.6.1",
"autosize": "^4.0.2", "autosize": "^4.0.2",
"brace": "^0.11.1", "brace": "^0.11.1",
@@ -46,7 +48,10 @@
"@babel/core": "^7.3.4", "@babel/core": "^7.3.4",
"@babel/preset-react": "^7.0.0", "@babel/preset-react": "^7.0.0",
"@types/chai": "^4.1.7", "@types/chai": "^4.1.7",
"@types/lodash": "^4.14.168",
"@types/mocha": "^5.2.7", "@types/mocha": "^5.2.7",
"@typescript-eslint/eslint-plugin": "^4.22.0",
"@typescript-eslint/parser": "^4.22.0",
"babel-loader": "^8.0.5", "babel-loader": "^8.0.5",
"beautify-lint": "^1.0.3", "beautify-lint": "^1.0.3",
"benchmark": "^2.1.1", "benchmark": "^2.1.1",
@@ -54,8 +59,8 @@
"chai": "^4.2.0", "chai": "^4.2.0",
"css-loader": "^0.28.11", "css-loader": "^0.28.11",
"es6-promise-polyfill": "^1.1.1", "es6-promise-polyfill": "^1.1.1",
"eslint": "^4.19.1", "eslint": "^7.24.0",
"eslint-plugin-node": "^6.0.1", "eslint-plugin-node": "^11.1.0",
"file-loader": "^1.1.11", "file-loader": "^1.1.11",
"html-webpack-plugin": "^3.2.0", "html-webpack-plugin": "^3.2.0",
"i18n-webpack-plugin": "^1.0.0", "i18n-webpack-plugin": "^1.0.0",
@@ -85,8 +90,7 @@
"stylelint-declaration-use-variable": "^1.6.1", "stylelint-declaration-use-variable": "^1.6.1",
"stylelint-order": "^0.8.1", "stylelint-order": "^0.8.1",
"ts-loader": "^4.5.0", "ts-loader": "^4.5.0",
"tslint": "^5.10.0", "typescript": "^4.2.4",
"typescript": "^2.9.2",
"uglify-es": "^3.3.9", "uglify-es": "^3.3.9",
"uglifyjs-webpack-plugin": "^1.3.0", "uglifyjs-webpack-plugin": "^1.3.0",
"url-loader": "^1.0.1", "url-loader": "^1.0.1",
@@ -112,14 +116,13 @@
"build": "webpack --mode production", "build": "webpack --mode production",
"build:dev": "webpack --mode development", "build:dev": "webpack --mode development",
"build:test": "webpack --config webpack.config-test.js", "build:test": "webpack --config webpack.config-test.js",
"lint": "npm run lint:typescript & npm run lint:javascript & npm run lint:style", "lint": "npm run lint:jsts & npm run lint:style",
"lint:javascript": "eslint *.js ./src/**/*.js ./tests/**/*.js ./utils/**/*.js", "lint:jsts": "eslint --fix '*.{js,jsx,ts,tsx}' './src/**/*.{js,jsx,ts,tsx}' './test/**/*.{js,jsx,ts,tsx}' './utils/**/*.{js,jsx,ts,tsx}'",
"lint:style": "stylelint ./css/*", "lint:style": "stylelint --fix ./css/*",
"lint:typescript": "tslint --project . --exclude **/*.d.ts --format stylish src/**/*.ts utils/**/*.ts",
"preinstall": "node ./scripts/engines-check.js", "preinstall": "node ./scripts/engines-check.js",
"test": "mochapack --webpack-config webpack.config-test.js -r jsdom-global/register ./test/index.js", "test": "mochapack --webpack-config webpack.config-test.js -r jsdom-global/register ./test/index.js",
"watch": "webpack --watch --mode production", "watch": "webpack --watch --mode production",
"watch:dev": "webpack --watch --mode development" "watch:dev": "webpack --watch --mode development"
}, },
"version": "0.51.3" "version": "0.51.7"
} }

View File

@@ -22,12 +22,12 @@ export function loadGlobalAliases(saveString: string): void {
// Prints all aliases to terminal // Prints all aliases to terminal
export function printAliases(): void { export function printAliases(): void {
for (var name in Aliases) { for (const name in Aliases) {
if (Aliases.hasOwnProperty(name)) { if (Aliases.hasOwnProperty(name)) {
post("alias " + name + "=" + Aliases[name]); post("alias " + name + "=" + Aliases[name]);
} }
} }
for (var name in GlobalAliases) { for (const name in GlobalAliases) {
if (GlobalAliases.hasOwnProperty(name)) { if (GlobalAliases.hasOwnProperty(name)) {
post("global alias " + name + "=" + GlobalAliases[name]); post("global alias " + name + "=" + GlobalAliases[name]);
} }
@@ -35,9 +35,9 @@ export function printAliases(): void {
} }
// Returns true if successful, false otherwise // Returns true if successful, false otherwise
export function parseAliasDeclaration(dec: string, global: boolean=false) { export function parseAliasDeclaration(dec: string, global = false): boolean {
var re = /^([_|\w|!|%|,|@]+)="(.+)"$/; const re = /^([_|\w|!|%|,|@]+)="(.+)"$/;
var matches = dec.match(re); const matches = dec.match(re);
if (matches == null || matches.length != 3) {return false;} if (matches == null || matches.length != 3) {return false;}
if (global){ if (global){
addGlobalAlias(matches[1],matches[2]); addGlobalAlias(matches[1],matches[2]);
@@ -100,17 +100,17 @@ export function substituteAliases(origCommand: string): string {
// For the unalias command, dont substite // For the unalias command, dont substite
if (commandArray[0] === "unalias") { return commandArray.join(" "); } if (commandArray[0] === "unalias") { return commandArray.join(" "); }
var alias = getAlias(commandArray[0]); const alias = getAlias(commandArray[0]);
if (alias != null) { if (alias != null) {
commandArray[0] = alias; commandArray[0] = alias;
} else { } else {
var alias = getGlobalAlias(commandArray[0]); const alias = getGlobalAlias(commandArray[0]);
if (alias != null) { if (alias != null) {
commandArray[0] = alias; commandArray[0] = alias;
} }
} }
for (var i = 0; i < commandArray.length; ++i) { for (let i = 0; i < commandArray.length; ++i) {
var alias = getGlobalAlias(commandArray[i]); const alias = getGlobalAlias(commandArray[i]);
if (alias != null) { if (alias != null) {
commandArray[i] = alias; commandArray[i] = alias;
} }

View File

@@ -49,31 +49,27 @@ interface IConstructorParams {
} }
export class Augmentation { export class Augmentation {
// Initiatizes a Augmentation object from a JSON save state.
static fromJSON(value: any): Augmentation {
return Generic_fromJSON(Augmentation, value.data);
}
// How much money this costs to buy // How much money this costs to buy
baseCost: number = 0; baseCost = 0;
// How much faction reputation is required to unlock this // How much faction reputation is required to unlock this
baseRepRequirement: number = 0; baseRepRequirement = 0;
// Description of what this Aug is and what it does // Description of what this Aug is and what it does
info: string = ""; info = "";
// Any Augmentation not immediately available in BitNode-1 is special (e.g. Bladeburner augs) // Any Augmentation not immediately available in BitNode-1 is special (e.g. Bladeburner augs)
isSpecial: boolean = false; isSpecial = false;
// Augmentation level - for repeatable Augs like NeuroFlux Governor // Augmentation level - for repeatable Augs like NeuroFlux Governor
level: number = 0; level = 0;
// Name of Augmentation // Name of Augmentation
name: string = ""; name = "";
// Whether the player owns this Augmentation // Whether the player owns this Augmentation
owned: boolean = false; owned = false;
// Array of names of all prerequisites // Array of names of all prerequisites
prereqs: string[] = []; prereqs: string[] = [];
@@ -83,7 +79,7 @@ export class Augmentation {
mults: IMap<number> = {} mults: IMap<number> = {}
// Initial cost. Doesn't change when you purchase multiple Augmentation // Initial cost. Doesn't change when you purchase multiple Augmentation
startingCost: number = 0; startingCost = 0;
constructor(params: IConstructorParams={ info: "", moneyCost: 0, name: "", repCost: 0 }) { constructor(params: IConstructorParams={ info: "", moneyCost: 0, name: "", repCost: 0 }) {
this.name = params.name; this.name = params.name;
@@ -141,7 +137,7 @@ export class Augmentation {
console.warn(`In Augmentation.addToFactions(), could not find faction with this name: ${factionList[i]}`); console.warn(`In Augmentation.addToFactions(), could not find faction with this name: ${factionList[i]}`);
continue; continue;
} }
faction!.augmentations.push(this.name); faction.augmentations.push(this.name);
} }
} }
@@ -154,7 +150,7 @@ export class Augmentation {
console.warn(`Invalid Faction object in addToAllFactions(). Key value: ${fac}`); console.warn(`Invalid Faction object in addToAllFactions(). Key value: ${fac}`);
continue; continue;
} }
facObj!.augmentations.push(this.name); facObj.augmentations.push(this.name);
} }
} }
} }
@@ -163,6 +159,12 @@ export class Augmentation {
toJSON(): any { toJSON(): any {
return Generic_toJSON("Augmentation", this); return Generic_toJSON("Augmentation", this);
} }
// Initiatizes a Augmentation object from a JSON save state.
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Augmentation {
return Generic_fromJSON(Augmentation, value.data);
}
} }
Reviver.constructors.Augmentation = Augmentation; Reviver.constructors.Augmentation = Augmentation;

View File

@@ -8,29 +8,14 @@ import { AugmentationsRoot } from "./ui/Root";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { CONSTANTS } from "../Constants"; import { CONSTANTS } from "../Constants";
import { Factions, factionExists } from "../Faction/Factions"; import { Factions, factionExists } from "../Faction/Factions";
import { startWorkerScript } from "../NetscriptWorker";
import { Player } from "../Player"; import { Player } from "../Player";
import { prestigeAugmentation } from "../Prestige"; import { prestigeAugmentation } from "../Prestige";
import { saveObject } from "../SaveObject"; import { saveObject } from "../SaveObject";
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";
import { Page, routing } from "../ui/navigationTracking"; import { Page, routing } from "../ui/navigationTracking";
import { dialogBoxCreate } from "../../utils/DialogBox"; import { dialogBoxCreate } from "../../utils/DialogBox";
import { createAccordionElement } from "../../utils/uiHelpers/createAccordionElement";
import {
Reviver,
Generic_toJSON,
Generic_fromJSON
} from "../../utils/JSONReviver";
import { formatNumber } from "../../utils/StringHelperFunctions";
import { clearObject } from "../../utils/helpers/clearObject"; import { clearObject } from "../../utils/helpers/clearObject";
import { createElement } from "../../utils/uiHelpers/createElement"; import { Money } from "../ui/React/Money";
import { isString } from "../../utils/helpers/isString";
import { removeChildrenFromElement } from "../../utils/uiHelpers/removeChildrenFromElement";
import React from "react"; import React from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
@@ -177,7 +162,7 @@ function initAugmentations() {
const CombatRib3 = new Augmentation({ const CombatRib3 = new Augmentation({
name:AugmentationNames.CombatRib3, repCost:14e3, moneyCost:24e6, name:AugmentationNames.CombatRib3, repCost:14e3, moneyCost:24e6,
info:"This is an upgrade to the Combat Rib II augmentation, and is capable of releasing even more potent combat-enhancing " + info:"This is an upgrade to the Combat Rib II augmentation, and is capable of releasing even more potent combat-enhancing " +
"drugs into the bloodstream<br><br>." + "drugs into the bloodstream.<br><br>" +
"This augmentation increases the player's strength and defense by 18%.", "This augmentation increases the player's strength and defense by 18%.",
prereqs:[AugmentationNames.CombatRib2], prereqs:[AugmentationNames.CombatRib2],
strength_mult: 1.18, strength_mult: 1.18,
@@ -403,7 +388,7 @@ function initAugmentations() {
info:"The body is injected with a chemical that artificially induces synaptic potentiation, " + info:"The body is injected with a chemical that artificially induces synaptic potentiation, " +
"otherwise known as the strengthening of synapses. This results in a enhanced cognitive abilities.<br><br>" + "otherwise known as the strengthening of synapses. This results in a enhanced cognitive abilities.<br><br>" +
"This augmentation:<br>" + "This augmentation:<br>" +
"Increases the player's hacking speed by 2% <br>" + "Increases the player's hacking speed by 2%.<br>" +
"Increases the player's hacking chance by 5%.<br>" + "Increases the player's hacking chance by 5%.<br>" +
"Increases the player's hacking experience gain rate by 5%.", "Increases the player's hacking experience gain rate by 5%.",
hacking_speed_mult: 1.02, hacking_speed_mult: 1.02,
@@ -880,9 +865,7 @@ function initAugmentations() {
info:"The body is genetically re-engineered so that it produces the ADR-V1 pheromone, " + info:"The body is genetically re-engineered so that it produces the ADR-V1 pheromone, " +
"an artificial pheromone discovered by scientists. The ADR-V1 pheromone, when excreted, " + "an artificial pheromone discovered by scientists. The ADR-V1 pheromone, when excreted, " +
"triggers feelings of admiration and approval in other people.<br><br>" + "triggers feelings of admiration and approval in other people.<br><br>" +
"This augmentation:<br>" + "This augmentation increases the amount of reputation the player gains when working for a faction or company by 10%.",
"Increases the amount of reputation the player gains when working for a company by 10% <br>" +
"Increases the amount of reputation the player gains for a faction by 10%.",
company_rep_mult: 1.1, company_rep_mult: 1.1,
faction_rep_mult: 1.1, faction_rep_mult: 1.1,
}); });
@@ -897,8 +880,7 @@ function initAugmentations() {
info:"The body is genetically re-engineered so that it produces the ADR-V2 pheromone, " + info:"The body is genetically re-engineered so that it produces the ADR-V2 pheromone, " +
"which is similar to but more potent than ADR-V1. This pheromone, when excreted, " + "which is similar to but more potent than ADR-V1. This pheromone, when excreted, " +
"triggers feelings of admiration, approval, and respect in others.<br><br>" + "triggers feelings of admiration, approval, and respect in others.<br><br>" +
"This augmentation:<br>" + "This augmentation increases the amount of reputation the player gains when working for a faction or company by 20%.",
"Increases the amount of reputation the player gains for a faction and company by 20%.",
company_rep_mult: 1.2, company_rep_mult: 1.2,
faction_rep_mult: 1.2, faction_rep_mult: 1.2,
}); });
@@ -915,8 +897,7 @@ function initAugmentations() {
"criminal organizations and allows the user to project and control holographic " + "criminal organizations and allows the user to project and control holographic " +
"simulacrums within a large radius. These simulacrums are commonly used for " + "simulacrums within a large radius. These simulacrums are commonly used for " +
"espionage and surveillance work.<br><br>" + "espionage and surveillance work.<br><br>" +
"This augmentation:<br>" + "This augmentation increases the amount of reputation the player gains when working for a faction or company by 15%.",
"Increases the amount of reputation the player gains when working for a faction or company by 15%.",
company_rep_mult: 1.15, company_rep_mult: 1.15,
faction_rep_mult: 1.15, faction_rep_mult: 1.15,
}); });
@@ -1152,7 +1133,7 @@ function initAugmentations() {
"cells, when powered, have a negative refractive index. As a result, they bend light " + "cells, when powered, have a negative refractive index. As a result, they bend light " +
"around the skin, making the user much harder to see from the naked eye.<br><br>" + "around the skin, making the user much harder to see from the naked eye.<br><br>" +
"This augmentation:<br>" + "This augmentation:<br>" +
"Increases the player's agility by 5% <br>" + "Increases the player's agility by 5%.<br>" +
"Increases the amount of money the player gains from crimes by 10%.", "Increases the amount of money the player gains from crimes by 10%.",
agility_mult: 1.05, agility_mult: 1.05,
crime_money_mult: 1.1, crime_money_mult: 1.1,
@@ -1170,8 +1151,8 @@ function initAugmentations() {
"cells, when powered, are capable of not only bending light but also of bending heat, " + "cells, when powered, are capable of not only bending light but also of bending heat, " +
"making the user more resilient as well as stealthy.<br><br>" + "making the user more resilient as well as stealthy.<br><br>" +
"This augmentation:<br>" + "This augmentation:<br>" +
"Increases the player's agility by 10% <br>" + "Increases the player's agility by 10%.<br>" +
"Increases the player's defense by 10% <br>" + "Increases the player's defense by 10%.<br>" +
"Increases the amount of money the player gains from crimes by 25%.", "Increases the amount of money the player gains from crimes by 25%.",
prereqs:[AugmentationNames.LuminCloaking1], prereqs:[AugmentationNames.LuminCloaking1],
agility_mult: 1.1, agility_mult: 1.1,
@@ -1259,7 +1240,7 @@ function initAugmentations() {
// Daedalus // Daedalus
const RedPill = new Augmentation({ const RedPill = new Augmentation({
name:AugmentationNames.TheRedPill, repCost:1e6, moneyCost:0, name:AugmentationNames.TheRedPill, repCost:1e6, moneyCost:0,
info:"It's time to leave the cave." info:"It's time to leave the cave.",
}); });
RedPill.addToFactions(["Daedalus"]); RedPill.addToFactions(["Daedalus"]);
if (augmentationExists(AugmentationNames.TheRedPill)) { if (augmentationExists(AugmentationNames.TheRedPill)) {
@@ -1335,7 +1316,7 @@ function initAugmentations() {
"capable of psychoanalyzing and profiling the personality of " + "capable of psychoanalyzing and profiling the personality of " +
"others using optical imaging software.<br><br>" + "others using optical imaging software.<br><br>" +
"This augmentation:<br>" + "This augmentation:<br>" +
"Increases the player's charisma by 50%. <br>" + "Increases the player's charisma by 50%.<br>" +
"Increases the player's charisma experience gain rate by 50%.<br>" + "Increases the player's charisma experience gain rate by 50%.<br>" +
"Increases the amount of reputation the player gains for a company by 25%.<br>" + "Increases the amount of reputation the player gains for a company by 25%.<br>" +
"Increases the amount of reputation the player gains for a faction by 25%.", "Increases the amount of reputation the player gains for a faction by 25%.",
@@ -1372,7 +1353,7 @@ function initAugmentations() {
name:AugmentationNames.Xanipher, repCost:350e3, moneyCost:850e6, name:AugmentationNames.Xanipher, repCost:350e3, moneyCost:850e6,
info:"A concoction of advanced nanobots that is orally ingested into the " + info:"A concoction of advanced nanobots that is orally ingested into the " +
"body. These nanobots induce physiological change and significantly " + "body. These nanobots induce physiological change and significantly " +
"improve the body's functionining in all aspects.<br><br>" + "improve the body's functioning in all aspects.<br><br>" +
"This augmentation:<br>" + "This augmentation:<br>" +
"Increases all of the player's stats by 20%.<br>" + "Increases all of the player's stats by 20%.<br>" +
"Increases the player's experience gain rate for all stats by 15%.", "Increases the player's experience gain rate for all stats by 15%.",
@@ -1554,12 +1535,12 @@ function initAugmentations() {
// Sector12 // Sector12
const CashRoot = new Augmentation({ const CashRoot = new Augmentation({
name:AugmentationNames.CashRoot, repCost:5e3, moneyCost:25e6, name:AugmentationNames.CashRoot, repCost:5e3, moneyCost:25e6,
info:"A collection of digital assets saved on a small chip. The chip is implanted " + info:<>A collection of digital assets saved on a small chip. The chip is implanted
"into your wrist. A small jack in the chip allows you to connect it to a computer " + into your wrist. A small jack in the chip allows you to connect it to a computer
"and upload the assets.<br><br>" + and upload the assets.<br /><br />
"This augmentation:<br>" + This augmentation:<br />
"Lets the player start with $1,000,000 after a reset.<br>" + Lets the player start with {Money(1e6)} after a reset.<br />
"Lets the player start with the BruteSSH.exe program after a reset." Lets the player start with the BruteSSH.exe program after a reset.</>,
}); });
CashRoot.addToFactions(["Sector-12"]); CashRoot.addToFactions(["Sector-12"]);
if (augmentationExists(AugmentationNames.CashRoot)) { if (augmentationExists(AugmentationNames.CashRoot)) {
@@ -1574,8 +1555,7 @@ function initAugmentations() {
"synthesizes glucose, amino acids, and vitamins and redistributes them " + "synthesizes glucose, amino acids, and vitamins and redistributes them " +
"across the body. The device is powered by the body's naturally wasted " + "across the body. The device is powered by the body's naturally wasted " +
"energy in the form of heat.<br><br>" + "energy in the form of heat.<br><br>" +
"This augmentation:<br>" + "This augmentation increases the player's experience gain rate for all combat stats by 20%.",
"Increases the player's experience gain rate for all combat stats by 20%.",
strength_exp_mult: 1.2, strength_exp_mult: 1.2,
defense_exp_mult: 1.2, defense_exp_mult: 1.2,
dexterity_exp_mult: 1.2, dexterity_exp_mult: 1.2,
@@ -1747,7 +1727,7 @@ function initAugmentations() {
"to induce wakefulness and concentration, suppress fear, reduce empathy, and " + "to induce wakefulness and concentration, suppress fear, reduce empathy, and " +
"improve reflexes and memory-recall among other things.<br><br>" + "improve reflexes and memory-recall among other things.<br><br>" +
"This augmentation:<br>" + "This augmentation:<br>" +
"Increases the player's sucess chance in Bladeburner contracts/operations by 3%.<br>" + "Increases the player's success chance in Bladeburner contracts/operations by 3%.<br>" +
"Increases the player's effectiveness in Bladeburner Field Analysis by 5%.<br>" + "Increases the player's effectiveness in Bladeburner Field Analysis by 5%.<br>" +
"Increases the player's Bladeburner stamina gain rate by 2%.", "Increases the player's Bladeburner stamina gain rate by 2%.",
bladeburner_success_chance_mult: 1.03, bladeburner_success_chance_mult: 1.03,
@@ -1785,8 +1765,7 @@ function initAugmentations() {
"nature of the plasma disrupts the electrical systems of Augmentations. However, " + "nature of the plasma disrupts the electrical systems of Augmentations. However, " +
"it can also be effective against non-augmented enemies due to its high temperature " + "it can also be effective against non-augmented enemies due to its high temperature " +
"and concussive force.<br><br>" + "and concussive force.<br><br>" +
"This augmentation:<br>" + "This augmentation increases the player's success chance in Bladeburner contracts/operations by 6%.",
"Increases the player's success chance in Bladeburner contracts/operations by 6%.",
bladeburner_success_chance_mult: 1.06, bladeburner_success_chance_mult: 1.06,
isSpecial: true, isSpecial: true,
}); });
@@ -1799,8 +1778,7 @@ function initAugmentations() {
"is more advanced and powerful than the original V1 model. This V2 model is " + "is more advanced and powerful than the original V1 model. This V2 model is " +
"more power-efficiency, more accurate, and can fire plasma bolts at a much " + "more power-efficiency, more accurate, and can fire plasma bolts at a much " +
"higher velocity than the V1 model.<br><br>" + "higher velocity than the V1 model.<br><br>" +
"This augmentation:<br>" + "This augmentation increases the player's success chance in Bladeburner contracts/operations by 8%.",
"Increases the player's success chance in Bladeburner contracts/operations by 8%.",
prereqs:[AugmentationNames.HyperionV1], prereqs:[AugmentationNames.HyperionV1],
bladeburner_success_chance_mult: 1.08, bladeburner_success_chance_mult: 1.08,
isSpecial: true, isSpecial: true,
@@ -1958,8 +1936,7 @@ function initAugmentations() {
info:"Upgrades the BLADE-51b Tesla Armor with a concentrated deuterium-fluoride laser " + info:"Upgrades the BLADE-51b Tesla Armor with a concentrated deuterium-fluoride laser " +
"weapon. It's precision an accuracy makes it useful for quickly neutralizing " + "weapon. It's precision an accuracy makes it useful for quickly neutralizing " +
"threats while keeping casualties to a minimum.<br><br>" + "threats while keeping casualties to a minimum.<br><br>" +
"This augmentation:<br>" + "This augmentation increases the player's success chance in Bladeburner contracts/operations by 8%.",
"Increases the player's success chance in Bladeburner contracts/operations by 8%.",
prereqs:[AugmentationNames.BladeArmor], prereqs:[AugmentationNames.BladeArmor],
bladeburner_success_chance_mult: 1.08, bladeburner_success_chance_mult: 1.08,
isSpecial: true, isSpecial: true,
@@ -1973,8 +1950,7 @@ function initAugmentations() {
"multiple-fiber system. The upgraded weapon uses multiple fiber laser " + "multiple-fiber system. The upgraded weapon uses multiple fiber laser " +
"modules that combine together to form a single, more powerful beam of up to " + "modules that combine together to form a single, more powerful beam of up to " +
"2000MW.<br><br>" + "2000MW.<br><br>" +
"This augmentation:<br>" + "This augmentation increases the player's success chance in Bladeburner contracts/operations by 10%.",
"Increases the player's success chance in Bladeburner contracts/operations by 10%.",
prereqs:[AugmentationNames.BladeArmorUnibeam], prereqs:[AugmentationNames.BladeArmorUnibeam],
bladeburner_success_chance_mult: 1.1, bladeburner_success_chance_mult: 1.1,
isSpecial: true, isSpecial: true,
@@ -2106,7 +2082,7 @@ export function displayAugmentationsContent(contentEl) {
exportGameFn={saveObject.exportGame.bind(saveObject)} exportGameFn={saveObject.exportGame.bind(saveObject)}
installAugmentationsFn={installAugmentations} installAugmentationsFn={installAugmentations}
/>, />,
contentEl contentEl,
); );
} }

View File

@@ -1,4 +1,4 @@
import { Augmentation } from "./Augmentation"; import { Augmentation } from "./Augmentation";
import { IMap } from "../types"; import { IMap } from "../types";
export let Augmentations: IMap<Augmentation> = {}; export const Augmentations: IMap<Augmentation> = {};

View File

@@ -1,8 +1,8 @@
export class PlayerOwnedAugmentation { export class PlayerOwnedAugmentation {
level: number = 1; level = 1;
name: string = ""; name = "";
constructor(name: string = "") { constructor(name = "") {
this.name = name; this.name = name;
} }
} }

View File

@@ -1,6 +1,6 @@
import { IMap } from "../../types"; import { IMap } from "../../types";
export let AugmentationNames: IMap<string> = { export const AugmentationNames: IMap<string> = {
Targeting1: "Augmented Targeting I", Targeting1: "Augmented Targeting I",
Targeting2: "Augmented Targeting II", Targeting2: "Augmented Targeting II",
Targeting3: "Augmented Targeting III", Targeting3: "Augmented Targeting III",
@@ -89,7 +89,7 @@ export let AugmentationNames: IMap<string> = {
BrachiBlades: "BrachiBlades", BrachiBlades: "BrachiBlades",
BionicArms: "Bionic Arms", BionicArms: "Bionic Arms",
SNA: "Social Negotiation Assistant (S.N.A)", SNA: "Social Negotiation Assistant (S.N.A)",
HydroflameLeftArm: "Hydroflame left arm", HydroflameLeftArm: "Hydroflame Left Arm",
EsperEyewear: "EsperTech Bladeburner Eyewear", EsperEyewear: "EsperTech Bladeburner Eyewear",
EMS4Recombination: "EMS-4 Recombination", EMS4Recombination: "EMS-4 Recombination",
OrionShoulder: "ORION-MKIV Shoulder", OrionShoulder: "ORION-MKIV Shoulder",

View File

@@ -15,7 +15,9 @@ import { SourceFileMinus1 } from "./SourceFileMinus1";
import { Settings } from "../../Settings/Settings"; import { Settings } from "../../Settings/Settings";
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums"; import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
type IProps = {} type IProps = {
// nothing special.
}
type IState = { type IState = {
rerenderFlag: boolean; rerenderFlag: boolean;
@@ -39,7 +41,7 @@ export class InstalledAugmentationsAndSourceFiles extends React.Component<IProps
this.listRef = React.createRef(); this.listRef = React.createRef();
} }
collapseAllHeaders() { collapseAllHeaders(): void {
const ul = this.listRef.current; const ul = this.listRef.current;
if (ul == null) { return; } if (ul == null) { return; }
const tickers = ul.getElementsByClassName("accordion-header"); const tickers = ul.getElementsByClassName("accordion-header");
@@ -55,7 +57,7 @@ export class InstalledAugmentationsAndSourceFiles extends React.Component<IProps
} }
} }
expandAllHeaders() { expandAllHeaders(): void {
const ul = this.listRef.current; const ul = this.listRef.current;
if (ul == null) { return; } if (ul == null) { return; }
const tickers = ul.getElementsByClassName("accordion-header"); const tickers = ul.getElementsByClassName("accordion-header");
@@ -71,7 +73,7 @@ export class InstalledAugmentationsAndSourceFiles extends React.Component<IProps
} }
} }
rerender() { rerender(): void {
this.setState((prevState) => { this.setState((prevState) => {
return { return {
rerenderFlag: !prevState.rerenderFlag, rerenderFlag: !prevState.rerenderFlag,
@@ -79,17 +81,17 @@ export class InstalledAugmentationsAndSourceFiles extends React.Component<IProps
}); });
} }
sortByAcquirementTime() { sortByAcquirementTime(): void {
Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.AcquirementTime; Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.AcquirementTime;
this.rerender(); this.rerender();
} }
sortInOrder() { sortInOrder(): void {
Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.Alphabetically Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.Alphabetically
this.rerender(); this.rerender();
} }
render() { render(): React.ReactNode {
return ( return (
<> <>
<ListConfiguration <ListConfiguration

View File

@@ -7,7 +7,7 @@ import { Player } from "../../Player";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { Augmentations} from "../Augmentations"; import { Augmentations} from "../Augmentations";
function calculateAugmentedStats() { function calculateAugmentedStats(): any {
const augP: any = {}; const augP: any = {};
for(const aug of Player.queuedAugmentations) { for(const aug of Player.queuedAugmentations) {
const augObj = Augmentations[aug.name]; const augObj = Augmentations[aug.name];
@@ -22,12 +22,12 @@ function calculateAugmentedStats() {
export function PlayerMultipliers(): React.ReactElement { export function PlayerMultipliers(): React.ReactElement {
const mults = calculateAugmentedStats(); const mults = calculateAugmentedStats();
function MultiplierTable(rows: any[]): React.ReactElement { function MultiplierTable(rows: any[]): React.ReactElement {
function improvements(r: number) { function improvements(r: number): JSX.Element[] {
let elems: any[] = []; let elems: JSX.Element[] = [];
if(r) { if(r) {
elems = [ elems = [
<td key='2'>&nbsp;=>&nbsp;</td>, <td key="2">&nbsp;{"=>"}&nbsp;</td>,
<td key='3'>{numeralWrapper.formatPercentage(r)}</td> <td key="3">{numeralWrapper.formatPercentage(r)}</td>,
]; ];
} }
return elems; return elems;
@@ -36,8 +36,8 @@ export function PlayerMultipliers(): React.ReactElement {
return <table> return <table>
<tbody> <tbody>
{rows.map((r: any) => <tr key={r[0]}> {rows.map((r: any) => <tr key={r[0]}>
<td key='0'><span>{r[0]} multiplier:&nbsp;</span></td> <td key="0"><span>{r[0]} multiplier:&nbsp;</span></td>
<td key='1' style={{textAlign: 'right'}}>{numeralWrapper.formatPercentage(r[1])}</td> <td key="1" style={{textAlign: 'right'}}>{numeralWrapper.formatPercentage(r[1])}</td>
{improvements(r[2])} {improvements(r[2])}
</tr>)} </tr>)}
</tbody> </tbody>
@@ -51,38 +51,38 @@ export function PlayerMultipliers(): React.ReactElement {
['Hacking Chance ', Player.hacking_chance_mult, Player.hacking_chance_mult*mults.hacking_chance_mult], ['Hacking Chance ', Player.hacking_chance_mult, Player.hacking_chance_mult*mults.hacking_chance_mult],
['Hacking Speed ', Player.hacking_speed_mult, Player.hacking_speed_mult*mults.hacking_speed_mult], ['Hacking Speed ', Player.hacking_speed_mult, Player.hacking_speed_mult*mults.hacking_speed_mult],
['Hacking Money ', Player.hacking_money_mult, Player.hacking_money_mult*mults.hacking_money_mult], ['Hacking Money ', Player.hacking_money_mult, Player.hacking_money_mult*mults.hacking_money_mult],
['Hacking Growth ', Player.hacking_grow_mult, Player.hacking_grow_mult*mults.hacking_grow_mult] ['Hacking Growth ', Player.hacking_grow_mult, Player.hacking_grow_mult*mults.hacking_grow_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([
['Hacking Level ', Player.hacking_mult, Player.hacking_mult*mults.hacking_mult], ['Hacking Level ', Player.hacking_mult, Player.hacking_mult*mults.hacking_mult],
['Hacking Experience ', Player.hacking_exp_mult, Player.hacking_exp_mult*mults.hacking_exp_mult] ['Hacking Experience ', Player.hacking_exp_mult, Player.hacking_exp_mult*mults.hacking_exp_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([
['Strength Level ', Player.strength_mult, Player.strength_mult*mults.strength_mult], ['Strength Level ', Player.strength_mult, Player.strength_mult*mults.strength_mult],
['Strength Experience ', Player.strength_exp_mult, Player.strength_exp_mult*mults.strength_exp_mult] ['Strength Experience ', Player.strength_exp_mult, Player.strength_exp_mult*mults.strength_exp_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([
['Defense Level ', Player.defense_mult, Player.defense_mult*mults.defense_mult], ['Defense Level ', Player.defense_mult, Player.defense_mult*mults.defense_mult],
['Defense Experience ', Player.defense_exp_mult, Player.defense_exp_mult*mults.defense_exp_mult] ['Defense Experience ', Player.defense_exp_mult, Player.defense_exp_mult*mults.defense_exp_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([
['Dexterity Level ', Player.dexterity_mult, Player.dexterity_mult*mults.dexterity_mult], ['Dexterity Level ', Player.dexterity_mult, Player.dexterity_mult*mults.dexterity_mult],
['Dexterity Experience ', Player.dexterity_exp_mult, Player.dexterity_exp_mult*mults.dexterity_exp_mult] ['Dexterity Experience ', Player.dexterity_exp_mult, Player.dexterity_exp_mult*mults.dexterity_exp_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([
['Agility Level ', Player.agility_mult, Player.agility_mult*mults.agility_mult], ['Agility Level ', Player.agility_mult, Player.agility_mult*mults.agility_mult],
['Agility Experience ', Player.agility_exp_mult, Player.agility_exp_mult*mults.agility_exp_mult] ['Agility Experience ', Player.agility_exp_mult, Player.agility_exp_mult*mults.agility_exp_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([
['Charisma Level ', Player.charisma_mult, Player.charisma_mult*mults.charisma_mult], ['Charisma Level ', Player.charisma_mult, Player.charisma_mult*mults.charisma_mult],
['Charisma Experience ', Player.charisma_exp_mult, Player.charisma_exp_mult*mults.charisma_exp_mult] ['Charisma Experience ', Player.charisma_exp_mult, Player.charisma_exp_mult*mults.charisma_exp_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([
@@ -90,13 +90,13 @@ export function PlayerMultipliers(): React.ReactElement {
['Hacknet Node purchase cost ', Player.hacknet_node_purchase_cost_mult, Player.hacknet_node_purchase_cost_mult*mults.hacknet_node_purchase_cost_mult], ['Hacknet Node purchase cost ', Player.hacknet_node_purchase_cost_mult, Player.hacknet_node_purchase_cost_mult*mults.hacknet_node_purchase_cost_mult],
['Hacknet Node RAM upgrade cost ', Player.hacknet_node_ram_cost_mult, Player.hacknet_node_ram_cost_mult*mults.hacknet_node_ram_cost_mult], ['Hacknet Node RAM upgrade cost ', Player.hacknet_node_ram_cost_mult, Player.hacknet_node_ram_cost_mult*mults.hacknet_node_ram_cost_mult],
['Hacknet Node Core purchase cost ', Player.hacknet_node_core_cost_mult, Player.hacknet_node_core_cost_mult*mults.hacknet_node_core_cost_mult], ['Hacknet Node Core purchase cost ', Player.hacknet_node_core_cost_mult, Player.hacknet_node_core_cost_mult*mults.hacknet_node_core_cost_mult],
['Hacknet Node level upgrade cost ', Player.hacknet_node_level_cost_mult, Player.hacknet_node_level_cost_mult*mults.hacknet_node_level_cost_mult] ['Hacknet Node level upgrade cost ', Player.hacknet_node_level_cost_mult, Player.hacknet_node_level_cost_mult*mults.hacknet_node_level_cost_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([
['Company reputation gain ', Player.company_rep_mult, Player.company_rep_mult*mults.company_rep_mult], ['Company reputation gain ', Player.company_rep_mult, Player.company_rep_mult*mults.company_rep_mult],
['Faction reputation gain ', Player.faction_rep_mult, Player.faction_rep_mult*mults.faction_rep_mult], ['Faction reputation gain ', Player.faction_rep_mult, Player.faction_rep_mult*mults.faction_rep_mult],
['Salary ', Player.work_money_mult, Player.work_money_mult*mults.work_money_mult] ['Salary ', Player.work_money_mult, Player.work_money_mult*mults.work_money_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([

View File

@@ -22,7 +22,7 @@ export function PurchasedAugmentations(): React.ReactElement {
augs.push( augs.push(
<li key={`${ownedAug.name}${ownedAug.level}`}> <li key={`${ownedAug.name}${ownedAug.level}`}>
<AugmentationAccordion aug={aug} level={level} /> <AugmentationAccordion aug={aug} level={level} />
</li> </li>,
) )
} }

View File

@@ -25,7 +25,7 @@ export class AugmentationsRoot extends React.Component<IProps, IState> {
super(props); super(props);
} }
render() { render(): React.ReactNode {
return ( return (
<div id="augmentations-content"> <div id="augmentations-content">
<h1>Purchased Augmentations</h1> <h1>Purchased Augmentations</h1>

View File

@@ -5,15 +5,12 @@
import * as React from "react"; import * as React from "react";
import { Player } from "../../Player"; import { Player } from "../../Player";
import { Settings } from "../../Settings/Settings";
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
import { SourceFiles } from "../../SourceFile/SourceFiles";
import { Exploit, ExploitName } from "../../Exploits/Exploit"; import { Exploit, ExploitName } from "../../Exploits/Exploit";
import { Accordion } from "../../ui/React/Accordion"; import { Accordion } from "../../ui/React/Accordion";
export function SourceFileMinus1(): React.ReactElement { export function SourceFileMinus1(): React.ReactElement {
let exploits = Player.exploits; const exploits = Player.exploits;
if(exploits.length === 0) { if(exploits.length === 0) {
return <></> return <></>

View File

@@ -16,7 +16,7 @@ class BitNode {
number: number; number: number;
constructor(n: number, name: string, desc: string="", info: string="") { constructor(n: number, name: string, desc="", info="") {
this.number = n; this.number = n;
this.name = name; this.name = name;
this.desc = desc; this.desc = desc;
@@ -234,7 +234,7 @@ BitNodes["BitNode11"] = new BitNode(11, "The Big Crash", "Okay. Sell it all.",
"Level 3: 56%"); "Level 3: 56%");
BitNodes["BitNode12"] = new BitNode(12, "The Recursion", "Repeat.", BitNodes["BitNode12"] = new BitNode(12, "The Recursion", "Repeat.",
"To iterate is human, to recurse divine.<br><br>" + "To iterate is human, to recurse divine.<br><br>" +
"Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give you Souce-File 12, or " + "Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give you Source-File 12, or " +
"if you already have this Source-File it will upgrade its level. There is no maximum level for Source-File 12. Each level " + "if you already have this Source-File it will upgrade its level. There is no maximum level for Source-File 12. Each level " +
"of Source-File 12 will increase all of your multipliers by 1%. This effect is multiplicative with itself. " + "of Source-File 12 will increase all of your multipliers by 1%. This effect is multiplicative with itself. " +
"In other words, level N of this Source-File will result in a multiplier of 1.01^N (or 0.99^N for multipliers that decrease)"); "In other words, level N of this Source-File will result in a multiplier of 1.01^N (or 0.99^N for multipliers that decrease)");
@@ -252,11 +252,11 @@ BitNodes["BitNode22"] = new BitNode(22, "", "COMING SOON");
BitNodes["BitNode23"] = new BitNode(23, "", "COMING SOON"); BitNodes["BitNode23"] = new BitNode(23, "", "COMING SOON");
BitNodes["BitNode24"] = new BitNode(24, "", "COMING SOON"); BitNodes["BitNode24"] = new BitNode(24, "", "COMING SOON");
export function initBitNodeMultipliers(p: IPlayer) { export function initBitNodeMultipliers(p: IPlayer): void {
if (p.bitNodeN == null) { if (p.bitNodeN == null) {
p.bitNodeN = 1; p.bitNodeN = 1;
} }
for (var mult in BitNodeMultipliers) { for (const mult in BitNodeMultipliers) {
if (BitNodeMultipliers.hasOwnProperty(mult)) { if (BitNodeMultipliers.hasOwnProperty(mult)) {
BitNodeMultipliers[mult] = 1; BitNodeMultipliers[mult] = 1;
} }
@@ -433,15 +433,15 @@ export function initBitNodeMultipliers(p: IPlayer) {
BitNodeMultipliers.FourSigmaMarketDataCost = 4; BitNodeMultipliers.FourSigmaMarketDataCost = 4;
BitNodeMultipliers.FourSigmaMarketDataApiCost = 4; BitNodeMultipliers.FourSigmaMarketDataApiCost = 4;
break; break;
case 12: //The Recursion case 12: { //The Recursion
var sf12Lvl = 0; let sf12Lvl = 0;
for (var i = 0; i < p.sourceFiles.length; i++) { for (let i = 0; i < p.sourceFiles.length; i++) {
if (p.sourceFiles[i].n === 12) { if (p.sourceFiles[i].n === 12) {
sf12Lvl = p.sourceFiles[i].lvl; sf12Lvl = p.sourceFiles[i].lvl;
} }
} }
var inc = Math.pow(1.02, sf12Lvl); const inc = Math.pow(1.02, sf12Lvl);
var dec = 1/inc; const dec = 1/inc;
// Multiplier for number of augs needed for Daedalus increases // Multiplier for number of augs needed for Daedalus increases
// up to a maximum of 1.34, which results in 40 Augs required // up to a maximum of 1.34, which results in 40 Augs required
@@ -499,6 +499,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
BitNodeMultipliers.BladeburnerRank = dec; BitNodeMultipliers.BladeburnerRank = dec;
BitNodeMultipliers.BladeburnerSkillCost = inc; BitNodeMultipliers.BladeburnerSkillCost = inc;
break; break;
}
default: default:
console.warn("Player.bitNodeN invalid"); console.warn("Player.bitNodeN invalid");
break; break;

View File

@@ -1,7 +1,6 @@
import { Augmentations } from "./Augmentation/Augmentations"; import { Augmentations } from "./Augmentation/Augmentations";
import { AugmentationNames } from "./Augmentation/data/AugmentationNames"; import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers"; import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers";
import { CONSTANTS } from "./Constants";
import { Engine } from "./engine"; import { Engine } from "./engine";
import { Faction } from "./Faction/Faction"; import { Faction } from "./Faction/Faction";
import { Factions, factionExists } from "./Faction/Factions"; import { Factions, factionExists } from "./Faction/Factions";
@@ -17,17 +16,19 @@ import { dialogBoxCreate } from "../utils/DialogBox";
import { import {
Reviver, Reviver,
Generic_toJSON, Generic_toJSON,
Generic_fromJSON Generic_fromJSON,
} from "../utils/JSONReviver"; } from "../utils/JSONReviver";
import { setTimeoutRef } from "./utils/SetTimeoutRef"; import { setTimeoutRef } from "./utils/SetTimeoutRef";
import { formatNumber } from "../utils/StringHelperFunctions"; import {
formatNumber,
convertTimeMsToTimeElapsedString,
} from "../utils/StringHelperFunctions";
import { ConsoleHelpText } from "./Bladeburner/data/Help"; import { ConsoleHelpText } from "./Bladeburner/data/Help";
import { City } from "./Bladeburner/City"; import { City } from "./Bladeburner/City";
import { BladeburnerConstants } from "./Bladeburner/data/Constants"; import { BladeburnerConstants } from "./Bladeburner/data/Constants";
import { Skill } from "./Bladeburner/Skill"; import { Skill } from "./Bladeburner/Skill";
import { Skills } from "./Bladeburner/Skills"; import { Skills } from "./Bladeburner/Skills";
import { SkillNames } from "./Bladeburner/data/SkillNames";
import { Operation } from "./Bladeburner/Operation"; import { Operation } from "./Bladeburner/Operation";
import { BlackOperation } from "./Bladeburner/BlackOperation"; import { BlackOperation } from "./Bladeburner/BlackOperation";
import { BlackOperations } from "./Bladeburner/BlackOperations"; import { BlackOperations } from "./Bladeburner/BlackOperations";
@@ -45,7 +46,6 @@ import { KEY } from "../utils/helpers/keyCodes";
import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement"; import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
import { appendLineBreaks } from "../utils/uiHelpers/appendLineBreaks"; import { appendLineBreaks } from "../utils/uiHelpers/appendLineBreaks";
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
import { createElement } from "../utils/uiHelpers/createElement"; import { createElement } from "../utils/uiHelpers/createElement";
import { createPopup } from "../utils/uiHelpers/createPopup"; import { createPopup } from "../utils/uiHelpers/createPopup";
import { removeElement } from "../utils/uiHelpers/removeElement"; import { removeElement } from "../utils/uiHelpers/removeElement";
@@ -236,7 +236,7 @@ Bladeburner.prototype.create = function() {
count:getRandomInt(25, 150), countGrowth:getRandomInt(5, 75)/10, count:getRandomInt(25, 150), countGrowth:getRandomInt(5, 75)/10,
weights:{hack:0,str:0.05,def:0.05,dex:0.35,agi:0.35,cha:0.1, int:0.05}, weights:{hack:0,str:0.05,def:0.05,dex:0.35,agi:0.35,cha:0.1, int:0.05},
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.9, int:1}, decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.9, int:1},
isStealth:true isStealth:true,
}); });
this.contracts["Bounty Hunter"] = new Contract({ this.contracts["Bounty Hunter"] = new Contract({
name:"Bounty Hunter", name:"Bounty Hunter",
@@ -248,7 +248,7 @@ Bladeburner.prototype.create = function() {
count:getRandomInt(5, 150), countGrowth:getRandomInt(5, 75)/10, count:getRandomInt(5, 150), countGrowth:getRandomInt(5, 75)/10,
weights:{hack:0,str:0.15,def:0.15,dex:0.25,agi:0.25,cha:0.1, int:0.1}, weights:{hack:0,str:0.15,def:0.15,dex:0.25,agi:0.25,cha:0.1, int:0.1},
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9}, decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9},
isKill:true isKill:true,
}); });
this.contracts["Retirement"] = new Contract({ this.contracts["Retirement"] = new Contract({
name:"Retirement", name:"Retirement",
@@ -260,7 +260,7 @@ Bladeburner.prototype.create = function() {
count:getRandomInt(5, 150), countGrowth:getRandomInt(5, 75)/10, count:getRandomInt(5, 150), countGrowth:getRandomInt(5, 75)/10,
weights:{hack:0,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0.1, int:0.1}, weights:{hack:0,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0.1, int:0.1},
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9}, decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9},
isKill:true isKill:true,
}); });
this.operations["Investigation"] = new Operation({ this.operations["Investigation"] = new Operation({
@@ -275,7 +275,7 @@ Bladeburner.prototype.create = function() {
count:getRandomInt(1, 100), countGrowth:getRandomInt(10, 40)/10, count:getRandomInt(1, 100), countGrowth:getRandomInt(10, 40)/10,
weights:{hack:0.25,str:0.05,def:0.05,dex:0.2,agi:0.1,cha:0.25, int:0.1}, weights:{hack:0.25,str:0.05,def:0.05,dex:0.2,agi:0.1,cha:0.25, int:0.1},
decays:{hack:0.85,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9}, decays:{hack:0.85,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9},
isStealth:true isStealth:true,
}); });
this.operations["Undercover Operation"] = new Operation({ this.operations["Undercover Operation"] = new Operation({
name:"Undercover Operation", name:"Undercover Operation",
@@ -288,7 +288,7 @@ Bladeburner.prototype.create = function() {
count:getRandomInt(1, 100), countGrowth:getRandomInt(10, 40)/10, count:getRandomInt(1, 100), countGrowth:getRandomInt(10, 40)/10,
weights:{hack:0.2,str:0.05,def:0.05,dex:0.2,agi:0.2,cha:0.2, int:0.1}, weights:{hack:0.2,str:0.05,def:0.05,dex:0.2,agi:0.2,cha:0.2, int:0.1},
decays:{hack:0.8,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9}, decays:{hack:0.8,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9},
isStealth:true isStealth:true,
}); });
this.operations["Sting Operation"] = new Operation({ this.operations["Sting Operation"] = new Operation({
name:"Sting Operation", name:"Sting Operation",
@@ -299,19 +299,19 @@ Bladeburner.prototype.create = function() {
count:getRandomInt(1, 150), countGrowth:getRandomInt(3, 40)/10, count:getRandomInt(1, 150), countGrowth:getRandomInt(3, 40)/10,
weights:{hack:0.25,str:0.05,def:0.05,dex:0.25,agi:0.1,cha:0.2, int:0.1}, weights:{hack:0.25,str:0.05,def:0.05,dex:0.25,agi:0.1,cha:0.2, int:0.1},
decays:{hack:0.8,str:0.85,def:0.85,dex:0.85,agi:0.85,cha:0.7, int:0.9}, decays:{hack:0.8,str:0.85,def:0.85,dex:0.85,agi:0.85,cha:0.7, int:0.9},
isStealth:true isStealth:true,
}); });
this.operations["Raid"] = new Operation({ this.operations["Raid"] = new Operation({
name:"Raid", name:"Raid",
desc:"Lead an assault on a known Synthoid community. Note that " + desc:"Lead an assault on a known Synthoid community. Note that " +
"there must be an existing Synthoid community in your current city " + "there must be an existing Synthoid community in your current city " +
"in order for this Operation to be successful", "in order for this Operation to be successful.",
baseDifficulty:800, difficultyFac:1.045, rewardFac:1.1, reqdRank:3000, baseDifficulty:800, difficultyFac:1.045, rewardFac:1.1, reqdRank:3000,
rankGain:55,rankLoss:2.5,hpLoss:50, rankGain:55,rankLoss:2.5,hpLoss:50,
count:getRandomInt(1, 150), countGrowth:getRandomInt(2, 40)/10, count:getRandomInt(1, 150), countGrowth:getRandomInt(2, 40)/10,
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9}, decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9},
isKill:true isKill:true,
}); });
this.operations["Stealth Retirement Operation"] = new Operation({ this.operations["Stealth Retirement Operation"] = new Operation({
name:"Stealth Retirement Operation", name:"Stealth Retirement Operation",
@@ -323,7 +323,7 @@ Bladeburner.prototype.create = function() {
count:getRandomInt(1, 150), countGrowth:getRandomInt(1, 20)/10, count:getRandomInt(1, 150), countGrowth:getRandomInt(1, 20)/10,
weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1}, weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1},
decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9}, decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9},
isStealth:true, isKill:true isStealth:true, isKill:true,
}); });
this.operations["Assassination"] = new Operation({ this.operations["Assassination"] = new Operation({
name:"Assassination", name:"Assassination",
@@ -335,7 +335,7 @@ Bladeburner.prototype.create = function() {
count:getRandomInt(1, 150), countGrowth:getRandomInt(1, 20)/10, count:getRandomInt(1, 150), countGrowth:getRandomInt(1, 20)/10,
weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1}, weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.8}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.8},
isStealth:true, isKill:true isStealth:true, isKill:true,
}); });
} }
@@ -1069,7 +1069,11 @@ Bladeburner.prototype.gainActionStats = function(action, success) {
Player.gainDexterityExp(unweightedGain * action.weights.dex * Player.dexterity_exp_mult * skillMult); Player.gainDexterityExp(unweightedGain * action.weights.dex * Player.dexterity_exp_mult * skillMult);
Player.gainAgilityExp(unweightedGain * action.weights.agi * Player.agility_exp_mult * skillMult); Player.gainAgilityExp(unweightedGain * action.weights.agi * Player.agility_exp_mult * skillMult);
Player.gainCharismaExp(unweightedGain * action.weights.cha * Player.charisma_exp_mult * skillMult); Player.gainCharismaExp(unweightedGain * action.weights.cha * Player.charisma_exp_mult * skillMult);
Player.gainIntelligenceExp(unweightedIntGain * action.weights.int * skillMult); let intExp = unweightedIntGain * action.weights.int * skillMult;
if (intExp > 1) {
intExp = Math.pow(intExp, 0.8);
}
Player.gainIntelligenceExp(intExp);
} }
Bladeburner.prototype.randomEvent = function() { Bladeburner.prototype.randomEvent = function() {
@@ -1267,7 +1271,7 @@ Bladeburner.prototype.createContent = function() {
DomElems.consoleInput.focus(); DomElems.consoleInput.focus();
} }
return false; return false;
} },
}); });
DomElems.consoleTable = createElement("table", {class:"bladeburner-console-table"}); DomElems.consoleTable = createElement("table", {class:"bladeburner-console-table"});
DomElems.consoleInputRow = createElement("tr", {class:"bladeburner-console-input-row", id:"bladeburner-console-input-row"}); DomElems.consoleInputRow = createElement("tr", {class:"bladeburner-console-input-row", id:"bladeburner-console-input-row"});
@@ -1275,7 +1279,7 @@ Bladeburner.prototype.createContent = function() {
DomElems.consoleInputHeader = createElement("pre", {innerText:"> "}); DomElems.consoleInputHeader = createElement("pre", {innerText:"> "});
DomElems.consoleInput = createElement("input", { DomElems.consoleInput = createElement("input", {
type:"text", class:"bladeburner-console-input", tabIndex:1, type:"text", class:"bladeburner-console-input", tabIndex:1,
onfocus:() => {DomElems.consoleInput.value = DomElems.consoleInput.value} onfocus:() => {DomElems.consoleInput.value = DomElems.consoleInput.value},
}); });
DomElems.consoleInputCell.appendChild(DomElems.consoleInputHeader); DomElems.consoleInputCell.appendChild(DomElems.consoleInputHeader);
@@ -1359,7 +1363,7 @@ Bladeburner.prototype.createOverviewContent = function() {
innerText:"Est. Synthoid Population: ", innerText:"Est. Synthoid Population: ",
display:"inline-block", display:"inline-block",
tooltip:"This is your Bladeburner division's estimate of how many Synthoids exist " + tooltip:"This is your Bladeburner division's estimate of how many Synthoids exist " +
"in your current city." "in your current city.",
}); });
DomElems.overviewEstPopHelpTip = createElement("div", { DomElems.overviewEstPopHelpTip = createElement("div", {
@@ -1377,7 +1381,7 @@ Bladeburner.prototype.createOverviewContent = function() {
"The Synthoid populations of cities can change due to your " + "The Synthoid populations of cities can change due to your " +
"actions or random events. If random events occur, they will " + "actions or random events. If random events occur, they will " +
"be logged in the Bladeburner Console."); "be logged in the Bladeburner Console.");
} },
}); });
DomElems.overviewEstComms = createElement("p", { DomElems.overviewEstComms = createElement("p", {
@@ -1391,14 +1395,14 @@ Bladeburner.prototype.createOverviewContent = function() {
innerText:"City Chaos: ", innerText:"City Chaos: ",
display:"inline-block", display:"inline-block",
tooltip:"The city's chaos level due to tensions and conflicts between humans and Synthoids. " + tooltip:"The city's chaos level due to tensions and conflicts between humans and Synthoids. " +
"Having too high of a chaos level can make contracts and operations harder." "Having too high of a chaos level can make contracts and operations harder.",
}); });
DomElems.overviewBonusTime = createElement("p", { DomElems.overviewBonusTime = createElement("p", {
innerText: "Bonus time: ", innerText: "Bonus time: ",
display: "inline-block", display: "inline-block",
tooltip: "You gain bonus time while offline or when the game is inactive (e.g. when the tab is throttled by browser). " + tooltip: "You gain bonus time while offline or when the game is inactive (e.g. when the tab is throttled by browser). " +
"Bonus time makes the Bladeburner mechanic progress faster, up to 5x the normal speed." "Bonus time makes the Bladeburner mechanic progress faster, up to 5x the normal speed.",
}); });
DomElems.overviewSkillPoints = createElement("p", {display:"block"}); DomElems.overviewSkillPoints = createElement("p", {display:"block"});
@@ -1434,7 +1438,7 @@ Bladeburner.prototype.createOverviewContent = function() {
innerText:"Cancel", class:"a-link-button", innerText:"Cancel", class:"a-link-button",
clickListener:() => { clickListener:() => {
removeElementById(popupId); return false; removeElementById(popupId); return false;
} },
})) }))
popupArguments.push(createElement("p", { // Info Text popupArguments.push(createElement("p", { // Info Text
innerText:"Travel to a different city for your Bladeburner " + innerText:"Travel to a different city for your Bladeburner " +
@@ -1456,12 +1460,12 @@ Bladeburner.prototype.createOverviewContent = function() {
removeElementById(popupId); removeElementById(popupId);
inst.updateOverviewContent(); inst.updateOverviewContent();
return false; return false;
} },
})); }));
})(this, i); })(this, i);
} }
createPopup(popupId, popupArguments); createPopup(popupId, popupArguments);
} },
})); }));
// Faction button // Faction button
@@ -1489,7 +1493,7 @@ Bladeburner.prototype.createOverviewContent = function() {
} }
} }
return false; return false;
} },
})); }));
} }
@@ -1522,14 +1526,14 @@ Bladeburner.prototype.createActionAndSkillsContent = function() {
DomElems.currentTab = buttons[i].toLowerCase(); DomElems.currentTab = buttons[i].toLowerCase();
inst.createActionAndSkillsContent(); inst.createActionAndSkillsContent();
return false; return false;
} },
})); }));
}) (buttons, i, this, currTab); }) (buttons, i, this, currTab);
} }
// General info/description for each action // General info/description for each action
DomElems.actionsAndSkillsDesc = createElement("p", { DomElems.actionsAndSkillsDesc = createElement("p", {
display:"block", margin:"4px", padding:"4px" display:"block", margin:"4px", padding:"4px",
}); });
// List for actions/skills // List for actions/skills
@@ -1574,7 +1578,7 @@ Bladeburner.prototype.createGeneralActionsContent = function() {
for (var actionName in GeneralActions) { for (var actionName in GeneralActions) {
if (GeneralActions.hasOwnProperty(actionName)) { if (GeneralActions.hasOwnProperty(actionName)) {
DomElems.generalActions[actionName] = createElement("div", { DomElems.generalActions[actionName] = createElement("div", {
class:"bladeburner-action", name:actionName class:"bladeburner-action", name:actionName,
}); });
DomElems.actionsAndSkillsList.appendChild(DomElems.generalActions[actionName]); DomElems.actionsAndSkillsList.appendChild(DomElems.generalActions[actionName]);
} }
@@ -1596,7 +1600,7 @@ Bladeburner.prototype.createContractsContent = function() {
for (var contractName in this.contracts) { for (var contractName in this.contracts) {
if (this.contracts.hasOwnProperty(contractName)) { if (this.contracts.hasOwnProperty(contractName)) {
DomElems.contracts[contractName] = createElement("div", { DomElems.contracts[contractName] = createElement("div", {
class:"bladeburner-action", name:contractName class:"bladeburner-action", name:contractName,
}); });
DomElems.actionsAndSkillsList.appendChild(DomElems.contracts[contractName]); DomElems.actionsAndSkillsList.appendChild(DomElems.contracts[contractName]);
} }
@@ -1625,7 +1629,7 @@ Bladeburner.prototype.createOperationsContent = function() {
for (var operationName in this.operations) { for (var operationName in this.operations) {
if (this.operations.hasOwnProperty(operationName)) { if (this.operations.hasOwnProperty(operationName)) {
DomElems.operations[operationName] = createElement("div", { DomElems.operations[operationName] = createElement("div", {
class:"bladeburner-action", name:operationName class:"bladeburner-action", name:operationName,
}); });
DomElems.actionsAndSkillsList.appendChild(DomElems.operations[operationName]); DomElems.actionsAndSkillsList.appendChild(DomElems.operations[operationName]);
} }
@@ -1663,7 +1667,7 @@ Bladeburner.prototype.createBlackOpsContent = function() {
for (var i = blackops.length-1; i >= 0 ; --i) { for (var i = blackops.length-1; i >= 0 ; --i) {
if (this.blackops[[blackops[i].name]] == null && i !== 0 && this.blackops[[blackops[i-1].name]] == null) {continue;} // If this one nor the next are completed then this isn't unlocked yet. if (this.blackops[[blackops[i].name]] == null && i !== 0 && this.blackops[[blackops[i-1].name]] == null) {continue;} // If this one nor the next are completed then this isn't unlocked yet.
DomElems.blackops[blackops[i].name] = createElement("div", { DomElems.blackops[blackops[i].name] = createElement("div", {
class:"bladeburner-action", name:blackops[i].name class:"bladeburner-action", name:blackops[i].name,
}); });
DomElems.actionsAndSkillsList.appendChild(DomElems.blackops[blackops[i].name]); DomElems.actionsAndSkillsList.appendChild(DomElems.blackops[blackops[i].name]);
} }
@@ -1746,7 +1750,7 @@ Bladeburner.prototype.createSkillsContent = function() {
// Skill Points // Skill Points
DomElems.skillPointsDisplay = createElement("p", { DomElems.skillPointsDisplay = createElement("p", {
innerHTML:"<br><strong>Skill Points: " + formatNumber(this.skillPoints, 0) + "</strong>" innerHTML:"<br><strong>Skill Points: " + formatNumber(this.skillPoints, 0) + "</strong>",
}); });
DomElems.actionAndSkillsDiv.appendChild(DomElems.skillPointsDisplay); DomElems.actionAndSkillsDiv.appendChild(DomElems.skillPointsDisplay);
@@ -1754,7 +1758,7 @@ Bladeburner.prototype.createSkillsContent = function() {
for (var skillName in Skills) { for (var skillName in Skills) {
if (Skills.hasOwnProperty(skillName)) { if (Skills.hasOwnProperty(skillName)) {
DomElems.skills[skillName] = createElement("div", { DomElems.skills[skillName] = createElement("div", {
class:"bladeburner-action", name:skillName class:"bladeburner-action", name:skillName,
}); });
DomElems.actionsAndSkillsList.appendChild(DomElems.skills[skillName]); DomElems.actionsAndSkillsList.appendChild(DomElems.skills[skillName]);
} }
@@ -1898,7 +1902,7 @@ Bladeburner.prototype.updateGeneralActionsUIElement = function(el, action) {
var progress = this.actionTimeCurrent / this.actionTimeToComplete; var progress = this.actionTimeCurrent / this.actionTimeToComplete;
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
display:"block", display:"block",
innerText:createProgressBarText({progress:progress}) innerText:createProgressBarText({progress:progress}),
})); }));
} else { } else {
// Start button // Start button
@@ -1911,13 +1915,13 @@ Bladeburner.prototype.updateGeneralActionsUIElement = function(el, action) {
this.startAction(this.action); this.startAction(this.action);
this.updateActionAndSkillsContent(); this.updateActionAndSkillsContent();
return false; return false;
} },
})); }));
} }
appendLineBreaks(el, 2); appendLineBreaks(el, 2);
el.appendChild(createElement("pre", { // Info el.appendChild(createElement("pre", { // Info
innerHTML:action.desc, display:"inline-block" innerHTML:action.desc, display:"inline-block",
})); }));
@@ -1933,14 +1937,14 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
formatNumber(this.actionTimeCurrent, 0) + " / " + formatNumber(this.actionTimeCurrent, 0) + " / " +
formatNumber(this.actionTimeToComplete, 0) + ")" formatNumber(this.actionTimeToComplete, 0) + ")"
: action.name, : action.name,
display:"inline-block" display:"inline-block",
})); }));
if (isActive) { // Progress bar if its active if (isActive) { // Progress bar if its active
var progress = this.actionTimeCurrent / this.actionTimeToComplete; var progress = this.actionTimeCurrent / this.actionTimeToComplete;
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
display:"block", display:"block",
innerText:createProgressBarText({progress:progress}) innerText:createProgressBarText({progress:progress}),
})); }));
} else { // Start button } else { // Start button
el.appendChild(createElement("a", { el.appendChild(createElement("a", {
@@ -1952,7 +1956,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
this.startAction(this.action); this.startAction(this.action);
this.updateActionAndSkillsContent(); this.updateActionAndSkillsContent();
return false; return false;
} },
})); }));
} }
@@ -1963,7 +1967,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
display:"inline-block", display:"inline-block",
innerText:"Level: " + action.level + " / " + action.maxLevel, innerText:"Level: " + action.level + " / " + action.maxLevel,
tooltip:action.getSuccessesNeededForNextLevel(BladeburnerConstants.ContractSuccessesPerLevel) + " successes " + tooltip:action.getSuccessesNeededForNextLevel(BladeburnerConstants.ContractSuccessesPerLevel) + " successes " +
"needed for next level" "needed for next level",
})); }));
el.appendChild(createElement("a", { el.appendChild(createElement("a", {
class: maxLevel ? "a-link-button-inactive" : "a-link-button", innerHTML:"&uarr;", class: maxLevel ? "a-link-button-inactive" : "a-link-button", innerHTML:"&uarr;",
@@ -1975,7 +1979,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
if (isActive) {this.startAction(this.action);} // Restart Action if (isActive) {this.startAction(this.action);} // Restart Action
this.updateContractsUIElement(el, action); this.updateContractsUIElement(el, action);
return false; return false;
} },
})); }));
el.appendChild(createElement("a", { el.appendChild(createElement("a", {
class: (action.level <= 1) ? "a-link-button-inactive" : "a-link-button", innerHTML:"&darr;", class: (action.level <= 1) ? "a-link-button-inactive" : "a-link-button", innerHTML:"&darr;",
@@ -1987,7 +1991,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
if (isActive) {this.startAction(this.action);} // Restart Action if (isActive) {this.startAction(this.action);} // Restart Action
this.updateContractsUIElement(el, action); this.updateContractsUIElement(el, action);
return false; return false;
} },
})); }));
var actionTime = action.getActionTime(this); var actionTime = action.getActionTime(this);
@@ -2007,7 +2011,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
var autolevelCheckboxId = "bladeburner-" + action.name + "-autolevel-checkbox"; var autolevelCheckboxId = "bladeburner-" + action.name + "-autolevel-checkbox";
el.appendChild(createElement("label", { el.appendChild(createElement("label", {
for:autolevelCheckboxId, innerText:"Autolevel: ",color:"white", for:autolevelCheckboxId, innerText:"Autolevel: ",color:"white",
tooltip:"Automatically increase contract level when possible" tooltip:"Automatically increase contract level when possible",
})); }));
const checkboxInput = createElement("input", { const checkboxInput = createElement("input", {
@@ -2031,14 +2035,14 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
formatNumber(this.actionTimeCurrent, 0) + " / " + formatNumber(this.actionTimeCurrent, 0) + " / " +
formatNumber(this.actionTimeToComplete, 0) + ")" formatNumber(this.actionTimeToComplete, 0) + ")"
: action.name, : action.name,
display:"inline-block" display:"inline-block",
})); }));
if (isActive) { // Progress bar if its active if (isActive) { // Progress bar if its active
var progress = this.actionTimeCurrent / this.actionTimeToComplete; var progress = this.actionTimeCurrent / this.actionTimeToComplete;
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
display:"block", display:"block",
innerText:createProgressBarText({progress:progress}) innerText:createProgressBarText({progress:progress}),
})); }));
} else { // Start button and set Team Size button } else { // Start button and set Team Size button
el.appendChild(createElement("a", { el.appendChild(createElement("a", {
@@ -2050,7 +2054,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
this.startAction(this.action); this.startAction(this.action);
this.updateActionAndSkillsContent(); this.updateActionAndSkillsContent();
return false; return false;
} },
})); }));
el.appendChild(createElement("a", { el.appendChild(createElement("a", {
innerText:"Set Team Size (Curr Size: " + formatNumber(action.teamCount, 0) + ")", class:"a-link-button", innerText:"Set Team Size (Curr Size: " + formatNumber(action.teamCount, 0) + ")", class:"a-link-button",
@@ -2061,7 +2065,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
innerText:"Enter the amount of team members you would like to take on these " + innerText:"Enter the amount of team members you would like to take on these " +
"operations. If you do not have the specified number of team members, " + "operations. If you do not have the specified number of team members, " +
"then as many as possible will be used. Note that team members may " + "then as many as possible will be used. Note that team members may " +
"be lost during operations." "be lost during operations.",
}); });
var input = createElement("input", { var input = createElement("input", {
@@ -2071,25 +2075,25 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
innerText:"Confirm", class:"a-link-button", innerText:"Confirm", class:"a-link-button",
clickListener:() => { clickListener:() => {
var num = Math.round(parseFloat(input.value)); var num = Math.round(parseFloat(input.value));
if (isNaN(num)) { if (isNaN(num) || num < 0) {
dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric)") dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric, positive)")
} else { } else {
action.teamCount = num; action.teamCount = num;
this.updateOperationsUIElement(el, action); this.updateOperationsUIElement(el, action);
} }
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} },
}); });
var cancelBtn = createElement("a", { var cancelBtn = createElement("a", {
innerText:"Cancel", class:"a-link-button", innerText:"Cancel", class:"a-link-button",
clickListener:() => { clickListener:() => {
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} },
}); });
createPopup(popupId, [txt, input, setBtn, cancelBtn]); createPopup(popupId, [txt, input, setBtn, cancelBtn]);
} },
})); }));
} }
@@ -2100,7 +2104,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
display:"inline-block", display:"inline-block",
innerText:"Level: " + action.level + " / " + action.maxLevel, innerText:"Level: " + action.level + " / " + action.maxLevel,
tooltip:action.getSuccessesNeededForNextLevel(BladeburnerConstants.OperationSuccessesPerLevel) + " successes " + tooltip:action.getSuccessesNeededForNextLevel(BladeburnerConstants.OperationSuccessesPerLevel) + " successes " +
"needed for next level" "needed for next level",
})); }));
el.appendChild(createElement("a", { el.appendChild(createElement("a", {
class: maxLevel ? "a-link-button-inactive" : "a-link-button", innerHTML:"&uarr;", class: maxLevel ? "a-link-button-inactive" : "a-link-button", innerHTML:"&uarr;",
@@ -2112,7 +2116,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
if (isActive) {this.startAction(this.action);} // Restart Action if (isActive) {this.startAction(this.action);} // Restart Action
this.updateOperationsUIElement(el, action); this.updateOperationsUIElement(el, action);
return false; return false;
} },
})); }));
el.appendChild(createElement("a", { el.appendChild(createElement("a", {
class: (action.level <= 1) ? "a-link-button-inactive" : "a-link-button", innerHTML:"&darr;", class: (action.level <= 1) ? "a-link-button-inactive" : "a-link-button", innerHTML:"&darr;",
@@ -2124,11 +2128,10 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
if (isActive) {this.startAction(this.action);} // Restart Action if (isActive) {this.startAction(this.action);} // Restart Action
this.updateOperationsUIElement(el, action); this.updateOperationsUIElement(el, action);
return false; return false;
} },
})); }));
// General Info // General Info
var difficulty = action.getDifficulty();
var actionTime = action.getActionTime(this); var actionTime = action.getActionTime(this);
appendLineBreaks(el, 2); appendLineBreaks(el, 2);
el.appendChild(createElement("pre", { el.appendChild(createElement("pre", {
@@ -2146,7 +2149,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
var autolevelCheckboxId = "bladeburner-" + action.name + "-autolevel-checkbox"; var autolevelCheckboxId = "bladeburner-" + action.name + "-autolevel-checkbox";
el.appendChild(createElement("label", { el.appendChild(createElement("label", {
for:autolevelCheckboxId, innerText:"Autolevel: ",color:"white", for:autolevelCheckboxId, innerText:"Autolevel: ",color:"white",
tooltip:"Automatically increase operation level when possible" tooltip:"Automatically increase operation level when possible",
})); }));
const checkboxInput = createElement("input", { const checkboxInput = createElement("input", {
@@ -2166,7 +2169,6 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
var isActive = el.classList.contains(ActiveActionCssClass); var isActive = el.classList.contains(ActiveActionCssClass);
var isCompleted = (this.blackops[action.name] != null); var isCompleted = (this.blackops[action.name] != null);
var estimatedSuccessChance = action.getSuccessChance(this, {est:true}); var estimatedSuccessChance = action.getSuccessChance(this, {est:true});
var difficulty = action.getDifficulty();
var actionTime = action.getActionTime(this); var actionTime = action.getActionTime(this);
var hasReqdRank = this.rank >= action.reqdRank; var hasReqdRank = this.rank >= action.reqdRank;
@@ -2190,7 +2192,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
var progress = this.actionTimeCurrent / this.actionTimeToComplete; var progress = this.actionTimeCurrent / this.actionTimeToComplete;
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
display:"block", display:"block",
innerText:createProgressBarText({progress:progress}) innerText:createProgressBarText({progress:progress}),
})); }));
} else { } else {
el.appendChild(createElement("a", { // Start button el.appendChild(createElement("a", { // Start button
@@ -2202,7 +2204,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
this.startAction(this.action); this.startAction(this.action);
this.updateActionAndSkillsContent(); this.updateActionAndSkillsContent();
return false; return false;
} },
})); }));
el.appendChild(createElement("a", { // Set Team Size Button el.appendChild(createElement("a", { // Set Team Size Button
innerText:"Set Team Size (Curr Size: " + formatNumber(action.teamCount, 0) + ")", class:"a-link-button", innerText:"Set Team Size (Curr Size: " + formatNumber(action.teamCount, 0) + ")", class:"a-link-button",
@@ -2213,7 +2215,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
innerText:"Enter the amount of team members you would like to take on this " + innerText:"Enter the amount of team members you would like to take on this " +
"BlackOp. If you do not have the specified number of team members, " + "BlackOp. If you do not have the specified number of team members, " +
"then as many as possible will be used. Note that team members may " + "then as many as possible will be used. Note that team members may " +
"be lost during operations." "be lost during operations.",
}); });
var input = createElement("input", { var input = createElement("input", {
@@ -2223,25 +2225,25 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
innerText:"Confirm", class:"a-link-button", innerText:"Confirm", class:"a-link-button",
clickListener:() => { clickListener:() => {
var num = Math.round(parseFloat(input.value)); var num = Math.round(parseFloat(input.value));
if (isNaN(num)) { if (isNaN(num) || num < 0) {
dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric)") dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric, positive)")
} else { } else {
action.teamCount = num; action.teamCount = num;
this.updateBlackOpsUIElement(el, action); this.updateBlackOpsUIElement(el, action);
} }
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} },
}); });
var cancelBtn = createElement("a", { var cancelBtn = createElement("a", {
innerText:"Cancel", class:"a-link-button", innerText:"Cancel", class:"a-link-button",
clickListener:() => { clickListener:() => {
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} },
}); });
createPopup(popupId, [txt, input, setBtn, cancelBtn]); createPopup(popupId, [txt, input, setBtn, cancelBtn]);
} },
})); }));
} }
@@ -2253,7 +2255,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
})); }));
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
display:"block", color:hasReqdRank ? "white" : "red", display:"block", color:hasReqdRank ? "white" : "red",
innerHTML:"Required Rank: " + formatNumber(action.reqdRank, 0) + "<br>" innerHTML:"Required Rank: " + formatNumber(action.reqdRank, 0) + "<br>",
})); }));
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
display:"inline-block", display:"inline-block",
@@ -2293,7 +2295,7 @@ Bladeburner.prototype.updateSkillsUIElement = function(el, skill) {
this.upgradeSkill(skill); this.upgradeSkill(skill);
this.createActionAndSkillsContent(); this.createActionAndSkillsContent();
return false; return false;
} },
})); }));
appendLineBreaks(el, 2); appendLineBreaks(el, 2);
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
@@ -2303,7 +2305,7 @@ Bladeburner.prototype.updateSkillsUIElement = function(el, skill) {
if (maxLvl) { if (maxLvl) {
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
color:"red", display:"block", color:"red", display:"block",
innerText:"MAX LEVEL" innerText:"MAX LEVEL",
})); }));
} else { } else {
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
@@ -2504,7 +2506,7 @@ Bladeburner.prototype.executeAutomateConsoleCommand = function(args) {
case "gen": case "gen":
if (GeneralActions[val] != null) { if (GeneralActions[val] != null) {
var action = new ActionIdentifier({ var action = new ActionIdentifier({
type:ActionTypes[val], name:val type:ActionTypes[val], name:val,
}); });
if (highLow) { if (highLow) {
this.automateActionHigh = action; this.automateActionHigh = action;
@@ -2520,7 +2522,7 @@ Bladeburner.prototype.executeAutomateConsoleCommand = function(args) {
case "contracts": case "contracts":
if (this.contracts[val] != null) { if (this.contracts[val] != null) {
var action = new ActionIdentifier({ var action = new ActionIdentifier({
type:ActionTypes.Contract, name:val type:ActionTypes.Contract, name:val,
}); });
if (highLow) { if (highLow) {
this.automateActionHigh = action; this.automateActionHigh = action;
@@ -2538,7 +2540,7 @@ Bladeburner.prototype.executeAutomateConsoleCommand = function(args) {
case "operation": case "operation":
if (this.operations[val] != null) { if (this.operations[val] != null) {
var action = new ActionIdentifier({ var action = new ActionIdentifier({
type:ActionTypes.Operation, name:val type:ActionTypes.Operation, name:val,
}); });
if (highLow) { if (highLow) {
this.automateActionHigh = action; this.automateActionHigh = action;
@@ -3206,8 +3208,8 @@ Bladeburner.prototype.setTeamSizeNetscriptFn = function(type, name, size, worker
return -1; return -1;
} }
const sanitizedSize = Math.round(size); let sanitizedSize = Math.round(size);
if (isNaN(sanitizedSize)) { if (isNaN(sanitizedSize) || sanitizedSize < 0) {
workerScript.log("bladeburner.setTeamSize", `Invalid size: ${size}`); workerScript.log("bladeburner.setTeamSize", `Invalid size: ${size}`);
return -1; return -1;
} }

View File

@@ -3,21 +3,20 @@ import { getRandomInt } from "../../utils/helpers/getRandomInt";
import { addOffset } from "../../utils/helpers/addOffset"; import { addOffset } from "../../utils/helpers/addOffset";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
import { BladeburnerConstants } from "./data/Constants"; import { BladeburnerConstants } from "./data/Constants";
// import { Contract } from "./Contract"; import { IBladeburner } from "./IBladeburner";
// import { Operation } from "./Operation"; import { IAction, ISuccessChanceParams } from "./IAction";
// import { BlackOperation } from "./BlackOperation";
class StatsMultiplier { class StatsMultiplier {
hack: number = 0;
str: number = 0;
def: number = 0;
dex: number = 0;
agi: number = 0;
cha: number = 0;
int: number = 0;
[key: string]: number; [key: string]: number;
};
hack = 0;
str = 0;
def = 0;
dex = 0;
agi = 0;
cha = 0;
int = 0;
}
export interface IActionParams { export interface IActionParams {
name?: string; name?: string;
@@ -43,32 +42,32 @@ export interface IActionParams {
teamCount?: number; teamCount?: number;
} }
export class Action { export class Action implements IAction {
name: string = ""; name = "";
desc: string = ""; desc = "";
// Difficulty scales with level. See getDifficulty() method // Difficulty scales with level. See getDifficulty() method
level: number = 1; level = 1;
maxLevel: number = 1; maxLevel = 1;
autoLevel: boolean = true; autoLevel = true;
baseDifficulty: number = 100; baseDifficulty = 100;
difficultyFac: number = 1.01; difficultyFac = 1.01;
// Rank increase/decrease is affected by this exponent // Rank increase/decrease is affected by this exponent
rewardFac: number = 1.02; rewardFac = 1.02;
successes: number = 0; successes = 0;
failures: number = 0; failures = 0;
// All of these scale with level/difficulty // All of these scale with level/difficulty
rankGain: number = 0; rankGain = 0;
rankLoss: number = 0; rankLoss = 0;
hpLoss: number = 0; hpLoss = 0;
hpLost: number = 0; hpLost = 0;
// Action Category. Current categories are stealth and kill // Action Category. Current categories are stealth and kill
isStealth: boolean = false; isStealth = false;
isKill: boolean = false; isKill = false;
/** /**
* Number of this contract remaining, and its growth rate * Number of this contract remaining, and its growth rate
@@ -81,7 +80,7 @@ export class Action {
weights: StatsMultiplier = {hack:1/7,str:1/7,def:1/7,dex:1/7,agi:1/7,cha:1/7,int:1/7}; weights: StatsMultiplier = {hack:1/7,str:1/7,def:1/7,dex:1/7,agi:1/7,cha:1/7,int:1/7};
// Diminishing returns of stats (stat ^ decay where 0 <= decay <= 1) // Diminishing returns of stats (stat ^ decay where 0 <= decay <= 1)
decays: StatsMultiplier = { hack: 0.9, str: 0.9, def: 0.9, dex: 0.9, agi: 0.9, cha: 0.9, int: 0.9 }; decays: StatsMultiplier = { hack: 0.9, str: 0.9, def: 0.9, dex: 0.9, agi: 0.9, cha: 0.9, int: 0.9 };
teamCount: number = 0; teamCount = 0;
// Base Class for Contracts, Operations, and BlackOps // Base Class for Contracts, Operations, and BlackOps
constructor(params: IActionParams| null = null) { // | null = null constructor(params: IActionParams| null = null) { // | null = null
@@ -138,7 +137,7 @@ export class Action {
* Tests for success. Should be called when an action has completed * Tests for success. Should be called when an action has completed
* @param inst {Bladeburner} - Bladeburner instance * @param inst {Bladeburner} - Bladeburner instance
*/ */
attempt(inst: any): boolean { attempt(inst: IBladeburner): boolean {
return (Math.random() < this.getSuccessChance(inst)); return (Math.random() < this.getSuccessChance(inst));
} }
@@ -147,7 +146,7 @@ export class Action {
return 1; return 1;
} }
getActionTime(inst: any): number { getActionTime(inst: IBladeburner): number {
const difficulty = this.getDifficulty(); const difficulty = this.getDifficulty();
let baseTime = difficulty / BladeburnerConstants.DifficultyToTimeFactor; let baseTime = difficulty / BladeburnerConstants.DifficultyToTimeFactor;
const skillFac = inst.skillMultipliers.actionTime; // Always < 1 const skillFac = inst.skillMultipliers.actionTime; // Always < 1
@@ -165,15 +164,15 @@ export class Action {
} }
// For actions that have teams. To be implemented by subtypes. // For actions that have teams. To be implemented by subtypes.
getTeamSuccessBonus(inst: any): number { getTeamSuccessBonus(inst: IBladeburner): number {
return 1; return 1;
} }
getActionTypeSkillSuccessBonus(inst: any): number { getActionTypeSkillSuccessBonus(inst: IBladeburner): number {
return 1; return 1;
} }
getChaosCompetencePenalty(inst: any, params: any): number { getChaosCompetencePenalty(inst: IBladeburner, params: ISuccessChanceParams): number {
const city = inst.getCurrentCity(); const city = inst.getCurrentCity();
if (params.est) { if (params.est) {
return Math.pow((city.popEst / BladeburnerConstants.PopulationThreshold), BladeburnerConstants.PopulationExponent); return Math.pow((city.popEst / BladeburnerConstants.PopulationThreshold), BladeburnerConstants.PopulationExponent);
@@ -182,7 +181,7 @@ export class Action {
} }
} }
getChaosDifficultyBonus(inst: any, params: any): number { getChaosDifficultyBonus(inst: IBladeburner/*, params: ISuccessChanceParams*/): number {
const city = inst.getCurrentCity(); const city = inst.getCurrentCity();
if (city.chaos > BladeburnerConstants.ChaosThreshold) { if (city.chaos > BladeburnerConstants.ChaosThreshold) {
const diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold); const diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold);
@@ -198,14 +197,14 @@ export class Action {
* @params - options: * @params - options:
* est (bool): Get success chance estimate instead of real success chance * est (bool): Get success chance estimate instead of real success chance
*/ */
getSuccessChance(inst: any, params: any={}) { getSuccessChance(inst: IBladeburner, params: ISuccessChanceParams={est: false}): number {
if (inst == null) {throw new Error("Invalid Bladeburner instance passed into Action.getSuccessChance");} if (inst == null) {throw new Error("Invalid Bladeburner instance passed into Action.getSuccessChance");}
let difficulty = this.getDifficulty(); let difficulty = this.getDifficulty();
let competence = 0; let competence = 0;
for (let stat in this.weights) { for (const stat in this.weights) {
if (this.weights.hasOwnProperty(stat)) { if (this.weights.hasOwnProperty(stat)) {
let playerStatLvl = Player.queryStatFromString(stat); const playerStatLvl = Player.queryStatFromString(stat);
let key = "eff" + stat.charAt(0).toUpperCase() + stat.slice(1); const key = "eff" + stat.charAt(0).toUpperCase() + stat.slice(1);
let effMultiplier = inst.skillMultipliers[key]; let effMultiplier = inst.skillMultipliers[key];
if (effMultiplier == null) { if (effMultiplier == null) {
console.error(`Failed to find Bladeburner Skill multiplier for: ${stat}`); console.error(`Failed to find Bladeburner Skill multiplier for: ${stat}`);
@@ -220,7 +219,7 @@ export class Action {
competence *= this.getTeamSuccessBonus(inst); competence *= this.getTeamSuccessBonus(inst);
competence *= this.getChaosCompetencePenalty(inst, params); competence *= this.getChaosCompetencePenalty(inst, params);
difficulty *= this.getChaosDifficultyBonus(inst, params); difficulty *= this.getChaosDifficultyBonus(inst);
if(this.name == "Raid" && inst.getCurrentCity().comms <= 0) { if(this.name == "Raid" && inst.getCurrentCity().comms <= 0) {
return 0; return 0;
@@ -253,18 +252,14 @@ export class Action {
} }
} }
static fromJSON(value: any): Action {
return Generic_fromJSON(Action, value.data);
}
toJSON(): any { toJSON(): any {
return Generic_toJSON("Action", this); return Generic_toJSON("Action", this);
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Action {
return Generic_fromJSON(Action, value.data);
}
} }
Reviver.constructors.Action = Action; Reviver.constructors.Action = Action;

View File

@@ -13,21 +13,22 @@ export class BlackOperation extends Operation {
return 1.5; return 1.5;
} }
getChaosCompetencePenalty(inst: any, params: any): number { getChaosCompetencePenalty(/*inst: IBladeburner, params: ISuccessChanceParams*/): number {
return 1; return 1;
} }
getChaosDifficultyBonus(inst: any, params: any): number { getChaosDifficultyBonus(/*inst: IBladeburner, params: ISuccessChanceParams*/): number {
return 1; return 1;
} }
static fromJSON(value: any): Operation {
return Generic_fromJSON(BlackOperation, value.data);
}
toJSON(): any { toJSON(): any {
return Generic_toJSON("BlackOperation", this); return Generic_toJSON("BlackOperation", this);
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Operation {
return Generic_fromJSON(BlackOperation, value.data);
}
} }
Reviver.constructors.BlackOperation = BlackOperation; Reviver.constructors.BlackOperation = BlackOperation;

View File

@@ -16,12 +16,12 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:50, rankLoss:10, hpLoss:100, rankGain:50, rankLoss:10, hpLoss:100,
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Zero"] = new BlackOperation({ BlackOperations["Operation Zero"] = new BlackOperation({
name:"Operation Zero", name:"Operation Zero",
desc:"AeroCorp is one of the world's largest defense contractors. " + desc:"AeroCorp is one of the world's largest defense contractors. " +
"It's leader, Steve Watataki, is thought to be a supporter of " + "Its leader, Steve Watataki, is thought to be a supporter of " +
"Synthoid rights. He must be removed.<br><br>" + "Synthoid rights. He must be removed.<br><br>" +
"The goal of Operation Zero is to covertly infiltrate AeroCorp and " + "The goal of Operation Zero is to covertly infiltrate AeroCorp and " +
"uncover any incriminating evidence or " + "uncover any incriminating evidence or " +
@@ -33,7 +33,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:60, rankLoss:15, hpLoss:50, rankGain:60, rankLoss:15, hpLoss:50,
weights:{hack:0.2,str:0.15,def:0.15,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.2,str:0.15,def:0.15,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isStealth:true isStealth:true,
}); });
BlackOperations["Operation X"] = new BlackOperation({ BlackOperations["Operation X"] = new BlackOperation({
name:"Operation X", name:"Operation X",
@@ -52,7 +52,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:75, rankLoss:15, hpLoss:100, rankGain:75, rankLoss:15, hpLoss:100,
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Titan"] = new BlackOperation({ BlackOperations["Operation Titan"] = new BlackOperation({
name:"Operation Titan", name:"Operation Titan",
@@ -70,7 +70,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:100, rankLoss:20, hpLoss:100, rankGain:100, rankLoss:20, hpLoss:100,
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Ares"] = new BlackOperation({ BlackOperations["Operation Ares"] = new BlackOperation({
name:"Operation Ares", name:"Operation Ares",
@@ -84,7 +84,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:125, rankLoss:20, hpLoss:200, rankGain:125, rankLoss:20, hpLoss:200,
weights:{hack:0,str:0.25,def:0.25,dex:0.25,agi:0.25,cha:0, int:0}, weights:{hack:0,str:0.25,def:0.25,dex:0.25,agi:0.25,cha:0, int:0},
decays:{hack:0,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Archangel"] = new BlackOperation({ BlackOperations["Operation Archangel"] = new BlackOperation({
name:"Operation Archangel", name:"Operation Archangel",
@@ -152,7 +152,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:750, rankLoss:60, hpLoss:1000, rankGain:750, rankLoss:60, hpLoss:1000,
weights:{hack:0.05,str:0.2,def:0.2,dex:0.25,agi:0.25,cha:0, int:0.05}, weights:{hack:0.05,str:0.2,def:0.2,dex:0.25,agi:0.25,cha:0, int:0.05},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Deckard"] = new BlackOperation({ BlackOperations["Operation Deckard"] = new BlackOperation({
name:"Operation Deckard", name:"Operation Deckard",
@@ -202,7 +202,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:2e3, rankLoss:150, hpLoss:1500, rankGain:2e3, rankLoss:150, hpLoss:1500,
weights:{hack:0,str:0.24,def:0.24,dex:0.24,agi:0.24,cha:0, int:0.04}, weights:{hack:0,str:0.24,def:0.24,dex:0.24,agi:0.24,cha:0, int:0.04},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Shoulder of Orion"] = new BlackOperation({ BlackOperations["Operation Shoulder of Orion"] = new BlackOperation({
name:"Operation Shoulder of Orion", name:"Operation Shoulder of Orion",
@@ -218,7 +218,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:2.5e3, rankLoss:500, hpLoss:1500, rankGain:2.5e3, rankLoss:500, hpLoss:1500,
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isStealth:true isStealth:true,
}); });
BlackOperations["Operation Hyron"] = new BlackOperation({ BlackOperations["Operation Hyron"] = new BlackOperation({
name:"Operation Hyron", name:"Operation Hyron",
@@ -240,7 +240,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:3e3, rankLoss:1e3, hpLoss:500, rankGain:3e3, rankLoss:1e3, hpLoss:500,
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Morpheus"] = new BlackOperation({ BlackOperations["Operation Morpheus"] = new BlackOperation({
name:"Operation Morpheus", name:"Operation Morpheus",
@@ -257,7 +257,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:4e3, rankLoss:1e3, hpLoss:100, rankGain:4e3, rankLoss:1e3, hpLoss:100,
weights:{hack:0.05,str:0.15,def:0.15,dex:0.3,agi:0.3,cha:0, int:0.05}, weights:{hack:0.05,str:0.15,def:0.15,dex:0.3,agi:0.3,cha:0, int:0.05},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isStealth:true isStealth:true,
}); });
BlackOperations["Operation Ion Storm"] = new BlackOperation({ BlackOperations["Operation Ion Storm"] = new BlackOperation({
name:"Operation Ion Storm", name:"Operation Ion Storm",
@@ -272,7 +272,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:5e3, rankLoss:1e3, hpLoss:5000, rankGain:5e3, rankLoss:1e3, hpLoss:5000,
weights:{hack:0,str:0.24,def:0.24,dex:0.24,agi:0.24,cha:0, int:0.04}, weights:{hack:0,str:0.24,def:0.24,dex:0.24,agi:0.24,cha:0, int:0.04},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Annihilus"] = new BlackOperation({ BlackOperations["Operation Annihilus"] = new BlackOperation({
name:"Operation Annihilus", name:"Operation Annihilus",
@@ -286,7 +286,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:7.5e3, rankLoss:1e3, hpLoss:10e3, rankGain:7.5e3, rankLoss:1e3, hpLoss:10e3,
weights:{hack:0,str:0.24,def:0.24,dex:0.24,agi:0.24,cha:0, int:0.04}, weights:{hack:0,str:0.24,def:0.24,dex:0.24,agi:0.24,cha:0, int:0.04},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Ultron"] = new BlackOperation({ BlackOperations["Operation Ultron"] = new BlackOperation({
name:"Operation Ultron", name:"Operation Ultron",
@@ -306,7 +306,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:10e3, rankLoss:2e3, hpLoss:10e3, rankGain:10e3, rankLoss:2e3, hpLoss:10e3,
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Centurion"] = new BlackOperation({ BlackOperations["Operation Centurion"] = new BlackOperation({
name:"Operation Centurion", name:"Operation Centurion",

View File

@@ -5,13 +5,13 @@ import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviv
import { addOffset } from "../../utils/helpers/addOffset"; import { addOffset } from "../../utils/helpers/addOffset";
export class ChangePopulationByCountParams { export class ChangePopulationByCountParams {
estChange: number = 0; estChange = 0;
estOffset: number = 0; estOffset = 0;
} }
export class ChangePopulationByPercentageParams { export class ChangePopulationByPercentageParams {
nonZero: boolean = false; nonZero = false;
changeEstEqually: boolean = false; changeEstEqually = false;
} }
export class City { export class City {
@@ -19,32 +19,32 @@ export class City {
/** /**
* Name of the city. * Name of the city.
*/ */
name: string = ""; name = "";
/** /**
* Population of the city. * Population of the city.
*/ */
pop: number = 0; pop = 0;
/** /**
* Population estimation of the city. * Population estimation of the city.
*/ */
popEst: number = 0; popEst = 0;
/** /**
* Number of communities in the city. * Number of communities in the city.
*/ */
comms: number = 0; comms = 0;
/** /**
* Estimated number of communities in the city. * Estimated number of communities in the city.
*/ */
commsEst: number = 0; commsEst = 0;
/** /**
* Chaos level of the city. * Chaos level of the city.
*/ */
chaos: number = 0; chaos = 0;
constructor(name: string = BladeburnerConstants.CityNames[2]) { constructor(name: string = BladeburnerConstants.CityNames[2]) {
this.name = name; this.name = name;
@@ -84,7 +84,7 @@ export class City {
/** /**
* p is the percentage, not the multiplier (e.g. pass in p = 5 for 5%) * p is the percentage, not the multiplier (e.g. pass in p = 5 for 5%)
*/ */
improvePopulationEstimateByPercentage(p: number, skillMult: number=1): void { improvePopulationEstimateByPercentage(p: number, skillMult=1): void {
p = p*skillMult; p = p*skillMult;
if (isNaN(p)) {throw new Error("NaN passed into City.improvePopulationEstimateByPercentage()");} if (isNaN(p)) {throw new Error("NaN passed into City.improvePopulationEstimateByPercentage()");}
if (this.popEst < this.pop) { if (this.popEst < this.pop) {
@@ -97,7 +97,7 @@ export class City {
} }
} }
improveCommunityEstimate(n: number=1): void { improveCommunityEstimate(n=1): void {
if (isNaN(n)) {throw new Error("NaN passed into City.improveCommunityEstimate()");} if (isNaN(n)) {throw new Error("NaN passed into City.improveCommunityEstimate()");}
if (this.commsEst < this.comms) { if (this.commsEst < this.comms) {
this.commsEst += n; this.commsEst += n;
@@ -154,19 +154,20 @@ export class City {
if (this.chaos < 0) {this.chaos = 0;} if (this.chaos < 0) {this.chaos = 0;}
} }
/**
* Initiatizes a City object from a JSON save state.
*/
static fromJSON(value: any): City {
return Generic_fromJSON(City, value.data);
}
/** /**
* Serialize the current object to a JSON save state. * Serialize the current object to a JSON save state.
*/ */
toJSON(): any { toJSON(): any {
return Generic_toJSON("City", this); return Generic_toJSON("City", this);
} }
/**
* Initiatizes a City object from a JSON save state.
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): City {
return Generic_fromJSON(City, value.data);
}
} }
Reviver.constructors.City = City; Reviver.constructors.City = City;

View File

@@ -1,4 +1,4 @@
// import { BladeburnerConstants } from "./data/Constants"; import { IBladeburner } from "./IBladeburner";
import { Action, IActionParams } from "./Action"; import { Action, IActionParams } from "./Action";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
@@ -8,17 +8,18 @@ export class Contract extends Action {
super(params); super(params);
} }
getActionTypeSkillSuccessBonus(inst: any): number { getActionTypeSkillSuccessBonus(inst: IBladeburner): number {
return inst.skillMultipliers.successChanceContract; return inst.skillMultipliers.successChanceContract;
} }
static fromJSON(value: any): Contract {
return Generic_fromJSON(Contract, value.data);
}
toJSON(): any { toJSON(): any {
return Generic_toJSON("Contract", this); return Generic_toJSON("Contract", this);
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Contract {
return Generic_fromJSON(Contract, value.data);
}
} }
Reviver.constructors.Contract = Contract; Reviver.constructors.Contract = Contract;

View File

@@ -11,7 +11,7 @@ export const GeneralActions: IMap<Action> = {};
name:actionName, name:actionName,
desc:"Improve your abilities at the Bladeburner unit's specialized training " + desc:"Improve your abilities at the Bladeburner unit's specialized training " +
"center. Doing this gives experience for all combat stats and also " + "center. Doing this gives experience for all combat stats and also " +
"increases your max stamina." "increases your max stamina.",
}); });
actionName = "Field Analysis"; actionName = "Field Analysis";
@@ -21,7 +21,7 @@ export const GeneralActions: IMap<Action> = {};
"Bladeburner's unit intelligence on Synthoid locations and " + "Bladeburner's unit intelligence on Synthoid locations and " +
"activities. Completing this action will improve the accuracy " + "activities. Completing this action will improve the accuracy " +
"of your Synthoid population estimated in the current city.<br><br>" + "of your Synthoid population estimated in the current city.<br><br>" +
"Does NOT require stamina." "Does NOT require stamina.",
}); });
actionName = "Recruitment"; actionName = "Recruitment";
@@ -29,7 +29,7 @@ export const GeneralActions: IMap<Action> = {};
name:actionName, name:actionName,
desc:"Attempt to recruit members for your Bladeburner team. These members " + desc:"Attempt to recruit members for your Bladeburner team. These members " +
"can help you conduct operations.<br><br>" + "can help you conduct operations.<br><br>" +
"Does NOT require stamina." "Does NOT require stamina.",
}); });
actionName = "Diplomacy"; actionName = "Diplomacy";
@@ -37,7 +37,7 @@ export const GeneralActions: IMap<Action> = {};
name: actionName, name: actionName,
desc: "Improve diplomatic relations with the Synthoid population. " + desc: "Improve diplomatic relations with the Synthoid population. " +
"Completing this action will reduce the Chaos level in your current city.<br><br>" + "Completing this action will reduce the Chaos level in your current city.<br><br>" +
"Does NOT require stamina." "Does NOT require stamina.",
}); });
actionName = "Hyperbolic Regeneration Chamber"; actionName = "Hyperbolic Regeneration Chamber";

View File

@@ -0,0 +1,71 @@
import { IBladeburner } from "./IBladeburner";
export interface IStatsMultiplier {
[key: string]: number;
hack: number;
str: number;
def: number;
dex: number;
agi: number;
cha: number;
int: number;
}
export interface ISuccessChanceParams {
est: boolean;
}
export interface IAction {
name: string;
desc: string;
// Difficulty scales with level. See getDifficulty() method
level: number;
maxLevel: number;
autoLevel: boolean;
baseDifficulty: number;
difficultyFac: number;
// Rank increase/decrease is affected by this exponent
rewardFac: number;
successes: number;
failures: number;
// All of these scale with level/difficulty
rankGain: number;
rankLoss: number;
hpLoss: number;
hpLost: number;
// Action Category. Current categories are stealth and kill
isStealth: boolean;
isKill: boolean;
/**
* Number of this contract remaining, and its growth rate
* Growth rate is an integer and the count will increase by that integer every "cycle"
*/
count: number;
countGrowth: number;
// Weighting of each stat in determining action success rate
weights: IStatsMultiplier;
// Diminishing returns of stats (stat ^ decay where 0 <= decay <= 1)
decays: IStatsMultiplier;
teamCount: number;
getDifficulty(): number;
attempt(inst: IBladeburner): boolean;
getActionTimePenalty(): number;
getActionTime(inst: IBladeburner): number;
getTeamSuccessBonus(inst: IBladeburner): number;
getActionTypeSkillSuccessBonus(inst: IBladeburner): number;
getChaosCompetencePenalty(inst: IBladeburner, params: ISuccessChanceParams): number;
getChaosDifficultyBonus(inst: IBladeburner): number;
getSuccessChance(inst: IBladeburner, params: ISuccessChanceParams): number;
getSuccessesNeededForNextLevel(baseSuccessesPerLevel: number): number;
setMaxLevel(baseSuccessesPerLevel: number): void;
toJSON(): any;
}

View File

@@ -0,0 +1,4 @@
export interface IActionIdentifier {
name: string;
type: string;
}

View File

@@ -0,0 +1,39 @@
import { IActionIdentifier } from "./IActionIdentifier";
import { City } from "./City";
export interface IBladeburner {
numHosp: number;
moneyLost: number;
rank: number;
maxRank: number;
skillPoints: number;
totalSkillPoints: number;
teamSize: number;
teamLost: number;
storedCycles: number;
randomEventCounter: number;
actionTimeToComplete: number;
actionTimeCurrent: number;
action: IActionIdentifier;
cities: any;
city: string;
skills: any;
skillMultipliers: any;
staminaBonus: number;
maxStamina: number;
stamina: number;
contracts: any;
operations: any;
blackops: any;
logging: any;
automateEnabled: boolean;
automateActionHigh: number;
automateThreshHigh: number;
automateActionLow: number;
automateThreshLow: number;
consoleHistory: string[];
consoleLogs: string[];
getCurrentCity(): City;
calculateStaminaPenalty(): number;
}

View File

@@ -1,3 +1,4 @@
import { IBladeburner } from "./IBladeburner";
import { BladeburnerConstants } from "./data/Constants"; import { BladeburnerConstants } from "./data/Constants";
import { Action, IActionParams } from "./Action"; import { Action, IActionParams } from "./Action";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
@@ -8,8 +9,8 @@ export interface IOperationParams extends IActionParams {
} }
export class Operation extends Action { export class Operation extends Action {
reqdRank: number = 100; reqdRank = 100;
teamCount: number = 0; teamCount = 0;
constructor(params: IOperationParams | null = null) { constructor(params: IOperationParams | null = null) {
super(params); super(params);
@@ -18,38 +19,39 @@ export class Operation extends Action {
} }
// For actions that have teams. To be implemented by subtypes. // For actions that have teams. To be implemented by subtypes.
getTeamSuccessBonus(inst: any): number { getTeamSuccessBonus(inst: IBladeburner): number {
if (this.teamCount && this.teamCount > 0) { if (this.teamCount && this.teamCount > 0) {
this.teamCount = Math.min(this.teamCount, inst.teamSize); this.teamCount = Math.min(this.teamCount, inst.teamSize);
let teamMultiplier = Math.pow(this.teamCount, 0.05); const teamMultiplier = Math.pow(this.teamCount, 0.05);
return teamMultiplier; return teamMultiplier;
} }
return 1; return 1;
} }
getActionTypeSkillSuccessBonus(inst: any): number { getActionTypeSkillSuccessBonus(inst: IBladeburner): number {
return inst.skillMultipliers.successChanceOperation; return inst.skillMultipliers.successChanceOperation;
} }
getChaosDifficultyBonus(inst: any, params: any): number { getChaosDifficultyBonus(inst: IBladeburner/*, params: ISuccessChanceParams*/): number {
const city = inst.getCurrentCity(); const city = inst.getCurrentCity();
if (city.chaos > BladeburnerConstants.ChaosThreshold) { if (city.chaos > BladeburnerConstants.ChaosThreshold) {
let diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold); const diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold);
let mult = Math.pow(diff, 0.1); const mult = Math.pow(diff, 0.1);
return mult; return mult;
} }
return 1; return 1;
} }
static fromJSON(value: any): Operation {
return Generic_fromJSON(Operation, value.data);
}
toJSON(): any { toJSON(): any {
return Generic_toJSON("Operation", this); return Generic_toJSON("Operation", this);
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Operation {
return Generic_fromJSON(Operation, value.data);
}
} }
Reviver.constructors.Operation = Operation; Reviver.constructors.Operation = Operation;

View File

@@ -33,36 +33,36 @@ export class Skill {
name: string; name: string;
desc: string; desc: string;
// Cost is in Skill Points // Cost is in Skill Points
baseCost: number = 1; baseCost = 1;
// Additive cost increase per level // Additive cost increase per level
costInc: number = 1; costInc = 1;
maxLvl: number = 0; maxLvl = 0;
/** /**
* These benefits are additive. So total multiplier will be level (handled externally) times the * These benefits are additive. So total multiplier will be level (handled externally) times the
* effects below * effects below
*/ */
successChanceAll: number = 0; successChanceAll = 0;
successChanceStealth: number = 0; successChanceStealth = 0;
successChanceKill: number = 0; successChanceKill = 0;
successChanceContract: number = 0; successChanceContract = 0;
successChanceOperation: number = 0; successChanceOperation = 0;
/** /**
* This multiplier affects everything that increases synthoid population/community estimate * This multiplier affects everything that increases synthoid population/community estimate
* e.g. Field analysis, Investigation Op, Undercover Op * e.g. Field analysis, Investigation Op, Undercover Op
*/ */
successChanceEstimate: number = 0; successChanceEstimate = 0;
actionTime: number = 0; actionTime = 0;
effHack: number = 0; effHack = 0;
effStr: number = 0; effStr = 0;
effDef: number = 0; effDef = 0;
effDex: number = 0; effDex = 0;
effAgi: number = 0; effAgi = 0;
effCha: number = 0; effCha = 0;
stamina: number = 0; stamina = 0;
money: number = 0; money = 0;
expGain: number = 0; expGain = 0;
constructor(params: ISkillParams={name:"foo", desc:"foo"}) { constructor(params: ISkillParams={name:"foo", desc:"foo"}) {
if (!params.name) { if (!params.name) {

View File

@@ -10,55 +10,55 @@ export const Skills: IMap<Skill> = {};
desc:"Each level of this skill increases your success chance " + desc:"Each level of this skill increases your success chance " +
"for all Contracts, Operations, and BlackOps by 3%", "for all Contracts, Operations, and BlackOps by 3%",
baseCost: 3, costInc: 2.1, baseCost: 3, costInc: 2.1,
successChanceAll:3 successChanceAll:3,
}); });
Skills[SkillNames.Cloak] = new Skill({ Skills[SkillNames.Cloak] = new Skill({
name:SkillNames.Cloak, name:SkillNames.Cloak,
desc:"Each level of this skill increases your " + desc:"Each level of this skill increases your " +
"success chance in stealth-related Contracts, Operations, and BlackOps by 5.5%", "success chance in stealth-related Contracts, Operations, and BlackOps by 5.5%",
baseCost: 2, costInc: 1.1, baseCost: 2, costInc: 1.1,
successChanceStealth:5.5 successChanceStealth:5.5,
}); });
Skills[SkillNames.ShortCircuit] = new Skill({ Skills[SkillNames.ShortCircuit] = new Skill({
name:SkillNames.ShortCircuit, name:SkillNames.ShortCircuit,
desc:"Each level of this skill increases your success chance " + desc:"Each level of this skill increases your success chance " +
"in Contracts, Operations, and BlackOps that involve retirement by 5.5%", "in Contracts, Operations, and BlackOps that involve retirement by 5.5%",
baseCost: 2, costInc: 2.1, baseCost: 2, costInc: 2.1,
successChanceKill:5.5 successChanceKill:5.5,
}); });
Skills[SkillNames.DigitalObserver] = new Skill({ Skills[SkillNames.DigitalObserver] = new Skill({
name:SkillNames.DigitalObserver, name:SkillNames.DigitalObserver,
desc:"Each level of this skill increases your success chance in " + desc:"Each level of this skill increases your success chance in " +
"all Operations and BlackOps by 4%", "all Operations and BlackOps by 4%",
baseCost: 2, costInc: 2.1, baseCost: 2, costInc: 2.1,
successChanceOperation:4 successChanceOperation:4,
}); });
Skills[SkillNames.Tracer] = new Skill({ Skills[SkillNames.Tracer] = new Skill({
name:SkillNames.Tracer, name:SkillNames.Tracer,
desc:"Each level of this skill increases your success chance in " + desc:"Each level of this skill increases your success chance in " +
"all Contracts by 4%", "all Contracts by 4%",
baseCost: 2, costInc: 2.1, baseCost: 2, costInc: 2.1,
successChanceContract:4 successChanceContract:4,
}); });
Skills[SkillNames.Overclock] = new Skill({ Skills[SkillNames.Overclock] = new Skill({
name:SkillNames.Overclock, name:SkillNames.Overclock,
desc:"Each level of this skill decreases the time it takes " + desc:"Each level of this skill decreases the time it takes " +
"to attempt a Contract, Operation, and BlackOp by 1% (Max Level: 90)", "to attempt a Contract, Operation, and BlackOp by 1% (Max Level: 90)",
baseCost: 3, costInc: 1.4, maxLvl: 90, baseCost: 3, costInc: 1.4, maxLvl: 90,
actionTime:1 actionTime:1,
}); });
Skills[SkillNames.Reaper] = new Skill({ Skills[SkillNames.Reaper] = new Skill({
name: SkillNames.Reaper, name: SkillNames.Reaper,
desc: "Each level of this skill increases your effective combat stats for Bladeburner actions by 2%", desc: "Each level of this skill increases your effective combat stats for Bladeburner actions by 2%",
baseCost: 2, costInc: 2.1, baseCost: 2, costInc: 2.1,
effStr: 2, effDef: 2, effDex: 2, effAgi: 2 effStr: 2, effDef: 2, effDex: 2, effAgi: 2,
}); });
Skills[SkillNames.EvasiveSystem] = new Skill({ Skills[SkillNames.EvasiveSystem] = new Skill({
name:SkillNames.EvasiveSystem, name:SkillNames.EvasiveSystem,
desc:"Each level of this skill increases your effective " + desc:"Each level of this skill increases your effective " +
"dexterity and agility for Bladeburner actions by 4%", "dexterity and agility for Bladeburner actions by 4%",
baseCost: 2, costInc: 2.1, baseCost: 2, costInc: 2.1,
effDex: 4, effAgi: 4 effDex: 4, effAgi: 4,
}); });
Skills[SkillNames.Datamancer] = new Skill({ Skills[SkillNames.Datamancer] = new Skill({
name:SkillNames.Datamancer, name:SkillNames.Datamancer,
@@ -67,13 +67,13 @@ export const Skills: IMap<Skill> = {};
"This affects all actions that can potentially increase " + "This affects all actions that can potentially increase " +
"the accuracy of your synthoid population/community estimates.", "the accuracy of your synthoid population/community estimates.",
baseCost:3, costInc:1, baseCost:3, costInc:1,
successChanceEstimate:5 successChanceEstimate:5,
}); });
Skills[SkillNames.CybersEdge] = new Skill({ Skills[SkillNames.CybersEdge] = new Skill({
name:SkillNames.CybersEdge, name:SkillNames.CybersEdge,
desc:"Each level of this skill increases your max stamina by 2%", desc:"Each level of this skill increases your max stamina by 2%",
baseCost:1, costInc:3, baseCost:1, costInc:3,
stamina:2 stamina:2,
}); });
Skills[SkillNames.HandsOfMidas] = new Skill({ Skills[SkillNames.HandsOfMidas] = new Skill({
name: SkillNames.HandsOfMidas, name: SkillNames.HandsOfMidas,

View File

@@ -1,4 +1,14 @@
export const ConsoleHelpText: {} = { export const ConsoleHelpText: {
helpList: string[];
automate: string[];
clear: string[];
cls: string[];
help: string[];
log: string[];
skill: string[];
start: string[];
stop: string[];
} = {
helpList: [ helpList: [
"Use 'help [command]' to get more information about a particular Bladeburner console command.", "Use 'help [command]' to get more information about a particular Bladeburner console command.",
"", "",
@@ -8,7 +18,7 @@ export const ConsoleHelpText: {} = {
" log [en/dis] [type] Enable or disable logging for events and actions", " log [en/dis] [type] Enable or disable logging for events and actions",
" skill [action] [name] Level or display info about your Bladeburner skills", " skill [action] [name] Level or display info about your Bladeburner skills",
" start [type] [name] Start a Bladeburner action/task" , " start [type] [name] Start a Bladeburner action/task" ,
" stop Stops your current Bladeburner action/task" " stop Stops your current Bladeburner action/task",
], ],
automate: [ automate: [
"automate [var] [val] [hi/low]", "automate [var] [val] [hi/low]",
@@ -30,17 +40,17 @@ export const ConsoleHelpText: {} = {
"Using the four console commands above will set the automation to perform Tracking contracts " + "Using the four console commands above will set the automation to perform Tracking contracts " +
"if your stamina is 100 or higher, and then switch to Field Analysis if your stamina drops below " + "if your stamina is 100 or higher, and then switch to Field Analysis if your stamina drops below " +
"50. Note that when setting the action, the name of the action is CASE-SENSITIVE. It must " + "50. Note that when setting the action, the name of the action is CASE-SENSITIVE. It must " +
"exactly match whatever the name is in the UI." "exactly match whatever the name is in the UI.",
], ],
clear: [ clear: [
"clear", "clear",
"", "",
"Clears the console" "Clears the console",
], ],
cls: [ cls: [
"cls", "cls",
"", "",
"Clears the console" "Clears the console",
], ],
help: [ help: [
"help [command]", "help [command]",
@@ -51,7 +61,7 @@ export const ConsoleHelpText: {} = {
"", "",
" help automate", " help automate",
"", "",
"will display specific information about using the automate console command" "will display specific information about using the automate console command",
], ],
log: [ log: [
"log [en/dis] [type]", "log [en/dis] [type]",
@@ -71,7 +81,7 @@ export const ConsoleHelpText: {} = {
"Logging can be universally enabled/disabled using the 'all' keyword:", "Logging can be universally enabled/disabled using the 'all' keyword:",
"", "",
" log dis all", " log dis all",
" log en all" " log en all",
], ],
skill: [ skill: [
"skill [action] [name]", "skill [action] [name]",
@@ -91,7 +101,7 @@ export const ConsoleHelpText: {} = {
"", "",
"This console command can also be used to level up skills:", "This console command can also be used to level up skills:",
"", "",
" skill level [skill name]" " skill level [skill name]",
], ],
start: [ start: [
"start [type] [name]", "start [type] [name]",
@@ -106,11 +116,11 @@ export const ConsoleHelpText: {} = {
"Examples:", "Examples:",
"", "",
" start contract Tracking", " start contract Tracking",
" start op 'Undercover Operation'" " start op 'Undercover Operation'",
], ],
stop:[ stop:[
"stop", "stop",
"", "",
"Stop your current action and go idle." "Stop your current action and go idle.",
], ],
} }

View File

@@ -38,7 +38,7 @@ for (var i = blackops.length-1; i >= 0 ; --i) {
import * as React from "react"; import * as React from "react";
export function BlackOperationsPage(inst: any): React.ReactElement { export function BlackOperationsPage(): React.ReactElement {
// Put Black Operations in sequence of required rank // Put Black Operations in sequence of required rank
const blackops = []; const blackops = [];
for (const name in BlackOperations) { for (const name in BlackOperations) {
@@ -55,9 +55,8 @@ export function BlackOperationsPage(inst: any): React.ReactElement {
Black Operations (Black Ops) are special, one-time covert operations. Each Black Op must be unlocked successively by completing the one before it.<br /><br /> Black Operations (Black Ops) are special, one-time covert operations. Each Black Op must be unlocked successively by completing the one before it.<br /><br />
<b>Your ultimate goal to climb through the ranks of Bladeburners is to complete all of the Black Ops.</b><br /><br /> <b>Your ultimate goal to climb through the ranks of Bladeburners is to complete all of the Black Ops.</b><br /><br />
Like normal operations, you may use a team for Black Ops. Failing a black op will incur heavy HP and rank losses.</p> Like normal operations, you may use a team for Black Ops. Failing a black op will incur heavy HP and rank losses.</p>
{blackops.map( op => {blackops.map(() => <div className="bladeburner-action">
<div className="bladeburner-action"> </div>,
</div>
)} )}
</div>) </div>)
} }

424
src/Casino/Blackjack.tsx Normal file
View File

@@ -0,0 +1,424 @@
import * as React from "react";
import { IPlayer } from "../PersonObjects/IPlayer";
import { Money } from "../ui/React/Money";
import { Game } from "./Game";
import { Deck } from "./CardDeck/Deck";
import { Hand } from "./CardDeck/Hand";
import { InputAdornment } from "@material-ui/core";
import { ReactCard } from "./CardDeck/ReactCard";
import { MuiTextField } from "../ui/React/MuiTextField";
import { MuiButton } from "../ui/React/MuiButton";
import { MuiPaper } from "../ui/React/MuiPaper";
const MAX_BET = 100e6;
enum Result {
Pending = "",
PlayerWon = "You won!",
PlayerWonByBlackjack = "You Won! Blackjack!",
DealerWon = "You lost!",
Tie = "Push! (Tie)",
}
type Props = {
p: IPlayer;
}
type State ={
playerHand: Hand;
dealerHand: Hand;
bet: number;
betInput: string;
gameInProgress: boolean;
result: Result;
gains: number; // Track gains only for this session
wagerInvalid: boolean;
wagerInvalidHelperText: string;
}
export class Blackjack extends Game<Props, State> {
deck: Deck;
constructor(props: Props) {
super(props);
this.deck = new Deck(5); // 5-deck multideck
const initialBet = 1e6;
this.state = {
playerHand: new Hand([]),
dealerHand: new Hand([]),
bet: initialBet,
betInput: String(initialBet),
gameInProgress: false,
result: Result.Pending,
gains: 0,
wagerInvalid: false,
wagerInvalidHelperText: "",
}
}
canStartGame = (): boolean => {
const { p } = this.props;
const { bet } = this.state;
return p.canAfford(bet);
}
startGame = (): void => {
if (!this.canStartGame()) { return; }
// Take money from player right away so that player's dont just "leave" to avoid the loss (I mean they could
// always reload without saving but w.e)
this.props.p.loseMoney(this.state.bet);
const playerHand = new Hand([ this.deck.safeDrawCard(), this.deck.safeDrawCard() ]);
const dealerHand = new Hand([ this.deck.safeDrawCard(), this.deck.safeDrawCard() ]);
this.setState({
playerHand,
dealerHand,
gameInProgress: true,
result: Result.Pending,
});
// If the player is dealt a blackjack and the dealer is not, then the player
// immediately wins
if (this.getTrueHandValue(playerHand) === 21) {
if (this.getTrueHandValue(dealerHand) === 21) {
this.finishGame(Result.Tie);
} else {
this.finishGame(Result.PlayerWonByBlackjack);
}
} else if (this.getTrueHandValue(dealerHand) === 21) {
// Check if dealer won by blackjack. We know at this point that the player does not also have blackjack.
this.finishGame(Result.DealerWon);
}
}
// Returns an array of numbers representing all possible values of the given Hand. The reason it needs to be
// an array is because an Ace can count as both 1 and 11.
getHandValue = (hand: Hand): number[] => {
let result: number[] = [ 0 ];
for (let i = 0 ; i < hand.cards.length; ++i) {
const value = hand.cards[i].value;
if (value >= 10) {
result = result.map((x) => x + 10);
} else if (value === 1) {
result = result.flatMap((x) => [ x + 1, x + 11 ]);
} else {
result = result.map((x) => x + value);
}
}
return result;
}
// Returns the single hand value used for determine things like victory and whether or not
// the dealer has to hit. Essentially this uses the biggest value that's 21 or under. If no such value exists,
// then it means the hand is busted and we can just return whatever
getTrueHandValue = (hand: Hand): number => {
const handValues = this.getHandValue(hand);
const valuesUnder21 = handValues.filter((x) => (x <= 21));
if (valuesUnder21.length > 0) {
valuesUnder21.sort((a, b) => a - b);
return valuesUnder21[valuesUnder21.length - 1];
} else {
// Just return the first value. It doesnt really matter anyways since hand is buted
return handValues[0];
}
}
// Returns all hand values that are 21 or under. If no values are 21 or under, then the first value is returned.
getHandDisplayValues = (hand: Hand): number[] => {
const handValues = this.getHandValue(hand);
if (this.isHandBusted(hand)) {
// Hand is busted so just return the 1st value, doesn't really matter
return [ ...new Set([ handValues[0] ]) ];
} else {
return [ ...new Set(handValues.filter((x) => x <= 21)) ];
}
}
isHandBusted = (hand: Hand): boolean => {
return this.getTrueHandValue(hand) > 21;
}
playerHit = (event: React.MouseEvent): void => {
if (!event.isTrusted) { return; }
const newHand = this.state.playerHand.addCards(this.deck.safeDrawCard());
this.setState({
playerHand: newHand,
});
// Check if player busted, and finish the game if so
if (this.isHandBusted(newHand)) {
this.finishGame(Result.DealerWon);
}
}
playerStay = (event: React.MouseEvent): void => {
if (!event.isTrusted) { return; }
// Determine if Dealer needs to hit. A dealer must hit if they have 16 or lower.
// If the dealer has a Soft 17 (Ace + 6), then they stay.
let newDealerHand = this.state.dealerHand;
while (true) {
// The dealer's "true" hand value is the 2nd one if its 21 or less (the 2nd value is always guaranteed
// to be equal or larger). Otherwise its the 1st.
const dealerHandValue = this.getTrueHandValue(newDealerHand);
if (dealerHandValue <= 16) {
newDealerHand = newDealerHand.addCards(this.deck.safeDrawCard());
} else {
break;
}
}
this.setState({
dealerHand: newDealerHand,
})
// If dealer has busted, then player wins
if (this.isHandBusted(newDealerHand)) {
this.finishGame(Result.PlayerWon);
} else {
const dealerHandValue = this.getTrueHandValue(newDealerHand);
const playerHandValue = this.getTrueHandValue(this.state.playerHand);
console.log(`dealerHandValue: ${dealerHandValue}`);
console.log(`playerHandValue: ${playerHandValue}`);
// We expect nobody to have busted. If someone busted, there is an error
// in our game logic
if (dealerHandValue > 21 || playerHandValue > 21) {
throw new Error("Someone busted when not expected to");
}
if (playerHandValue > dealerHandValue) {
this.finishGame(Result.PlayerWon);
} else if (playerHandValue < dealerHandValue) {
this.finishGame(Result.DealerWon);
} else {
this.finishGame(Result.Tie);
}
}
}
finishGame = (result: Result): void => {
let gains = 0;
if (this.isPlayerWinResult(result)) {
gains = this.state.bet;
// We 2x the gains because we took away money at the start, so we need to give the original bet back.
this.win(this.props.p, 2 * gains);
} else if (result === Result.DealerWon) {
gains = -1 * this.state.bet;
// Dont need to take money here since we already did it at the start
} else if (result === Result.Tie) {
this.win(this.props.p, this.state.bet); // Get the original bet back
}
this.setState({
gameInProgress: false,
result,
gains: this.state.gains + gains,
});
}
isPlayerWinResult = (result: Result): boolean => {
return (result === Result.PlayerWon || result === Result.PlayerWonByBlackjack);
}
wagerOnChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
const { p } = this.props;
const betInput = event.target.value;
const wager = Math.round(parseFloat(betInput));
if (isNaN(wager)) {
this.setState({
bet: 0,
betInput,
wagerInvalid: true,
wagerInvalidHelperText: "Not a valid number",
});
} else if (wager <= 0) {
this.setState({
bet: 0,
betInput,
wagerInvalid: true,
wagerInvalidHelperText: "Must bet a postive amount",
});
} else if (wager > MAX_BET) {
this.setState({
bet: 0,
betInput,
wagerInvalid: true,
wagerInvalidHelperText: "Exceeds max bet",
});
} else if (!p.canAfford(wager)) {
this.setState({
bet: 0,
betInput,
wagerInvalid: true,
wagerInvalidHelperText: "Not enough money",
});
} else {
// Valid wager
this.setState({
bet: wager,
betInput,
wagerInvalid: false,
wagerInvalidHelperText: "",
result: Result.Pending, // Reset previous game status to clear the win/lose text UI
});
}
}
// Start game button
startOnClick = (event: React.MouseEvent): void => {
// Protect against scripting...although maybe this would be fun to automate
if (!event.isTrusted) { return; }
if (!this.state.wagerInvalid) {
this.startGame();
}
}
render(): React.ReactNode {
const {
betInput,
playerHand,
dealerHand,
gameInProgress,
result,
wagerInvalid,
wagerInvalidHelperText,
gains,
} = this.state;
// Get the player totals to display.
const playerHandValues = this.getHandDisplayValues(playerHand);
const dealerHandValues = this.getHandDisplayValues(dealerHand);
return (
<div>
{/* Wager input */}
<div>
<MuiTextField
value={betInput}
label={
<>
{"Wager (Max: "}
{Money(MAX_BET)}
{")"}
</>
}
disabled={gameInProgress}
onChange={this.wagerOnChange}
error={wagerInvalid}
helperText={wagerInvalid ? wagerInvalidHelperText : ""}
type="number"
variant="filled"
style={{
width: "200px",
}}
InputProps={{
startAdornment: <InputAdornment position="start" >$</InputAdornment>,
}} />
<p>
{"Total earnings this session: "}
{Money(gains)}
</p>
</div>
{/* Buttons */}
{!gameInProgress ? (
<div>
<MuiButton
color="primary"
onClick={this.startOnClick}
disabled={wagerInvalid || !this.canStartGame()}>
Start
</MuiButton>
</div>
) : (
<div>
<MuiButton color="primary" onClick={this.playerHit} >
Hit
</MuiButton>
<MuiButton color="secondary" onClick={this.playerStay} >
Stay
</MuiButton>
</div>
)}
{/* Main game part. Displays both if the game is in progress OR if there's a result so you can see
* the cards that led to that result. */}
{(gameInProgress || result !== Result.Pending) && (
<div>
<MuiPaper variant="outlined" elevation={2}>
<pre>Player</pre>
{playerHand.cards.map((card, i) => (
<ReactCard card={card} key={i} />
))}
<pre>Value(s): </pre>
{playerHandValues.map((value, i) => (
<pre key={i}>{value}</pre>
))}
</MuiPaper>
<br />
<MuiPaper variant="outlined" elevation={2}>
<pre>Dealer</pre>
{dealerHand.cards.map((card, i) => (
// Hide every card except the first while game is in progress
<ReactCard card={card} hidden={gameInProgress && i !== 0} key={i} />
))}
{!gameInProgress && (
<>
<pre>Value(s): </pre>
{dealerHandValues.map((value, i) => (
<pre key={i}>{value}</pre>
))}
</>
)}
</MuiPaper>
</div>
)}
{/* Results from previous round */}
{result !== Result.Pending && (
<p>
{result}
{this.isPlayerWinResult(result) && (
<>
{" You gained "}
{Money(this.state.bet)}
</>
)}
{result === Result.DealerWon && (
<>
{" You lost "}
{Money(this.state.bet)}
</>
)}
</p>
)}
</div>
)
}
}

View File

@@ -0,0 +1,42 @@
// Enum values are lowercased to match css classes
export enum Suit {
Clubs = "clubs",
Diamonds = "diamonds",
Hearts = "hearts",
Spades = "spades",
}
export class Card {
constructor(readonly value: number, readonly suit: Suit) {
if (value < 1 || value > 13) {
throw new Error(`Card instantiated with improper value: ${value}`);
}
}
formatValue(): string {
switch (this.value) {
case 1:
return "A";
case 11:
return "J";
case 12:
return "Q";
case 13:
return "K";
default:
return `${this.value}`;
}
}
isRedSuit(): boolean {
return this.suit === Suit.Hearts || this.suit === Suit.Diamonds;
}
getStringRepresentation(): string {
const value = this.formatValue();
return `${value} of ${this.suit}`;
}
}

View File

@@ -0,0 +1,58 @@
import { Card, Suit } from "./Card";
import { shuffle } from "lodash";
export class Deck {
private cards: Card[] = [];
// Support multiple decks
constructor(private numDecks = 1) {
this.reset();
}
shuffle(): void {
this.cards = shuffle(this.cards); // Just use lodash
}
drawCard(): Card {
if (this.cards.length == 0) {
throw new Error("Tried to draw card from empty deck");
}
return this.cards.shift() as Card; // Guaranteed to return a Card since we throw an Error if array is empty
}
// Draws a card, resetting the deck beforehands if the Deck is empty
safeDrawCard(): Card {
if (this.cards.length === 0) {
this.reset();
}
return this.drawCard();
}
// Reset the deck back to the original 52 cards and shuffle it
reset(): void {
this.cards = [];
for (let i = 1; i <= 13; ++i) {
for (let j = 0; j < this.numDecks; ++j) {
this.cards.push(new Card(i, Suit.Clubs));
this.cards.push(new Card(i, Suit.Diamonds));
this.cards.push(new Card(i, Suit.Hearts));
this.cards.push(new Card(i, Suit.Spades));
}
}
this.shuffle();
}
size(): number {
return this.cards.length;
}
isEmpty(): boolean {
return this.cards.length === 0;
}
}

View File

@@ -0,0 +1,25 @@
/**
* Represents a Hand of cards.
*
* This class is IMMUTABLE
*/
import { Card } from "./Card";
export class Hand {
constructor(readonly cards: readonly Card[]) {}
addCards(...cards: Card[]): Hand {
return new Hand([ ...this.cards, ...cards ]);
}
removeByIndex(i: number): Hand {
if (i >= this.cards.length) {
throw new Error(`Tried to remove invalid card from Hand by index: ${i}`);
}
return new Hand([ ...this.cards.slice().splice(i, 1) ])
}
}

View File

@@ -0,0 +1,40 @@
import React, { FC } from "react";
import { Card, Suit } from "./Card";
type Props = {
card: Card;
hidden?: boolean;
}
export const ReactCard: FC<Props> = ({ card, hidden }) => {
let suit : React.ReactNode;
switch (card.suit) {
case Suit.Clubs:
suit = <span>&#9827;</span>;
break;
case Suit.Diamonds:
suit = <span>&#9830;</span>;
break;
case Suit.Hearts:
suit = <span>&#9829;</span>;
break;
case Suit.Spades:
suit = <span>&#9824;</span>;
break;
default:
throw new Error(`MissingCaseException: ${card.suit}`);
}
return (
<div className={`casino-card ${card.isRedSuit() ? "red" : "black"}`}>
<>
<div className="value">
{hidden ? " - " : card.formatValue()}
</div>
<div className={`suit`}>
{hidden ? " - " : suit}
</div>
</>
</div>
)
}

View File

@@ -41,7 +41,7 @@ export class CoinFlip extends Game<IProps, IState> {
this.updateInvestment = this.updateInvestment.bind(this); this.updateInvestment = this.updateInvestment.bind(this);
} }
updateInvestment(e: React.FormEvent<HTMLInputElement>) { updateInvestment(e: React.FormEvent<HTMLInputElement>): void {
let investment: number = parseInt(e.currentTarget.value); let investment: number = parseInt(e.currentTarget.value);
if (isNaN(investment)) { if (isNaN(investment)) {
investment = minPlay; investment = minPlay;
@@ -55,7 +55,7 @@ export class CoinFlip extends Game<IProps, IState> {
this.setState({investment: investment}); this.setState({investment: investment});
} }
play(guess: string) { play(guess: string): void {
if(this.reachedLimit(this.props.p)) return; if(this.reachedLimit(this.props.p)) return;
const v = BadRNG.random(); const v = BadRNG.random();
let letter: string; let letter: string;
@@ -80,7 +80,7 @@ export class CoinFlip extends Game<IProps, IState> {
} }
render() { render(): React.ReactNode {
return <> return <>
<pre> <pre>
++<br /> ++<br />
@@ -89,7 +89,7 @@ export class CoinFlip extends Game<IProps, IState> {
| | | |<br /> | | | |<br />
++<br /> ++<br />
</pre> </pre>
<span className="text">Play for: </span><input type="number" className='text-input' onChange={this.updateInvestment} value={this.state.investment} /><br /> <span className="text">Play for: </span><input type="number" className="text-input" onChange={this.updateInvestment} value={this.state.investment} /><br />
<StdButton onClick={trusted(() => this.play('H'))} text={"Head!"} disabled={this.state.playLock} /> <StdButton onClick={trusted(() => this.play('H'))} text={"Head!"} disabled={this.state.playLock} />
<StdButton onClick={trusted(() => this.play('T'))} text={"Tail!"} disabled={this.state.playLock} /> <StdButton onClick={trusted(() => this.play('T'))} text={"Tail!"} disabled={this.state.playLock} />
<h1>{this.state.status}</h1> <h1>{this.state.status}</h1>

View File

@@ -5,7 +5,7 @@ import { dialogBoxCreate } from "../../utils/DialogBox";
const gainLimit = 10e9; const gainLimit = 10e9;
export class Game<T,U> extends React.Component<T, U> { export class Game<T,U> extends React.Component<T, U> {
win(p: IPlayer, n: number) { win(p: IPlayer, n: number): void{
p.gainMoney(n); p.gainMoney(n);
p.recordMoneySource(n, "casino"); p.recordMoneySource(n, "casino");
} }

View File

@@ -1,6 +1,6 @@
export interface RNG { export interface RNG {
random(): number random(): number;
} }
/* /*
@@ -9,16 +9,16 @@ export interface RNG {
*/ */
class RNG0 implements RNG { class RNG0 implements RNG {
x: number; x: number;
m: number = 1024; m = 1024;
a: number = 341; a = 341;
c: number = 1; c = 1;
constructor() { constructor() {
this.x = 0; this.x = 0;
this.reset(); this.reset();
} }
step() { step(): void {
this.x = (this.a*this.x+this.c) % this.m; this.x = (this.a*this.x+this.c) % this.m;
} }
@@ -27,7 +27,7 @@ class RNG0 implements RNG {
return this.x/this.m; return this.x/this.m;
} }
reset() { reset(): void {
this.x = (new Date()).getTime() % this.m; this.x = (new Date()).getTime() % this.m;
} }
} }
@@ -39,9 +39,9 @@ export const BadRNG: RNG0 = new RNG0();
* The period is 6e12. * The period is 6e12.
*/ */
export class WHRNG implements RNG { export class WHRNG implements RNG {
s1: number = 0; s1 = 0;
s2: number = 0; s2 = 0;
s3: number = 0; s3 = 0;
constructor(totalPlaytime: number) { constructor(totalPlaytime: number) {
// This one is seeded by the players total play time. // This one is seeded by the players total play time.
@@ -51,7 +51,7 @@ export class WHRNG implements RNG {
this.s3 = v; this.s3 = v;
} }
step() { step(): void {
this.s1 = (171 * this.s1) % 30269; this.s1 = (171 * this.s1) % 30269;
this.s2 = (172 * this.s2) % 30307; this.s2 = (172 * this.s2) % 30307;
this.s3 = (170 * this.s3) % 30323; this.s3 = (170 * this.s3) % 30323;

View File

@@ -28,10 +28,6 @@ function isRed(n: number): boolean {
21, 23, 25, 27, 30, 32, 34, 36].includes(n); 21, 23, 25, 27, 30, 32, 34, 36].includes(n);
} }
function isBlack(n: number): boolean {
return !isRed(n);
}
type Strategy = { type Strategy = {
match: (n: number) => boolean; match: (n: number) => boolean;
payout: number; payout: number;
@@ -102,14 +98,14 @@ const strategies: {
Third2: { Third2: {
match: (n: number): boolean => { match: (n: number): boolean => {
if (n === 0) return false; if (n === 0) return false;
return 13 <= n && n <= 24; return n >= 13 && n <= 24;
}, },
payout: 2, payout: 2,
}, },
Third3: { Third3: {
match: (n: number): boolean => { match: (n: number): boolean => {
if (n === 0) return false; if (n === 0) return false;
return 25 <= n; return n >= 25;
}, },
payout: 2, payout: 2,
}, },
@@ -125,7 +121,7 @@ function Single(s: number): Strategy {
} }
export class Roulette extends Game<IProps, IState> { export class Roulette extends Game<IProps, IState> {
interval: number = -1; interval = -1;
rng: WHRNG; rng: WHRNG;
constructor(props: IProps) { constructor(props: IProps) {
@@ -140,7 +136,7 @@ export class Roulette extends Game<IProps, IState> {
lock: true, lock: true,
strategy: { strategy: {
payout: 0, payout: 0,
match: (n: number): boolean => { return false }, match: (): boolean => { return false },
}, },
} }
@@ -150,21 +146,21 @@ export class Roulette extends Game<IProps, IState> {
} }
componentDidMount() { componentDidMount(): void {
this.interval = setInterval(this.step, 50); this.interval = setInterval(this.step, 50);
} }
step() { step(): void {
if (!this.state.lock) { if (!this.state.lock) {
this.setState({n: Math.floor(Math.random()*37)}); this.setState({n: Math.floor(Math.random()*37)});
} }
} }
componentWillUnmount() { componentWillUnmount(): void {
clearInterval(this.interval); clearInterval(this.interval);
} }
updateInvestment(e: React.FormEvent<HTMLInputElement>) { updateInvestment(e: React.FormEvent<HTMLInputElement>): void {
let investment: number = parseInt(e.currentTarget.value); let investment: number = parseInt(e.currentTarget.value);
if (isNaN(investment)) { if (isNaN(investment)) {
investment = minPlay; investment = minPlay;
@@ -178,13 +174,13 @@ export class Roulette extends Game<IProps, IState> {
this.setState({investment: investment}); this.setState({investment: investment});
} }
currentNumber() { currentNumber(): string {
if (this.state.n === 0) return '0'; if (this.state.n === 0) return '0';
const color = isRed(this.state.n) ? 'R' : 'B'; const color = isRed(this.state.n) ? 'R' : 'B';
return `${this.state.n}${color}`; return `${this.state.n}${color}`;
} }
play(s: Strategy) { play(s: Strategy): void {
if(this.reachedLimit(this.props.p)) return; if(this.reachedLimit(this.props.p)) return;
this.setState({ this.setState({
canPlay: false, canPlay: false,
@@ -223,10 +219,10 @@ export class Roulette extends Game<IProps, IState> {
} }
render() { render(): React.ReactNode {
return <> return <>
<h1>{this.currentNumber()}</h1> <h1>{this.currentNumber()}</h1>
<input type="number" className='text-input' onChange={this.updateInvestment} placeholder={"Amount to play"} value={this.state.investment} disabled={!this.state.canPlay} /> <input type="number" className="text-input" onChange={this.updateInvestment} placeholder={"Amount to play"} value={this.state.investment} disabled={!this.state.canPlay} />
<h1>{this.state.status}</h1> <h1>{this.state.status}</h1>
<table> <table>
<tbody> <tbody>

View File

@@ -20,7 +20,7 @@ type IState = {
} }
// statically shuffled array of symbols. // statically shuffled array of symbols.
let symbols = ["D", "C", "$", "?", "♥", "A", "C", "B", "C", "E", "B", "E", "C", const symbols = ["D", "C", "$", "?", "♥", "A", "C", "B", "C", "E", "B", "E", "C",
"*", "D", "♥", "B", "A", "A", "A", "C", "A", "D", "B", "E", "?", "D", "*", "*", "D", "♥", "B", "A", "A", "A", "C", "A", "D", "B", "E", "?", "D", "*",
"@", "♥", "B", "E", "?"]; "@", "♥", "B", "E", "?"];
@@ -63,7 +63,7 @@ const maxPlay = 1e6;
export class SlotMachine extends Game<IProps, IState> { export class SlotMachine extends Game<IProps, IState> {
rng: WHRNG; rng: WHRNG;
interval: number = -1; interval = -1;
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
@@ -86,11 +86,11 @@ export class SlotMachine extends Game<IProps, IState> {
this.updateInvestment = this.updateInvestment.bind(this); this.updateInvestment = this.updateInvestment.bind(this);
} }
componentDidMount() { componentDidMount(): void {
this.interval = setInterval(this.step, 50); this.interval = setInterval(this.step, 50);
} }
step() { step(): void {
let stoppedOne = false; let stoppedOne = false;
const index = this.state.index.slice(); const index = this.state.index.slice();
for(const i in index) { for(const i in index) {
@@ -106,7 +106,7 @@ export class SlotMachine extends Game<IProps, IState> {
} }
} }
componentWillUnmount() { componentWillUnmount(): void {
clearInterval(this.interval); clearInterval(this.interval);
} }
@@ -118,7 +118,7 @@ export class SlotMachine extends Game<IProps, IState> {
]; ];
} }
play() { play(): void {
if(this.reachedLimit(this.props.p)) return; if(this.reachedLimit(this.props.p)) return;
this.setState({status: 'playing'}); this.setState({status: 'playing'});
this.win(this.props.p, -this.state.investment); this.win(this.props.p, -this.state.investment);
@@ -127,7 +127,7 @@ export class SlotMachine extends Game<IProps, IState> {
setTimeout(this.lock, this.rng.random()*2000+1000); setTimeout(this.lock, this.rng.random()*2000+1000);
} }
lock() { lock(): void {
this.setState({ this.setState({
locks: [ locks: [
Math.floor(this.rng.random()*symbols.length), Math.floor(this.rng.random()*symbols.length),
@@ -139,10 +139,10 @@ export class SlotMachine extends Game<IProps, IState> {
}) })
} }
checkWinnings() { checkWinnings(): void {
const t = this.getTable(); const t = this.getTable();
const getPaylineData = function(payline: number[][]): string[] { const getPaylineData = function(payline: number[][]): string[] {
let data = []; const data = [];
for(const point of payline) { for(const point of payline) {
data.push(t[point[0]][point[1]]); data.push(t[point[0]][point[1]]);
} }
@@ -176,14 +176,14 @@ export class SlotMachine extends Game<IProps, IState> {
if(this.reachedLimit(this.props.p)) return; if(this.reachedLimit(this.props.p)) return;
} }
unlock() { unlock(): void {
this.setState({ this.setState({
locks: [-1, -1, -1, -1, -1], locks: [-1, -1, -1, -1, -1],
canPlay: false, canPlay: false,
}) })
} }
updateInvestment(e: React.FormEvent<HTMLInputElement>) { updateInvestment(e: React.FormEvent<HTMLInputElement>): void {
let investment: number = parseInt(e.currentTarget.value); let investment: number = parseInt(e.currentTarget.value);
if (isNaN(investment)) { if (isNaN(investment)) {
investment = minPlay; investment = minPlay;
@@ -197,7 +197,7 @@ export class SlotMachine extends Game<IProps, IState> {
this.setState({investment: investment}); this.setState({investment: investment});
} }
render() { render(): React.ReactNode {
const t = this.getTable(); const t = this.getTable();
return <> return <>
<pre> <pre>
@@ -209,7 +209,7 @@ export class SlotMachine extends Game<IProps, IState> {
| | {symbols[(this.state.index[0]+1)%symbols.length]} | {symbols[(this.state.index[1]+1)%symbols.length]} | {symbols[(this.state.index[2]+1)%symbols.length]} | {symbols[(this.state.index[3]+1)%symbols.length]} | {symbols[(this.state.index[4]+1)%symbols.length]} | |<br /> | | {symbols[(this.state.index[0]+1)%symbols.length]} | {symbols[(this.state.index[1]+1)%symbols.length]} | {symbols[(this.state.index[2]+1)%symbols.length]} | {symbols[(this.state.index[3]+1)%symbols.length]} | {symbols[(this.state.index[4]+1)%symbols.length]} | |<br />
++<br /> ++<br />
</pre> </pre>
<input type="number" className='text-input' onChange={this.updateInvestment} placeholder={"Amount to play"} value={this.state.investment} disabled={!this.state.canPlay} /> <input type="number" className="text-input" onChange={this.updateInvestment} placeholder={"Amount to play"} value={this.state.investment} disabled={!this.state.canPlay} />
<StdButton onClick={trusted(this.play)} text={"Spin!"} disabled={!this.state.canPlay} /> <StdButton onClick={trusted(this.play)} text={"Spin!"} disabled={!this.state.canPlay} />
<h1>{this.state.status}</h1> <h1>{this.state.status}</h1>
<h2>Pay lines</h2> <h2>Pay lines</h2>

View File

@@ -90,7 +90,7 @@ function cinematicTextEnd() {
var mainMenu = document.getElementById("mainmenu-container"); var mainMenu = document.getElementById("mainmenu-container");
container.appendChild(createElement("br")); container.appendChild(createElement("br"));
return new Promise (function(resolve, reject) { return new Promise (function(resolve) {
container.appendChild(createElement("a", { container.appendChild(createElement("a", {
class:"a-link-button", innerText:"Continue...", class:"a-link-button", innerText:"Continue...",
clickListener:()=>{ clickListener:()=>{
@@ -99,7 +99,7 @@ function cinematicTextEnd() {
mainMenu.style.visibility = "visible"; mainMenu.style.visibility = "visible";
cinematicTextFlag = false; cinematicTextFlag = false;
resolve(); resolve();
} },
})); }));
}); });
} }

View File

@@ -2,7 +2,7 @@ import {
CodingContract, CodingContract,
CodingContractRewardType, CodingContractRewardType,
CodingContractTypes, CodingContractTypes,
ICodingContractReward ICodingContractReward,
} from "./CodingContracts"; } from "./CodingContracts";
import { Factions } from "./Faction/Factions"; import { Factions } from "./Faction/Factions";
import { Player } from "./Player"; import { Player } from "./Player";
@@ -15,7 +15,7 @@ import { HacknetServer } from "./Hacknet/HacknetServer";
import { getRandomInt } from "../utils/helpers/getRandomInt"; import { getRandomInt } from "../utils/helpers/getRandomInt";
export function generateRandomContract() { export function generateRandomContract(): void {
// First select a random problem type // First select a random problem type
const problemType = getRandomProblemType(); const problemType = getRandomProblemType();
@@ -31,7 +31,7 @@ export function generateRandomContract() {
randServer.addContract(contract); randServer.addContract(contract);
} }
export function generateRandomContractOnHome() { export function generateRandomContractOnHome(): void {
// First select a random problem type // First select a random problem type
const problemType = getRandomProblemType(); const problemType = getRandomProblemType();
@@ -53,7 +53,7 @@ export interface IGenerateContractParams {
fn?: string; fn?: string;
} }
export function generateContract(params: IGenerateContractParams) { export function generateContract(params: IGenerateContractParams): void {
// Problem Type // Problem Type
let problemType; let problemType;
const problemTypes = Object.keys(CodingContractTypes); const problemTypes = Object.keys(CodingContractTypes);
@@ -88,7 +88,7 @@ export function generateContract(params: IGenerateContractParams) {
fn = getRandomFilename(server, reward); fn = getRandomFilename(server, reward);
} }
let contract = new CodingContract(fn, problemType, reward); const contract = new CodingContract(fn, problemType, reward);
server.addContract(contract); server.addContract(contract);
} }
@@ -117,15 +117,15 @@ function sanitizeRewardType(rewardType: CodingContractRewardType): CodingContrac
return type; return type;
} }
function getRandomProblemType() { function getRandomProblemType(): string {
const problemTypes = Object.keys(CodingContractTypes); const problemTypes = Object.keys(CodingContractTypes);
let randIndex = getRandomInt(0, problemTypes.length - 1); const randIndex = getRandomInt(0, problemTypes.length - 1);
return problemTypes[randIndex]; return problemTypes[randIndex];
} }
function getRandomReward(): ICodingContractReward { function getRandomReward(): ICodingContractReward {
let reward: ICodingContractReward = { const reward: ICodingContractReward = {
name: "", name: "",
type: getRandomInt(0, CodingContractRewardType.Money), type: getRandomInt(0, CodingContractRewardType.Money),
}; };
@@ -145,8 +145,8 @@ function getRandomReward(): ICodingContractReward {
case CodingContractRewardType.FactionReputation: { case CodingContractRewardType.FactionReputation: {
// Get a random faction that player is a part of. That // Get a random faction that player is a part of. That
// faction must allow hacking contracts // faction must allow hacking contracts
var numFactions = factionsThatAllowHacking.length; const numFactions = factionsThatAllowHacking.length;
var randFaction = factionsThatAllowHacking[getRandomInt(0, numFactions - 1)]; const randFaction = factionsThatAllowHacking[getRandomInt(0, numFactions - 1)];
reward.name = randFaction; reward.name = randFaction;
break; break;
} }

View File

@@ -2,7 +2,7 @@ import {
codingContractTypesMetadata, codingContractTypesMetadata,
DescriptionFunc, DescriptionFunc,
GeneratorFunc, GeneratorFunc,
SolverFunc SolverFunc,
} from "./data/codingcontracttypes"; } from "./data/codingcontracttypes";
import { IMap } from "./types"; import { IMap } from "./types";
@@ -10,7 +10,7 @@ import { IMap } from "./types";
import { import {
Generic_fromJSON, Generic_fromJSON,
Generic_toJSON, Generic_toJSON,
Reviver Reviver,
} from "../utils/JSONReviver"; } from "../utils/JSONReviver";
import { KEY } from "../utils/helpers/keyCodes"; import { KEY } from "../utils/helpers/keyCodes";
import { createElement } from "../utils/uiHelpers/createElement"; import { createElement } from "../utils/uiHelpers/createElement";
@@ -108,12 +108,6 @@ export interface ICodingContractReward {
* The player receives a reward if the problem is solved correctly * The player receives a reward if the problem is solved correctly
*/ */
export class CodingContract { export class CodingContract {
/**
* Initiatizes a CodingContract from a JSON save state.
*/
static fromJSON(value: any): CodingContract {
return Generic_fromJSON(CodingContract, value.data);
}
/* Relevant data for the contract's problem */ /* Relevant data for the contract's problem */
data: any; data: any;
@@ -126,13 +120,13 @@ export class CodingContract {
reward: ICodingContractReward | null; reward: ICodingContractReward | null;
/* Number of times the Contract has been attempted */ /* Number of times the Contract has been attempted */
tries: number = 0; tries = 0;
/* String representing the contract's type. Must match type in ContractTypes */ /* String representing the contract's type. Must match type in ContractTypes */
type: string; type: string;
constructor(fn: string = "", constructor(fn = "",
type: string = "Find Largest Prime Factor", type = "Find Largest Prime Factor",
reward: ICodingContractReward | null = null) { reward: ICodingContractReward | null = null) {
this.fn = fn; this.fn = fn;
if (!this.fn.endsWith(".cct")) { if (!this.fn.endsWith(".cct")) {
@@ -178,9 +172,9 @@ export class CodingContract {
*/ */
async prompt(): Promise<CodingContractResult> { async prompt(): Promise<CodingContractResult> {
// tslint:disable-next-line // tslint:disable-next-line
return new Promise<CodingContractResult>((resolve: Function, reject: Function) => { return new Promise<CodingContractResult>((resolve) => {
const contractType: CodingContractType = CodingContractTypes[this.type]; const contractType: CodingContractType = CodingContractTypes[this.type];
const popupId: string = `coding-contract-prompt-popup-${this.fn}`; const popupId = `coding-contract-prompt-popup-${this.fn}`;
const title: HTMLElement = createElement("h1", { const title: HTMLElement = createElement("h1", {
innerHTML: this.type, innerHTML: this.type,
}); });
@@ -190,10 +184,16 @@ export class CodingContract {
"after which the contract will self-destruct.<br><br>", "after which the contract will self-destruct.<br><br>",
`${contractType.desc(this.data).replace(/\n/g, "<br>")}`].join(" "), `${contractType.desc(this.data).replace(/\n/g, "<br>")}`].join(" "),
}); });
let answerInput: HTMLInputElement;
let solveBtn: HTMLElement; let solveBtn: HTMLElement;
let cancelBtn: HTMLElement; const cancelBtn = createElement("a", {
answerInput = createElement("input", { class: "a-link-button",
clickListener: () => {
resolve(CodingContractResult.Cancelled);
removeElementById(popupId);
},
innerText: "Cancel",
});
const answerInput = createElement("input", {
onkeydown: (e: any) => { onkeydown: (e: any) => {
if (e.keyCode === KEY.ENTER && answerInput.value !== "") { if (e.keyCode === KEY.ENTER && answerInput.value !== "") {
e.preventDefault(); e.preventDefault();
@@ -219,14 +219,6 @@ export class CodingContract {
}, },
innerText: "Solve", innerText: "Solve",
}); });
cancelBtn = createElement("a", {
class: "a-link-button",
clickListener: () => {
resolve(CodingContractResult.Cancelled);
removeElementById(popupId);
},
innerText: "Cancel",
});
const lineBreak: HTMLElement = createElement("br"); const lineBreak: HTMLElement = createElement("br");
createPopup(popupId, [title, lineBreak, txt, lineBreak, lineBreak, answerInput, solveBtn, cancelBtn]); createPopup(popupId, [title, lineBreak, txt, lineBreak, lineBreak, answerInput, solveBtn, cancelBtn]);
answerInput.focus(); answerInput.focus();
@@ -239,6 +231,14 @@ export class CodingContract {
toJSON(): any { toJSON(): any {
return Generic_toJSON("CodingContract", this); return Generic_toJSON("CodingContract", this);
} }
/**
* Initiatizes a CodingContract from a JSON save state.
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): CodingContract {
return Generic_fromJSON(CodingContract, value.data);
}
} }
Reviver.constructors.CodingContract = CodingContract; Reviver.constructors.CodingContract = CodingContract;

View File

@@ -6,7 +6,7 @@ import { Reviver } from "../../utils/JSONReviver";
export let Companies: IMap<Company> = {}; export let Companies: IMap<Company> = {};
function addCompany(params: IConstructorParams) { function addCompany(params: IConstructorParams): void {
if (Companies[params.name] != null) { if (Companies[params.name] != null) {
console.warn(`Duplicate Company Position being defined: ${params.name}`); console.warn(`Duplicate Company Position being defined: ${params.name}`);
} }
@@ -15,7 +15,7 @@ function addCompany(params: IConstructorParams) {
// Used to initialize new Company objects for the Companies map // Used to initialize new Company objects for the Companies map
// Called when creating new game or after a prestige/reset // Called when creating new game or after a prestige/reset
export function initCompanies() { export function initCompanies(): void {
// Save Old Company data for 'favor' // Save Old Company data for 'favor'
const oldCompanies = Companies; const oldCompanies = Companies;
@@ -40,11 +40,11 @@ export function initCompanies() {
} }
// Used to load Companies map from a save // Used to load Companies map from a save
export function loadCompanies(saveString: string) { export function loadCompanies(saveString: string): void {
Companies = JSON.parse(saveString, Reviver); Companies = JSON.parse(saveString, Reviver);
} }
// Utility function to check if a string is valid company name // Utility function to check if a string is valid company name
export function companyExists(name: string) { export function companyExists(name: string): boolean {
return Companies.hasOwnProperty(name); return Companies.hasOwnProperty(name);
} }

View File

@@ -25,12 +25,6 @@ const DefaultConstructorParams: IConstructorParams = {
} }
export class Company { export class Company {
/**
* Initiatizes a Company from a JSON save state.
*/
static fromJSON(value: any): Company {
return Generic_fromJSON(Company, value.data);
}
/** /**
* Company name * Company name
@@ -136,7 +130,7 @@ export class Company {
gainFavor(): void { gainFavor(): void {
if (this.favor == null) { this.favor = 0; } if (this.favor == null) { this.favor = 0; }
if (this.rolloverRep == null) { this.rolloverRep = 0; } if (this.rolloverRep == null) { this.rolloverRep = 0; }
var res = this.getFavorGain(); const res = this.getFavorGain();
if (res.length != 2) { if (res.length != 2) {
console.error("Invalid result from getFavorGain() function"); console.error("Invalid result from getFavorGain() function");
return; return;
@@ -170,6 +164,14 @@ export class Company {
toJSON(): any { toJSON(): any {
return Generic_toJSON("Company", this); return Generic_toJSON("Company", this);
} }
/**
* Initiatizes a Company from a JSON save state.
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Company {
return Generic_fromJSON(Company, value.data);
}
} }
Reviver.constructors.Company = Company; Reviver.constructors.Company = Company;

View File

@@ -5,7 +5,7 @@ import { IMap } from "../types";
export const CompanyPositions: IMap<CompanyPosition> = {}; export const CompanyPositions: IMap<CompanyPosition> = {};
function addCompanyPosition(params: IConstructorParams) { function addCompanyPosition(params: IConstructorParams): void {
if (CompanyPositions[params.name] != null) { if (CompanyPositions[params.name] != null) {
console.warn(`Duplicate Company Position being defined: ${params.name}`); console.warn(`Duplicate Company Position being defined: ${params.name}`);
} }

View File

@@ -5,8 +5,8 @@ import { CompanyPosition } from "./CompanyPosition";
* Returns a string with the given CompanyPosition's stat requirements * Returns a string with the given CompanyPosition's stat requirements
*/ */
export function getJobRequirementText(company: Company, pos: CompanyPosition, tooltiptext: boolean = false): string { export function getJobRequirementText(company: Company, pos: CompanyPosition, tooltiptext = false): string {
let reqText: string = ""; let reqText = "";
const offset: number = company.jobStatReqOffset; const offset: number = company.jobStatReqOffset;
const reqHacking: number = pos.requiredHacking > 0 ? pos.requiredHacking+offset : 0; const reqHacking: number = pos.requiredHacking > 0 ? pos.requiredHacking+offset : 0;
const reqStrength: number = pos.requiredStrength > 0 ? pos.requiredStrength+offset : 0; const reqStrength: number = pos.requiredStrength > 0 ? pos.requiredStrength+offset : 0;

View File

@@ -95,7 +95,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 3, expMultiplier: 3,
salaryMultiplier: 3, salaryMultiplier: 3,
@@ -107,7 +107,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 3, expMultiplier: 3,
salaryMultiplier: 3, salaryMultiplier: 3,
@@ -119,7 +119,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 2.6, expMultiplier: 2.6,
salaryMultiplier: 2.6, salaryMultiplier: 2.6,
@@ -131,7 +131,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 2.75, expMultiplier: 2.75,
salaryMultiplier: 2.75, salaryMultiplier: 2.75,
@@ -143,7 +143,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 2.75, expMultiplier: 2.75,
salaryMultiplier: 2.75, salaryMultiplier: 2.75,
@@ -155,7 +155,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 2.25, expMultiplier: 2.25,
salaryMultiplier: 2.25, salaryMultiplier: 2.25,
@@ -167,7 +167,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 2.25, expMultiplier: 2.25,
salaryMultiplier: 2.25, salaryMultiplier: 2.25,
@@ -179,7 +179,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 2.5, expMultiplier: 2.5,
salaryMultiplier: 2.5, salaryMultiplier: 2.5,
@@ -191,7 +191,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 2.2, expMultiplier: 2.2,
salaryMultiplier: 2.2, salaryMultiplier: 2.2,
@@ -202,7 +202,7 @@ export const companiesMetadata: IConstructorParams[] = [
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions AllBusinessPositions,
), ),
expMultiplier: 2, expMultiplier: 2,
salaryMultiplier: 2, salaryMultiplier: 2,
@@ -214,7 +214,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllSoftwareConsultantPositions, AllSoftwareConsultantPositions,
AllBusinessPositions AllBusinessPositions,
), ),
expMultiplier: 1.8, expMultiplier: 1.8,
salaryMultiplier: 1.8, salaryMultiplier: 1.8,
@@ -226,7 +226,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
CEOOnly, CEOOnly,
AllTechnologyPositions, AllTechnologyPositions,
AllSoftwareConsultantPositions AllSoftwareConsultantPositions,
), ),
expMultiplier: 1.75, expMultiplier: 1.75,
salaryMultiplier: 1.75, salaryMultiplier: 1.75,
@@ -238,7 +238,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
CEOOnly, CEOOnly,
AllTechnologyPositions, AllTechnologyPositions,
AllSoftwareConsultantPositions AllSoftwareConsultantPositions,
), ),
expMultiplier: 1.8, expMultiplier: 1.8,
salaryMultiplier: 1.8, salaryMultiplier: 1.8,
@@ -250,7 +250,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSoftwareConsultantPositions AllSoftwareConsultantPositions,
), ),
expMultiplier: 1.8, expMultiplier: 1.8,
salaryMultiplier: 1.8, salaryMultiplier: 1.8,
@@ -262,7 +262,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSoftwareConsultantPositions AllSoftwareConsultantPositions,
), ),
expMultiplier: 1.9, expMultiplier: 1.9,
salaryMultiplier: 1.9, salaryMultiplier: 1.9,
@@ -274,7 +274,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSoftwareConsultantPositions AllSoftwareConsultantPositions,
), ),
expMultiplier: 2, expMultiplier: 2,
salaryMultiplier: 2, salaryMultiplier: 2,
@@ -286,7 +286,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSoftwareConsultantPositions AllSoftwareConsultantPositions,
), ),
expMultiplier: 1.9, expMultiplier: 1.9,
salaryMultiplier: 1.9, salaryMultiplier: 1.9,
@@ -299,7 +299,7 @@ export const companiesMetadata: IConstructorParams[] = [
CEOOnly, CEOOnly,
OperationsManagerOnly, OperationsManagerOnly,
AllTechnologyPositions, AllTechnologyPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 1.7, expMultiplier: 1.7,
salaryMultiplier: 1.7, salaryMultiplier: 1.7,
@@ -351,7 +351,7 @@ export const companiesMetadata: IConstructorParams[] = [
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSoftwareConsultantPositions, AllSoftwareConsultantPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 1.8, expMultiplier: 1.8,
salaryMultiplier: 1.8, salaryMultiplier: 1.8,
@@ -364,7 +364,7 @@ export const companiesMetadata: IConstructorParams[] = [
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSoftwareConsultantPositions, AllSoftwareConsultantPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 1.75, expMultiplier: 1.75,
salaryMultiplier: 1.75, salaryMultiplier: 1.75,
@@ -379,7 +379,7 @@ export const companiesMetadata: IConstructorParams[] = [
SecurityEngineerPositions, SecurityEngineerPositions,
AllITPositions, AllITPositions,
AllSecurityPositions, AllSecurityPositions,
AllAgentPositions AllAgentPositions,
), ),
expMultiplier: 2, expMultiplier: 2,
salaryMultiplier: 2, salaryMultiplier: 2,
@@ -394,7 +394,7 @@ export const companiesMetadata: IConstructorParams[] = [
SecurityEngineerPositions, SecurityEngineerPositions,
AllITPositions, AllITPositions,
AllSecurityPositions, AllSecurityPositions,
AllAgentPositions AllAgentPositions,
), ),
expMultiplier: 2, expMultiplier: 2,
salaryMultiplier: 2, salaryMultiplier: 2,
@@ -409,7 +409,7 @@ export const companiesMetadata: IConstructorParams[] = [
AllITPositions, AllITPositions,
AllSecurityPositions, AllSecurityPositions,
AllAgentPositions, AllAgentPositions,
AllSoftwareConsultantPositions AllSoftwareConsultantPositions,
), ),
expMultiplier: 1.5, expMultiplier: 1.5,
salaryMultiplier: 1.5, salaryMultiplier: 1.5,
@@ -422,7 +422,7 @@ export const companiesMetadata: IConstructorParams[] = [
AllTechnologyPositions, AllTechnologyPositions,
AllSoftwareConsultantPositions, AllSoftwareConsultantPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 1.4, expMultiplier: 1.4,
salaryMultiplier: 1.4, salaryMultiplier: 1.4,
@@ -433,7 +433,7 @@ export const companiesMetadata: IConstructorParams[] = [
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
SoftwarePositionsUpToLeadDeveloper, SoftwarePositionsUpToLeadDeveloper,
BusinessPositionsUpToOperationsManager BusinessPositionsUpToOperationsManager,
), ),
expMultiplier: 1.3, expMultiplier: 1.3,
salaryMultiplier: 1.3, salaryMultiplier: 1.3,
@@ -445,7 +445,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
SoftwarePositionsUpToLeadDeveloper, SoftwarePositionsUpToLeadDeveloper,
BusinessPositionsUpToOperationsManager, BusinessPositionsUpToOperationsManager,
AllSoftwareConsultantPositions AllSoftwareConsultantPositions,
), ),
expMultiplier: 1.5, expMultiplier: 1.5,
salaryMultiplier: 1.5, salaryMultiplier: 1.5,
@@ -456,7 +456,7 @@ export const companiesMetadata: IConstructorParams[] = [
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllSecurityPositions, AllSecurityPositions,
SoftwarePositionsUpToLeadDeveloper SoftwarePositionsUpToLeadDeveloper,
), ),
expMultiplier: 1.3, expMultiplier: 1.3,
salaryMultiplier: 1.3, salaryMultiplier: 1.3,
@@ -466,7 +466,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.VolhavenSysCoreSecurities, name: LocationName.VolhavenSysCoreSecurities,
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions AllTechnologyPositions,
), ),
expMultiplier: 1.3, expMultiplier: 1.3,
salaryMultiplier: 1.3, salaryMultiplier: 1.3,
@@ -476,7 +476,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.VolhavenCompuTek, name: LocationName.VolhavenCompuTek,
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions AllTechnologyPositions,
), ),
expMultiplier: 1.2, expMultiplier: 1.2,
salaryMultiplier: 1.2, salaryMultiplier: 1.2,
@@ -486,7 +486,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.AevumNetLinkTechnologies, name: LocationName.AevumNetLinkTechnologies,
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions AllTechnologyPositions,
), ),
expMultiplier: 1.2, expMultiplier: 1.2,
salaryMultiplier: 1.2, salaryMultiplier: 1.2,
@@ -509,7 +509,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.Sector12FoodNStuff, name: LocationName.Sector12FoodNStuff,
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
EmployeeOnly, PartTimeEmployeeOnly EmployeeOnly, PartTimeEmployeeOnly,
), ),
expMultiplier: 1, expMultiplier: 1,
salaryMultiplier: 1, salaryMultiplier: 1,
@@ -519,7 +519,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.Sector12JoesGuns, name: LocationName.Sector12JoesGuns,
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
EmployeeOnly, PartTimeEmployeeOnly EmployeeOnly, PartTimeEmployeeOnly,
), ),
expMultiplier: 1, expMultiplier: 1,
salaryMultiplier: 1, salaryMultiplier: 1,
@@ -531,7 +531,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllSoftwarePositions, AllSoftwarePositions,
AllSoftwareConsultantPositions, AllSoftwareConsultantPositions,
AllITPositions AllITPositions,
), ),
expMultiplier: 1.1, expMultiplier: 1.1,
salaryMultiplier: 1.1, salaryMultiplier: 1.1,
@@ -541,7 +541,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.NewTokyoNoodleBar, name: LocationName.NewTokyoNoodleBar,
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
WaiterOnly, PartTimeWaiterOnly WaiterOnly, PartTimeWaiterOnly,
), ),
expMultiplier: 1, expMultiplier: 1,
salaryMultiplier: 1, salaryMultiplier: 1,

View File

@@ -8,23 +8,23 @@ export const SoftwareCompanyPositions: string[] = [
"Head of Software", "Head of Software",
"Head of Engineering", "Head of Engineering",
"Vice President of Technology", "Vice President of Technology",
"Chief Technology Officer" "Chief Technology Officer",
]; ];
export const ITCompanyPositions: string[] = [ export const ITCompanyPositions: string[] = [
"IT Intern", "IT Intern",
"IT Analyst", "IT Analyst",
"IT Manager", "IT Manager",
"Systems Administrator" "Systems Administrator",
]; ];
export const SecurityEngineerCompanyPositions: string[] = [ export const SecurityEngineerCompanyPositions: string[] = [
"Security Engineer" "Security Engineer",
]; ];
export const NetworkEngineerCompanyPositions: string[] = [ export const NetworkEngineerCompanyPositions: string[] = [
"Network Engineer", "Network Engineer",
"Network Administrator" "Network Administrator",
]; ];
export const BusinessCompanyPositions: string[] = [ export const BusinessCompanyPositions: string[] = [
@@ -33,7 +33,7 @@ export const BusinessCompanyPositions: string[] = [
"Business Manager", "Business Manager",
"Operations Manager", "Operations Manager",
"Chief Financial Officer", "Chief Financial Officer",
"Chief Executive Officer" "Chief Executive Officer",
]; ];
export const SecurityCompanyPositions: string[] = [ export const SecurityCompanyPositions: string[] = [
@@ -42,31 +42,31 @@ export const SecurityCompanyPositions: string[] = [
"Security Guard", "Security Guard",
"Security Officer", "Security Officer",
"Security Supervisor", "Security Supervisor",
"Head of Security" "Head of Security",
]; ];
export const AgentCompanyPositions: string[] = [ export const AgentCompanyPositions: string[] = [
"Field Agent", "Field Agent",
"Secret Agent", "Secret Agent",
"Special Operative" "Special Operative",
]; ];
export const MiscCompanyPositions: string[] = [ export const MiscCompanyPositions: string[] = [
"Waiter", "Waiter",
"Employee" "Employee",
]; ];
export const SoftwareConsultantCompanyPositions: string[] = [ export const SoftwareConsultantCompanyPositions: string[] = [
"Software Consultant", "Software Consultant",
"Senior Software Consultant" "Senior Software Consultant",
]; ];
export const BusinessConsultantCompanyPositions: string[] = [ export const BusinessConsultantCompanyPositions: string[] = [
"Business Consultant", "Business Consultant",
"Senior Business Consultant" "Senior Business Consultant",
]; ];
export const PartTimeCompanyPositions: string[] = [ export const PartTimeCompanyPositions: string[] = [
"Part-time Waiter", "Part-time Waiter",
"Part-time Employee" "Part-time Employee",
]; ];

View File

@@ -5,8 +5,8 @@
*/ */
import { IMap } from "./types"; import { IMap } from "./types";
export let CONSTANTS: IMap<any> = { export const CONSTANTS: IMap<any> = {
Version: "0.51.3", Version: "0.51.7",
/** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience /** 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 * and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
@@ -228,39 +228,61 @@ export let CONSTANTS: IMap<any> = {
LatestUpdate: LatestUpdate:
` `
v0.51.3 - 2021-04-16 Y'all broke it on the first day (hydroflame) v0.51.7 - 2021-04-28 n00dles
------- -------
Passive faction reputation Tutorial servers
* Reworked, from 1 rep / 2 minute. Now is a complicated percentage of the
reputation you'd gain working for them. It's not op but it feels a bit * All the tutorial servers have been reverted to their original value
more useful. * The new server n00dles has been added as tutorial server.
Terminal
* 'tail' now accepts Pid.
* 'analyze' now handles Hacknet Servers correctly.
* 'ServerProfiler.exe' now handles Hacknet Servers correctly.
SF12
* Now makes you start with Neuroflux Governor equal to the level of the SF.
Netscript Netscript
* print/tprint now take any number of arguments.
* print/tprint will now print object as json.
* print/tprint now handle passing in an undefined argument properly.
Casino * Deprecated 'getServerRam'.
* Cannot bet negative money anymore. * 'getServerMaxRam' added to replace 'getServerRam'
* Roulette max bet is a bit higher. * 'getServerUsedRam' added to replace 'getServerRam'
* Coin Flip has a small cooldown. * 'getBitnodeMultipliers' is available inside BN5
* All buttons reject unstrusted mouse events. * Time logged by hack/grow/weaken now displays in human time.
* thread count logged by hack/grow/weaken now displays with commas every
thousands place.
Documentation Donation
* Changed a message that said nsjs only works on Chrome.
* Always visible but locked until favor requirements are reached.
Augmentations
* City factions has been rebalanced to give a reason to visit them all.
Sleeves
* Fix sleeves not being able to work at Volhavens gym.
Lint
* This shouldn't change anything but was like 10h of work.
Bugfix
* hacknet.maxNumNodes now works for both nodes and servers.
* Fixed a bug where the popup boxes would contain data from previous popup boxes.
* .js files will also have the export async function boilerplate.
Misc. Misc.
* turned off autocomplete for the terminal text input.
* Fixed an issue on Windows+Firefox where pressing up on the terminal would * Plethora of typo fixed (@Pimgd)
bring the cursor to the begining of the line. (Issue #836) * ps documentation fix (@Dawe)
* Hacknet node names is easier to handle for screen readers. * The dev menu now has a quick bitflume option.
* Money spent on classes is now tracked independently of work money. * Fix SF -1 not being as powerful as intended.
* running coding contract from the terminal will display its name. * Fix cashroot starter kit not displaying correctly.
` * Fix DOM element 'character-overview-text' being nested twice.
* Hacknet documentation example fix.
* Money amount under 1000 dont display 3 decimal anymore.
* Fix nextSourceFile flag miscalculation on the bitverse (for Bn12)
* Faction invite text says "Decide later"/"Join!" instead of "No"/"Yes"
`,
} }

View File

@@ -5,7 +5,6 @@ import { CorporationUpgrades } from "./data/Corporation
import { EmployeePositions } from "./EmployeePositions"; import { EmployeePositions } from "./EmployeePositions";
import { Industries, import { Industries,
IndustryStartingCosts, IndustryStartingCosts,
IndustryDescriptions,
IndustryResearchTrees } from "./IndustryData"; IndustryResearchTrees } from "./IndustryData";
import { IndustryUpgrades } from "./IndustryUpgrades"; import { IndustryUpgrades } from "./IndustryUpgrades";
import { Material } from "./Material"; import { Material } from "./Material";
@@ -15,11 +14,8 @@ import { ResearchMap } from "./ResearchMap";
import { Warehouse } from "./Warehouse"; import { Warehouse } from "./Warehouse";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { CONSTANTS } from "../Constants";
import { Factions } from "../Faction/Factions";
import { showLiterature } from "../Literature/LiteratureHelpers"; import { showLiterature } from "../Literature/LiteratureHelpers";
import { LiteratureNames } from "../Literature/data/LiteratureNames"; import { LiteratureNames } from "../Literature/data/LiteratureNames";
import { createCityMap } from "../Locations/Cities";
import { CityName } from "../Locations/data/CityNames"; import { CityName } from "../Locations/data/CityNames";
import { Player } from "../Player"; import { Player } from "../Player";
@@ -29,7 +25,6 @@ import { Page, routing } from "../ui/navigationTr
import { calculateEffectWithFactors } from "../utils/calculateEffectWithFactors"; import { calculateEffectWithFactors } from "../utils/calculateEffectWithFactors";
import { dialogBoxCreate } from "../../utils/DialogBox"; import { dialogBoxCreate } from "../../utils/DialogBox";
import { clearSelector } from "../../utils/uiHelpers/clearSelector";
import { Reviver, import { Reviver,
Generic_toJSON, Generic_toJSON,
Generic_fromJSON } from "../../utils/JSONReviver"; Generic_fromJSON } from "../../utils/JSONReviver";
@@ -99,7 +94,6 @@ export const BaseMaxProducts = 3; // Initial value for maximum
let researchTreeBoxOpened = false; let researchTreeBoxOpened = false;
let researchTreeBox = null; let researchTreeBox = null;
$(document).mousedown(function(event) { $(document).mousedown(function(event) {
const boxId = "corporation-research-popup-box";
const contentId = "corporation-research-popup-box-content"; const contentId = "corporation-research-popup-box-content";
if (researchTreeBoxOpened) { if (researchTreeBoxOpened) {
if ( $(event.target).closest("#" + contentId).get(0) == null ) { if ( $(event.target).closest("#" + contentId).get(0) == null ) {
@@ -111,7 +105,6 @@ $(document).mousedown(function(event) {
} }
}); });
var empManualAssignmentModeActive = false;
function Industry(params={}) { function Industry(params={}) {
this.offices = { //Maps locations to offices. 0 if no office at that location this.offices = { //Maps locations to offices. 0 if no office at that location
[CityName.Aevum]: 0, [CityName.Aevum]: 0,
@@ -122,7 +115,7 @@ function Industry(params={}) {
}), }),
[CityName.NewTokyo]: 0, [CityName.NewTokyo]: 0,
[CityName.Ishima]: 0, [CityName.Ishima]: 0,
[CityName.Volhaven]: 0 [CityName.Volhaven]: 0,
}; };
this.name = params.name ? params.name : 0; this.name = params.name ? params.name : 0;
@@ -183,7 +176,7 @@ function Industry(params={}) {
}), }),
[CityName.NewTokyo]: 0, [CityName.NewTokyo]: 0,
[CityName.Ishima]: 0, [CityName.Ishima]: 0,
[CityName.Volhaven]: 0 [CityName.Volhaven]: 0,
}; };
this.init(); this.init();
@@ -378,7 +371,7 @@ Industry.prototype.init = function() {
"Metal": 5, "Metal": 5,
"Energy": 5, "Energy": 5,
"Water": 2, "Water": 2,
"Hardware": 4 "Hardware": 4,
} }
this.prodMats = ["RealEstate"]; this.prodMats = ["RealEstate"];
this.makesProducts = true; this.makesProducts = true;
@@ -441,8 +434,7 @@ Industry.prototype.calculateProductionFactors = function() {
continue; continue;
} }
var materials = warehouse.materials, var materials = warehouse.materials;
office = this.offices[city];
var cityMult = Math.pow(0.002 * materials.RealEstate.qty+1, this.reFac) * var cityMult = Math.pow(0.002 * materials.RealEstate.qty+1, this.reFac) *
Math.pow(0.002 * materials.Hardware.qty+1, this.hwFac) * Math.pow(0.002 * materials.Hardware.qty+1, this.hwFac) *
@@ -535,7 +527,7 @@ Industry.prototype.process = function(marketCycles=1, state, company) {
} }
// Process change in demand and competition for this industry's materials // Process change in demand and competition for this industry's materials
Industry.prototype.processMaterialMarket = function(marketCycles=1) { Industry.prototype.processMaterialMarket = function() {
//References to prodMats and reqMats //References to prodMats and reqMats
var reqMats = this.reqMats, prodMats = this.prodMats; var reqMats = this.reqMats, prodMats = this.prodMats;
@@ -589,7 +581,7 @@ Industry.prototype.processProductMarket = function(marketCycles=1) {
//Process production, purchase, and import/export of materials //Process production, purchase, and import/export of materials
Industry.prototype.processMaterials = function(marketCycles=1, company) { Industry.prototype.processMaterials = function(marketCycles=1, company) {
var revenue = 0, expenses = 0, industry = this; var revenue = 0, expenses = 0;
this.calculateProductionFactors(); this.calculateProductionFactors();
//At the start of the export state, set the imports of everything to 0 //At the start of the export state, set the imports of everything to 0
@@ -642,7 +634,7 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
mat.qty += buyAmt; mat.qty += buyAmt;
expenses += (buyAmt * mat.bCost); expenses += (buyAmt * mat.bCost);
} }
})(matName, industry); })(matName, this);
this.updateWarehouseSizeUsed(warehouse); this.updateWarehouseSizeUsed(warehouse);
} }
} //End process purchase of materials } //End process purchase of materials
@@ -1003,7 +995,7 @@ Industry.prototype.processProduct = function(marketCycles=1, product, corporatio
if (warehouse instanceof Warehouse) { if (warehouse instanceof Warehouse) {
switch(this.state) { switch(this.state) {
case "PRODUCTION": case "PRODUCTION": {
//Calculate the maximum production of this material based //Calculate the maximum production of this material based
//on the office's productivity //on the office's productivity
var maxProd = this.getOfficeProductivity(office, {forProduct:true}) var maxProd = this.getOfficeProductivity(office, {forProduct:true})
@@ -1065,8 +1057,8 @@ Industry.prototype.processProduct = function(marketCycles=1, product, corporatio
//Keep track of production Per second //Keep track of production Per second
product.data[city][1] = prod * producableFrac / (SecsPerMarketCycle * marketCycles); product.data[city][1] = prod * producableFrac / (SecsPerMarketCycle * marketCycles);
break; break;
}
case "SALE": case "SALE": {
//Process sale of Products //Process sale of Products
product.pCost = 0; //Estimated production cost product.pCost = 0; //Estimated production cost
for (var reqMatName in product.reqMats) { for (var reqMatName in product.reqMats) {
@@ -1174,7 +1166,7 @@ Industry.prototype.processProduct = function(marketCycles=1, product, corporatio
product.data[city][2] = 0; //data[2] is sell property product.data[city][2] = 0; //data[2] is sell property
} }
break; break;
}
case "START": case "START":
case "PURCHASE": case "PURCHASE":
case "EXPORT": case "EXPORT":
@@ -1199,10 +1191,9 @@ Industry.prototype.discontinueProduct = function(product) {
} }
Industry.prototype.upgrade = function(upgrade, refs) { Industry.prototype.upgrade = function(upgrade, refs) {
var corporation = refs.corporation, division = refs.division, var corporation = refs.corporation;
office = refs.office; var office = refs.office;
var upgN = upgrade[0], basePrice = upgrade[1], priceMult = upgrade[2], var upgN = upgrade[0];
upgradeBenefit = upgrade[3];
while (this.upgrades.length <= upgN) {this.upgrades.push(0);} while (this.upgrades.length <= upgN) {this.upgrades.push(0);}
++this.upgrades[upgN]; ++this.upgrades[upgN];
@@ -1374,9 +1365,6 @@ Industry.prototype.createResearchBox = function() {
}, },
} }
// Construct the tree with Treant
const treantTree = new Treant(markup);
// Add Event Listeners for all Nodes // Add Event Listeners for all Nodes
const allResearch = researchTree.getAllNodes(); const allResearch = researchTree.getAllNodes();
for (let i = 0; i < allResearch.length; ++i) { for (let i = 0; i < allResearch.length; ++i) {
@@ -1620,7 +1608,7 @@ var OfficeSpaceTiers = {
Basic: "Basic", Basic: "Basic",
Enhanced: "Enhanced", Enhanced: "Enhanced",
Luxurious: "Luxurious", Luxurious: "Luxurious",
Extravagant: "Extravagant" Extravagant: "Extravagant",
} }
function OfficeSpace(params={}) { function OfficeSpace(params={}) {
@@ -1658,7 +1646,7 @@ OfficeSpace.prototype.atCapacity = function() {
} }
OfficeSpace.prototype.process = function(marketCycles=1, parentRefs) { OfficeSpace.prototype.process = function(marketCycles=1, parentRefs) {
var corporation = parentRefs.corporation, industry = parentRefs.industry; var industry = parentRefs.industry;
// HRBuddy AutoRecruitment and training // HRBuddy AutoRecruitment and training
if (industry.hasResearch("HRBuddy-Recruitment") && !this.atCapacity()) { if (industry.hasResearch("HRBuddy-Recruitment") && !this.atCapacity()) {
@@ -1741,7 +1729,6 @@ OfficeSpace.prototype.calculateEmployeeProductivity = function(parentRefs) {
//Takes care of UI as well //Takes care of UI as well
OfficeSpace.prototype.findEmployees = function(parentRefs) { OfficeSpace.prototype.findEmployees = function(parentRefs) {
var company = parentRefs.corporation, division = parentRefs.industry;
if (this.atCapacity()) { return; } if (this.atCapacity()) { return; }
if (document.getElementById("cmpy-mgmt-hire-employee-popup") != null) {return;} if (document.getElementById("cmpy-mgmt-hire-employee-popup") != null) {return;}
@@ -1800,7 +1787,7 @@ OfficeSpace.prototype.findEmployees = function(parentRefs) {
office.hireEmployee(employee, parentRefs); office.hireEmployee(employee, parentRefs);
removeElementById("cmpy-mgmt-hire-employee-popup"); removeElementById("cmpy-mgmt-hire-employee-popup");
return false; return false;
} },
}); });
return div; return div;
}; };
@@ -1812,7 +1799,7 @@ OfficeSpace.prototype.findEmployees = function(parentRefs) {
clickListener:() => { clickListener:() => {
removeElementById("cmpy-mgmt-hire-employee-popup"); removeElementById("cmpy-mgmt-hire-employee-popup");
return false; return false;
} },
}); });
var elems = [text, var elems = [text,
@@ -1825,7 +1812,7 @@ OfficeSpace.prototype.findEmployees = function(parentRefs) {
} }
OfficeSpace.prototype.hireEmployee = function(employee, parentRefs) { OfficeSpace.prototype.hireEmployee = function(employee, parentRefs) {
var company = parentRefs.corporation, division = parentRefs.industry; var company = parentRefs.corporation;
var yesBtn = yesNoTxtInpBoxGetYesButton(), var yesBtn = yesNoTxtInpBoxGetYesButton(),
noBtn = yesNoTxtInpBoxGetNoButton(); noBtn = yesNoTxtInpBoxGetNoButton();
yesBtn.innerHTML = "Hire"; yesBtn.innerHTML = "Hire";
@@ -1958,15 +1945,14 @@ Corporation.prototype.storeCycles = function(numCycles=1) {
} }
Corporation.prototype.process = function() { Corporation.prototype.process = function() {
var corp = this;
if (this.storedCycles >= CyclesPerIndustryStateCycle) { if (this.storedCycles >= CyclesPerIndustryStateCycle) {
const state = this.getState(); const state = this.getState();
const marketCycles = 1; const marketCycles = 1;
const gameCycles = (marketCycles * CyclesPerIndustryStateCycle); const gameCycles = (marketCycles * CyclesPerIndustryStateCycle);
this.storedCycles -= gameCycles; this.storedCycles -= gameCycles;
this.divisions.forEach(function(ind) { this.divisions.forEach((ind) => {
ind.process(marketCycles, state, corp); ind.process(marketCycles, state, this);
}); });
// Process cooldowns // Process cooldowns
@@ -2111,7 +2097,7 @@ Corporation.prototype.goPublic = function() {
onkeyup:(e) => { onkeyup:(e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {yesBtn.click();} if (e.keyCode === KEY.ENTER) {yesBtn.click();}
} },
}); });
var br = createElement("br", {}); var br = createElement("br", {});
yesBtn = createElement("a", { yesBtn = createElement("a", {
@@ -2138,7 +2124,7 @@ Corporation.prototype.goPublic = function() {
dialogBoxCreate(`You took your ${this.name} public and earned ` + dialogBoxCreate(`You took your ${this.name} public and earned ` +
`${numeralWrapper.formatMoney(numShares * initialSharePrice)} in your IPO`); `${numeralWrapper.formatMoney(numShares * initialSharePrice)} in your IPO`);
return false; return false;
} },
}); });
var noBtn = createElement("a", { var noBtn = createElement("a", {
class:"a-link-button", class:"a-link-button",
@@ -2146,7 +2132,7 @@ Corporation.prototype.goPublic = function() {
clickListener:() => { clickListener:() => {
removeElementById(goPublicPopupId); removeElementById(goPublicPopupId);
return false; return false;
} },
}); });
createPopup(goPublicPopupId, [txt, br, input, yesBtn, noBtn]); createPopup(goPublicPopupId, [txt, br, input, yesBtn, noBtn]);
} }
@@ -2208,7 +2194,6 @@ Corporation.prototype.calculateShareSale = function(numShares) {
Corporation.prototype.convertCooldownToString = function(cd) { Corporation.prototype.convertCooldownToString = function(cd) {
// The cooldown value is based on game cycles. Convert to a simple string // The cooldown value is based on game cycles. Convert to a simple string
const CyclesPerSecond = 1000 / CONSTANTS.MilliPerCycle;
const seconds = cd / 5; const seconds = cd / 5;
const SecondsPerMinute = 60; const SecondsPerMinute = 60;
@@ -2351,7 +2336,7 @@ Corporation.prototype.createUI = function() {
companyManagementDiv = createElement("div", { companyManagementDiv = createElement("div", {
id:"cmpy-mgmt-container", id:"cmpy-mgmt-container",
position:"fixed", position:"fixed",
class:"generic-menupage-container" class:"generic-menupage-container",
}); });
document.getElementById("entire-game-container").appendChild(companyManagementDiv); document.getElementById("entire-game-container").appendChild(companyManagementDiv);

View File

@@ -6,16 +6,10 @@ import { Generic_fromJSON,
export const AllCorporationStates: string[] = ["START", "PURCHASE", "PRODUCTION", "SALE", "EXPORT"]; export const AllCorporationStates: string[] = ["START", "PURCHASE", "PRODUCTION", "SALE", "EXPORT"];
export class CorporationState { export class CorporationState {
// Initiatizes a CorporationState object from a JSON save state.
static fromJSON(value: any): CorporationState {
return Generic_fromJSON(CorporationState, value.data);
}
// Number representing what state the Corporation is in. The number // Number representing what state the Corporation is in. The number
// is an index for the array that holds all Corporation States // is an index for the array that holds all Corporation States
state: number = 0; state = 0;
constructor() {}
// Get the name of the current state // Get the name of the current state
// NOTE: This does NOT return the number stored in the 'state' property, // NOTE: This does NOT return the number stored in the 'state' property,
@@ -40,6 +34,12 @@ export class CorporationState {
toJSON(): any { toJSON(): any {
return Generic_toJSON("CorporationState", this); return Generic_toJSON("CorporationState", this);
} }
// Initiatizes a CorporationState object from a JSON save state.
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): CorporationState {
return Generic_fromJSON(CorporationState, value.data);
}
} }
Reviver.constructors.CorporationState = CorporationState; Reviver.constructors.CorporationState = CorporationState;

View File

@@ -4,8 +4,6 @@ import { getBaseResearchTreeCopy,
import { numeralWrapper } from "../ui/numeralFormat"; import { numeralWrapper } from "../ui/numeralFormat";
import { Reviver } from "../../utils/JSONReviver";
interface IIndustryMap<T> { interface IIndustryMap<T> {
Energy: T; Energy: T;
Utilities: T; Utilities: T;
@@ -107,7 +105,7 @@ export const IndustryDescriptions: IIndustryMap<string> = {
// Map of available Research for each Industry. This data is held in a // Map of available Research for each Industry. This data is held in a
// ResearchTree object // ResearchTree object
export let IndustryResearchTrees: IIndustryMap<ResearchTree> = { export const IndustryResearchTrees: IIndustryMap<ResearchTree> = {
Energy: getBaseResearchTreeCopy(), Energy: getBaseResearchTreeCopy(),
Utilities: getBaseResearchTreeCopy(), Utilities: getBaseResearchTreeCopy(),
Agriculture: getBaseResearchTreeCopy(), Agriculture: getBaseResearchTreeCopy(),
@@ -124,7 +122,7 @@ export let IndustryResearchTrees: IIndustryMap<ResearchTree> = {
RealEstate: getProductIndustryResearchTreeCopy(), RealEstate: getProductIndustryResearchTreeCopy(),
} }
export function resetIndustryResearchTrees() { export function resetIndustryResearchTrees(): void {
IndustryResearchTrees.Energy = getBaseResearchTreeCopy(); IndustryResearchTrees.Energy = getBaseResearchTreeCopy();
IndustryResearchTrees.Utilities = getBaseResearchTreeCopy(); IndustryResearchTrees.Utilities = getBaseResearchTreeCopy();
IndustryResearchTrees.Agriculture = getBaseResearchTreeCopy(); IndustryResearchTrees.Agriculture = getBaseResearchTreeCopy();

View File

@@ -11,5 +11,5 @@ export const IndustryUpgrades: IMap<any[]> = {
"this upgrade grants your company a static increase of 3 and 1 to its awareness and " + "this upgrade grants your company a static increase of 3 and 1 to its awareness and " +
"popularity, respectively. It will then increase your company's awareness by 1%, and its popularity " + "popularity, respectively. It will then increase your company's awareness by 1%, and its popularity " +
"by a random percentage between 1% and 3%. These effects are increased by other upgrades " + "by a random percentage between 1% and 3%. These effects are increased by other upgrades " +
"that increase the power of your advertising."] "that increase the power of your advertising."],
} }

View File

@@ -7,56 +7,52 @@ interface IConstructorParams {
} }
export class Material { export class Material {
// Initiatizes a Material object from a JSON save state.
static fromJSON(value: any): Material {
return Generic_fromJSON(Material, value.data);
}
// Name of material // Name of material
name: string = "InitName"; name = "InitName";
// Amount of material owned // Amount of material owned
qty: number = 0; qty = 0;
// Material's "quality". Unbounded // Material's "quality". Unbounded
qlt: number = 0; qlt = 0;
// How much demand the Material has in the market, and the range of possible // How much demand the Material has in the market, and the range of possible
// values for this "demand" // values for this "demand"
dmd: number = 0; dmd = 0;
dmdR: number[] = [0, 0]; dmdR: number[] = [0, 0];
// How much competition there is for this Material in the market, and the range // How much competition there is for this Material in the market, and the range
// of possible values for this "competition" // of possible values for this "competition"
cmp: number = 0; cmp = 0;
cmpR: number[] = [0, 0]; cmpR: number[] = [0, 0];
// Maximum volatility of this Materials stats // Maximum volatility of this Materials stats
mv: number = 0; mv = 0;
// Markup. Determines how high of a price you can charge on the material // Markup. Determines how high of a price you can charge on the material
// compared to the market price without suffering loss in # of sales // compared to the market price without suffering loss in # of sales
// Quality is divided by this to determine markup limits // Quality is divided by this to determine markup limits
// e,g, If mku is 10 and quality is 100 then you can markup prices by 100/10 = 10 // e,g, If mku is 10 and quality is 100 then you can markup prices by 100/10 = 10
mku: number = 0; mku = 0;
// How much of this material is being bought, sold, imported and produced every second // How much of this material is being bought, sold, imported and produced every second
buy: number = 0; buy = 0;
sll: number = 0; sll = 0;
prd: number = 0; prd = 0;
imp: number = 0; imp = 0;
// Exports of this material to another warehouse/industry // Exports of this material to another warehouse/industry
exp: any[] = []; exp: any[] = [];
// Total amount of this material exported in the last cycle // Total amount of this material exported in the last cycle
totalExp: number = 0; totalExp = 0;
// Cost / sec to buy this material. AKA Market Price // Cost / sec to buy this material. AKA Market Price
bCost: number = 0; bCost = 0;
// Cost / sec to sell this material // Cost / sec to sell this material
sCost: number = 0; sCost = 0;
// Flags to keep track of whether production and/or sale of this material is limited // Flags to keep track of whether production and/or sale of this material is limited
// [Whether production/sale is limited, limit amount] // [Whether production/sale is limited, limit amount]
@@ -64,9 +60,9 @@ export class Material {
sllman: any[] = [false, 0]; // Sale sllman: any[] = [false, 0]; // Sale
// Flags that signal whether automatic sale pricing through Market TA is enabled // Flags that signal whether automatic sale pricing through Market TA is enabled
marketTa1: boolean = false; marketTa1 = false;
marketTa2: boolean = false; marketTa2 = false;
marketTa2Price: number = 0; marketTa2Price = 0;
constructor(params: IConstructorParams = {}) { constructor(params: IConstructorParams = {}) {
if (params.name) { this.name = params.name; } if (params.name) { this.name = params.name; }
@@ -166,7 +162,7 @@ export class Material {
const compChange: number = 1 + compVolatility; const compChange: number = 1 + compVolatility;
if (Math.random() < 0.5) { if (Math.random() < 0.5) {
this.cmp *= compChange; this.cmp *= compChange;
if (this.cmp > this.cmpR[1]) {this.cmp = this.cmpR[1]}; if (this.cmp > this.cmpR[1]) {this.cmp = this.cmpR[1]}
this.bCost *= (1 / priceChange); // Competition increases, so price goes down this.bCost *= (1 / priceChange); // Competition increases, so price goes down
} else { } else {
this.cmp *= (1 / compChange); this.cmp *= (1 / compChange);
@@ -192,6 +188,12 @@ export class Material {
toJSON(): any { toJSON(): any {
return Generic_toJSON("Material", this); return Generic_toJSON("Material", this);
} }
// Initiatizes a Material object from a JSON save state.
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Material {
return Generic_fromJSON(Material, value.data);
}
} }
Reviver.constructors.Material = Material; Reviver.constructors.Material = Material;

View File

@@ -42,49 +42,45 @@ interface IIndustry {
export class Product { export class Product {
// Initiatizes a Product object from a JSON save state.
static fromJSON(value: any): Product {
return Generic_fromJSON(Product, value.data);
}
// Product name // Product name
name: string = ""; name = "";
// The demand for this Product in the market. Gradually decreases // The demand for this Product in the market. Gradually decreases
dmd: number = 0; dmd = 0;
// How much competition there is in the market for this Product // How much competition there is in the market for this Product
cmp: number = 0; cmp = 0;
// Markup. Affects how high of a price you can charge for this Product // Markup. Affects how high of a price you can charge for this Product
// without suffering a loss in the # of sales // without suffering a loss in the # of sales
mku: number = 0; mku = 0;
// Production cost - estimation of how much money it costs to make this Product // Production cost - estimation of how much money it costs to make this Product
pCost: number = 0; pCost = 0;
// Sell cost // Sell cost
sCost: number = 0; sCost = 0;
// Variables for handling the creation process of this Product // Variables for handling the creation process of this Product
fin: boolean = false; // Whether this Product has finished being created fin = false; // Whether this Product has finished being created
prog: number = 0; // Creation progress - A number betwee 0-100 representing percentage prog = 0; // Creation progress - A number betwee 0-100 representing percentage
createCity: string = ""; // City in which the product is/was being created createCity = ""; // City in which the product is/was being created
designCost: number = 0; // How much money was invested into designing this Product designCost = 0; // How much money was invested into designing this Product
advCost: number = 0; // How much money was invested into advertising this Product advCost = 0; // How much money was invested into advertising this Product
// Aggregate score for this Product's 'rating' // Aggregate score for this Product's 'rating'
// This is based on the stats/properties below. The weighting of the // This is based on the stats/properties below. The weighting of the
// stats/properties below differs between different industries // stats/properties below differs between different industries
rat: number = 0; rat = 0;
// Stats/properties of this Product // Stats/properties of this Product
qlt: number = 0; qlt = 0;
per: number = 0; per = 0;
dur: number = 0; dur = 0;
rel: number = 0; rel = 0;
aes: number = 0; aes = 0;
fea: number = 0; fea = 0;
// Data refers to the production, sale, and quantity of the products // Data refers to the production, sale, and quantity of the products
// These values are specific to a city // These values are specific to a city
@@ -93,11 +89,11 @@ export class Product {
// Location of this Product // Location of this Product
// Only applies for location-based products like restaurants/hospitals // Only applies for location-based products like restaurants/hospitals
loc: string = ""; loc = "";
// How much space 1 unit of the Product takes (in the warehouse) // How much space 1 unit of the Product takes (in the warehouse)
// Not applicable for all Products // Not applicable for all Products
siz: number = 0; siz = 0;
// Material requirements. An object that maps the name of a material to how much it requires // Material requirements. An object that maps the name of a material to how much it requires
// to make 1 unit of the product. // to make 1 unit of the product.
@@ -110,8 +106,8 @@ export class Product {
sllman: IMap<any[]> = createCityMap<any[]>([false, 0]); sllman: IMap<any[]> = createCityMap<any[]>([false, 0]);
// Flags that signal whether automatic sale pricing through Market TA is enabled // Flags that signal whether automatic sale pricing through Market TA is enabled
marketTa1: boolean = false; marketTa1 = false;
marketTa2: boolean = false; marketTa2 = false;
marketTa2Price: IMap<number> = createCityMap<number>(0); marketTa2Price: IMap<number> = createCityMap<number>(0);
constructor(params: IConstructorParams={}) { constructor(params: IConstructorParams={}) {
@@ -135,7 +131,7 @@ export class Product {
// empWorkMult is a multiplier that increases progress rate based on // empWorkMult is a multiplier that increases progress rate based on
// productivity of employees // productivity of employees
createProduct(marketCycles: number=1, empWorkMult: number=1): void { createProduct(marketCycles=1, empWorkMult=1): void {
if (this.fin) { return; } if (this.fin) { return; }
this.prog += (marketCycles * .01 * empWorkMult); this.prog += (marketCycles * .01 * empWorkMult);
} }
@@ -145,18 +141,18 @@ export class Product {
this.fin = true; this.fin = true;
//Calculate properties //Calculate properties
var progrMult = this.prog / 100; const progrMult = this.prog / 100;
const engrRatio = employeeProd[EmployeePositions.Engineer] / employeeProd["total"]; const engrRatio = employeeProd[EmployeePositions.Engineer] / employeeProd["total"];
const mgmtRatio = employeeProd[EmployeePositions.Management] / employeeProd["total"]; const mgmtRatio = employeeProd[EmployeePositions.Management] / employeeProd["total"];
const rndRatio = employeeProd[EmployeePositions.RandD] / employeeProd["total"]; const rndRatio = employeeProd[EmployeePositions.RandD] / employeeProd["total"];
const opsRatio = employeeProd[EmployeePositions.Operations] / employeeProd["total"]; const opsRatio = employeeProd[EmployeePositions.Operations] / employeeProd["total"];
const busRatio = employeeProd[EmployeePositions.Business] / employeeProd["total"]; const busRatio = employeeProd[EmployeePositions.Business] / employeeProd["total"];
var designMult = 1 + (Math.pow(this.designCost, 0.1) / 100); const designMult = 1 + (Math.pow(this.designCost, 0.1) / 100);
var balanceMult = (1.2 * engrRatio) + (0.9 * mgmtRatio) + (1.3 * rndRatio) + const balanceMult = (1.2 * engrRatio) + (0.9 * mgmtRatio) + (1.3 * rndRatio) +
(1.5 * opsRatio) + (busRatio); (1.5 * opsRatio) + (busRatio);
var sciMult = 1 + (Math.pow(industry.sciResearch.qty, industry.sciFac) / 800); const sciMult = 1 + (Math.pow(industry.sciResearch.qty, industry.sciFac) / 800);
var totalMult = progrMult * balanceMult * designMult * sciMult; const totalMult = progrMult * balanceMult * designMult * sciMult;
this.qlt = totalMult * ((0.10 * employeeProd[EmployeePositions.Engineer]) + this.qlt = totalMult * ((0.10 * employeeProd[EmployeePositions.Engineer]) +
(0.05 * employeeProd[EmployeePositions.Management]) + (0.05 * employeeProd[EmployeePositions.Management]) +
@@ -189,14 +185,14 @@ export class Product {
(0.05 * employeeProd[EmployeePositions.Operations]) + (0.05 * employeeProd[EmployeePositions.Operations]) +
(0.05 * employeeProd[EmployeePositions.Business])); (0.05 * employeeProd[EmployeePositions.Business]));
this.calculateRating(industry); this.calculateRating(industry);
var advMult = 1 + (Math.pow(this.advCost, 0.1) / 100); const advMult = 1 + (Math.pow(this.advCost, 0.1) / 100);
this.mku = 100 / (advMult * Math.pow((this.qlt + 0.001), 0.65) * (busRatio + mgmtRatio)); this.mku = 100 / (advMult * Math.pow((this.qlt + 0.001), 0.65) * (busRatio + mgmtRatio));
this.dmd = industry.awareness === 0 ? 20 : Math.min(100, advMult * (100 * (industry.popularity / industry.awareness))); this.dmd = industry.awareness === 0 ? 20 : Math.min(100, advMult * (100 * (industry.popularity / industry.awareness)));
this.cmp = getRandomInt(0, 70); this.cmp = getRandomInt(0, 70);
//Calculate the product's required materials //Calculate the product's required materials
//For now, just set it to be the same as the requirements to make materials //For now, just set it to be the same as the requirements to make materials
for (var matName in industry.reqMats) { for (const matName in industry.reqMats) {
if (industry.reqMats.hasOwnProperty(matName)) { if (industry.reqMats.hasOwnProperty(matName)) {
this.reqMats[matName] = industry.reqMats[matName]; this.reqMats[matName] = industry.reqMats[matName];
} }
@@ -205,14 +201,18 @@ export class Product {
//Calculate the product's size //Calculate the product's size
//For now, just set it to be the same size as the requirements to make materials //For now, just set it to be the same size as the requirements to make materials
this.siz = 0; this.siz = 0;
for (var matName in industry.reqMats) { for (const matName in industry.reqMats) {
this.siz += MaterialSizes[matName] * industry.reqMats[matName]; this.siz += MaterialSizes[matName] * industry.reqMats[matName];
} }
//Delete unneeded variables //Delete unneeded variables
// @ts-ignore
delete this.prog; delete this.prog;
// @ts-ignore
delete this.createCity; delete this.createCity;
// @ts-ignore
delete this.designCost; delete this.designCost;
// @ts-ignore
delete this.advCost; delete this.advCost;
} }
@@ -236,6 +236,12 @@ export class Product {
toJSON(): any { toJSON(): any {
return Generic_toJSON("Product", this); return Generic_toJSON("Product", this);
} }
// Initiatizes a Product object from a JSON save state.
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Product {
return Generic_fromJSON(Product, value.data);
}
} }
Reviver.constructors.Product = Product; Reviver.constructors.Product = Product;

View File

@@ -10,7 +10,7 @@ export interface IProductRatingWeight {
Reliability?: number; Reliability?: number;
} }
export const ProductRatingWeights: IMap<object> = { export const ProductRatingWeights: IMap<any> = {
[Industries.Food]: { [Industries.Food]: {
Quality: 0.7, Quality: 0.7,
Durability: 0.1, Durability: 0.1,
@@ -73,5 +73,5 @@ export const ProductRatingWeights: IMap<object> = {
Reliability: 0.1, Reliability: 0.1,
Aesthetics: 0.35, Aesthetics: 0.35,
Features: 0.1, Features: 0.1,
} },
} }

View File

@@ -16,25 +16,25 @@ export interface IConstructorParams {
export class Research { export class Research {
// Name of research. This will be used to identify researches in the Research Tree // Name of research. This will be used to identify researches in the Research Tree
name: string = ""; name = "";
// How much scientific research it costs to unlock this // How much scientific research it costs to unlock this
cost: number = 0; cost = 0;
// Description of what the Research does // Description of what the Research does
desc: string = ""; desc = "";
// All possible generic upgrades for the company, in the form of multipliers // All possible generic upgrades for the company, in the form of multipliers
advertisingMult: number = 1; advertisingMult = 1;
employeeChaMult: number = 1; employeeChaMult = 1;
employeeCreMult: number = 1; employeeCreMult = 1;
employeeEffMult: number = 1; employeeEffMult = 1;
employeeIntMult: number = 1; employeeIntMult = 1;
productionMult: number = 1; productionMult = 1;
productProductionMult: number = 1; productProductionMult = 1;
salesMult: number = 1; salesMult = 1;
sciResearchMult: number = 1; sciResearchMult = 1;
storageMult: number = 1; storageMult = 1;
constructor(p: IConstructorParams={name: "", cost: 0, desc: ""}) { constructor(p: IConstructorParams={name: "", cost: 0, desc: ""}) {
this.name = p.name; this.name = p.name;

View File

@@ -5,9 +5,9 @@ import { Research,
import { researchMetadata } from "./data/ResearchMetadata"; import { researchMetadata } from "./data/ResearchMetadata";
import { IMap } from "../types"; import { IMap } from "../types";
export let ResearchMap: IMap<Research> = {}; export const ResearchMap: IMap<Research> = {};
function addResearch(p: IConstructorParams) { function addResearch(p: IConstructorParams): void {
if (ResearchMap[p.name] != null) { if (ResearchMap[p.name] != null) {
console.warn(`Duplicate Research being defined: ${p.name}`); console.warn(`Duplicate Research being defined: ${p.name}`);
} }

View File

@@ -26,10 +26,10 @@ export class Node {
// How much Scientific Research is needed for this // How much Scientific Research is needed for this
// Necessary to show it on the UI // Necessary to show it on the UI
cost: number = 0; cost = 0;
// Whether or not this Research has been unlocked // Whether or not this Research has been unlocked
researched: boolean = false; researched = false;
// Parent node in the tree // Parent node in the tree
// The parent node defines the prerequisite Research (there can only be one) // The parent node defines the prerequisite Research (there can only be one)
@@ -37,7 +37,7 @@ export class Node {
parent: Node | null = null; parent: Node | null = null;
// Name of the Research held in this Node // Name of the Research held in this Node
text: string = ""; text = "";
constructor(p: IConstructorParams = {cost: 0, text: ""}) { constructor(p: IConstructorParams = {cost: 0, text: ""}) {
if (ResearchMap[p.text] == null) { if (ResearchMap[p.text] == null) {
@@ -56,21 +56,21 @@ export class Node {
} }
} }
addChild(n: Node) { addChild(n: Node): void {
this.children.push(n); this.children.push(n);
n.parent = this; n.parent = this;
} }
// Return an object that describes a TreantJS-compatible markup/config for this Node // Return an object that describes a TreantJS-compatible markup/config for this Node
// See: http://fperucic.github.io/treant-js/ // See: http://fperucic.github.io/treant-js/
createTreantMarkup(): object { createTreantMarkup(): any {
const childrenArray = []; const childrenArray = [];
for (let i = 0; i < this.children.length; ++i) { for (let i = 0; i < this.children.length; ++i) {
childrenArray.push(this.children[i].createTreantMarkup()); childrenArray.push(this.children[i].createTreantMarkup());
} }
// Determine what css class this Node should have in the diagram // Determine what css class this Node should have in the diagram
let htmlClass: string = ""; let htmlClass = "";
if (this.researched) { if (this.researched) {
htmlClass = "researched"; htmlClass = "researched";
} else if (this.parent && this.parent.researched === false) { } else if (this.parent && this.parent.researched === false) {
@@ -109,7 +109,7 @@ export class Node {
return null; return null;
} }
setParent(n: Node) { setParent(n: Node): void {
this.parent = n; this.parent = n;
} }
} }
@@ -124,11 +124,9 @@ export class ResearchTree {
// Root Node // Root Node
root: Node | null = null; root: Node | null = null;
constructor() {}
// Return an object that contains a Tree markup for TreantJS (using the JSON approach) // Return an object that contains a Tree markup for TreantJS (using the JSON approach)
// See: http://fperucic.github.io/treant-js/ // See: http://fperucic.github.io/treant-js/
createTreantMarkup(): object { createTreantMarkup(): any {
if (this.root == null) { return {}; } if (this.root == null) { return {}; }
const treeMarkup = this.root.createTreantMarkup(); const treeMarkup = this.root.createTreantMarkup();
@@ -205,7 +203,7 @@ export class ResearchTree {
// Helper function for all the multiplier getter fns // Helper function for all the multiplier getter fns
getMultiplierHelper(propName: string): number { getMultiplierHelper(propName: string): number {
let res: number = 1; let res = 1;
if (this.root == null) { return res; } if (this.root == null) { return res; }
const queue: Node[] = []; const queue: Node[] = [];

View File

@@ -19,17 +19,13 @@ interface IConstructorParams {
} }
export class Warehouse { 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 // Text that describes how the space in this Warehouse is being used
// Used to create a tooltip in the UI // Used to create a tooltip in the UI
breakdown: string = ""; breakdown = "";
// Warehouse's level, which affects its maximum size // Warehouse's level, which affects its maximum size
level: number = 1; level = 1;
// City that this Warehouse is in // City that this Warehouse is in
loc: string; loc: string;
@@ -41,19 +37,19 @@ export class Warehouse {
size: number; size: number;
// Amount of space currently used by warehouse // Amount of space currently used by warehouse
sizeUsed: number = 0; sizeUsed = 0;
// Whether Smart Supply is enabled for this Industry (the Industry that this Warehouse is for) // Whether Smart Supply is enabled for this Industry (the Industry that this Warehouse is for)
smartSupplyEnabled: boolean = false; smartSupplyEnabled = false;
// Flag that indicates whether Smart Supply accounts for imports when calculating // Flag that indicates whether Smart Supply accounts for imports when calculating
// the amount fo purchase // the amount fo purchase
smartSupplyConsiderExports: boolean = false; smartSupplyConsiderExports = false;
// Stores the amount of product to be produced. Used for Smart Supply unlock. // 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, // The production tracked by smart supply is always based on the previous cycle,
// so it will always trail the "true" production by 1 cycle // so it will always trail the "true" production by 1 cycle
smartSupplyStore: number = 0; smartSupplyStore = 0;
constructor(params: IConstructorParams = {}) { constructor(params: IConstructorParams = {}) {
this.loc = params.loc ? params.loc : ""; this.loc = params.loc ? params.loc : "";
@@ -70,7 +66,7 @@ export class Warehouse {
Drugs: new Material({name: "Drugs"}), Drugs: new Material({name: "Drugs"}),
Robots: new Material({name: "Robots"}), Robots: new Material({name: "Robots"}),
AICores: new Material({name: "AI Cores"}), AICores: new Material({name: "AI Cores"}),
RealEstate: new Material({name: "Real Estate"}) RealEstate: new Material({name: "Real Estate"}),
} }
if (params.corp && params.industry) { if (params.corp && params.industry) {
@@ -79,11 +75,11 @@ export class Warehouse {
} }
// Re-calculate how much space is being used by this Warehouse // Re-calculate how much space is being used by this Warehouse
updateMaterialSizeUsed() { updateMaterialSizeUsed(): void {
this.sizeUsed = 0; this.sizeUsed = 0;
this.breakdown = ""; this.breakdown = "";
for (const matName in this.materials) { for (const matName in this.materials) {
var mat = this.materials[matName]; const mat = this.materials[matName];
if (MaterialSizes.hasOwnProperty(matName)) { if (MaterialSizes.hasOwnProperty(matName)) {
this.sizeUsed += (mat.qty * MaterialSizes[matName]); this.sizeUsed += (mat.qty * MaterialSizes[matName]);
if (mat.qty > 0) { if (mat.qty > 0) {
@@ -96,7 +92,7 @@ export class Warehouse {
} }
} }
updateSize(corporation: IParent, industry: IParent) { updateSize(corporation: IParent, industry: IParent): void {
try { try {
this.size = (this.level * 100) this.size = (this.level * 100)
* corporation.getStorageMultiplier() * corporation.getStorageMultiplier()
@@ -110,6 +106,12 @@ export class Warehouse {
toJSON(): any { toJSON(): any {
return Generic_toJSON("Warehouse", this); return Generic_toJSON("Warehouse", this);
} }
// Initiatizes a Warehouse object from a JSON save state.
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Warehouse {
return Generic_fromJSON(Warehouse, value.data);
}
} }
Reviver.constructors.Warehouse = Warehouse; Reviver.constructors.Warehouse = Warehouse;

View File

@@ -82,7 +82,7 @@ export const researchMetadata: IConstructorParams[] = [
cost: 15e3, cost: 15e3,
desc: "Use automated software to handle the hiring of employees. With this " + desc: "Use automated software to handle the hiring of employees. With this " +
"research, each office will automatically hire one employee per " + "research, each office will automatically hire one employee per " +
"market cycle if there is available space." "market cycle if there is available space.",
}, },
{ {
@@ -90,7 +90,7 @@ export const researchMetadata: IConstructorParams[] = [
cost: 20e3, cost: 20e3,
desc: "Use automated software to handle the training of employees. With this " + desc: "Use automated software to handle the training of employees. With this " +
"research, each employee hired with HRBuddy-Recruitment will automatically " + "research, each employee hired with HRBuddy-Recruitment will automatically " +
"be assigned to 'Training', rather than being unassigned." "be assigned to 'Training', rather than being unassigned.",
}, },
{ {
name: "JoyWire", name: "JoyWire",

View File

@@ -17,6 +17,4 @@ export class BaseReactComponent extends Component {
routing() { routing() {
return this.props.routing; return this.props.routing;
} }
render() {}
} }

View File

@@ -16,7 +16,7 @@ import { Corporation,
import { Industries, import { Industries,
IndustryStartingCosts, IndustryStartingCosts,
IndustryDescriptions, IndustryDescriptions,
IndustryResearchTrees } from "../IndustryData"; } from "../IndustryData";
import { MaterialSizes } from "../MaterialSizes"; import { MaterialSizes } from "../MaterialSizes";
@@ -61,13 +61,13 @@ export class CorporationEventHandler {
createBribeFactionsPopup() { createBribeFactionsPopup() {
const popupId = "cmpy-mgmt-bribe-factions-popup"; const popupId = "cmpy-mgmt-bribe-factions-popup";
const txt = createElement("p", { const txt = createElement("p", {
innerText:"You can use Corporation funds or stock shares to bribe Faction Leaders in exchange for faction reputation" innerText:"You can use Corporation funds or stock shares to bribe Faction Leaders in exchange for faction reputation",
}); });
const factionSelector = createElement("select", { margin:"3px" }); const factionSelector = createElement("select", { margin:"3px" });
for (let i = 0; i < Player.factions.length; ++i) { for (let i = 0; i < Player.factions.length; ++i) {
const facName = Player.factions[i]; const facName = Player.factions[i];
factionSelector.add(createElement("option", { factionSelector.add(createElement("option", {
text: facName, value: facName text: facName, value: facName,
})); }));
} }
var repGainText = createElement("p"); var repGainText = createElement("p");
@@ -93,7 +93,7 @@ export class CorporationEventHandler {
factionSelector.options[factionSelector.selectedIndex].value + factionSelector.options[factionSelector.selectedIndex].value +
" with this bribe"; " with this bribe";
} }
} },
}); });
stockSharesInput = createElement("input", { stockSharesInput = createElement("input", {
type:"number", placeholder:"Stock Shares", margin: "5px", type:"number", placeholder:"Stock Shares", margin: "5px",
@@ -115,7 +115,7 @@ export class CorporationEventHandler {
factionSelector.options[factionSelector.selectedIndex].value + factionSelector.options[factionSelector.selectedIndex].value +
" with this bribe"; " with this bribe";
} }
} },
}); });
var confirmButton = createElement("button", { var confirmButton = createElement("button", {
class:"a-link-button", innerText:"Bribe", display:"inline-block", class:"a-link-button", innerText:"Bribe", display:"inline-block",
@@ -145,7 +145,7 @@ export class CorporationEventHandler {
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} }
} },
}); });
const cancelButton = createPopupCloseButton(popupId, { const cancelButton = createPopupCloseButton(popupId, {
class: "std-button", class: "std-button",
@@ -187,7 +187,7 @@ export class CorporationEventHandler {
costIndicator.innerText = "Purchase " + numShares + " shares for a total of " + costIndicator.innerText = "Purchase " + numShares + " shares for a total of " +
numeralWrapper.format(numShares * buybackPrice, '$0.000a'); numeralWrapper.format(numShares * buybackPrice, '$0.000a');
} }
} },
}); });
var confirmBtn = createElement("button", { var confirmBtn = createElement("button", {
class:"a-link-button", innerText:"Buy shares", display:"inline-block", class:"a-link-button", innerText:"Buy shares", display:"inline-block",
@@ -221,7 +221,7 @@ export class CorporationEventHandler {
} }
return false; return false;
} },
}); });
var cancelBtn = createPopupCloseButton(popupId, { var cancelBtn = createPopupCloseButton(popupId, {
class: "std-button", class: "std-button",
@@ -249,7 +249,7 @@ export class CorporationEventHandler {
removeElementById(popupId); removeElementById(popupId);
this.rerender(); this.rerender();
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" }); const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" });
@@ -264,7 +264,7 @@ export class CorporationEventHandler {
const exportTxt = createElement("p", { const exportTxt = createElement("p", {
innerText:"Select the industry and city to export this material to, as well as " + innerText:"Select the industry and city to export this material to, as well as " +
"how much of this material to export per second. You can set the export " + "how much of this material to export per second. You can set the export " +
"amount to 'MAX' to export all of the materials in this warehouse." "amount to 'MAX' to export all of the materials in this warehouse.",
}); });
//Select industry and city to export to //Select industry and city to export to
@@ -286,7 +286,7 @@ export class CorporationEventHandler {
return; return;
} }
} }
} },
}); });
for (let i = 0; i < corp.divisions.length; ++i) { for (let i = 0; i < corp.divisions.length; ++i) {
@@ -299,7 +299,7 @@ export class CorporationEventHandler {
//Select amount to export //Select amount to export
const exportAmount = createElement("input", { const exportAmount = createElement("input", {
class: "text-input", class: "text-input",
placeholder:"Export amount / s" placeholder:"Export amount / s",
}); });
const exportBtn = createElement("button", { const exportBtn = createElement("button", {
@@ -328,14 +328,14 @@ export class CorporationEventHandler {
mat.exp.push(exportObj); mat.exp.push(exportObj);
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" }); const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" });
const currExportsText = createElement("p", { const currExportsText = createElement("p", {
innerText:"Below is a list of all current exports of this material from this warehouse. " + innerText:"Below is a list of all current exports of this material from this warehouse. " +
"Clicking on one of the exports below will REMOVE that export." "Clicking on one of the exports below will REMOVE that export.",
}); });
const currExports = []; const currExports = [];
for (var i = 0; i < mat.exp.length; ++i) { for (var i = 0; i < mat.exp.length; ++i) {
@@ -349,7 +349,7 @@ export class CorporationEventHandler {
mat.exp.splice(i, 1); //Remove export object mat.exp.splice(i, 1); //Remove export object
removeElementById(popupId); removeElementById(popupId);
createExportMaterialPopup(mat); createExportMaterialPopup(mat);
} },
})); }));
})(i, mat, currExports); })(i, mat, currExports);
} }
@@ -385,7 +385,7 @@ export class CorporationEventHandler {
onkeyup: (e) => { onkeyup: (e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {allocateBtn.click();} if (e.keyCode === KEY.ENTER) {allocateBtn.click();}
} },
}); });
allocateBtn = createElement("button", { allocateBtn = createElement("button", {
@@ -404,7 +404,7 @@ export class CorporationEventHandler {
this.rerender(); this.rerender();
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { const cancelBtn = createPopupCloseButton(popupId, {
@@ -478,7 +478,7 @@ export class CorporationEventHandler {
} else { } else {
updateDynamicText(this.corp); updateDynamicText(this.corp);
} }
} },
}); });
issueBtn = createElement("button", { issueBtn = createElement("button", {
@@ -523,7 +523,7 @@ export class CorporationEventHandler {
this.rerender(); this.rerender();
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { const cancelBtn = createPopupCloseButton(popupId, {
@@ -541,7 +541,7 @@ export class CorporationEventHandler {
const popupId = "cmpy-mgmt-limit-product-production-popup"; const popupId = "cmpy-mgmt-limit-product-production-popup";
const txt = createElement("p", { const txt = createElement("p", {
innerText:"Enter a limit to the amount of this product you would " + innerText:"Enter a limit to the amount of this product you would " +
"like to product per second. Leave the box empty to set no limit." "like to product per second. Leave the box empty to set no limit.",
}); });
let confirmBtn; let confirmBtn;
const input = createElement("input", { const input = createElement("input", {
@@ -551,7 +551,7 @@ export class CorporationEventHandler {
onkeyup: (e) => { onkeyup: (e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) { confirmBtn.click(); } if (e.keyCode === KEY.ENTER) { confirmBtn.click(); }
} },
}); });
confirmBtn = createElement("button", { confirmBtn = createElement("button", {
class: "std-button", class: "std-button",
@@ -578,7 +578,7 @@ export class CorporationEventHandler {
removeElementById(popupId); removeElementById(popupId);
this.rerender(); this.rerender();
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" }); const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" });
cancelBtn.style.margin = "6px"; cancelBtn.style.margin = "6px";
@@ -600,7 +600,7 @@ export class CorporationEventHandler {
if (division.offices[cityName] instanceof OfficeSpace) { if (division.offices[cityName] instanceof OfficeSpace) {
designCity.add(createElement("option", { designCity.add(createElement("option", {
value: cityName, value: cityName,
text: cityName text: cityName,
})); }));
} }
} }
@@ -630,7 +630,7 @@ export class CorporationEventHandler {
onkeyup: (e) => { onkeyup: (e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) { confirmBtn.click(); } if (e.keyCode === KEY.ENTER) { confirmBtn.click(); }
} },
}); });
confirmBtn = createElement("button", { confirmBtn = createElement("button", {
class: "std-button", class: "std-button",
@@ -665,7 +665,7 @@ export class CorporationEventHandler {
} }
this.rerender(); this.rerender();
return false; return false;
} },
}) })
const cancelBtn = createPopupCloseButton(popupId, { const cancelBtn = createPopupCloseButton(popupId, {
class: "std-button", class: "std-button",
@@ -679,8 +679,6 @@ export class CorporationEventHandler {
// Create a popup that lets the player use the Market TA research for Materials // Create a popup that lets the player use the Market TA research for Materials
createMaterialMarketTaPopup(mat, industry) { createMaterialMarketTaPopup(mat, industry) {
const corp = this.corp;
const popupId = "cmpy-mgmt-marketta-popup"; const popupId = "cmpy-mgmt-marketta-popup";
const markupLimit = mat.getMarkupLimit(); const markupLimit = mat.getMarkupLimit();
const ta1 = createElement("p", { const ta1 = createElement("p", {
@@ -699,7 +697,7 @@ export class CorporationEventHandler {
for: useTa1AutoSaleId, for: useTa1AutoSaleId,
innerText: "Use Market-TA.I for Auto-Sale Price", innerText: "Use Market-TA.I for Auto-Sale Price",
tooltip: "If this is enabled, then this Material will automatically " + tooltip: "If this is enabled, then this Material will automatically " +
"be sold at the price identified by Market-TA.I (i.e. the price shown above)" "be sold at the price identified by Market-TA.I (i.e. the price shown above)",
}) })
const useTa1AutoSaleCheckbox = createElement("input", { const useTa1AutoSaleCheckbox = createElement("input", {
checked: mat.marketTa1, checked: mat.marketTa1,
@@ -708,7 +706,7 @@ export class CorporationEventHandler {
type: "checkbox", type: "checkbox",
changeListener: (e) => { changeListener: (e) => {
mat.marketTa1 = e.target.checked; mat.marketTa1 = e.target.checked;
} },
}); });
useTa1AutoSaleDiv.appendChild(useTa1AutoSaleLabel); useTa1AutoSaleDiv.appendChild(useTa1AutoSaleLabel);
useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox); useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox);
@@ -766,7 +764,7 @@ export class CorporationEventHandler {
tooltip: "If this is enabled, then this Material will automatically " + tooltip: "If this is enabled, then this Material will automatically " +
"be sold at the optimal price such that the amount sold matches the " + "be sold at the optimal price such that the amount sold matches the " +
"amount produced. (i.e. the highest possible price, while still ensuring " + "amount produced. (i.e. the highest possible price, while still ensuring " +
" that all produced materials will be sold)" " that all produced materials will be sold)",
}) })
const useTa2AutoSaleCheckbox = createElement("input", { const useTa2AutoSaleCheckbox = createElement("input", {
checked: mat.marketTa2, checked: mat.marketTa2,
@@ -775,14 +773,14 @@ export class CorporationEventHandler {
type: "checkbox", type: "checkbox",
changeListener: (e) => { changeListener: (e) => {
mat.marketTa2 = e.target.checked; mat.marketTa2 = e.target.checked;
} },
}); });
useTa2AutoSaleDiv.appendChild(useTa2AutoSaleLabel); useTa2AutoSaleDiv.appendChild(useTa2AutoSaleLabel);
useTa2AutoSaleDiv.appendChild(useTa2AutoSaleCheckbox); useTa2AutoSaleDiv.appendChild(useTa2AutoSaleCheckbox);
const ta2OverridesTa1 = createElement("p", { const ta2OverridesTa1 = createElement("p", {
innerText: "Note that Market-TA.II overrides Market-TA.I. This means that if " + innerText: "Note that Market-TA.II overrides Market-TA.I. This means that if " +
"both are enabled, then Market-TA.II will take effect, not Market-TA.I" "both are enabled, then Market-TA.II will take effect, not Market-TA.I",
}); });
createPopup(popupId, [ta1, useTa1AutoSaleDiv, ta2Text, ta2Input, useTa2AutoSaleDiv, ta2OverridesTa1, closeBtn]); createPopup(popupId, [ta1, useTa1AutoSaleDiv, ta2Text, ta2Input, useTa2AutoSaleDiv, ta2OverridesTa1, closeBtn]);
@@ -805,7 +803,7 @@ export class CorporationEventHandler {
if (!(division.offices[cityName] instanceof OfficeSpace)) { if (!(division.offices[cityName] instanceof OfficeSpace)) {
citySelector.add(createElement("option", { citySelector.add(createElement("option", {
text: cityName, text: cityName,
value: cityName value: cityName,
})); }));
} }
} }
@@ -832,7 +830,7 @@ export class CorporationEventHandler {
removeElementById(popupId); removeElementById(popupId);
this.rerender(); this.rerender();
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { const cancelBtn = createPopupCloseButton(popupId, {
class: "std-button", class: "std-button",
@@ -852,7 +850,7 @@ export class CorporationEventHandler {
innerHTML: "Create a new division to expand into a new industry:", innerHTML: "Create a new division to expand into a new industry:",
}); });
var selector = createElement("select", { var selector = createElement("select", {
class:"dropdown" class:"dropdown",
}); });
var industryDescription = createElement("p", {}); var industryDescription = createElement("p", {});
var yesBtn; var yesBtn;
@@ -866,11 +864,11 @@ export class CorporationEventHandler {
onkeyup:(e)=>{ onkeyup:(e)=>{
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {yesBtn.click();} if (e.keyCode === KEY.ENTER) {yesBtn.click();}
} },
}); });
var nameLabel = createElement("label", { var nameLabel = createElement("label", {
for:"cmpy-mgmt-expand-industry-name-input", for:"cmpy-mgmt-expand-industry-name-input",
innerText:"Division name: " innerText:"Division name: ",
}); });
yesBtn = createElement("span", { yesBtn = createElement("span", {
class:"popup-box-button", class:"popup-box-button",
@@ -905,7 +903,7 @@ export class CorporationEventHandler {
this.rerender(); this.rerender();
} }
return false; return false;
} },
}); });
const noBtn = createPopupCloseButton(popupId, { const noBtn = createPopupCloseButton(popupId, {
@@ -923,7 +921,7 @@ export class CorporationEventHandler {
// Have Agriculture be first as recommended option // Have Agriculture be first as recommended option
if (!ownedIndustries["Agriculture"]) { if (!ownedIndustries["Agriculture"]) {
selector.add(createElement("option", { selector.add(createElement("option", {
text:Industries["Agriculture"], value:"Agriculture" text:Industries["Agriculture"], value:"Agriculture",
})); }));
} }
@@ -964,8 +962,6 @@ export class CorporationEventHandler {
// Create a popup that lets the player use the Market TA research for Products // Create a popup that lets the player use the Market TA research for Products
createProductMarketTaPopup(product, industry) { createProductMarketTaPopup(product, industry) {
const corp = this.corp;
const popupId = "cmpy-mgmt-marketta-popup"; const popupId = "cmpy-mgmt-marketta-popup";
const markupLimit = product.rat / product.mku; const markupLimit = product.rat / product.mku;
const ta1 = createElement("p", { const ta1 = createElement("p", {
@@ -984,7 +980,7 @@ export class CorporationEventHandler {
for: useTa1AutoSaleId, for: useTa1AutoSaleId,
innerText: "Use Market-TA.I for Auto-Sale Price", innerText: "Use Market-TA.I for Auto-Sale Price",
tooltip: "If this is enabled, then this Product will automatically " + tooltip: "If this is enabled, then this Product will automatically " +
"be sold at the price identified by Market-TA.I (i.e. the price shown above)" "be sold at the price identified by Market-TA.I (i.e. the price shown above)",
}) })
const useTa1AutoSaleCheckbox = createElement("input", { const useTa1AutoSaleCheckbox = createElement("input", {
checked: product.marketTa1, checked: product.marketTa1,
@@ -993,7 +989,7 @@ export class CorporationEventHandler {
type: "checkbox", type: "checkbox",
changeListener: (e) => { changeListener: (e) => {
product.marketTa1 = e.target.checked; product.marketTa1 = e.target.checked;
} },
}); });
useTa1AutoSaleDiv.appendChild(useTa1AutoSaleLabel); useTa1AutoSaleDiv.appendChild(useTa1AutoSaleLabel);
useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox); useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox);
@@ -1043,7 +1039,7 @@ export class CorporationEventHandler {
tooltip: "If this is enabled, then this Product will automatically " + tooltip: "If this is enabled, then this Product will automatically " +
"be sold at the optimal price such that the amount sold matches the " + "be sold at the optimal price such that the amount sold matches the " +
"amount produced. (i.e. the highest possible price, while still ensuring " + "amount produced. (i.e. the highest possible price, while still ensuring " +
" that all produced materials will be sold)" " that all produced materials will be sold)",
}) })
const useTa2AutoSaleCheckbox = createElement("input", { const useTa2AutoSaleCheckbox = createElement("input", {
checked: product.marketTa2, checked: product.marketTa2,
@@ -1052,14 +1048,14 @@ export class CorporationEventHandler {
type: "checkbox", type: "checkbox",
changeListener: (e) => { changeListener: (e) => {
product.marketTa2 = e.target.checked; product.marketTa2 = e.target.checked;
} },
}); });
useTa2AutoSaleDiv.appendChild(useTa2AutoSaleLabel); useTa2AutoSaleDiv.appendChild(useTa2AutoSaleLabel);
useTa2AutoSaleDiv.appendChild(useTa2AutoSaleCheckbox); useTa2AutoSaleDiv.appendChild(useTa2AutoSaleCheckbox);
const ta2OverridesTa1 = createElement("p", { const ta2OverridesTa1 = createElement("p", {
innerText: "Note that Market-TA.II overrides Market-TA.I. This means that if " + innerText: "Note that Market-TA.II overrides Market-TA.I. This means that if " +
"both are enabled, then Market-TA.II will take effect, not Market-TA.I" "both are enabled, then Market-TA.II will take effect, not Market-TA.I",
}); });
createPopup(popupId, [ta1, useTa1AutoSaleDiv, ta2Text, ta2Input, useTa2AutoSaleDiv, ta2OverridesTa1, closeBtn]); createPopup(popupId, [ta1, useTa1AutoSaleDiv, ta2Text, ta2Input, useTa2AutoSaleDiv, ta2OverridesTa1, closeBtn]);
@@ -1076,7 +1072,7 @@ export class CorporationEventHandler {
const purchasePopupId = "cmpy-mgmt-material-purchase-popup"; const purchasePopupId = "cmpy-mgmt-material-purchase-popup";
const txt = createElement("p", { const txt = createElement("p", {
innerHTML: "Enter the amount of " + mat.name + " you would like " + innerHTML: "Enter the amount of " + mat.name + " you would like " +
"to purchase per second. This material's cost changes constantly" "to purchase per second. This material's cost changes constantly",
}); });
let confirmBtn; let confirmBtn;
let input = createElement("input", { let input = createElement("input", {
@@ -1087,7 +1083,7 @@ export class CorporationEventHandler {
onkeyup: (e) => { onkeyup: (e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();} if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
} },
}); });
confirmBtn = createElement("button", { confirmBtn = createElement("button", {
innerText: "Confirm", class: "std-button", innerText: "Confirm", class: "std-button",
@@ -1101,7 +1097,7 @@ export class CorporationEventHandler {
this.rerender(); this.rerender();
return false; return false;
} }
} },
}); });
const clearButton = createElement("button", { const clearButton = createElement("button", {
innerText: "Clear Purchase", class: "std-button", innerText: "Clear Purchase", class: "std-button",
@@ -1110,7 +1106,7 @@ export class CorporationEventHandler {
removeElementById(purchasePopupId); removeElementById(purchasePopupId);
this.rerender(); this.rerender();
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(purchasePopupId, { const cancelBtn = createPopupCloseButton(purchasePopupId, {
class: "std-button", class: "std-button",
@@ -1153,7 +1149,7 @@ export class CorporationEventHandler {
e.preventDefault(); e.preventDefault();
updateBulkPurchaseText(e.target.value); updateBulkPurchaseText(e.target.value);
if (e.keyCode === KEY.ENTER) {bulkPurchaseConfirmBtn.click();} if (e.keyCode === KEY.ENTER) {bulkPurchaseConfirmBtn.click();}
} },
}); });
bulkPurchaseConfirmBtn = createElement("button", { bulkPurchaseConfirmBtn = createElement("button", {
@@ -1184,7 +1180,7 @@ export class CorporationEventHandler {
removeElementById(purchasePopupId); removeElementById(purchasePopupId);
return false; return false;
} }
} },
}) })
elems.push(bulkPurchaseInfo); elems.push(bulkPurchaseInfo);
@@ -1224,7 +1220,7 @@ export class CorporationEventHandler {
onkeyup: (e) => { onkeyup: (e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();} if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
} },
}); });
let inputButtonInitValue = mat.sCost ? mat.sCost : null; let inputButtonInitValue = mat.sCost ? mat.sCost : null;
@@ -1241,7 +1237,7 @@ export class CorporationEventHandler {
onkeyup: (e) => { onkeyup: (e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();} if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
} },
}); });
confirmBtn = createElement("button", { confirmBtn = createElement("button", {
class: "std-button", class: "std-button",
@@ -1307,7 +1303,7 @@ export class CorporationEventHandler {
removeElementById(sellPopupId); removeElementById(sellPopupId);
this.rerender(); this.rerender();
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(sellPopupId, { const cancelBtn = createPopupCloseButton(sellPopupId, {
class: "std-button", class: "std-button",
@@ -1347,7 +1343,7 @@ export class CorporationEventHandler {
onkeyup: (e) => { onkeyup: (e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();} if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
} },
}); });
let inputButtonInitValue = product.sCost ? product.sCost : null; let inputButtonInitValue = product.sCost ? product.sCost : null;
@@ -1365,7 +1361,7 @@ export class CorporationEventHandler {
onkeyup: (e) => { onkeyup: (e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();} if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
} },
}); });
const checkboxDiv = createElement("div", { const checkboxDiv = createElement("div", {
border: "1px solid white", border: "1px solid white",
@@ -1478,7 +1474,7 @@ export class CorporationEventHandler {
removeElementById(popupId); removeElementById(popupId);
this.rerender(); this.rerender();
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { class: "std-button" }); const cancelBtn = createPopupCloseButton(popupId, { class: "std-button" });
@@ -1515,12 +1511,10 @@ export class CorporationEventHandler {
} else { } else {
const stockSaleResults = this.corp.calculateShareSale(numShares); const stockSaleResults = this.corp.calculateShareSale(numShares);
const profit = stockSaleResults[0]; const profit = stockSaleResults[0];
const newSharePrice = stockSaleResults[1];
const newSharesUntilUpdate = stockSaleResults[2];
profitIndicator.innerText = "Sell " + numShares + " shares for a total of " + profitIndicator.innerText = "Sell " + numShares + " shares for a total of " +
numeralWrapper.format(profit, '$0.000a'); numeralWrapper.format(profit, '$0.000a');
} }
} },
}); });
const confirmBtn = createElement("button", { const confirmBtn = createElement("button", {
class:"a-link-button", innerText:"Sell shares", display:"inline-block", class:"a-link-button", innerText:"Sell shares", display:"inline-block",
@@ -1562,7 +1556,7 @@ export class CorporationEventHandler {
return false; return false;
} }
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { const cancelBtn = createPopupCloseButton(popupId, {
class: "std-button", class: "std-button",
@@ -1579,10 +1573,10 @@ export class CorporationEventHandler {
const popupId = "cmpy-mgmt-throw-office-party-popup"; const popupId = "cmpy-mgmt-throw-office-party-popup";
const txt = createElement("p", { const txt = createElement("p", {
innerText:"Enter the amount of money you would like to spend PER EMPLOYEE " + innerText:"Enter the amount of money you would like to spend PER EMPLOYEE " +
"on this office party" "on this office party",
}); });
const totalCostTxt = createElement("p", { const totalCostTxt = createElement("p", {
innerText:"Throwing this party will cost a total of $0" innerText:"Throwing this party will cost a total of $0",
}); });
let confirmBtn; let confirmBtn;
const input = createElement("input", { const input = createElement("input", {
@@ -1598,7 +1592,7 @@ export class CorporationEventHandler {
onkeyup:(e)=>{ onkeyup:(e)=>{
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();} if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
} },
}); });
confirmBtn = createElement("button", { confirmBtn = createElement("button", {
class: "std-button", class: "std-button",
@@ -1622,7 +1616,7 @@ export class CorporationEventHandler {
} }
} }
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { class: "std-button", innerText: "Cancel" }); const cancelBtn = createPopupCloseButton(popupId, { class: "std-button", innerText: "Cancel" });
@@ -1661,7 +1655,7 @@ export class CorporationEventHandler {
const upgradeCostMax = OfficeInitialCost * mult; const upgradeCostMax = OfficeInitialCost * mult;
const text = createElement("p", { const text = createElement("p", {
innerText:"Increase the size of your office space to fit additional employees!" innerText:"Increase the size of your office space to fit additional employees!",
}); });
const text2 = createElement("p", { innerText: "Upgrade size: " }); const text2 = createElement("p", { innerText: "Upgrade size: " });
@@ -1680,7 +1674,7 @@ export class CorporationEventHandler {
} }
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} },
}); });
const confirmBtn15 = createElement("button", { const confirmBtn15 = createElement("button", {
class: this.corp.funds.lt(upgradeCost15) ? "a-link-button-inactive" : "a-link-button", class: this.corp.funds.lt(upgradeCost15) ? "a-link-button-inactive" : "a-link-button",
@@ -1697,7 +1691,7 @@ export class CorporationEventHandler {
} }
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} },
}); });
const confirmBtnMax = createElement("button", { const confirmBtnMax = createElement("button", {
class:this.corp.funds.lt(upgradeCostMax) ? "a-link-button-inactive" : "a-link-button", class:this.corp.funds.lt(upgradeCostMax) ? "a-link-button-inactive" : "a-link-button",
@@ -1714,7 +1708,7 @@ export class CorporationEventHandler {
} }
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" }); const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" });
cancelBtn.style.margin = "4px"; cancelBtn.style.margin = "4px";

Some files were not shown because too many files have changed in this diff Show More