Compare commits

...

140 Commits

Author SHA1 Message Date
Olivier Gagnon
b28f607056 v0.51.9 2021-05-17 23:59:45 -04:00
Olivier Gagnon
218a9dd250 Sleeves earnings is now tracked in Character Stats Money 2021-05-17 22:03:48 -04:00
Olivier Gagnon
7a1fdd6c28 Merge branch 'dev' of github.com:danielyxie/bitburner into dev 2021-05-17 22:03:27 -04:00
Olivier Gagnon
b69a262faf ls no longer prints lingering newline 2021-05-17 21:58:11 -04:00
hydroflame
66c87b1f64 Merge pull request #673 from danielyxie/dependabot/npm_and_yarn/jquery-3.5.0
Bump jquery from 3.3.1 to 3.5.0
2021-05-17 21:51:00 -04:00
hydroflame
9bc1a4a895 Merge pull request #671 from danielyxie/dependabot/npm_and_yarn/acorn-6.4.1
Bump acorn from 6.2.0 to 6.4.1
2021-05-17 21:45:40 -04:00
dependabot[bot]
7a0d0b3fec Bump jquery from 3.3.1 to 3.5.0
Bumps [jquery](https://github.com/jquery/jquery) from 3.3.1 to 3.5.0.
- [Release notes](https://github.com/jquery/jquery/releases)
- [Commits](https://github.com/jquery/jquery/compare/3.3.1...3.5.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-18 01:26:20 +00:00
dependabot[bot]
dd077152f4 Bump acorn from 6.2.0 to 6.4.1
Bumps [acorn](https://github.com/acornjs/acorn) from 6.2.0 to 6.4.1.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/6.2.0...6.4.1)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-18 01:20:42 +00:00
hydroflame
2347e0b1fd Merge pull request #956 from danielyxie/dependabot/npm_and_yarn/codemirror-5.58.2
Bump codemirror from 5.43.0 to 5.58.2
2021-05-17 21:19:48 -04:00
Olivier Gagnon
188dcbad89 bladeburner supress option now correctly updates when blade become accessible/unaccessible 2021-05-17 21:17:17 -04:00
hydroflame
eb7004feaa Merge pull request #959 from MartinFournier/suppress-bladeburner-popup
Add setting to suppress Bladeburner prompts
2021-05-17 21:09:21 -04:00
Olivier Gagnon
062cd2dc38 update changelog 2021-05-17 21:08:29 -04:00
hydroflame
2f3e5c79e7 Merge pull request #954 from Daniferrito/bladeburner-fixes
Bladeburner fixes
2021-05-17 21:05:19 -04:00
Olivier Gagnon
bd172434d1 Fixed an issue where bladeburner would miscalculate hospitalization cost. 2021-05-17 20:18:05 -04:00
Olivier Gagnon
afc1347d3a Deleting a file without ext print a normal error msg. 2021-05-17 18:09:47 -04:00
Olivier Gagnon
b9c292f7cf Can no longer export negative amount 2021-05-17 18:04:10 -04:00
Olivier Gagnon
6df824613e Fix more bugs 2021-05-17 18:00:22 -04:00
Olivier Gagnon
de113a7b92 City hall no longer just has nothing when you can't create corp 2021-05-17 17:56:31 -04:00
Olivier Gagnon
4ec14460b6 more fixes 2021-05-17 17:49:39 -04:00
Olivier Gagnon
3f63d91448 Merge branch 'dev' of github.com:danielyxie/bitburner into dev 2021-05-17 17:12:37 -04:00
Olivier Gagnon
2ae9a3d2a7 fix fconf not being created and fix formatting in netscript functions 2021-05-17 17:12:35 -04:00
Martin Fournier
ae04b7357e Add setting to suppress Bladeburner popups
Used to suppress the message that is shown when your Bladeburner action
is cancelled when busy with something else.

Will be hidden if the player does not have access to Bladeburners.
2021-05-15 13:33:30 -04:00
hydroflame
bf141c7eb0 Merge pull request #958 from Daniferrito/dynamic-possibleLogs
Added dynamic generation of functionNames
2021-05-15 11:23:42 -04:00
Olivier Gagnon
1503d82e35 update changelog 2021-05-15 11:19:02 -04:00
hydroflame
a75efd9c62 Merge pull request #955 from Daniferrito/import-autoreload
Import autoreload
2021-05-15 11:16:24 -04:00
Olivier Gagnon
299e964e2b update changelog 2021-05-15 11:09:32 -04:00
hydroflame
69fbfe87c0 Merge branch 'dev' into import-autoreload 2021-05-15 11:08:36 -04:00
hydroflame
60a229030b Merge pull request #951 from Daniferrito/aliases
Recursive and multi-command alias
2021-05-15 11:06:06 -04:00
Olivier Gagnon
e27b19ffae update changelog 2021-05-15 11:05:52 -04:00
Olivier Gagnon
5e2c40ea23 Merge branch 'dev' of github.com:danielyxie/bitburner into dev 2021-05-15 10:56:00 -04:00
Olivier Gagnon
8411de8e42 remove offline calc from importing game 2021-05-15 10:54:19 -04:00
Daniel Ferri
525c0ada55 Added dynamic generation of functionNames 2021-05-12 21:10:36 +02:00
hydroflame
0e06565e27 Merge pull request #953 from MartinFournier/docker-support
Add basic docker support for development
2021-05-12 00:29:36 -04:00
dependabot[bot]
5e517d1671 Bump codemirror from 5.43.0 to 5.58.2
Bumps [codemirror](https://github.com/codemirror/CodeMirror) from 5.43.0 to 5.58.2.
- [Release notes](https://github.com/codemirror/CodeMirror/releases)
- [Changelog](https://github.com/codemirror/CodeMirror/blob/master/CHANGELOG.md)
- [Commits](https://github.com/codemirror/CodeMirror/compare/5.43.0...5.58.2)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-12 00:32:31 +00:00
Daniel Ferri
1b57c1f7e0 Changed loops to be more concise 2021-05-11 20:16:18 +02:00
Daniel Ferri
0cb2fd1a87 Removed useless code 2021-05-11 19:46:51 +02:00
Daniel Ferri
08b0c7710d Changed import so it saves and reloads the page 2021-05-11 19:27:02 +02:00
Daniel Ferri
f8a085af7a Autofocus the input when opening a "Set Team Size" popup 2021-05-11 15:34:05 +02:00
Daniel Ferri
c95a926154 Add overflow time of bladeburner updates to the next update 2021-05-11 15:32:43 +02:00
Olivier Gagnon
5af10c8406 Offline money gain is based off hacking exp / time since last aug instead 2021-05-10 20:11:03 -04:00
Olivier Gagnon
0f2b7517b4 Added export bonus 2021-05-10 18:26:50 -04:00
Martin Fournier
ac8565d820 Add basic docker support for development
Assuming docker engine is installed, it is now possible to run the dev
server using 'docker-compose up --build' or run the production version using
'docker build -t bitburner . && docker run -it -p 8000:80 bitburner'.
2021-05-10 08:54:25 -04:00
Olivier Gagnon
2bd4892fa8 hotfix ls not listing all files lol 2021-05-08 22:38:48 -04:00
Daniel Ferri
46862d30fd Recursive and multi-command alias 2021-05-08 18:44:21 +02:00
Olivier Gagnon
f6af61d15b hotfix ls printing a bunch of newlines 2021-05-07 22:37:50 -04:00
Olivier Gagnon
04e8bc944e build 2021-05-07 22:29:18 -04:00
Olivier Gagnon
d96ad9fa6e v0.51.8 2021-05-07 22:26:02 -04:00
Olivier Gagnon
5dd32ef4e4 Scripts transfer stats to parent on death. 2021-05-07 22:01:52 -04:00
Olivier Gagnon
6dde89f3c4 0518 2021-05-07 22:01:52 -04:00
Olivier Gagnon
9a9d2e1f81 ls-changes 2021-05-07 22:01:23 -04:00
Pimvgd
d347bf568e Update Overview.jsx
fix space
2021-05-07 19:34:57 -04:00
Daniel Ferri
62e2f0582a Fixed bug with faction invitations not getting deleted 2021-05-07 19:12:30 -04:00
Daniel Ferri
68eb68a89e Added accepting numbers in 1b format to faction donations 2021-05-07 19:12:30 -04:00
Daniel Ferri
13206a8c3e Fixed casing on import
Did not want to compile without the change
2021-05-07 19:12:30 -04:00
Olivier Gagnon
cfd78e2d36 Add installBackdoor 2021-05-07 02:14:46 -04:00
Olivier Gagnon
8b7f140115 Merge branch 'dev' of github.com:danielyxie/bitburner into dev 2021-05-07 02:14:34 -04:00
Olivier Gagnon
16c8c78b54 Add installBackdoor 2021-05-07 02:13:33 -04:00
Olivier Gagnon
cbb47772db Add installBackdoor 2021-05-07 02:09:30 -04:00
Olivier Gagnon
0642491402 hotfix backdooring the world daemon not resetting flags 2021-05-06 11:12:41 -04:00
Olivier Gagnon
c7e34d4a56 hotfix backdooring the world daemon not resetting flags 2021-05-06 11:12:04 -04:00
hydroflame
8be63be17b Merge pull request #942 from danielyxie/dev
Another build for the quick and easy stuff.
2021-05-05 21:40:14 -04:00
Olivier Gagnon
08207ac79b another build 2021-05-05 21:39:48 -04:00
Olivier Gagnon
6747a509ff Reword the Milestones 2021-05-05 21:36:43 -04:00
Olivier Gagnon
c7c86240db Faction Donation does not appear on special or gang factions, passive rep doesnt work on gang or special factions 2021-05-05 21:32:06 -04:00
hydroflame
ce0c3d71f4 Merge pull request #941 from danielyxie/dev
hotfix for some stuff
2021-05-05 21:07:09 -04:00
Olivier Gagnon
5bb6a72c90 build 2021-05-05 21:02:54 -04:00
hydroflame
5a06c60c27 Merge pull request #940 from danielyxie/0517-2
0517 hotfix
2021-05-05 21:00:14 -04:00
Olivier Gagnon
764c2533b4 hashGainRate updated to use the correct usedRam and maxRam 2021-05-05 19:18:47 -04:00
Olivier Gagnon
a9cee6f907 Fix analyze Root Access displaying always Yes 2021-05-05 19:15:56 -04:00
Olivier Gagnon
a10100bf60 You cna now cd in dir that only contain text files. 2021-05-05 19:09:14 -04:00
Olivier Gagnon
cedac23dfa CodingContractPopup now correctly displays innerHTML, desc should be changed to return jsx though. 2021-05-05 19:06:08 -04:00
Olivier Gagnon
f7c1d64033 Delete Active Scripts actually deletes active scripts on all servers, not just home 2021-05-05 18:58:53 -04:00
hydroflame
7d6d0eac32 Merge pull request #939 from ModdedGamers/dev
Make it clear that maxNumNodes returns Infinity
2021-05-05 11:03:22 -04:00
Modded Gamers
34768591b7 Make it clear that maxNumNodes returns Infinity
this function returns Infinity in some cases, so this makes that clearer.
2021-05-05 10:00:16 -04:00
Daniel Xie
827c79f70c Add build for hotfix 2021-05-05 04:31:54 -07:00
Daniel Xie
0415c7aa7c Give NeuroFlux for SF-12 before re-calculating multipliers 2021-05-05 04:23:10 -07:00
hydroflame
0c744d98b9 Merge pull request #933 from danielyxie/dev
* .ns script no longer needlessly recompile
* scping the exact same content over doesn't trigger an actual scp
* world daemon can be backdoored
* Coding contract title is click-to-copy
* Sleeve memory covenant upgrade reacts better.
2021-05-03 19:54:31 -04:00
Olivier Gagnon
11cbda6974 build 2021-05-03 19:54:11 -04:00
Olivier Gagnon
e284f49747 Covenant sleeve memory upgrade styling and more reactive text field 2021-05-03 19:52:19 -04:00
Olivier Gagnon
7777c400a5 Make coding contract title click-to-copy 2021-05-03 19:46:04 -04:00
Olivier Gagnon
dae0448744 world daemon can now be backdoored 2021-05-03 19:00:01 -04:00
Olivier Gagnon
02a4e85353 Build nsjs recompile hotfix 2021-05-03 18:54:54 -04:00
hydroflame
3cbf225c98 Fix script needlessly being recompiled (#932)
* Fix nsjs recompiling needlesly.
2021-05-03 18:53:10 -04:00
hydroflame
8006e976a5 Merge pull request #929 from danielyxie/dev
Fix research tree not appearing
2021-05-03 18:25:04 -04:00
Olivier Gagnon
5613d371c9 Fix research tree not appearing 2021-05-03 18:24:22 -04:00
hydroflame
7c9d6669f7 Merge pull request #928 from danielyxie/dev
Hotfix Mission.jsx fake unused import
2021-05-03 17:25:19 -04:00
Olivier Gagnon
c6f0551709 Hotfix Mission.jsx fake unused import 2021-05-03 17:24:39 -04:00
hydroflame
f57eed4de1 Merge pull request #926 from danielyxie/dev
Hotfix
2021-05-03 16:03:12 -04:00
Olivier Gagnon
b99711788f Hotfix negative money, n00dles metadata and guide 2021-05-03 16:02:26 -04:00
Olivier Gagnon
08aac8e35d change noodles metadata. 2021-05-03 12:56:27 -04:00
hydroflame
e3579b7229 Merge pull request #925 from danielyxie/dev
did I forget the build again?
2021-05-03 12:27:21 -04:00
Olivier Gagnon
662d0dd5fb did I forget the build again 2021-05-03 12:26:37 -04:00
hydroflame
77c40b5d67 Merge pull request #924 from danielyxie/dev
Forgot to push the build
2021-05-03 12:21:28 -04:00
Olivier Gagnon
ee759a8dd6 Merge branch 'dev' of github.com:danielyxie/bitburner into dev 2021-05-03 12:20:54 -04:00
hydroflame
ad9c7ec696 Merge pull request #923 from danielyxie/dev
0.51.7
2021-05-03 12:18:18 -04:00
Olivier Gagnon
c9b5aaa2f7 v0.51.7 2021-05-03 12:17:05 -04:00
hydroflame
b554328a77 Merge pull request #915 from danielyxie/noodles
Noodles
2021-05-03 12:01:39 -04:00
Olivier Gagnon
c421c57e56 address comments. 2021-05-03 11:58:11 -04:00
hydroflame
fb42d5cd79 Merge pull request #918 from Pimvgd/patch-4
typo fixes for blackops
2021-05-03 02:26:47 -04:00
hydroflame
6203d8d6f4 Merge pull request #919 from Daniferrito/patch-2
Update ps documentation
2021-05-03 02:21:22 -04:00
Olivier Gagnon
d422028737 analyze and ServerProfiler.exe handle hacknet servers better. 2021-05-03 02:20:31 -04:00
Olivier Gagnon
136d769d55 Change faction invitation Yes,No to say Join and Decide later 2021-05-03 02:01:45 -04:00
Olivier Gagnon
daaab1d6f1 Fix forgotten text for Source-File 12 2021-05-03 01:55:04 -04:00
Olivier Gagnon
4f7befb639 Fix miscalculation of source file flags on the bitverse screen. 2021-05-03 01:50:09 -04:00
Olivier Gagnon
9976ed136c fix money formatting for amount under 1000 2021-05-03 01:44:02 -04:00
Olivier Gagnon
8c2e661e08 Remove console.log 2021-05-03 01:41:16 -04:00
Olivier Gagnon
e6e598eeb4 moved augmentations between city faction to be more even. 2021-05-03 01:40:22 -04:00
Olivier Gagnon
4d9439a007 Added getServerMaxRam and getServerUsedRam, deprecated getServerRam 2021-05-03 01:07:46 -04:00
Olivier Gagnon
9951c8b18f Fix mistake in hacknet API example 2021-05-03 00:51:12 -04:00
Olivier Gagnon
800c673839 Fix character-overview-text being nested twice. 2021-05-03 00:47:56 -04:00
Olivier Gagnon
065544909b thread count formatted with commas every thousands. 2021-05-03 00:45:21 -04:00
Olivier Gagnon
4eaf68c940 Donation is always visible but locked before favor requirements are fulfilled. 2021-05-03 00:37:53 -04:00
Olivier Gagnon
a14a694df3 Fix sleeves not being to work out at volhaven 2021-05-03 00:27:12 -04:00
Dani
3ab61cbaf3 Update ps documentation 2021-05-02 23:48:20 +02:00
Pimvgd
f49aff05d7 typo fixes for blackops 2021-05-02 23:44:59 +02:00
hydroflame
e2371a0ef6 Merge pull request #917 from Daniferrito/patch-1
Fixed #916
2021-05-02 17:38:47 -04:00
Dani
6a2b3ee52e Fixed #916 2021-05-02 23:37:09 +02:00
Olivier Gagnon
5a45e3584d Formatted time in netscript hgw display in human time, milliFormat now displays milli sometimes 2021-05-02 01:04:49 -04:00
Olivier Gagnon
56ce83cce5 Fix cashroot not displaying properly 2021-05-02 00:07:04 -04:00
Olivier Gagnon
d126b6d8c5 Fix sf minus 1 bad constant 2021-05-01 23:44:23 -04:00
Olivier Gagnon
7172ef6dae SF12 now lets player start with Neuroflux 2021-05-01 23:42:52 -04:00
Olivier Gagnon
a8d0b6e13d Tail now accepts PID 2021-05-01 23:33:44 -04:00
Olivier Gagnon
d2d6453a78 quick b1tflum3 2021-05-01 23:23:04 -04:00
Olivier Gagnon
89cdecb05f getBitnodeMultipliers is available inside BN5 2021-05-01 23:08:51 -04:00
Olivier Gagnon
81fdff9068 Revert tutorial servers and add the n00dles server. 2021-05-01 23:08:51 -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
hydroflame
b2ac383b69 Merge pull request #909 from danielyxie/dev
When you hotfix you need to build
2021-04-29 13:41:48 -04:00
Olivier Gagnon
77cb63e36a When you hotfix you need to build 2021-04-29 13:41:13 -04:00
hydroflame
7df4aac8e6 Merge pull request #908 from danielyxie/dev
hotfix netscript access to formulas and getServer
2021-04-29 13:39:35 -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
346 changed files with 4655 additions and 4151 deletions

14
.dockerignore Normal file
View File

@@ -0,0 +1,14 @@
node_modules/
.git
.gitattributes
.gitignore
.editorconfig
.dockerignore
Dockerfile
docker-compose.yml
*.md
Quotes.txt
netscript_tests/

View File

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

View File

@@ -76,7 +76,7 @@ module.exports = {
"imports": "always-multiline",
"exports": "always-multiline",
"functions": "always-multiline",
}
},
],
"comma-spacing": [
"off",
@@ -102,14 +102,14 @@ module.exports = {
"error",
],
"curly": [
"off"
"off",
],
"default-case": [
"off"
"off",
],
"dot-location": [
"error",
"property"
"property",
],
"dot-notation": [
"off",
@@ -310,104 +310,104 @@ module.exports = {
"error",
],
"no-div-regex": [
"error"
"error",
],
"no-dupe-args": [
"error"
"error",
],
"no-dupe-class-members": [
"error"
"error",
],
"no-dupe-keys": [
"error"
"error",
],
"no-duplicate-case": [
"error"
"error",
],
"no-duplicate-imports": [
"error",
{
"includeExports": true
}
"includeExports": true,
},
],
"no-else-return": [
"off"
"off",
],
"no-empty": [
"off",
{
"allowEmptyCatch": false
}
"allowEmptyCatch": false,
},
],
"no-empty-character-class": [
"error"
"error",
],
"no-empty-function": [
"off"
"off",
],
"no-empty-pattern": [
"error"
"error",
],
"no-eq-null": [
"off"
"off",
],
"no-ex-assign": [
"off"
"off",
],
"no-extra-boolean-cast": [
"error"
"error",
],
"no-extra-parens": [
"off"
"off",
],
"no-extra-semi": [
"off"
"off",
],
"no-eval": [
"off"
"off",
],
"no-extend-native": [
"off"
"off",
],
"no-extra-bind": [
"error"
"error",
],
"no-extra-label": [
"error"
"error",
],
"no-fallthrough": [
"off"
"off",
],
"no-floating-decimal": [
"off"
"off",
],
"no-func-assign": [
"error"
"error",
],
"no-global-assign": [
"error"
"error",
],
"no-implicit-coercion": [
"off"
"off",
],
"no-implicit-globals": [
"error"
"error",
],
"no-implied-eval": [
"error"
"error",
],
"no-inline-comments": [
"off"
"off",
],
"no-inner-declarations": [
"off",
"both"
"both",
],
"no-invalid-regexp": [
"error"
"error",
],
"no-invalid-this": [
"off"
"off",
],
"no-irregular-whitespace": [
"error",
@@ -415,451 +415,461 @@ module.exports = {
"skipStrings": false,
"skipComments": false,
"skipRegExps": false,
"skipTemplates": false
}
"skipTemplates": false,
},
],
"no-iterator": [
"error"
"error",
],
"no-label-var": [
"error"
"error",
],
"no-labels": [
"off"
"off",
],
"no-lone-blocks": [
"error"
"error",
],
"no-lonely-if": [
"off"
"off",
],
"no-loop-func": [
"off"
"off",
],
"no-magic-numbers": [
"off"
"off",
],
"no-mixed-operators": [
"off"
"off",
],
"no-mixed-requires": [
"error"
"error",
],
"no-mixed-spaces-and-tabs": [
"off"
"off",
],
"no-multi-assign": [
"off"
"off",
],
"no-multi-spaces": [
"off"
"off",
],
"no-multi-str": [
"error"
"error",
],
"no-multiple-empty-lines": [
"off",
{
"max": 1
}
"max": 1,
},
],
"no-native-reassign": [
"error"
"error",
],
"no-negated-condition": [
"off"
"off",
],
"no-negated-in-lhs": [
"error"
"error",
],
"no-nested-ternary": [
"off"
"off",
],
"no-new": [
"error"
"error",
],
"no-new-func": [
"error"
"error",
],
"no-new-object": [
"error"
"error",
],
"no-new-require": [
"error"
"error",
],
"no-new-symbol": [
"error"
"error",
],
"no-new-wrappers": [
"error"
"error",
],
"no-octal": [
"error"
"error",
],
"no-octal-escape": [
"error"
"error",
],
"no-obj-calls": [
"error"
"error",
],
"no-param-reassign": [
"off"
"off",
],
"no-path-concat": [
"error"
"error",
],
"no-plusplus": [
"off"
"off",
],
"no-process-env": [
"off"
"off",
],
"no-process-exit": [
"error"
"error",
],
"no-proto": [
"error"
"error",
],
"no-prototype-builtins": [
"off"
"off",
],
"no-redeclare": [
"off"
"off",
],
"no-regex-spaces": [
"error"
"error",
],
"no-restricted-globals": [
"error"
"error",
],
"no-restricted-imports": [
"error"
"error",
],
"no-restricted-modules": [
"error"
"error",
],
"no-restricted-properties": [
"off",
{
"object": "console",
"property": "log",
"message": "'log' is too general, use an appropriate level when logging."
}
"message": "'log' is too general, use an appropriate level when logging.",
},
],
"no-restricted-syntax": [
"error"
"error",
],
"no-return-assign": [
"off"
"off",
],
"no-return-await": [
"error"
"error",
],
"no-script-url": [
"error"
"error",
],
"no-self-assign": [
"error",
{
"props": false
}
"props": false,
},
],
"no-self-compare": [
"error"
"error",
],
"no-sequences": [
"error"
"error",
],
"no-shadow": [
"off"
"off",
],
"no-shadow-restricted-names": [
"error"
"error",
],
"no-spaced-func": [
"off"
"off",
],
"no-sparse-arrays": [
"error"
"error",
],
"no-sync": [
"error"
"error",
],
"no-tabs": [
"off"
"off",
],
"no-template-curly-in-string": [
"error"
"error",
],
"no-ternary": [
"off"
"off",
],
"no-this-before-super": [
"off"
"off",
],
"no-throw-literal": [
"error"
"error",
],
"no-trailing-spaces": [
"off"
"off",
],
"no-undef": [
"off"
"off",
],
"no-undef-init": [
"error"
"error",
],
"no-undefined": [
"off"
"off",
],
"no-underscore-dangle": [
"off"
"off",
],
"no-unexpected-multiline": [
"error"
"error",
],
"no-unmodified-loop-condition": [
"error"
"error",
],
"no-unneeded-ternary": [
"off"
"off",
],
"no-unreachable": [
"off"
"off",
],
"no-unsafe-finally": [
"error"
"error",
],
"no-unsafe-negation": [
"error"
"error",
],
"no-unused-expressions": [
"off"
"off",
],
"no-unused-labels": [
"error"
"error",
],
"no-unused-vars": [
"off"
"off",
],
"no-use-before-define": [
"off"
"off",
],
"no-useless-call": [
"off"
"off",
],
"no-useless-computed-key": [
"error"
"error",
],
"no-useless-concat": [
"off"
"off",
],
"no-useless-constructor": [
"error"
"error",
],
"no-useless-escape": [
"off"
"off",
],
"no-useless-rename": [
"error",
{
"ignoreDestructuring": false,
"ignoreExport": false,
"ignoreImport": false
}
"ignoreImport": false,
},
],
"no-useless-return": [
"off"
"off",
],
"no-var": [
"off"
"off",
],
"no-void": [
"off"
"off",
],
"no-warning-comments": [
"off"
"off",
],
"no-whitespace-before-property": [
"error"
"error",
],
"no-with": [
"error"
"error",
],
"nonblock-statement-body-position": [
"off",
"below"
"below",
],
"object-curly-newline": [
"off"
"off",
],
"object-curly-spacing": [
"off"
"off",
],
"object-property-newline": [
"off"
"off",
],
"object-shorthand": [
"off"
"off",
],
"one-var": [
"off"
"off",
],
"one-var-declaration-per-line": [
"off"
"off",
],
"operator-assignment": [
"off"
"off",
],
"operator-linebreak": [
"off",
"none"
"none",
],
"padded-blocks": [
"off"
"off",
],
"padding-line-between-statements": [
"error"
"error",
],
"prefer-arrow-callback": [
"off"
"off",
],
"prefer-const": [
"off"
"off",
],
"prefer-destructuring": [
"off"
"off",
],
"prefer-numeric-literals": [
"error"
"error",
],
"prefer-promise-reject-errors": [
"off"
"off",
],
"prefer-reflect": [
"off"
"off",
],
"prefer-rest-params": [
"off"
"off",
],
"prefer-spread": [
"off"
"off",
],
"prefer-template": [
"off"
"off",
],
"quote-props": [
"off"
"off",
],
"quotes": [
"off"
"off",
],
"radix": [
"off",
"as-needed"
"as-needed",
],
"require-await": [
"off"
"off",
],
"require-jsdoc": [
"off"
"off",
],
"require-yield": [
"error"
"error",
],
"rest-spread-spacing": [
"error",
"never"
"never",
],
"semi": [
"off"
"off",
],
"semi-spacing": [
"off"
"off",
],
"semi-style": [
"error",
"last"
"last",
],
"sort-imports": [
"off"
"off",
],
"sort-keys": [
"off"
"off",
],
"sort-vars": [
"off"
"off",
],
"space-before-blocks": [
"off"
"off",
],
"space-before-function-paren": [
"off"
"off",
],
"space-in-parens": [
"off"
"off",
],
"space-infix-ops": [
"off"
"off",
],
"space-unary-ops": [
"off"
"off",
],
"spaced-comment": [
"off"
"off",
],
"strict": [
"off"
"off",
],
"switch-colon-spacing": [
"error",
{
"after": true,
"before": false
}
"before": false,
},
],
"symbol-description": [
"error"
"error",
],
"template-curly-spacing": [
"error"
"error",
],
"template-tag-spacing": [
"error"
"error",
],
"unicode-bom": [
"error",
"never"
"never",
],
"use-isnan": [
"error"
"error",
],
"valid-jsdoc": [
"off"
"off",
],
"valid-typeof": [
"error"
"error",
],
"vars-on-top": [
"off"
"off",
],
"wrap-iife": [
"error",
"any"
"any",
],
"wrap-regex": [
"off"
"off",
],
"yield-star-spacing": [
"error",
"before"
"before",
],
"yoda": [
"error",
"never"
]
"never",
],
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/explicit-function-return-type": "off",
},
"overrides": [
{
// enable the rule specifically for TypeScript files
"files": ["*.ts", "*.tsx"],
"rules": {
"@typescript-eslint/explicit-function-return-type": ["error"],
"@typescript-eslint/explicit-module-boundary-types": ["error"],
},
},
{
// TypeScript configuration
"files": [ "**/*.ts", "**/*.tsx" ],
@@ -888,7 +898,7 @@ module.exports = {
"singleline": {
"delimiter": "semi",
"requireLast": false,
}
},
}],
"@typescript-eslint/member-ordering": ["error", {
"default": [
@@ -900,11 +910,11 @@ module.exports = {
"instance-method",
"abstract-method",
"static-method",
]
],
}],
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-use-before-define": "off",
}
}
]
},
},
],
};

35
Dockerfile Normal file
View File

@@ -0,0 +1,35 @@
FROM node:15.14.0 AS base
WORKDIR /app
# Scripts used in the npm preinstall hook
COPY scripts/engines-check.js scripts/semver.js scripts/
# Adding our dependencies and install before adding the rest of the files
# This prevents reinstallation of npm packages for every subsequent code modification
ENV npm_config_update_notifier=false
COPY package.json package-lock.json ./
RUN npm ci --loglevel=error --no-audit --no-fund && npm rebuild node-sass
# Adding all the remaining source files
COPY . .
# We need more than the default 512MB otherwise webpack will throw 'heap out of memory' exceptions
# https://nodejs.org/api/cli.html#cli_max_old_space_size_size_in_megabytes
ENV NODE_OPTIONS=--max-old-space-size=1536
FROM base AS dev
# This is the main development build using the file watcher if you mount volumes
USER node
EXPOSE 8000
CMD npm run start:container
FROM base AS prod-dist
# We'll simply build the production dist files here to later reuse in a simple webserver
RUN npm run build
FROM nginx:1.20.0-alpine AS prod
WORKDIR /usr/share/nginx/html
COPY --from=prod-dist /app/dist ./dist
COPY --from=prod-dist /app/index.html /app/favicon.ico /app/license.txt ./
EXPOSE 80

View File

@@ -1,24 +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;
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;
font-size:15pt;
font-family: sans-serif;
}
.casino-card.red {
color: red;
color: red;
}
.casino-card.black {
color: black;
}
color: black;
}

View File

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

View File

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

View File

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

2
css/grid.min.css vendored

File diff suppressed because one or more lines are too long

View File

@@ -2,4 +2,4 @@
position: fixed;
padding: 6px;
width: 60%;
}
}

View File

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

View File

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

View File

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

View File

@@ -375,7 +375,7 @@ a:visited {
}
.noscrollbar::-webkit-scrollbar {
display: none;
display: none;
}
input[type=checkbox] {
@@ -383,42 +383,42 @@ input[type=checkbox] {
}
.optionCheckbox {
margin: 5px;
float: right;
margin: 5px;
float: right;
}
.optionRange {
-webkit-appearance: none;
background: #777;
outline: none;
opacity: 0.7;
height: 10px;
-webkit-transition: .2s;
transition: opacity .2s;
margin: 3px;
-webkit-appearance: none;
background: #777;
outline: none;
opacity: 0.7;
height: 10px;
-webkit-transition: 0.2s;
transition: opacity 0.2s;
margin: 3px;
}
.optionRange::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 10px;
height: 10px;
background: var(--my-font-color);
cursor: pointer;
-webkit-appearance: none;
appearance: none;
width: 10px;
height: 10px;
background: var(--my-font-color);
cursor: pointer;
}
.optionRange::-moz-range-thumb {
width: 10px;
height: 10px;
background: var(--my-font-color);
cursor: pointer;
width: 10px;
height: 10px;
background: var(--my-font-color);
cursor: pointer;
}
.noselect {
-moz-user-select: -moz-none;
-khtml-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
-moz-user-select: -moz-none;
-khtml-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}

View File

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

View File

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

File diff suppressed because one or more lines are too long

238
dist/engineStyle.css vendored
View File

@@ -385,8 +385,8 @@ input[type=checkbox] {
outline: none;
opacity: 0.7;
height: 10px;
-webkit-transition: .2s;
transition: opacity .2s;
-webkit-transition: 0.2s;
transition: opacity 0.2s;
margin: 3px; }
.optionRange::-webkit-slider-thumb {
@@ -1027,7 +1027,7 @@ button {
*/
#codemirror-form-wrapper {
height: 80%;
margin: 10px 0px 0px 6px; }
margin: 10px 0 0 6px; }
.CodeMirror {
height: 100%;
@@ -1041,10 +1041,10 @@ button {
* Highlight matches
*/
.cm-matchhighlight {
background-color: #8F908A; }
background-color: #8f908a; }
.CodeMirror-selection-highlight-scrollbar {
background-color: #8F908A; }
background-color: #8f908a; }
/**
* Show Invisibles
@@ -1052,7 +1052,7 @@ button {
.cm-whitespace::before {
position: absolute;
pointer-events: none;
color: #404F7D; }
color: #404f7d; }
/**
* Vim command display
@@ -1415,7 +1415,7 @@ button {
color: yellow; }
.bitnode.level-2 {
color: #48D1CC; }
color: #48d1cc; }
.bitnode.level-3 {
color: blue; }
@@ -2417,7 +2417,7 @@ button {
.sleeve-panel {
display: inline-block;
margin: 0px;
margin: 0;
padding: 2px; }
.sleeve-panel select {
display: block; }
@@ -2436,7 +2436,7 @@ button {
.resleeve-panel {
display: inline-block;
margin: 0px;
margin: 0;
padding: 2px; }
.resleeve-aug-selector {
@@ -2478,7 +2478,7 @@ button {
cursor: pointer; }
.Treant .collapsed .collapse-switch {
background-color: #868DEE; }
background-color: #868dee; }
.Treant > .node img {
border: none;
@@ -2489,7 +2489,7 @@ button {
padding: 4px;
min-width: 60px;
text-align: center;
border: 2px solid #E8E8E3;
border: 2px solid #e8e8e3;
border-radius: 2px;
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
font-size: 12px; }
@@ -4266,34 +4266,34 @@ html {
margin-left: 0 !important; }
.m-1 {
margin: .25rem !important; }
margin: 0.25rem !important; }
.mt-1, .my-1 {
margin-top: .25rem !important; }
margin-top: 0.25rem !important; }
.mr-1, .mx-1 {
margin-right: .25rem !important; }
margin-right: 0.25rem !important; }
.mb-1, .my-1 {
margin-bottom: .25rem !important; }
margin-bottom: 0.25rem !important; }
.ml-1, .mx-1 {
margin-left: .25rem !important; }
margin-left: 0.25rem !important; }
.m-2 {
margin: .5rem !important; }
margin: 0.5rem !important; }
.mt-2, .my-2 {
margin-top: .5rem !important; }
margin-top: 0.5rem !important; }
.mr-2, .mx-2 {
margin-right: .5rem !important; }
margin-right: 0.5rem !important; }
.mb-2, .my-2 {
margin-bottom: .5rem !important; }
margin-bottom: 0.5rem !important; }
.ml-2, .mx-2 {
margin-left: .5rem !important; }
margin-left: 0.5rem !important; }
.m-3 {
margin: 1rem !important; }
@@ -4356,34 +4356,34 @@ html {
padding-left: 0 !important; }
.p-1 {
padding: .25rem !important; }
padding: 0.25rem !important; }
.pt-1, .py-1 {
padding-top: .25rem !important; }
padding-top: 0.25rem !important; }
.pr-1, .px-1 {
padding-right: .25rem !important; }
padding-right: 0.25rem !important; }
.pb-1, .py-1 {
padding-bottom: .25rem !important; }
padding-bottom: 0.25rem !important; }
.pl-1, .px-1 {
padding-left: .25rem !important; }
padding-left: 0.25rem !important; }
.p-2 {
padding: .5rem !important; }
padding: 0.5rem !important; }
.pt-2, .py-2 {
padding-top: .5rem !important; }
padding-top: 0.5rem !important; }
.pr-2, .px-2 {
padding-right: .5rem !important; }
padding-right: 0.5rem !important; }
.pb-2, .py-2 {
padding-bottom: .5rem !important; }
padding-bottom: 0.5rem !important; }
.pl-2, .px-2 {
padding-left: .5rem !important; }
padding-left: 0.5rem !important; }
.p-3 {
padding: 1rem !important; }
@@ -4457,25 +4457,25 @@ html {
.ml-sm-0, .mx-sm-0 {
margin-left: 0 !important; }
.m-sm-1 {
margin: .25rem !important; }
margin: 0.25rem !important; }
.mt-sm-1, .my-sm-1 {
margin-top: .25rem !important; }
margin-top: 0.25rem !important; }
.mr-sm-1, .mx-sm-1 {
margin-right: .25rem !important; }
margin-right: 0.25rem !important; }
.mb-sm-1, .my-sm-1 {
margin-bottom: .25rem !important; }
margin-bottom: 0.25rem !important; }
.ml-sm-1, .mx-sm-1 {
margin-left: .25rem !important; }
margin-left: 0.25rem !important; }
.m-sm-2 {
margin: .5rem !important; }
margin: 0.5rem !important; }
.mt-sm-2, .my-sm-2 {
margin-top: .5rem !important; }
margin-top: 0.5rem !important; }
.mr-sm-2, .mx-sm-2 {
margin-right: .5rem !important; }
margin-right: 0.5rem !important; }
.mb-sm-2, .my-sm-2 {
margin-bottom: .5rem !important; }
margin-bottom: 0.5rem !important; }
.ml-sm-2, .mx-sm-2 {
margin-left: .5rem !important; }
margin-left: 0.5rem !important; }
.m-sm-3 {
margin: 1rem !important; }
.mt-sm-3, .my-sm-3 {
@@ -4517,25 +4517,25 @@ html {
.pl-sm-0, .px-sm-0 {
padding-left: 0 !important; }
.p-sm-1 {
padding: .25rem !important; }
padding: 0.25rem !important; }
.pt-sm-1, .py-sm-1 {
padding-top: .25rem !important; }
padding-top: 0.25rem !important; }
.pr-sm-1, .px-sm-1 {
padding-right: .25rem !important; }
padding-right: 0.25rem !important; }
.pb-sm-1, .py-sm-1 {
padding-bottom: .25rem !important; }
padding-bottom: 0.25rem !important; }
.pl-sm-1, .px-sm-1 {
padding-left: .25rem !important; }
padding-left: 0.25rem !important; }
.p-sm-2 {
padding: .5rem !important; }
padding: 0.5rem !important; }
.pt-sm-2, .py-sm-2 {
padding-top: .5rem !important; }
padding-top: 0.5rem !important; }
.pr-sm-2, .px-sm-2 {
padding-right: .5rem !important; }
padding-right: 0.5rem !important; }
.pb-sm-2, .py-sm-2 {
padding-bottom: .5rem !important; }
padding-bottom: 0.5rem !important; }
.pl-sm-2, .px-sm-2 {
padding-left: .5rem !important; }
padding-left: 0.5rem !important; }
.p-sm-3 {
padding: 1rem !important; }
.pt-sm-3, .py-sm-3 {
@@ -4589,25 +4589,25 @@ html {
.ml-md-0, .mx-md-0 {
margin-left: 0 !important; }
.m-md-1 {
margin: .25rem !important; }
margin: 0.25rem !important; }
.mt-md-1, .my-md-1 {
margin-top: .25rem !important; }
margin-top: 0.25rem !important; }
.mr-md-1, .mx-md-1 {
margin-right: .25rem !important; }
margin-right: 0.25rem !important; }
.mb-md-1, .my-md-1 {
margin-bottom: .25rem !important; }
margin-bottom: 0.25rem !important; }
.ml-md-1, .mx-md-1 {
margin-left: .25rem !important; }
margin-left: 0.25rem !important; }
.m-md-2 {
margin: .5rem !important; }
margin: 0.5rem !important; }
.mt-md-2, .my-md-2 {
margin-top: .5rem !important; }
margin-top: 0.5rem !important; }
.mr-md-2, .mx-md-2 {
margin-right: .5rem !important; }
margin-right: 0.5rem !important; }
.mb-md-2, .my-md-2 {
margin-bottom: .5rem !important; }
margin-bottom: 0.5rem !important; }
.ml-md-2, .mx-md-2 {
margin-left: .5rem !important; }
margin-left: 0.5rem !important; }
.m-md-3 {
margin: 1rem !important; }
.mt-md-3, .my-md-3 {
@@ -4649,25 +4649,25 @@ html {
.pl-md-0, .px-md-0 {
padding-left: 0 !important; }
.p-md-1 {
padding: .25rem !important; }
padding: 0.25rem !important; }
.pt-md-1, .py-md-1 {
padding-top: .25rem !important; }
padding-top: 0.25rem !important; }
.pr-md-1, .px-md-1 {
padding-right: .25rem !important; }
padding-right: 0.25rem !important; }
.pb-md-1, .py-md-1 {
padding-bottom: .25rem !important; }
padding-bottom: 0.25rem !important; }
.pl-md-1, .px-md-1 {
padding-left: .25rem !important; }
padding-left: 0.25rem !important; }
.p-md-2 {
padding: .5rem !important; }
padding: 0.5rem !important; }
.pt-md-2, .py-md-2 {
padding-top: .5rem !important; }
padding-top: 0.5rem !important; }
.pr-md-2, .px-md-2 {
padding-right: .5rem !important; }
padding-right: 0.5rem !important; }
.pb-md-2, .py-md-2 {
padding-bottom: .5rem !important; }
padding-bottom: 0.5rem !important; }
.pl-md-2, .px-md-2 {
padding-left: .5rem !important; }
padding-left: 0.5rem !important; }
.p-md-3 {
padding: 1rem !important; }
.pt-md-3, .py-md-3 {
@@ -4721,25 +4721,25 @@ html {
.ml-lg-0, .mx-lg-0 {
margin-left: 0 !important; }
.m-lg-1 {
margin: .25rem !important; }
margin: 0.25rem !important; }
.mt-lg-1, .my-lg-1 {
margin-top: .25rem !important; }
margin-top: 0.25rem !important; }
.mr-lg-1, .mx-lg-1 {
margin-right: .25rem !important; }
margin-right: 0.25rem !important; }
.mb-lg-1, .my-lg-1 {
margin-bottom: .25rem !important; }
margin-bottom: 0.25rem !important; }
.ml-lg-1, .mx-lg-1 {
margin-left: .25rem !important; }
margin-left: 0.25rem !important; }
.m-lg-2 {
margin: .5rem !important; }
margin: 0.5rem !important; }
.mt-lg-2, .my-lg-2 {
margin-top: .5rem !important; }
margin-top: 0.5rem !important; }
.mr-lg-2, .mx-lg-2 {
margin-right: .5rem !important; }
margin-right: 0.5rem !important; }
.mb-lg-2, .my-lg-2 {
margin-bottom: .5rem !important; }
margin-bottom: 0.5rem !important; }
.ml-lg-2, .mx-lg-2 {
margin-left: .5rem !important; }
margin-left: 0.5rem !important; }
.m-lg-3 {
margin: 1rem !important; }
.mt-lg-3, .my-lg-3 {
@@ -4781,25 +4781,25 @@ html {
.pl-lg-0, .px-lg-0 {
padding-left: 0 !important; }
.p-lg-1 {
padding: .25rem !important; }
padding: 0.25rem !important; }
.pt-lg-1, .py-lg-1 {
padding-top: .25rem !important; }
padding-top: 0.25rem !important; }
.pr-lg-1, .px-lg-1 {
padding-right: .25rem !important; }
padding-right: 0.25rem !important; }
.pb-lg-1, .py-lg-1 {
padding-bottom: .25rem !important; }
padding-bottom: 0.25rem !important; }
.pl-lg-1, .px-lg-1 {
padding-left: .25rem !important; }
padding-left: 0.25rem !important; }
.p-lg-2 {
padding: .5rem !important; }
padding: 0.5rem !important; }
.pt-lg-2, .py-lg-2 {
padding-top: .5rem !important; }
padding-top: 0.5rem !important; }
.pr-lg-2, .px-lg-2 {
padding-right: .5rem !important; }
padding-right: 0.5rem !important; }
.pb-lg-2, .py-lg-2 {
padding-bottom: .5rem !important; }
padding-bottom: 0.5rem !important; }
.pl-lg-2, .px-lg-2 {
padding-left: .5rem !important; }
padding-left: 0.5rem !important; }
.p-lg-3 {
padding: 1rem !important; }
.pt-lg-3, .py-lg-3 {
@@ -4853,25 +4853,25 @@ html {
.ml-xl-0, .mx-xl-0 {
margin-left: 0 !important; }
.m-xl-1 {
margin: .25rem !important; }
margin: 0.25rem !important; }
.mt-xl-1, .my-xl-1 {
margin-top: .25rem !important; }
margin-top: 0.25rem !important; }
.mr-xl-1, .mx-xl-1 {
margin-right: .25rem !important; }
margin-right: 0.25rem !important; }
.mb-xl-1, .my-xl-1 {
margin-bottom: .25rem !important; }
margin-bottom: 0.25rem !important; }
.ml-xl-1, .mx-xl-1 {
margin-left: .25rem !important; }
margin-left: 0.25rem !important; }
.m-xl-2 {
margin: .5rem !important; }
margin: 0.5rem !important; }
.mt-xl-2, .my-xl-2 {
margin-top: .5rem !important; }
margin-top: 0.5rem !important; }
.mr-xl-2, .mx-xl-2 {
margin-right: .5rem !important; }
margin-right: 0.5rem !important; }
.mb-xl-2, .my-xl-2 {
margin-bottom: .5rem !important; }
margin-bottom: 0.5rem !important; }
.ml-xl-2, .mx-xl-2 {
margin-left: .5rem !important; }
margin-left: 0.5rem !important; }
.m-xl-3 {
margin: 1rem !important; }
.mt-xl-3, .my-xl-3 {
@@ -4913,25 +4913,25 @@ html {
.pl-xl-0, .px-xl-0 {
padding-left: 0 !important; }
.p-xl-1 {
padding: .25rem !important; }
padding: 0.25rem !important; }
.pt-xl-1, .py-xl-1 {
padding-top: .25rem !important; }
padding-top: 0.25rem !important; }
.pr-xl-1, .px-xl-1 {
padding-right: .25rem !important; }
padding-right: 0.25rem !important; }
.pb-xl-1, .py-xl-1 {
padding-bottom: .25rem !important; }
padding-bottom: 0.25rem !important; }
.pl-xl-1, .px-xl-1 {
padding-left: .25rem !important; }
padding-left: 0.25rem !important; }
.p-xl-2 {
padding: .5rem !important; }
padding: 0.5rem !important; }
.pt-xl-2, .py-xl-2 {
padding-top: .5rem !important; }
padding-top: 0.5rem !important; }
.pr-xl-2, .px-xl-2 {
padding-right: .5rem !important; }
padding-right: 0.5rem !important; }
.pb-xl-2, .py-xl-2 {
padding-bottom: .5rem !important; }
padding-bottom: 0.5rem !important; }
.pl-xl-2, .px-xl-2 {
padding-left: .5rem !important; }
padding-left: 0.5rem !important; }
.p-xl-3 {
padding: 1rem !important; }
.pt-xl-3, .py-xl-3 {
@@ -4980,14 +4980,14 @@ html {
visibility: hidden !important; }
.add-exp-button {
margin-right: 0px; }
margin-right: 0; }
.remove-exp-button {
margin-left: 0px; }
margin-left: 0; }
.exp-input {
margin-right: 0px;
margin-left: 0px;
margin-right: 0;
margin-left: 0;
margin-top: 5px;
margin-bottom: 5px;
padding: 2px 5px; }
@@ -4998,14 +4998,14 @@ html {
vertical-align: middle; }
.touch-right {
margin-right: 0px; }
margin-right: 0; }
.touch-left {
margin-left: 0px; }
margin-left: 0; }
.touch-sides {
margin-left: 0px;
margin-right: 0px; }
margin-left: 0;
margin-right: 0; }
.casino-card {
padding: 10px;

34
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -56,8 +56,3 @@ through destroying BitNodes is:
* Source-Files
* Scripts on the home computer
BitNode Details
^^^^^^^^^^^^^^^
TODO

View File

@@ -47,7 +47,7 @@ List of all Source-Files
+------------------------------------+-------------------------------------------------------------------------------------+
| BitNode-9: Coming Soon | |
+------------------------------------+-------------------------------------------------------------------------------------+
| BitNode-10: Digital Carbon | * Each level of this grants a Duplicate Sleeve |
| BitNode-10: Digital Carbon | * Each level of this grants a Duplicate Sleeve. |
| | * Allows the player to access the :ref:`netscript_sleeveapi` in other BitNodes |
+------------------------------------+-------------------------------------------------------------------------------------+
| BitNode-11: The Big Crash | * Company favor increases both the player's salary and reputation gain at that |

View File

@@ -11,7 +11,7 @@ user's physical and mental faculties.
Augmentations provide persistent upgrades in the form of multipliers.
These multipliers apply to a wide variety of things such as stats,
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
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View File

@@ -3,15 +3,186 @@
Changelog
=========
v0.51.9 - 2021-05-17 offline progress and exports! (hydroflame)
---------------------------------------------------------------
**Alias**
* several commands can be included in 1 alias. Recursive alias now work to
a depth of 10. (@Dawe)
**Offline**
* Offline money gain has been reworked (it is more generous)
* If you're not working anywhere and go offline the game will work for you
at all your factions evenly.
**Export**
* Exporting now gives +1 favor to all joined factions every 24h.
**Corp**
* Self-fund with an invalid name no longer takes away 150b anyway.
* Can no longer export negative amount
**Bladeburner**
* No longer waste overflowing time.
**Text Editors**
* All settings will now be saved and loaded correctly.
**Terminal**
* 'scan' now works for servers that are more than 21 character long.
**Misc.**
* ls now correctly lists all files.
* importing auto save+reloads (@Dawe)
* Fix a bug where .fconf could not be created
* Fix formatting inconsistencies for some logs of netscript functions.
* Fix a bug where Cashroot starter kit would appear as [object Object] in
confirmation dialog.
* Fix some ram not displayed as 0.00GB
* Fix error message throw undefined variable error
* City hall now has some generic text if you can't create a corp yet.
* Deleting a file without extension now returns an appropriate error message.
* Fixed an issue where bladeburner would miscalculate the cost of hospitalization.
* It is now possible to suppress bladeburner "action stopped" popup.
* Updated several dependencies (big who cares, I know)
* ls no longer prints lingering newline.
* Money earned/spent by sleeves is now tracked under Character>Money
v0.51.8 - 2021-05-07 It was there all along (hydroflame)
--------------------------------------------------------
**Servers**
* Update n00dles metadata
**Netscript**
* 'hashGainRate' use the correct 'usedRam' and 'maxRam'
* Fix 'setActionAutolevel' logging.
* Fix 'setActionLevel' not working at all.
* Add 'installBackdoor' singularity function.
**Hacknet**
* Fix Hacknet Servers total production always displaying 0
**Documentation**
* Updated guide to no longer recommend BN12.
* Fix documentation for maxNumNodes (@ModdedGamers)
* Fix typo in 'sourcefiles.rst'
* Fix typo in 'recommendedbitnodeorder.rst'
* Fix 'getServer' documentation missing 'server' argument.
* Fix missing ram cost in 'getData.rst'
* Fix basic formulas examples.
* Fix typo in BN11 description.
* Fix formatting issue in Bladeburner (@Pimgd)
**Misc.**
* Fix negative money being displayed in full.
* Fix Hacking Missions not working.
* Fix Corporation tree not rendering.
* Fix script being needlessly recompiled. This should save real ram (not game ram)
* w0r1d_d43m0n can be backdoored
* Coding Contracts title is click-to-copy (@Rodeth)
* Covenant memory upgrade works better.
* Fix Neuroflux not being correctly calculated when entering BN with SF12.
* Delete Active Script now delete all active scripts, not just home.
* Now you can 'cd' in directories that only contain '.txt' files.
* Fix 'analyze' always saying players had root access
* Passive faction rep no longer builds for special factions.
* Donation option no longer appears for special factions.
* Rephrased some milestones.
* donation textbox now accepts money in the format '1b' and the like (@Dawe)
* Fix being able to join hated factions simultaneously. (@Dawe)
* 'ls' now displays files in multiple column. (Helps players with many files)
* Bladeburner multiplers now appear under Character>Stats and
Character>Augmentation when they are relevant.
* Fix missing functions syntax highlight in codemirror.
* Fix infiltration number formatting.
* script income transfers to parent on death. This helps keep track of
income for scripts that spawn short lived scripts.
v0.51.7 - 2021-04-28 n00dles (hydroflame)
-----------------------------------------
**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

View File

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

View File

@@ -323,7 +323,7 @@ Source-File
:Max Level: 3
This Source-File unlocks Sleeve technology in other BitNodes.
Each level of this Source-File also grants you a Duplicate Sleeve
Each level of this Source-File also grants you a Duplicate Sleeve.
Difficulty
Hard
@@ -373,9 +373,10 @@ Description
Source-File
:Max Level: Infinity
Each level 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)
Each level of Source-File 12 will let you start with Neuroflux Governor
equal to the level of this Source-File.
This BitNode is meant to be done passively or when waiting for new content.
Difficulty
Initially very easy, but then it (obviously) becomes harder as you continue to do it.
@@ -396,27 +397,22 @@ For fast progression
1. Repeat **BitNode-1: Source Genesis** until you max out its Source-File. Its Source-File
is extremely powerful, as it raises all multipliers by a significant amount.
2. Repeat **BitNode-12: The Recursion** several times. This BitNode will be extremely easy the
first few times you tackle it, and its Source-File raises all multipliers. Furthermore,
its effect stacks multiplicatively with itself and other Source-Files/Augmentations,
which gets better as time goes on
3. Do **BitNode-5: Artificial Intelligence** once or twice. The intelligence stat it unlocks
2. Do **BitNode-5: Artificial Intelligence** once or twice. The intelligence stat it unlocks
will gradually build up as you continue to play the game, and will be helpful
in the future. The Source-File also provides hacking multipliers, which are
strong because hacking is typically one of the best ways of earning money.
4. (Optional) Consider doing **BitNode-4: The Singularity**. Its Source-File does not directly make you
3. (Optional) Consider doing **BitNode-4: The Singularity**. Its Source-File does not directly make you
more powerful in any way, but it does unlock :ref:`netscript_singularityfunctions` which
let you automate significantly more aspects of the game.
5. Do **BitNode-3: Corporatocracy** once to unlock the Corporation mechanic. This mechanic
4. Do **BitNode-3: Corporatocracy** once to unlock the Corporation mechanic. This mechanic
has high profit potential.
6. Do **BitNode-6: Bladeburners** once to unlock the Bladeburners mechanic. The Bladeburner
5. Do **BitNode-6: Bladeburners** once to unlock the Bladeburners mechanic. The Bladeburner
mechanic is useful for some of the future BitNodes (such as 9 and 10).
7. Do **BitNode-9: Hacktocracy** to unlock the Hacknet Server mechanic. You can
6. Do **BitNode-9: Hacktocracy** to unlock the Hacknet Server mechanic. You can
consider repeating it as well, as its Level 2 and 3 effects are pretty helpful as well.
.. todo:: To be continued as more BitNodes get added

View File

@@ -1,9 +1,10 @@
getServer() Netscript Function
==========================================
.. js:function:: getServer()
.. js:function:: getServer([hostname])
:RAM cost: 4 GB
:param string hostname: Hostname of the server, defaults to host server.
If you are not in BitNode-5, then you must have Source-File 5-1 in order to run this function.

View File

@@ -0,0 +1,15 @@
getServerMaxRam() Netscript Function
====================================
.. js:function:: getServerMaxRam(hostname)
:RAM cost: 0.05 GB
:param string hostname: Hostname of target server.
:returns: Total ram available on that server. In GB.
Example:
.. code-block:: javascript
maxRam = getServerMaxRam("helios"); // returns: 16
print("helios has "+maxRam + "GB");

View File

@@ -3,6 +3,8 @@ getServerRam() Netscript Function
.. js:function:: getServerRam(hostname)
.. warning:: This function is deprecated.
:RAM cost: 0.1 GB
:param string hostname: Hostname of target server.
:returns: An array of 2 number, first number is the total RAM, second the

View File

@@ -0,0 +1,15 @@
getServerUsedRam() Netscript Function
=====================================
.. js:function:: getServerUsedRam(hostname)
:RAM cost: 0.05 GB
:param string hostname: Hostname of target server.
:returns: Used ram on that server. In GB.
Example:
.. code-block:: javascript
usedRam = getServerUsedRam("harakiri-sushi"); // returns: 5.6
print("harakiri-sushi uses "+usedRam + "GB");

View File

@@ -15,7 +15,8 @@ ps() Netscript Function
{
filename: Script name,
threads: Number of threads script is running with,
args: Script's arguments
args: Script's arguments,
pid: Script's pid
}
Example:
@@ -23,7 +24,8 @@ ps() Netscript Function
.. code-block:: javascript
processes = ps("home");
for (let i = 0; i < ps.length; ++i) {
tprint(ps[i].filename + ' ' + ps[i].threads);
tprint(ps[i].args);
for (let i = 0; i < processes.length; ++i) {
tprint(processes[i].filename + ' ' + processes[i].threads);
tprint(processes[i].args);
tprint(processes[i].pid);
}

View File

@@ -3,6 +3,7 @@ getData() Netscript Function
.. js:function:: getData(filename[, hostname=current hostname])
:RAM cost: 5 GB
:param string filename: Filename of the contract
:param string hostname: Hostname of the server containing the contract.
Optional. Defaults to current server if not provided

View File

@@ -20,4 +20,4 @@ growPercent() Netscript Function
.. code-block:: javascript
tprint(growPercent(getServer(), 50, getPlayer()))
tprint(formulas.basic.growPercent(getServer(), 50, getPlayer()))

View File

@@ -21,4 +21,4 @@ growTime() Netscript Function
server = getServer();
server.hackDifficulty = server.minDifficulty;
tprint(growTime(server, getPlayer()));
tprint(formulas.basic.growTime(server, getPlayer()));

View File

@@ -21,4 +21,4 @@ hackChance() Netscript Function
server = getServer();
server.hackDifficulty = server.minDifficulty;
tprint(hackChance(server, getPlayer()));
tprint(formulas.basic.hackChance(server, getPlayer()));

View File

@@ -21,4 +21,4 @@ hackExp() Netscript Function
server = getServer();
server.hackDifficulty = 99.9;
tprint(hackExp(server, getPlayer()));
tprint(formulas.basic.hackExp(server, getPlayer()));

View File

@@ -22,4 +22,4 @@ hackPercent() Netscript Function
server = getServer();
server.hackDifficulty = server.minDifficulty;
tprint(hackPercent(server, getPlayer()));
tprint(formulas.basic.hackPercent(server, getPlayer()));

View File

@@ -21,4 +21,4 @@ hackTime() Netscript Function
server = getServer();
server.hackDifficulty = server.minDifficulty;
tprint(hackTime(server, getPlayer()));
tprint(formulas.basic.hackTime(server, getPlayer()));

View File

@@ -21,4 +21,4 @@ weakenTime() Netscript Function
server = getServer();
server.hackDifficulty = server.minDifficulty;
tprint(weakenTime(server, getPlayer()));
tprint(formulas.basic.weakenTime(server, getPlayer()));

View File

@@ -1,11 +1,12 @@
hashGainRate() Netscript Function
==========================================
.. js:function:: hashGainRate(level, ram, core[, mult])
.. js:function:: hashGainRate(level, ramUsed, maxRam, core[, mult])
:RAM cost: 0 GB
:param number level: level of the server.
:param number ram: ram of the server.
:param number ramUsed: ram used on the server.
:param number maxRam: max ram of the server.
:param number core: cores of the server.
:returns: Money per second that a server with those stats would gain per second.
@@ -18,7 +19,7 @@ hashGainRate() Netscript Function
.. code-block:: javascript
server = hacknet.getNodeStats(1);
currentRate = formulas.hacknetNodes.hashGainRate(server.level, server.ram, server.cores);
levelRate = formulas.hacknetNodes.hashGainRate(server.level+1, server.ram, server.cores);
ramRate = formulas.hacknetNodes.hashGainRate(server.level, server.ram*2, server.cores);
coresRate = formulas.hacknetNodes.hashGainRate(server.level, server.ram, server.cores+1);
currentRate = formulas.hacknetNodes.hashGainRate(server.level, 0, server.ram, server.cores);
levelRate = formulas.hacknetNodes.hashGainRate(server.level+1, 0, server.ram, server.cores);
ramRate = formulas.hacknetNodes.hashGainRate(server.level, 0, server.ram*2, server.cores);
coresRate = formulas.hacknetNodes.hashGainRate(server.level, 0, server.ram, server.cores+1);

View File

@@ -4,4 +4,4 @@ maxNumNodes() Netscript Function
.. js:function:: maxNumNodes()
:RAM cost: 0 GB
:returns: Maximum number of Hacknet Nodes you can own.
:returns: Maximum number of Hacknet Nodes you can own, unless you have not unlocked HackNet servers. Then, it returns Infinity.

View File

@@ -5,13 +5,13 @@ Netscript Bladeburner API
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
later in the game
later in the game.
.. warning:: This page contains spoilers for the game
The Bladeburner API is unlocked in BitNode-7. If you are in BitNode-7, you will
automatically gain access to this API. Otherwise, you must have Source-File 7 in
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**
@@ -157,7 +157,7 @@ identifier by attaching the Bladeburner API functions to an object::
}
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
if (!this.hasSimulacrum() && this.ns.isBusy()) {
this.ns.print("Idling bc player is busy with some other action");

View File

@@ -54,7 +54,8 @@ This includes information such as function signatures, what they do, and their r
getServerMinSecurityLevel() <basicfunctions/getServerMinSecurityLevel>
getServerRequiredHackingLevel() <basicfunctions/getServerRequiredHackingLevel>
getServerNumPortsRequired() <basicfunctions/getServerNumPortsRequired>
getServerRam() <basicfunctions/getServerRam>
getServerMaxRam() <basicfunctions/getServerMaxRam>
getServerUsedRam() <basicfunctions/getServerUsedRam>
serverExists() <basicfunctions/serverExists>
fileExists() <basicfunctions/fileExists>
isRunning() <basicfunctions/isRunning>
@@ -90,3 +91,8 @@ This includes information such as function signatures, what they do, and their r
wget() <basicfunctions/wget>
getFavorToDonate() <basicfunctions/getFavorToDonate>
flags() <basicfunctions/flags>
.. toctree::
:caption: Deprecated:
getServerRam() <basicfunctions/getServerRam>

View File

@@ -86,7 +86,7 @@ The following is an example of one way a script can be used to automate the
purchasing and upgrading of Hacknet Nodes.
This script attempts to purchase Hacknet Nodes until the player has a total of 8. Then
it gradually upgrades those Node's to a minimum of level 140, 64 GB RAM, and 8 cores
it gradually upgrades those Node's to a minimum of level 80, 16 GB RAM, and 8 cores
.. code:: javascript
@@ -129,3 +129,16 @@ it gradually upgrades those Node's to a minimum of level 140, 64 GB RAM, and 8 c
};
print("All nodes upgraded to 16GB RAM");
for (var i = 0; i < cnt; i++) {
while (hacknet.getNodeStats(i).cores < 8) {
var cost = hacknet.getCoreUpgradeCost(i, 1);
while (myMoney() < cost) {
print("Need $" + cost + " . Have $" + myMoney());
sleep(3000);
}
res = hacknet.upgradeCore(i, 1);
};
};
print("All nodes upgraded to 8 cores");

View File

@@ -27,6 +27,7 @@ level 3, then you will be able to access all of the Singularity Functions.
getCurrentServer() <singularityfunctions/getCurrentServer>
connect() <singularityfunctions/connect>
manualHack() <singularityfunctions/manualHack>
installBackdoor() <singularityfunctions/installBackdoor>
getPlayer() <singularityfunctions/getPlayer>
hospitalize() <singularityfunctions/hospitalize>
isBusy() <singularityfunctions/isBusy>

View File

@@ -0,0 +1,22 @@
installBackdoor() Netscript Function
====================================
.. js:function:: installBackdoor()
:RAM cost: 2 GB
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 install a backdoor on the server you are currently connected to.
Examples:
.. code-block:: javascript
connect("foodnstuff");
installBackdoor();
.. warning::
For NS2 users:
This function is async.

15
docker-compose.yml Normal file
View File

@@ -0,0 +1,15 @@
version: "3.4"
services:
web:
image: bitburner:dev
build:
context: .
dockerfile: Dockerfile
target: dev
ports:
- "8000:8000"
volumes:
- ./src:/app/src
- ./css:/app/css
- ./utils:/app/utils
- ./test:/app/test

View File

@@ -327,8 +327,8 @@
Would you like to join? <br/> <br/>
Warning: Joining this faction may prevent you from joining other factions during this run!
</p>
<button id="faction-invitation-box-yes" class="popup-box-button"> Yes </button>
<button id="faction-invitation-box-no" class="popup-box-button"> No </button>
<button id="faction-invitation-box-yes" class="popup-box-button"> Join! </button>
<button id="faction-invitation-box-no" class="popup-box-button"> Decide later </button>
</div>
</div>
@@ -506,6 +506,16 @@
<input class="optionCheckbox" type="checkbox" name="settingsSuppressHospitalizationPopup" id="settingsSuppressHospitalizationPopup">
</fieldset>
<!-- Suppress Bladeburner popups -->
<fieldset>
<label for="settingsSuppressBladeburnerPopup" class="tooltip">Suppress Bladeburner Popup:
<span class="tooltiptext">
If this is set, then having your Bladeburner actions interrupted by being busy with something else will not display a popup message.
</span>
</label>
<input class="optionCheckbox" type="checkbox" name="settingsSuppressBladeburnerPopup" id="settingsSuppressBladeburnerPopup">
</fieldset>
<!-- Disable Terminal and Navigation Shortcuts -->
<fieldset>
<label for="settingsDisableHotkeys" class="tooltip">Disable Hotkeys:
@@ -587,14 +597,14 @@
Copy Save data to Clipboard
</button>
<button id="debug-delete-scripts-link" class="a-link-button tooltip">
(DEBUG) Delete Active Scripts
Delete all active scripts
<span class="tooltiptextleft">
Debug option used to forcefully kill all active running scripts, in case there is a bug or some unexpected issue with the game. After
Forcefully kill all active running scripts, in case there is a bug or some unexpected issue with the game. After
using this, save the game and then reload the page.
</span>
</button>
<button id="debug-soft-reset" class="a-link-button tooltip">
(DEBUG) Soft Reset
Soft Reset
<span class="tooltiptextleft">
Perform a soft reset. Resets everything as if you had just purchased an Augmentation.
</span>

86
package-lock.json generated
View File

@@ -1,11 +1,11 @@
{
"name": "bitburner",
"version": "0.51.5",
"version": "0.51.8",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "0.51.5",
"version": "0.51.8",
"hasInstallScript": true,
"license": "SEE LICENSE IN license.txt",
"dependencies": {
@@ -13,7 +13,7 @@
"@types/numeral": "0.0.25",
"@types/react": "^16.8.6",
"@types/react-dom": "^16.8.2",
"acorn": "^6.2.0",
"acorn": "^6.4.1",
"acorn-walk": "^6.2.0",
"ajv": "^5.1.5",
"ajv-keywords": "^2.0.0",
@@ -21,14 +21,14 @@
"async": "^2.6.1",
"autosize": "^4.0.2",
"brace": "^0.11.1",
"codemirror": "^5.43.0",
"codemirror": "^5.58.2",
"decimal.js": "7.2.3",
"enhanced-resolve": "^4.0.0",
"escodegen": "^1.11.0",
"escope": "^3.6.0",
"file-saver": "^1.3.8",
"interpret": "^1.0.0",
"jquery": "^3.3.1",
"jquery": "^3.5.0",
"jshint": "^2.10.2",
"json-loader": "^0.5.4",
"jsplumb": "^2.6.8",
@@ -1545,9 +1545,9 @@
}
},
"node_modules/acorn": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz",
"integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw==",
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
"integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==",
"bin": {
"acorn": "bin/acorn"
},
@@ -1565,18 +1565,6 @@
"acorn-walk": "^6.0.1"
}
},
"node_modules/acorn-globals/node_modules/acorn": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz",
"integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/acorn-jsx": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz",
@@ -3516,9 +3504,9 @@
}
},
"node_modules/codemirror": {
"version": "5.43.0",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.43.0.tgz",
"integrity": "sha512-mljwQWUaWIf85I7QwTBryF2ASaIvmYAL4s5UCanCJFfKeXOKhrqdHWdHiZWAMNT+hjLTCnVx2S/SYTORIgxsgA=="
"version": "5.58.2",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.58.2.tgz",
"integrity": "sha512-K/hOh24cCwRutd1Mk3uLtjWzNISOkm4fvXiMO7LucCrqbh6aJDdtqUziim3MZUI6wOY0rvY1SlL1Ork01uMy6w=="
},
"node_modules/collapse-white-space": {
"version": "1.0.4",
@@ -8542,9 +8530,9 @@
"dev": true
},
"node_modules/jquery": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz",
"integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg=="
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.0.tgz",
"integrity": "sha512-Xb7SVYMvygPxbFMpTFQiHh1J7HClEaThguL15N/Gg37Lri/qKyhRGZYzHRyLH8Stq3Aow0LsHO2O2ci86fCrNQ=="
},
"node_modules/js-base64": {
"version": "2.4.3",
@@ -8637,18 +8625,6 @@
"integrity": "sha1-a9KZwTsMRiay2iwDk81DhdYGrLk=",
"dev": true
},
"node_modules/jsdom/node_modules/acorn": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz",
"integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/jsesc": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
@@ -20259,9 +20235,9 @@
}
},
"acorn": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.2.0.tgz",
"integrity": "sha512-8oe72N3WPMjA+2zVG71Ia0nXZ8DpQH+QyyHO+p06jT8eg8FGG3FbcUIi8KziHlAfheJQZeoqbvq1mQSQHXKYLw=="
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz",
"integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA=="
},
"acorn-globals": {
"version": "4.3.2",
@@ -20271,14 +20247,6 @@
"requires": {
"acorn": "^6.0.1",
"acorn-walk": "^6.0.1"
},
"dependencies": {
"acorn": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz",
"integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==",
"dev": true
}
}
},
"acorn-jsx": {
@@ -21942,9 +21910,9 @@
"dev": true
},
"codemirror": {
"version": "5.43.0",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.43.0.tgz",
"integrity": "sha512-mljwQWUaWIf85I7QwTBryF2ASaIvmYAL4s5UCanCJFfKeXOKhrqdHWdHiZWAMNT+hjLTCnVx2S/SYTORIgxsgA=="
"version": "5.58.2",
"resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.58.2.tgz",
"integrity": "sha512-K/hOh24cCwRutd1Mk3uLtjWzNISOkm4fvXiMO7LucCrqbh6aJDdtqUziim3MZUI6wOY0rvY1SlL1Ork01uMy6w=="
},
"collapse-white-space": {
"version": "1.0.4",
@@ -26149,9 +26117,9 @@
}
},
"jquery": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz",
"integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg=="
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.0.tgz",
"integrity": "sha512-Xb7SVYMvygPxbFMpTFQiHh1J7HClEaThguL15N/Gg37Lri/qKyhRGZYzHRyLH8Stq3Aow0LsHO2O2ci86fCrNQ=="
},
"js-base64": {
"version": "2.4.3",
@@ -26225,14 +26193,6 @@
"whatwg-url": "^7.0.0",
"ws": "^6.1.2",
"xml-name-validator": "^3.0.0"
},
"dependencies": {
"acorn": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz",
"integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==",
"dev": true
}
}
},
"jsdom-global": {

View File

@@ -10,7 +10,7 @@
"@types/numeral": "0.0.25",
"@types/react": "^16.8.6",
"@types/react-dom": "^16.8.2",
"acorn": "^6.2.0",
"acorn": "^6.4.1",
"acorn-walk": "^6.2.0",
"ajv": "^5.1.5",
"ajv-keywords": "^2.0.0",
@@ -18,14 +18,14 @@
"async": "^2.6.1",
"autosize": "^4.0.2",
"brace": "^0.11.1",
"codemirror": "^5.43.0",
"codemirror": "^5.58.2",
"decimal.js": "7.2.3",
"enhanced-resolve": "^4.0.0",
"escodegen": "^1.11.0",
"escope": "^3.6.0",
"file-saver": "^1.3.8",
"interpret": "^1.0.0",
"jquery": "^3.3.1",
"jquery": "^3.5.0",
"jshint": "^2.10.2",
"json-loader": "^0.5.4",
"jsplumb": "^2.6.8",
@@ -113,16 +113,18 @@
},
"scripts": {
"start:dev": "webpack-dev-server --progress --env.devServer --mode development",
"start:container": "webpack-dev-server --progress --env.devServer --mode development --env.runInContainer",
"build": "webpack --mode production",
"build:dev": "webpack --mode development",
"build:test": "webpack --config webpack.config-test.js",
"lint": "npm run lint:jsts & npm run lint:style",
"lint:jsts": "eslint '*.{js,jsx,ts,tsx}' './src/**/*.{js,jsx,ts,tsx}' './test/**/*.{js,jsx,ts,tsx}' './utils/**/*.{js,jsx,ts,tsx}'",
"lint:style": "stylelint ./css/*",
"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 --fix ./css/*",
"preinstall": "node ./scripts/engines-check.js",
"test": "mochapack --webpack-config webpack.config-test.js -r jsdom-global/register ./test/index.js",
"test:container": "mochapack --webpack-config webpack.config-test.js --slow 2000 --timeout 10000 -r jsdom-global/register ./test/index.js",
"watch": "webpack --watch --mode production",
"watch:dev": "webpack --watch --mode development"
},
"version": "0.51.5"
"version": "0.51.9"
}

View File

@@ -22,12 +22,12 @@ export function loadGlobalAliases(saveString: string): void {
// Prints all aliases to terminal
export function printAliases(): void {
for (var name in Aliases) {
for (const name in Aliases) {
if (Aliases.hasOwnProperty(name)) {
post("alias " + name + "=" + Aliases[name]);
}
}
for (var name in GlobalAliases) {
for (const name in GlobalAliases) {
if (GlobalAliases.hasOwnProperty(name)) {
post("global alias " + name + "=" + GlobalAliases[name]);
}
@@ -36,8 +36,8 @@ export function printAliases(): void {
// Returns true if successful, false otherwise
export function parseAliasDeclaration(dec: string, global = false): boolean {
var re = /^([_|\w|!|%|,|@]+)="(.+)"$/;
var matches = dec.match(re);
const re = /^([_|\w|!|%|,|@]+)="(.+)"$/;
const matches = dec.match(re);
if (matches == null || matches.length != 3) {return false;}
if (global){
addGlobalAlias(matches[1],matches[2]);
@@ -51,14 +51,14 @@ function addAlias(name: string, value: string): void {
if (name in GlobalAliases) {
delete GlobalAliases[name];
}
Aliases[name] = value;
Aliases[name] = value.trim();
}
function addGlobalAlias(name: string, value: string): void {
if (name in Aliases){
delete Aliases[name];
}
GlobalAliases[name] = value;
GlobalAliases[name] = value.trim();
}
function getAlias(name: string): string | null {
@@ -97,22 +97,29 @@ export function removeAlias(name: string): boolean {
export function substituteAliases(origCommand: string): string {
const commandArray = origCommand.split(" ");
if (commandArray.length > 0){
// For the unalias command, dont substite
if (commandArray[0] === "unalias") { return commandArray.join(" "); }
// For the alias and unalias commands, dont substite
if (commandArray[0] === "unalias" || commandArray[0] === "alias") { return commandArray.join(" "); }
var alias = getAlias(commandArray[0]);
if (alias != null) {
commandArray[0] = alias;
} else {
var alias = getGlobalAlias(commandArray[0]);
let somethingSubstituted = true;
let depth = 0;
while(somethingSubstituted && depth < 10){
depth++;
somethingSubstituted = false
const alias = getAlias(commandArray[0])?.split(" ");
if (alias != null) {
commandArray[0] = alias;
somethingSubstituted = true
commandArray.splice(0, 1, ...alias);
//commandArray[0] = alias;
}
}
for (var i = 0; i < commandArray.length; ++i) {
var alias = getGlobalAlias(commandArray[i]);
if (alias != null) {
commandArray[i] = alias;
for (let i = 0; i < commandArray.length; ++i) {
const alias = getGlobalAlias(commandArray[i])?.split(" ");
if (alias != null) {
somethingSubstituted = true
commandArray.splice(i, 1, ...alias);
i += alias.length - 1;
//commandArray[i] = alias;
}
}
}
}

View File

@@ -9,7 +9,7 @@ import { Factions } from "../Faction/Factions";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
interface IConstructorParams {
info: string;
info: string | JSX.Element;
isSpecial?: boolean;
moneyCost: number;
name: string;
@@ -49,31 +49,27 @@ interface IConstructorParams {
}
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
baseCost: number = 0;
baseCost = 0;
// How much faction reputation is required to unlock this
baseRepRequirement: number = 0;
baseRepRequirement = 0;
// Description of what this Aug is and what it does
info: string = "";
info: string | JSX.Element;
// 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
level: number = 0;
level = 0;
// Name of Augmentation
name: string = "";
name = "";
// Whether the player owns this Augmentation
owned: boolean = false;
owned = false;
// Array of names of all prerequisites
prereqs: string[] = [];
@@ -83,7 +79,7 @@ export class Augmentation {
mults: IMap<number> = {}
// Initial cost. Doesn't change when you purchase multiple Augmentation
startingCost: number = 0;
startingCost = 0;
constructor(params: IConstructorParams={ info: "", moneyCost: 0, name: "", repCost: 0 }) {
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]}`);
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}`);
continue;
}
facObj!.augmentations.push(this.name);
facObj.augmentations.push(this.name);
}
}
}
@@ -163,6 +159,12 @@ export class Augmentation {
toJSON(): any {
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;

View File

@@ -8,29 +8,14 @@ import { AugmentationsRoot } from "./ui/Root";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { CONSTANTS } from "../Constants";
import { Factions, factionExists } from "../Faction/Factions";
import { startWorkerScript } from "../NetscriptWorker";
import { Player } from "../Player";
import { prestigeAugmentation } from "../Prestige";
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 { onExport } from "../ExportBonus";
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 { createElement } from "../../utils/uiHelpers/createElement";
import { isString } from "../../utils/helpers/isString";
import { removeChildrenFromElement } from "../../utils/uiHelpers/removeChildrenFromElement";
import { Money } from "../ui/React/Money";
import React from "react";
@@ -76,7 +61,7 @@ function initAugmentations() {
"This augmentation increases the player's dexterity by 10%.",
dexterity_mult: 1.1,
});
Targeting1.addToFactions(["Slum Snakes", "The Dark Army", "The Syndicate", "Sector-12", "Volhaven", "Ishima",
Targeting1.addToFactions(["Slum Snakes", "The Dark Army", "The Syndicate", "Sector-12", "Ishima",
"OmniTek Incorporated", "KuaiGong International", "Blade Industries"]);
if (augmentationExists(AugmentationNames.Targeting1)) {
delete Augmentations[AugmentationNames.Targeting1];
@@ -91,7 +76,7 @@ function initAugmentations() {
prereqs:[AugmentationNames.Targeting1],
dexterity_mult: 1.2,
});
Targeting2.addToFactions(["The Dark Army", "The Syndicate", "Sector-12", "Volhaven", "Ishima",
Targeting2.addToFactions(["The Dark Army", "The Syndicate", "Sector-12",
"OmniTek Incorporated", "KuaiGong International", "Blade Industries"]);
if (augmentationExists(AugmentationNames.Targeting2)) {
delete Augmentations[AugmentationNames.Targeting2];
@@ -152,7 +137,7 @@ function initAugmentations() {
strength_mult: 1.1,
defense_mult: 1.1,
});
CombatRib1.addToFactions(["Slum Snakes", "The Dark Army", "The Syndicate", "Sector-12", "Volhaven", "Ishima",
CombatRib1.addToFactions(["Slum Snakes", "The Dark Army", "The Syndicate", "Volhaven", "Ishima",
"OmniTek Incorporated", "KuaiGong International", "Blade Industries"]);
if (augmentationExists(AugmentationNames.CombatRib1)) {
delete Augmentations[AugmentationNames.CombatRib1];
@@ -168,7 +153,7 @@ function initAugmentations() {
strength_mult: 1.14,
defense_mult: 1.14,
});
CombatRib2.addToFactions(["The Dark Army", "The Syndicate", "Sector-12", "Volhaven", "Ishima",
CombatRib2.addToFactions(["The Dark Army", "The Syndicate", "Volhaven",
"OmniTek Incorporated", "KuaiGong International", "Blade Industries"]);
if (augmentationExists(AugmentationNames.CombatRib2)) {
delete Augmentations[AugmentationNames.CombatRib2];
@@ -404,7 +389,7 @@ function initAugmentations() {
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>" +
"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 experience gain rate by 5%.",
hacking_speed_mult: 1.02,
@@ -444,7 +429,7 @@ function initAugmentations() {
"This augmentation increases the player's hacking speed by 3%.",
hacking_speed_mult: 1.03,
});
SynapticEnhancement.addToFactions(["CyberSec"]);
SynapticEnhancement.addToFactions(["CyberSec", "Aevum"]);
if (augmentationExists(AugmentationNames.SynapticEnhancement)) {
delete Augmentations[AugmentationNames.SynapticEnhancement];
}
@@ -772,7 +757,7 @@ function initAugmentations() {
"when working for a company by 20%.",
company_rep_mult: 1.2,
});
NuoptimalInjectorImplant.addToFactions(["Tian Di Hui", "Volhaven", "New Tokyo", "Chongqing", "Ishima",
NuoptimalInjectorImplant.addToFactions(["Tian Di Hui", "Volhaven", "New Tokyo", "Chongqing",
"Clarke Incorporated", "Four Sigma", "Bachman & Associates"]);
if (augmentationExists(AugmentationNames.NuoptimalInjectorImplant)) {
delete Augmentations[AugmentationNames.NuoptimalInjectorImplant];
@@ -1080,7 +1065,7 @@ function initAugmentations() {
agility_exp_mult: 1.1,
charisma_exp_mult: 1.1,
});
Neurotrainer1.addToFactions(["CyberSec"]);
Neurotrainer1.addToFactions(["CyberSec", "Aevum"]);
if (augmentationExists(AugmentationNames.Neurotrainer1)) {
delete Augmentations[AugmentationNames.Neurotrainer1];
}
@@ -1256,7 +1241,7 @@ function initAugmentations() {
// Daedalus
const RedPill = new Augmentation({
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"]);
if (augmentationExists(AugmentationNames.TheRedPill)) {
@@ -1332,7 +1317,7 @@ function initAugmentations() {
"capable of psychoanalyzing and profiling the personality of " +
"others using optical imaging software.<br><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 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%.",
@@ -1556,7 +1541,7 @@ function initAugmentations() {
and upload the assets.<br /><br />
This augmentation:<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"]);
if (augmentationExists(AugmentationNames.CashRoot)) {
@@ -1743,7 +1728,7 @@ function initAugmentations() {
"to induce wakefulness and concentration, suppress fear, reduce empathy, and " +
"improve reflexes and memory-recall among other things.<br><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 Bladeburner stamina gain rate by 2%.",
bladeburner_success_chance_mult: 1.03,
@@ -2093,12 +2078,17 @@ export function displayAugmentationsContent(contentEl) {
if (!routing.isOn(Page.Augmentations)) { return; }
if (!(contentEl instanceof HTMLElement)) { return; }
function backup() {
saveObject.exportGame();
onExport(Player);
}
ReactDOM.render(
<AugmentationsRoot
exportGameFn={saveObject.exportGame.bind(saveObject)}
exportGameFn={backup}
installAugmentationsFn={installAugmentations}
/>,
contentEl
contentEl,
);
}

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
import { IMap } from "../../types";
export let AugmentationNames: IMap<string> = {
export const AugmentationNames: IMap<string> = {
Targeting1: "Augmented Targeting I",
Targeting2: "Augmented Targeting II",
Targeting3: "Augmented Targeting III",

View File

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

View File

@@ -7,7 +7,7 @@ import { Player } from "../../Player";
import { numeralWrapper } from "../../ui/numeralFormat";
import { Augmentations} from "../Augmentations";
function calculateAugmentedStats() {
function calculateAugmentedStats(): any {
const augP: any = {};
for(const aug of Player.queuedAugmentations) {
const augObj = Augmentations[aug.name];
@@ -22,12 +22,12 @@ function calculateAugmentedStats() {
export function PlayerMultipliers(): React.ReactElement {
const mults = calculateAugmentedStats();
function MultiplierTable(rows: any[]): React.ReactElement {
function improvements(r: number) {
let elems: any[] = [];
function improvements(r: number): JSX.Element[] {
let elems: JSX.Element[] = [];
if(r) {
elems = [
<td key="2">&nbsp;{"=>"}&nbsp;</td>,
<td key="3">{numeralWrapper.formatPercentage(r)}</td>
<td key="3">{numeralWrapper.formatPercentage(r)}</td>,
];
}
return elems;
@@ -44,6 +44,18 @@ export function PlayerMultipliers(): React.ReactElement {
</table>
}
function BladeburnerMults(): React.ReactElement {
if(!Player.canAccessBladeburner()) return (<></>);
return (<>
{MultiplierTable([
['Bladeburner Success Chance', Player.bladeburner_max_stamina_mult, Player.bladeburner_max_stamina_mult*mults.bladeburner_max_stamina_mult],
['Bladeburner Max Stamina', Player.bladeburner_max_stamina_mult, Player.bladeburner_max_stamina_mult*mults.bladeburner_max_stamina_mult],
['Bladeburner Stamina Gain', Player.bladeburner_max_stamina_mult, Player.bladeburner_max_stamina_mult*mults.bladeburner_max_stamina_mult],
['Bladeburner Field Analysis', Player.bladeburner_max_stamina_mult, Player.bladeburner_max_stamina_mult*mults.bladeburner_max_stamina_mult],
])}<br />
</>);
}
return (
<>
<p><strong><u>Multipliers:</u></strong></p><br />
@@ -51,38 +63,38 @@ export function PlayerMultipliers(): React.ReactElement {
['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 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 />
{MultiplierTable([
['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 />
{MultiplierTable([
['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 />
{MultiplierTable([
['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 />
{MultiplierTable([
['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 />
{MultiplierTable([
['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 />
{MultiplierTable([
['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 />
{MultiplierTable([
@@ -90,19 +102,21 @@ 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 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 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 />
{MultiplierTable([
['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],
['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 />
{MultiplierTable([
['Crime success ', Player.crime_success_mult, Player.crime_success_mult*mults.crime_success_mult],
['Crime money ', Player.crime_money_mult, Player.crime_money_mult*mults.crime_money_mult],
])}<br />
<BladeburnerMults />
</>
)
}

View File

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

View File

@@ -10,6 +10,8 @@ import { PurchasedAugmentations } from "./PurchasedAugmentations";
import { Player } from "../../Player";
import { StdButton } from "../../ui/React/StdButton";
import { LastExportBonus, canGetBonus } from "../../ExportBonus";
import { convertTimeMsToTimeElapsedString } from "../../../utils/StringHelperFunctions";
type IProps = {
exportGameFn: () => void;
@@ -17,15 +19,31 @@ type IProps = {
}
type IState = {
rerender: boolean;
}
export class AugmentationsRoot extends React.Component<IProps, IState> {
constructor(props: IProps) {
super(props);
this.state = {
rerender: false,
};
this.export = this.export.bind(this);
}
render() {
export() {
this.props.exportGameFn();
this.setState({
rerender: !this.state.rerender,
});
}
render(): React.ReactNode {
function exportBonusStr(): string {
if(canGetBonus()) return "(+1 favor to all factions)";
return "";
}
return (
<div id="augmentations-content">
<h1>Purchased Augmentations</h1>
@@ -60,8 +78,8 @@ export class AugmentationsRoot extends React.Component<IProps, IState> {
<StdButton
addClasses="flashing-button"
onClick={this.props.exportGameFn}
text="Backup Save (Export)"
onClick={this.export}
text={`Backup Save ${exportBonusStr()}`}
tooltip="It's always a good idea to backup/export your save!"
/>
<PurchasedAugmentations />

View File

@@ -5,15 +5,12 @@
import * as React from "react";
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 { Accordion } from "../../ui/React/Accordion";
export function SourceFileMinus1(): React.ReactElement {
let exploits = Player.exploits;
const exploits = Player.exploits;
if(exploits.length === 0) {
return <></>

View File

@@ -16,7 +16,7 @@ class BitNode {
number: number;
constructor(n: number, name: string, desc: string="", info: string="") {
constructor(n: number, name: string, desc="", info="") {
this.number = n;
this.name = name;
this.desc = desc;
@@ -221,7 +221,7 @@ BitNodes["BitNode11"] = new BitNode(11, "The Big Crash", "Okay. Sell it all.",
"The growth rate of servers is significantly reduced<br>" +
"Weakening a server is twice as effective<br>" +
"Company wages are decreased by 50%<br>" +
"Corporation valuations are 99% lower and are therefore significantly less profitable<br>" +
"Corporation valuations are 90% lower and are therefore significantly less profitable<br>" +
"Hacknet Node production is significantly decreased<br>" +
"Crime and Infiltration are more lucrative<br>" +
"Augmentations are twice as expensive<br><br>" +
@@ -236,8 +236,7 @@ BitNodes["BitNode12"] = new BitNode(12, "The Recursion", "Repeat.",
"To iterate is human, to recurse divine.<br><br>" +
"Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give 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 " +
"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)");
"of Source-File 12 lets you start any BitNodes with NeuroFlux Governor equal to the level of this source file.");
// Books: Frontera, Shiner
BitNodes["BitNode13"] = new BitNode(13, "fOS", "COMING SOON"); //Unlocks the new game mode and the rest of the BitNodes
BitNodes["BitNode14"] = new BitNode(14, "", "COMING SOON");
@@ -252,11 +251,11 @@ BitNodes["BitNode22"] = new BitNode(22, "", "COMING SOON");
BitNodes["BitNode23"] = new BitNode(23, "", "COMING SOON");
BitNodes["BitNode24"] = new BitNode(24, "", "COMING SOON");
export function initBitNodeMultipliers(p: IPlayer) {
export function initBitNodeMultipliers(p: IPlayer): void {
if (p.bitNodeN == null) {
p.bitNodeN = 1;
}
for (var mult in BitNodeMultipliers) {
for (const mult in BitNodeMultipliers) {
if (BitNodeMultipliers.hasOwnProperty(mult)) {
BitNodeMultipliers[mult] = 1;
}
@@ -433,15 +432,15 @@ export function initBitNodeMultipliers(p: IPlayer) {
BitNodeMultipliers.FourSigmaMarketDataCost = 4;
BitNodeMultipliers.FourSigmaMarketDataApiCost = 4;
break;
case 12: //The Recursion
var sf12Lvl = 0;
for (var i = 0; i < p.sourceFiles.length; i++) {
case 12: { //The Recursion
let sf12Lvl = 0;
for (let i = 0; i < p.sourceFiles.length; i++) {
if (p.sourceFiles[i].n === 12) {
sf12Lvl = p.sourceFiles[i].lvl;
}
}
var inc = Math.pow(1.02, sf12Lvl);
var dec = 1/inc;
const inc = Math.pow(1.02, sf12Lvl);
const dec = 1/inc;
// Multiplier for number of augs needed for Daedalus increases
// up to a maximum of 1.34, which results in 40 Augs required
@@ -499,6 +498,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
BitNodeMultipliers.BladeburnerRank = dec;
BitNodeMultipliers.BladeburnerSkillCost = inc;
break;
}
default:
console.warn("Player.bitNodeN invalid");
break;

View File

@@ -1,7 +1,6 @@
import { Augmentations } from "./Augmentation/Augmentations";
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers";
import { CONSTANTS } from "./Constants";
import { Engine } from "./engine";
import { Faction } from "./Faction/Faction";
import { Factions, factionExists } from "./Faction/Factions";
@@ -17,17 +16,20 @@ import { dialogBoxCreate } from "../utils/DialogBox";
import {
Reviver,
Generic_toJSON,
Generic_fromJSON
Generic_fromJSON,
} from "../utils/JSONReviver";
import { setTimeoutRef } from "./utils/SetTimeoutRef";
import { formatNumber } from "../utils/StringHelperFunctions";
import {
formatNumber,
convertTimeMsToTimeElapsedString,
} from "../utils/StringHelperFunctions";
import { Settings } from "./Settings/Settings";
import { ConsoleHelpText } from "./Bladeburner/data/Help";
import { City } from "./Bladeburner/City";
import { BladeburnerConstants } from "./Bladeburner/data/Constants";
import { Skill } from "./Bladeburner/Skill";
import { Skills } from "./Bladeburner/Skills";
import { SkillNames } from "./Bladeburner/data/SkillNames";
import { Operation } from "./Bladeburner/Operation";
import { BlackOperation } from "./Bladeburner/BlackOperation";
import { BlackOperations } from "./Bladeburner/BlackOperations";
@@ -45,7 +47,6 @@ import { KEY } from "../utils/helpers/keyCodes";
import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
import { appendLineBreaks } from "../utils/uiHelpers/appendLineBreaks";
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
import { createElement } from "../utils/uiHelpers/createElement";
import { createPopup } from "../utils/uiHelpers/createPopup";
import { removeElement } from "../utils/uiHelpers/removeElement";
@@ -158,6 +159,7 @@ function Bladeburner(params={}) {
// These times are in seconds
this.actionTimeToComplete = 0; // 0 or -1 is an infinite running action (like training)
this.actionTimeCurrent = 0;
this.actionTimeOverflow = 0;
// ActionIdentifier Object
var idleActionType = ActionTypes["Idle"];
@@ -236,7 +238,7 @@ Bladeburner.prototype.create = function() {
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},
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({
name:"Bounty Hunter",
@@ -248,7 +250,7 @@ Bladeburner.prototype.create = function() {
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},
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({
name:"Retirement",
@@ -260,7 +262,7 @@ Bladeburner.prototype.create = function() {
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},
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({
@@ -275,7 +277,7 @@ Bladeburner.prototype.create = function() {
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},
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({
name:"Undercover Operation",
@@ -288,7 +290,7 @@ Bladeburner.prototype.create = function() {
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},
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({
name:"Sting Operation",
@@ -299,19 +301,19 @@ Bladeburner.prototype.create = function() {
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},
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({
name:"Raid",
desc:"Lead an assault on a known Synthoid community. Note that " +
"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,
rankGain:55,rankLoss:2.5,hpLoss:50,
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},
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({
name:"Stealth Retirement Operation",
@@ -323,7 +325,7 @@ Bladeburner.prototype.create = function() {
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},
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({
name:"Assassination",
@@ -335,7 +337,7 @@ Bladeburner.prototype.create = function() {
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},
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,
});
}
@@ -358,7 +360,9 @@ Bladeburner.prototype.process = function() {
msg += `<br><br>Your automation was disabled as well. You will have to re-enable it through the Bladeburner console`
this.automateEnabled = false;
}
dialogBoxCreate(msg);
if (!Settings.SuppressBladeburnerPopup) {
dialogBoxCreate(msg);
}
}
this.resetAction();
}
@@ -381,22 +385,16 @@ Bladeburner.prototype.process = function() {
this.stamina = Math.min(this.maxStamina, this.stamina);
// Count increase for contracts/operations
for (var contractName in this.contracts) {
if (this.contracts.hasOwnProperty(contractName)) {
var contract = this.contracts[contractName];
contract.count += (seconds * contract.countGrowth/BladeburnerConstants.ActionCountGrowthPeriod);
}
for (let contract of Object.values(this.contracts)) {
contract.count += (seconds * contract.countGrowth/BladeburnerConstants.ActionCountGrowthPeriod);
}
for (var operationName in this.operations) {
if (this.operations.hasOwnProperty(operationName)) {
var op = this.operations[operationName];
op.count += (seconds * op.countGrowth/BladeburnerConstants.ActionCountGrowthPeriod);
}
for (let op of Object.values(this.operations)) {
op.count += (seconds * op.countGrowth/BladeburnerConstants.ActionCountGrowthPeriod);
}
// Chaos goes down very slowly
for (var i = 0; i < BladeburnerConstants.CityNames.length; ++i) {
var city = this.cities[BladeburnerConstants.CityNames[i]];
for (let cityName of BladeburnerConstants.CityNames) {
var city = this.cities[cityName];
if (!(city instanceof City)) {throw new Error("Invalid City object when processing passive chaos reduction in Bladeburner.process");}
city.chaos -= (0.0001 * seconds);
city.chaos = Math.max(0, city.chaos);
@@ -406,7 +404,8 @@ Bladeburner.prototype.process = function() {
this.randomEventCounter -= seconds;
if (this.randomEventCounter <= 0) {
this.randomEvent();
this.randomEventCounter = getRandomInt(240, 600);
// Add instead of setting because we might have gone over the required time for the event
this.randomEventCounter += getRandomInt(240, 600);
}
this.processAction(seconds);
@@ -664,8 +663,12 @@ Bladeburner.prototype.processAction = function(seconds) {
throw new Error("Bladeburner.action is not an ActionIdentifier Object");
}
this.actionTimeCurrent += seconds;
// If the previous action went past its completion time, add to the next action
// This is not added inmediatly in case the automation changes the action
this.actionTimeCurrent += seconds + this.actionTimeOverflow;
this.actionTimeOverflow = 0;
if (this.actionTimeCurrent >= this.actionTimeToComplete) {
this.actionTimeOverflow = this.actionTimeCurrent - this.actionTimeToComplete;
return this.completeAction();
}
}
@@ -736,7 +739,7 @@ Bladeburner.prototype.completeAction = function() {
}
}
var logLossText = "";
if (loss > 0) {logLossText += "Lost " + formatNumber(loss, 3) + " rank.";}
if (loss > 0) {logLossText += "Lost " + formatNumber(loss, 3) + " rank. ";}
if (damage > 0) {logLossText += "Took " + formatNumber(damage, 0) + " damage.";}
if (isOperation && this.logging.ops) {
this.log(action.name + " failed! " + logLossText);
@@ -1271,7 +1274,7 @@ Bladeburner.prototype.createContent = function() {
DomElems.consoleInput.focus();
}
return false;
}
},
});
DomElems.consoleTable = createElement("table", {class:"bladeburner-console-table"});
DomElems.consoleInputRow = createElement("tr", {class:"bladeburner-console-input-row", id:"bladeburner-console-input-row"});
@@ -1279,7 +1282,7 @@ Bladeburner.prototype.createContent = function() {
DomElems.consoleInputHeader = createElement("pre", {innerText:"> "});
DomElems.consoleInput = createElement("input", {
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);
@@ -1363,7 +1366,7 @@ Bladeburner.prototype.createOverviewContent = function() {
innerText:"Est. Synthoid Population: ",
display:"inline-block",
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", {
@@ -1381,7 +1384,7 @@ Bladeburner.prototype.createOverviewContent = function() {
"The Synthoid populations of cities can change due to your " +
"actions or random events. If random events occur, they will " +
"be logged in the Bladeburner Console.");
}
},
});
DomElems.overviewEstComms = createElement("p", {
@@ -1395,14 +1398,14 @@ Bladeburner.prototype.createOverviewContent = function() {
innerText:"City Chaos: ",
display:"inline-block",
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", {
innerText: "Bonus time: ",
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). " +
"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"});
@@ -1438,7 +1441,7 @@ Bladeburner.prototype.createOverviewContent = function() {
innerText:"Cancel", class:"a-link-button",
clickListener:() => {
removeElementById(popupId); return false;
}
},
}))
popupArguments.push(createElement("p", { // Info Text
innerText:"Travel to a different city for your Bladeburner " +
@@ -1460,12 +1463,12 @@ Bladeburner.prototype.createOverviewContent = function() {
removeElementById(popupId);
inst.updateOverviewContent();
return false;
}
},
}));
})(this, i);
}
createPopup(popupId, popupArguments);
}
},
}));
// Faction button
@@ -1493,7 +1496,7 @@ Bladeburner.prototype.createOverviewContent = function() {
}
}
return false;
}
},
}));
}
@@ -1526,14 +1529,14 @@ Bladeburner.prototype.createActionAndSkillsContent = function() {
DomElems.currentTab = buttons[i].toLowerCase();
inst.createActionAndSkillsContent();
return false;
}
},
}));
}) (buttons, i, this, currTab);
}
// General info/description for each action
DomElems.actionsAndSkillsDesc = createElement("p", {
display:"block", margin:"4px", padding:"4px"
display:"block", margin:"4px", padding:"4px",
});
// List for actions/skills
@@ -1578,7 +1581,7 @@ Bladeburner.prototype.createGeneralActionsContent = function() {
for (var actionName in GeneralActions) {
if (GeneralActions.hasOwnProperty(actionName)) {
DomElems.generalActions[actionName] = createElement("div", {
class:"bladeburner-action", name:actionName
class:"bladeburner-action", name:actionName,
});
DomElems.actionsAndSkillsList.appendChild(DomElems.generalActions[actionName]);
}
@@ -1600,7 +1603,7 @@ Bladeburner.prototype.createContractsContent = function() {
for (var contractName in this.contracts) {
if (this.contracts.hasOwnProperty(contractName)) {
DomElems.contracts[contractName] = createElement("div", {
class:"bladeburner-action", name:contractName
class:"bladeburner-action", name:contractName,
});
DomElems.actionsAndSkillsList.appendChild(DomElems.contracts[contractName]);
}
@@ -1629,7 +1632,7 @@ Bladeburner.prototype.createOperationsContent = function() {
for (var operationName in this.operations) {
if (this.operations.hasOwnProperty(operationName)) {
DomElems.operations[operationName] = createElement("div", {
class:"bladeburner-action", name:operationName
class:"bladeburner-action", name:operationName,
});
DomElems.actionsAndSkillsList.appendChild(DomElems.operations[operationName]);
}
@@ -1667,7 +1670,7 @@ Bladeburner.prototype.createBlackOpsContent = function() {
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.
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]);
}
@@ -1750,7 +1753,7 @@ Bladeburner.prototype.createSkillsContent = function() {
// Skill Points
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);
@@ -1758,7 +1761,7 @@ Bladeburner.prototype.createSkillsContent = function() {
for (var skillName in Skills) {
if (Skills.hasOwnProperty(skillName)) {
DomElems.skills[skillName] = createElement("div", {
class:"bladeburner-action", name:skillName
class:"bladeburner-action", name:skillName,
});
DomElems.actionsAndSkillsList.appendChild(DomElems.skills[skillName]);
}
@@ -1889,20 +1892,21 @@ Bladeburner.prototype.updateActionAndSkillsContent = function() {
Bladeburner.prototype.updateGeneralActionsUIElement = function(el, action) {
removeChildrenFromElement(el);
var isActive = el.classList.contains(ActiveActionCssClass);
var computedActionTimeCurrent = Math.min(this.actionTimeCurrent+this.actionTimeOverflow,this.actionTimeToComplete);
el.appendChild(createElement("h2", { // Header
innerText:isActive ? action.name + " (IN PROGRESS - " +
formatNumber(this.actionTimeCurrent, 0) + " / " +
formatNumber(computedActionTimeCurrent, 0) + " / " +
formatNumber(this.actionTimeToComplete, 0) + ")"
: action.name,
display:"inline-block",
}));
if (isActive) { // Progress bar if its active
var progress = this.actionTimeCurrent / this.actionTimeToComplete;
var progress = computedActionTimeCurrent / this.actionTimeToComplete;
el.appendChild(createElement("p", {
display:"block",
innerText:createProgressBarText({progress:progress})
innerText:createProgressBarText({progress:progress}),
}));
} else {
// Start button
@@ -1915,13 +1919,13 @@ Bladeburner.prototype.updateGeneralActionsUIElement = function(el, action) {
this.startAction(this.action);
this.updateActionAndSkillsContent();
return false;
}
},
}));
}
appendLineBreaks(el, 2);
el.appendChild(createElement("pre", { // Info
innerHTML:action.desc, display:"inline-block"
innerHTML:action.desc, display:"inline-block",
}));
@@ -1931,20 +1935,21 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
removeChildrenFromElement(el);
var isActive = el.classList.contains(ActiveActionCssClass);
var estimatedSuccessChance = action.getSuccessChance(this, {est:true});
var computedActionTimeCurrent = Math.min(this.actionTimeCurrent+this.actionTimeOverflow,this.actionTimeToComplete);
el.appendChild(createElement("h2", { // Header
innerText:isActive ? action.name + " (IN PROGRESS - " +
formatNumber(this.actionTimeCurrent, 0) + " / " +
formatNumber(computedActionTimeCurrent, 0) + " / " +
formatNumber(this.actionTimeToComplete, 0) + ")"
: action.name,
display:"inline-block"
display:"inline-block",
}));
if (isActive) { // Progress bar if its active
var progress = this.actionTimeCurrent / this.actionTimeToComplete;
var progress = computedActionTimeCurrent / this.actionTimeToComplete;
el.appendChild(createElement("p", {
display:"block",
innerText:createProgressBarText({progress:progress})
innerText:createProgressBarText({progress:progress}),
}));
} else { // Start button
el.appendChild(createElement("a", {
@@ -1956,7 +1961,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
this.startAction(this.action);
this.updateActionAndSkillsContent();
return false;
}
},
}));
}
@@ -1967,7 +1972,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
display:"inline-block",
innerText:"Level: " + action.level + " / " + action.maxLevel,
tooltip:action.getSuccessesNeededForNextLevel(BladeburnerConstants.ContractSuccessesPerLevel) + " successes " +
"needed for next level"
"needed for next level",
}));
el.appendChild(createElement("a", {
class: maxLevel ? "a-link-button-inactive" : "a-link-button", innerHTML:"&uarr;",
@@ -1979,7 +1984,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
if (isActive) {this.startAction(this.action);} // Restart Action
this.updateContractsUIElement(el, action);
return false;
}
},
}));
el.appendChild(createElement("a", {
class: (action.level <= 1) ? "a-link-button-inactive" : "a-link-button", innerHTML:"&darr;",
@@ -1991,7 +1996,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
if (isActive) {this.startAction(this.action);} // Restart Action
this.updateContractsUIElement(el, action);
return false;
}
},
}));
var actionTime = action.getActionTime(this);
@@ -2011,7 +2016,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
var autolevelCheckboxId = "bladeburner-" + action.name + "-autolevel-checkbox";
el.appendChild(createElement("label", {
for:autolevelCheckboxId, innerText:"Autolevel: ",color:"white",
tooltip:"Automatically increase contract level when possible"
tooltip:"Automatically increase contract level when possible",
}));
const checkboxInput = createElement("input", {
@@ -2030,19 +2035,21 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
removeChildrenFromElement(el);
var isActive = el.classList.contains(ActiveActionCssClass);
var estimatedSuccessChance = action.getSuccessChance(this, {est:true});
var computedActionTimeCurrent = Math.min(this.actionTimeCurrent+this.actionTimeOverflow,this.actionTimeToComplete);
el.appendChild(createElement("h2", { // Header
innerText:isActive ? action.name + " (IN PROGRESS - " +
formatNumber(this.actionTimeCurrent, 0) + " / " +
formatNumber(computedActionTimeCurrent, 0) + " / " +
formatNumber(this.actionTimeToComplete, 0) + ")"
: action.name,
display:"inline-block"
display:"inline-block",
}));
if (isActive) { // Progress bar if its active
var progress = this.actionTimeCurrent / this.actionTimeToComplete;
var progress = computedActionTimeCurrent / this.actionTimeToComplete;
el.appendChild(createElement("p", {
display:"block",
innerText:createProgressBarText({progress:progress})
innerText:createProgressBarText({progress:progress}),
}));
} else { // Start button and set Team Size button
el.appendChild(createElement("a", {
@@ -2054,7 +2061,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
this.startAction(this.action);
this.updateActionAndSkillsContent();
return false;
}
},
}));
el.appendChild(createElement("a", {
innerText:"Set Team Size (Curr Size: " + formatNumber(action.teamCount, 0) + ")", class:"a-link-button",
@@ -2065,7 +2072,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
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, " +
"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", {
@@ -2083,17 +2090,18 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
}
removeElementById(popupId);
return false;
}
},
});
var cancelBtn = createElement("a", {
innerText:"Cancel", class:"a-link-button",
clickListener:() => {
removeElementById(popupId);
return false;
}
},
});
createPopup(popupId, [txt, input, setBtn, cancelBtn]);
}
input.focus();
},
}));
}
@@ -2104,7 +2112,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
display:"inline-block",
innerText:"Level: " + action.level + " / " + action.maxLevel,
tooltip:action.getSuccessesNeededForNextLevel(BladeburnerConstants.OperationSuccessesPerLevel) + " successes " +
"needed for next level"
"needed for next level",
}));
el.appendChild(createElement("a", {
class: maxLevel ? "a-link-button-inactive" : "a-link-button", innerHTML:"&uarr;",
@@ -2116,7 +2124,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
if (isActive) {this.startAction(this.action);} // Restart Action
this.updateOperationsUIElement(el, action);
return false;
}
},
}));
el.appendChild(createElement("a", {
class: (action.level <= 1) ? "a-link-button-inactive" : "a-link-button", innerHTML:"&darr;",
@@ -2128,11 +2136,10 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
if (isActive) {this.startAction(this.action);} // Restart Action
this.updateOperationsUIElement(el, action);
return false;
}
},
}));
// General Info
var difficulty = action.getDifficulty();
var actionTime = action.getActionTime(this);
appendLineBreaks(el, 2);
el.appendChild(createElement("pre", {
@@ -2150,7 +2157,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
var autolevelCheckboxId = "bladeburner-" + action.name + "-autolevel-checkbox";
el.appendChild(createElement("label", {
for:autolevelCheckboxId, innerText:"Autolevel: ",color:"white",
tooltip:"Automatically increase operation level when possible"
tooltip:"Automatically increase operation level when possible",
}));
const checkboxInput = createElement("input", {
@@ -2170,9 +2177,9 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
var isActive = el.classList.contains(ActiveActionCssClass);
var isCompleted = (this.blackops[action.name] != null);
var estimatedSuccessChance = action.getSuccessChance(this, {est:true});
var difficulty = action.getDifficulty();
var actionTime = action.getActionTime(this);
var hasReqdRank = this.rank >= action.reqdRank;
var computedActionTimeCurrent = Math.min(this.actionTimeCurrent+this.actionTimeOverflow,this.actionTimeToComplete);
// UI for Completed Black Op
if (isCompleted) {
@@ -2184,17 +2191,17 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
el.appendChild(createElement("h2", { // Header
innerText:isActive ? action.name + " (IN PROGRESS - " +
formatNumber(this.actionTimeCurrent, 0) + " / " +
formatNumber(computedActionTimeCurrent, 0) + " / " +
formatNumber(this.actionTimeToComplete, 0) + ")"
: action.name,
display:"inline-block",
}));
if (isActive) { // Progress bar if its active
var progress = this.actionTimeCurrent / this.actionTimeToComplete;
var progress = computedActionTimeCurrent / this.actionTimeToComplete;
el.appendChild(createElement("p", {
display:"block",
innerText:createProgressBarText({progress:progress})
innerText:createProgressBarText({progress:progress}),
}));
} else {
el.appendChild(createElement("a", { // Start button
@@ -2206,7 +2213,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
this.startAction(this.action);
this.updateActionAndSkillsContent();
return false;
}
},
}));
el.appendChild(createElement("a", { // Set Team Size Button
innerText:"Set Team Size (Curr Size: " + formatNumber(action.teamCount, 0) + ")", class:"a-link-button",
@@ -2217,7 +2224,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
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, " +
"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", {
@@ -2235,17 +2242,18 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
}
removeElementById(popupId);
return false;
}
},
});
var cancelBtn = createElement("a", {
innerText:"Cancel", class:"a-link-button",
clickListener:() => {
removeElementById(popupId);
return false;
}
},
});
createPopup(popupId, [txt, input, setBtn, cancelBtn]);
}
input.focus();
},
}));
}
@@ -2257,7 +2265,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
}));
el.appendChild(createElement("p", {
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", {
display:"inline-block",
@@ -2297,7 +2305,7 @@ Bladeburner.prototype.updateSkillsUIElement = function(el, skill) {
this.upgradeSkill(skill);
this.createActionAndSkillsContent();
return false;
}
},
}));
appendLineBreaks(el, 2);
el.appendChild(createElement("p", {
@@ -2307,7 +2315,7 @@ Bladeburner.prototype.updateSkillsUIElement = function(el, skill) {
if (maxLvl) {
el.appendChild(createElement("p", {
color:"red", display:"block",
innerText:"MAX LEVEL"
innerText:"MAX LEVEL",
}));
} else {
el.appendChild(createElement("p", {
@@ -2508,7 +2516,7 @@ Bladeburner.prototype.executeAutomateConsoleCommand = function(args) {
case "gen":
if (GeneralActions[val] != null) {
var action = new ActionIdentifier({
type:ActionTypes[val], name:val
type:ActionTypes[val], name:val,
});
if (highLow) {
this.automateActionHigh = action;
@@ -2524,7 +2532,7 @@ Bladeburner.prototype.executeAutomateConsoleCommand = function(args) {
case "contracts":
if (this.contracts[val] != null) {
var action = new ActionIdentifier({
type:ActionTypes.Contract, name:val
type:ActionTypes.Contract, name:val,
});
if (highLow) {
this.automateActionHigh = action;
@@ -2542,7 +2550,7 @@ Bladeburner.prototype.executeAutomateConsoleCommand = function(args) {
case "operation":
if (this.operations[val] != null) {
var action = new ActionIdentifier({
type:ActionTypes.Operation, name:val
type:ActionTypes.Operation, name:val,
});
if (highLow) {
this.automateActionHigh = action;
@@ -3210,7 +3218,7 @@ Bladeburner.prototype.setTeamSizeNetscriptFn = function(type, name, size, worker
return -1;
}
const sanitizedSize = Math.round(size);
let sanitizedSize = Math.round(size);
if (isNaN(sanitizedSize) || sanitizedSize < 0) {
workerScript.log("bladeburner.setTeamSize", `Invalid size: ${size}`);
return -1;

View File

@@ -3,21 +3,20 @@ import { getRandomInt } from "../../utils/helpers/getRandomInt";
import { addOffset } from "../../utils/helpers/addOffset";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
import { BladeburnerConstants } from "./data/Constants";
// import { Contract } from "./Contract";
// import { Operation } from "./Operation";
// import { BlackOperation } from "./BlackOperation";
import { IBladeburner } from "./IBladeburner";
import { IAction, ISuccessChanceParams } from "./IAction";
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;
};
hack = 0;
str = 0;
def = 0;
dex = 0;
agi = 0;
cha = 0;
int = 0;
}
export interface IActionParams {
name?: string;
@@ -43,32 +42,32 @@ export interface IActionParams {
teamCount?: number;
}
export class Action {
name: string = "";
desc: string = "";
export class Action implements IAction {
name = "";
desc = "";
// Difficulty scales with level. See getDifficulty() method
level: number = 1;
maxLevel: number = 1;
autoLevel: boolean = true;
baseDifficulty: number = 100;
difficultyFac: number = 1.01;
level = 1;
maxLevel = 1;
autoLevel = true;
baseDifficulty = 100;
difficultyFac = 1.01;
// Rank increase/decrease is affected by this exponent
rewardFac: number = 1.02;
rewardFac = 1.02;
successes: number = 0;
failures: number = 0;
successes = 0;
failures = 0;
// All of these scale with level/difficulty
rankGain: number = 0;
rankLoss: number = 0;
hpLoss: number = 0;
hpLost: number = 0;
rankGain = 0;
rankLoss = 0;
hpLoss = 0;
hpLost = 0;
// Action Category. Current categories are stealth and kill
isStealth: boolean = false;
isKill: boolean = false;
isStealth = false;
isKill = false;
/**
* 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};
// 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 };
teamCount: number = 0;
teamCount = 0;
// Base Class for Contracts, Operations, and BlackOps
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
* @param inst {Bladeburner} - Bladeburner instance
*/
attempt(inst: any): boolean {
attempt(inst: IBladeburner): boolean {
return (Math.random() < this.getSuccessChance(inst));
}
@@ -147,7 +146,7 @@ export class Action {
return 1;
}
getActionTime(inst: any): number {
getActionTime(inst: IBladeburner): number {
const difficulty = this.getDifficulty();
let baseTime = difficulty / BladeburnerConstants.DifficultyToTimeFactor;
const skillFac = inst.skillMultipliers.actionTime; // Always < 1
@@ -165,15 +164,15 @@ export class Action {
}
// For actions that have teams. To be implemented by subtypes.
getTeamSuccessBonus(inst: any): number {
getTeamSuccessBonus(inst: IBladeburner): number {
return 1;
}
getActionTypeSkillSuccessBonus(inst: any): number {
getActionTypeSkillSuccessBonus(inst: IBladeburner): number {
return 1;
}
getChaosCompetencePenalty(inst: any, params: any): number {
getChaosCompetencePenalty(inst: IBladeburner, params: ISuccessChanceParams): number {
const city = inst.getCurrentCity();
if (params.est) {
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();
if (city.chaos > BladeburnerConstants.ChaosThreshold) {
const diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold);
@@ -198,14 +197,14 @@ export class Action {
* @params - options:
* 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");}
let difficulty = this.getDifficulty();
let competence = 0;
for (let stat in this.weights) {
for (const stat in this.weights) {
if (this.weights.hasOwnProperty(stat)) {
let playerStatLvl = Player.queryStatFromString(stat);
let key = "eff" + stat.charAt(0).toUpperCase() + stat.slice(1);
const playerStatLvl = Player.queryStatFromString(stat);
const key = "eff" + stat.charAt(0).toUpperCase() + stat.slice(1);
let effMultiplier = inst.skillMultipliers[key];
if (effMultiplier == null) {
console.error(`Failed to find Bladeburner Skill multiplier for: ${stat}`);
@@ -220,7 +219,7 @@ export class Action {
competence *= this.getTeamSuccessBonus(inst);
competence *= this.getChaosCompetencePenalty(inst, params);
difficulty *= this.getChaosDifficultyBonus(inst, params);
difficulty *= this.getChaosDifficultyBonus(inst);
if(this.name == "Raid" && inst.getCurrentCity().comms <= 0) {
return 0;
@@ -253,18 +252,14 @@ export class Action {
}
}
static fromJSON(value: any): Action {
return Generic_fromJSON(Action, value.data);
}
toJSON(): any {
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;

View File

@@ -13,21 +13,22 @@ export class BlackOperation extends Operation {
return 1.5;
}
getChaosCompetencePenalty(inst: any, params: any): number {
getChaosCompetencePenalty(/*inst: IBladeburner, params: ISuccessChanceParams*/): number {
return 1;
}
getChaosDifficultyBonus(inst: any, params: any): number {
getChaosDifficultyBonus(/*inst: IBladeburner, params: ISuccessChanceParams*/): number {
return 1;
}
static fromJSON(value: any): Operation {
return Generic_fromJSON(BlackOperation, value.data);
}
toJSON(): any {
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;

View File

@@ -16,7 +16,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
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},
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({
name:"Operation Zero",
@@ -33,7 +33,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
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},
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({
name:"Operation X",
@@ -52,7 +52,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
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},
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({
name:"Operation Titan",
@@ -70,7 +70,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
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},
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({
name:"Operation Ares",
@@ -84,7 +84,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
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},
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({
name:"Operation Archangel",
@@ -152,7 +152,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
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},
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({
name:"Operation Deckard",
@@ -160,7 +160,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
"technology in Operation K, we've discovered that a small group of " +
"MK-VI Synthoids were able to make off with the schematics and design " +
"of the technology before the Operation. It is almost a certainty that " +
"these Synthoids are some of the rogue MK-VI ones from the Synthoid Uprising." +
"these Synthoids are some of the rogue MK-VI ones from the Synthoid Uprising.<br><br>" +
"The goal of Operation Deckard is to hunt down these Synthoids and retire " +
"them. I don't need to tell you how critical this mission is.",
baseDifficulty:20e3, reqdRank:40e3,
@@ -202,7 +202,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
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},
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({
name:"Operation Shoulder of Orion",
@@ -218,7 +218,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
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},
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({
name:"Operation Hyron",
@@ -231,7 +231,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
"means that the supercomputer may be able to reason abstractly " +
"and become self-aware.<br><br>" +
"I do not need to remind you why sentient-level AIs pose a serious " +
"thread to all of mankind.<br><br>" +
"threat to all of mankind.<br><br>" +
"The research for this project is being conducted at one of Fulcrum " +
"Technologies secret facilities in Aevum, codenamed 'Alpha Ranch'. " +
"Infiltrate the compound, delete and destroy the work, and then find and kill the " +
@@ -240,7 +240,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
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},
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({
name:"Operation Morpheus",
@@ -257,7 +257,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
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},
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({
name:"Operation Ion Storm",
@@ -272,7 +272,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
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},
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({
name:"Operation Annihilus",
@@ -286,7 +286,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
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},
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({
name:"Operation Ultron",
@@ -306,7 +306,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
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},
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({
name:"Operation Centurion",
@@ -342,4 +342,4 @@ export const BlackOperations: IMap<BlackOperation> = {};
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},
});
})()
})()

View File

@@ -5,13 +5,13 @@ import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviv
import { addOffset } from "../../utils/helpers/addOffset";
export class ChangePopulationByCountParams {
estChange: number = 0;
estOffset: number = 0;
estChange = 0;
estOffset = 0;
}
export class ChangePopulationByPercentageParams {
nonZero: boolean = false;
changeEstEqually: boolean = false;
nonZero = false;
changeEstEqually = false;
}
export class City {
@@ -19,32 +19,32 @@ export class City {
/**
* Name of the city.
*/
name: string = "";
name = "";
/**
* Population of the city.
*/
pop: number = 0;
pop = 0;
/**
* Population estimation of the city.
*/
popEst: number = 0;
popEst = 0;
/**
* Number of communities in the city.
*/
comms: number = 0;
comms = 0;
/**
* Estimated number of communities in the city.
*/
commsEst: number = 0;
commsEst = 0;
/**
* Chaos level of the city.
*/
chaos: number = 0;
chaos = 0;
constructor(name: string = BladeburnerConstants.CityNames[2]) {
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%)
*/
improvePopulationEstimateByPercentage(p: number, skillMult: number=1): void {
improvePopulationEstimateByPercentage(p: number, skillMult=1): void {
p = p*skillMult;
if (isNaN(p)) {throw new Error("NaN passed into City.improvePopulationEstimateByPercentage()");}
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 (this.commsEst < this.comms) {
this.commsEst += n;
@@ -154,19 +154,20 @@ export class City {
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.
*/
toJSON(): any {
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;

View File

@@ -1,4 +1,4 @@
// import { BladeburnerConstants } from "./data/Constants";
import { IBladeburner } from "./IBladeburner";
import { Action, IActionParams } from "./Action";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
@@ -8,17 +8,18 @@ export class Contract extends Action {
super(params);
}
getActionTypeSkillSuccessBonus(inst: any): number {
getActionTypeSkillSuccessBonus(inst: IBladeburner): number {
return inst.skillMultipliers.successChanceContract;
}
static fromJSON(value: any): Contract {
return Generic_fromJSON(Contract, value.data);
}
toJSON(): any {
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;

View File

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

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

View File

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

View File

@@ -10,55 +10,55 @@ export const Skills: IMap<Skill> = {};
desc:"Each level of this skill increases your success chance " +
"for all Contracts, Operations, and BlackOps by 3%",
baseCost: 3, costInc: 2.1,
successChanceAll:3
successChanceAll:3,
});
Skills[SkillNames.Cloak] = new Skill({
name:SkillNames.Cloak,
desc:"Each level of this skill increases your " +
"success chance in stealth-related Contracts, Operations, and BlackOps by 5.5%",
baseCost: 2, costInc: 1.1,
successChanceStealth:5.5
successChanceStealth:5.5,
});
Skills[SkillNames.ShortCircuit] = new Skill({
name:SkillNames.ShortCircuit,
desc:"Each level of this skill increases your success chance " +
"in Contracts, Operations, and BlackOps that involve retirement by 5.5%",
baseCost: 2, costInc: 2.1,
successChanceKill:5.5
successChanceKill:5.5,
});
Skills[SkillNames.DigitalObserver] = new Skill({
name:SkillNames.DigitalObserver,
desc:"Each level of this skill increases your success chance in " +
"all Operations and BlackOps by 4%",
baseCost: 2, costInc: 2.1,
successChanceOperation:4
successChanceOperation:4,
});
Skills[SkillNames.Tracer] = new Skill({
name:SkillNames.Tracer,
desc:"Each level of this skill increases your success chance in " +
"all Contracts by 4%",
baseCost: 2, costInc: 2.1,
successChanceContract:4
successChanceContract:4,
});
Skills[SkillNames.Overclock] = new Skill({
name:SkillNames.Overclock,
desc:"Each level of this skill decreases the time it takes " +
"to attempt a Contract, Operation, and BlackOp by 1% (Max Level: 90)",
baseCost: 3, costInc: 1.4, maxLvl: 90,
actionTime:1
actionTime:1,
});
Skills[SkillNames.Reaper] = new Skill({
name: SkillNames.Reaper,
desc: "Each level of this skill increases your effective combat stats for Bladeburner actions by 2%",
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({
name:SkillNames.EvasiveSystem,
desc:"Each level of this skill increases your effective " +
"dexterity and agility for Bladeburner actions by 4%",
baseCost: 2, costInc: 2.1,
effDex: 4, effAgi: 4
effDex: 4, effAgi: 4,
});
Skills[SkillNames.Datamancer] = new Skill({
name:SkillNames.Datamancer,
@@ -67,13 +67,13 @@ export const Skills: IMap<Skill> = {};
"This affects all actions that can potentially increase " +
"the accuracy of your synthoid population/community estimates.",
baseCost:3, costInc:1,
successChanceEstimate:5
successChanceEstimate:5,
});
Skills[SkillNames.CybersEdge] = new Skill({
name:SkillNames.CybersEdge,
desc:"Each level of this skill increases your max stamina by 2%",
baseCost:1, costInc:3,
stamina:2
stamina:2,
});
Skills[SkillNames.HandsOfMidas] = new Skill({
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: [
"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",
" skill [action] [name] Level or display info about your Bladeburner skills",
" start [type] [name] Start a Bladeburner action/task" ,
" stop Stops your current Bladeburner action/task"
" stop Stops your current Bladeburner action/task",
],
automate: [
"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 " +
"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 " +
"exactly match whatever the name is in the UI."
"exactly match whatever the name is in the UI.",
],
clear: [
"clear",
"",
"Clears the console"
"Clears the console",
],
cls: [
"cls",
"",
"Clears the console"
"Clears the console",
],
help: [
"help [command]",
@@ -51,7 +61,7 @@ export const ConsoleHelpText: {} = {
"",
" help automate",
"",
"will display specific information about using the automate console command"
"will display specific information about using the automate console command",
],
log: [
"log [en/dis] [type]",
@@ -71,7 +81,7 @@ export const ConsoleHelpText: {} = {
"Logging can be universally enabled/disabled using the 'all' keyword:",
"",
" log dis all",
" log en all"
" log en all",
],
skill: [
"skill [action] [name]",
@@ -91,7 +101,7 @@ export const ConsoleHelpText: {} = {
"",
"This console command can also be used to level up skills:",
"",
" skill level [skill name]"
" skill level [skill name]",
],
start: [
"start [type] [name]",
@@ -106,11 +116,11 @@ export const ConsoleHelpText: {} = {
"Examples:",
"",
" start contract Tracking",
" start op 'Undercover Operation'"
" start op 'Undercover Operation'",
],
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";
export function BlackOperationsPage(inst: any): React.ReactElement {
export function BlackOperationsPage(): React.ReactElement {
// Put Black Operations in sequence of required rank
const blackops = [];
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 />
<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>
{blackops.map( op =>
<div className="bladeburner-action">
</div>
{blackops.map(() => <div className="bladeburner-action">
</div>,
)}
</div>)
}

View File

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

View File

@@ -1,6 +1,6 @@
export interface RNG {
random(): number
random(): number;
}
/*
@@ -9,16 +9,16 @@ export interface RNG {
*/
class RNG0 implements RNG {
x: number;
m: number = 1024;
a: number = 341;
c: number = 1;
m = 1024;
a = 341;
c = 1;
constructor() {
this.x = 0;
this.reset();
}
step() {
step(): void {
this.x = (this.a*this.x+this.c) % this.m;
}
@@ -27,7 +27,7 @@ class RNG0 implements RNG {
return this.x/this.m;
}
reset() {
reset(): void {
this.x = (new Date()).getTime() % this.m;
}
}
@@ -39,9 +39,9 @@ export const BadRNG: RNG0 = new RNG0();
* The period is 6e12.
*/
export class WHRNG implements RNG {
s1: number = 0;
s2: number = 0;
s3: number = 0;
s1 = 0;
s2 = 0;
s3 = 0;
constructor(totalPlaytime: number) {
// This one is seeded by the players total play time.
@@ -51,7 +51,7 @@ export class WHRNG implements RNG {
this.s3 = v;
}
step() {
step(): void {
this.s1 = (171 * this.s1) % 30269;
this.s2 = (172 * this.s2) % 30307;
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);
}
function isBlack(n: number): boolean {
return !isRed(n);
}
type Strategy = {
match: (n: number) => boolean;
payout: number;
@@ -102,14 +98,14 @@ const strategies: {
Third2: {
match: (n: number): boolean => {
if (n === 0) return false;
return 13 <= n && n <= 24;
return n >= 13 && n <= 24;
},
payout: 2,
},
Third3: {
match: (n: number): boolean => {
if (n === 0) return false;
return 25 <= n;
return n >= 25;
},
payout: 2,
},
@@ -125,7 +121,7 @@ function Single(s: number): Strategy {
}
export class Roulette extends Game<IProps, IState> {
interval: number = -1;
interval = -1;
rng: WHRNG;
constructor(props: IProps) {
@@ -140,7 +136,7 @@ export class Roulette extends Game<IProps, IState> {
lock: true,
strategy: {
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);
}
step() {
step(): void {
if (!this.state.lock) {
this.setState({n: Math.floor(Math.random()*37)});
}
}
componentWillUnmount() {
componentWillUnmount(): void {
clearInterval(this.interval);
}
updateInvestment(e: React.FormEvent<HTMLInputElement>) {
updateInvestment(e: React.FormEvent<HTMLInputElement>): void {
let investment: number = parseInt(e.currentTarget.value);
if (isNaN(investment)) {
investment = minPlay;
@@ -178,13 +174,13 @@ export class Roulette extends Game<IProps, IState> {
this.setState({investment: investment});
}
currentNumber() {
currentNumber(): string {
if (this.state.n === 0) return '0';
const color = isRed(this.state.n) ? 'R' : 'B';
return `${this.state.n}${color}`;
}
play(s: Strategy) {
play(s: Strategy): void {
if(this.reachedLimit(this.props.p)) return;
this.setState({
canPlay: false,
@@ -223,10 +219,10 @@ export class Roulette extends Game<IProps, IState> {
}
render() {
render(): React.ReactNode {
return <>
<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>
<table>
<tbody>

View File

@@ -20,7 +20,7 @@ type IState = {
}
// 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", "*",
"@", "♥", "B", "E", "?"];
@@ -63,7 +63,7 @@ const maxPlay = 1e6;
export class SlotMachine extends Game<IProps, IState> {
rng: WHRNG;
interval: number = -1;
interval = -1;
constructor(props: IProps) {
super(props);
@@ -86,11 +86,11 @@ export class SlotMachine extends Game<IProps, IState> {
this.updateInvestment = this.updateInvestment.bind(this);
}
componentDidMount() {
componentDidMount(): void {
this.interval = setInterval(this.step, 50);
}
step() {
step(): void {
let stoppedOne = false;
const index = this.state.index.slice();
for(const i in index) {
@@ -106,7 +106,7 @@ export class SlotMachine extends Game<IProps, IState> {
}
}
componentWillUnmount() {
componentWillUnmount(): void {
clearInterval(this.interval);
}
@@ -118,7 +118,7 @@ export class SlotMachine extends Game<IProps, IState> {
];
}
play() {
play(): void {
if(this.reachedLimit(this.props.p)) return;
this.setState({status: 'playing'});
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);
}
lock() {
lock(): void {
this.setState({
locks: [
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 getPaylineData = function(payline: number[][]): string[] {
let data = [];
const data = [];
for(const point of payline) {
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;
}
unlock() {
unlock(): void {
this.setState({
locks: [-1, -1, -1, -1, -1],
canPlay: false,
})
}
updateInvestment(e: React.FormEvent<HTMLInputElement>) {
updateInvestment(e: React.FormEvent<HTMLInputElement>): void {
let investment: number = parseInt(e.currentTarget.value);
if (isNaN(investment)) {
investment = minPlay;
@@ -197,7 +197,7 @@ export class SlotMachine extends Game<IProps, IState> {
this.setState({investment: investment});
}
render() {
render(): React.ReactNode {
const t = this.getTable();
return <>
<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 />
++<br />
</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} />
<h1>{this.state.status}</h1>
<h2>Pay lines</h2>

View File

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

View File

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

View File

@@ -2,7 +2,7 @@ import {
codingContractTypesMetadata,
DescriptionFunc,
GeneratorFunc,
SolverFunc
SolverFunc,
} from "./data/codingcontracttypes";
import { IMap } from "./types";
@@ -10,12 +10,14 @@ import { IMap } from "./types";
import {
Generic_fromJSON,
Generic_toJSON,
Reviver
Reviver,
} from "../utils/JSONReviver";
import { KEY } from "../utils/helpers/keyCodes";
import { createElement } from "../utils/uiHelpers/createElement";
import { createPopup } from "../utils/uiHelpers/createPopup";
import { createPopup, removePopup } from "./ui/React/createPopup";
import { removeElementById } from "../utils/uiHelpers/removeElementById";
import { CodingContractPopup } from "./ui/React/CodingContractPopup";
/* tslint:disable:no-magic-numbers completed-docs max-classes-per-file no-console */
@@ -108,12 +110,6 @@ export interface ICodingContractReward {
* The player receives a reward if the problem is solved correctly
*/
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 */
data: any;
@@ -126,13 +122,13 @@ export class CodingContract {
reward: ICodingContractReward | null;
/* Number of times the Contract has been attempted */
tries: number = 0;
tries = 0;
/* String representing the contract's type. Must match type in ContractTypes */
type: string;
constructor(fn: string = "",
type: string = "Find Largest Prime Factor",
constructor(fn = "",
type = "Find Largest Prime Factor",
reward: ICodingContractReward | null = null) {
this.fn = fn;
if (!this.fn.endsWith(".cct")) {
@@ -177,59 +173,26 @@ export class CodingContract {
* Creates a popup to prompt the player to solve the problem
*/
async prompt(): Promise<CodingContractResult> {
// tslint:disable-next-line
return new Promise<CodingContractResult>((resolve: Function, reject: Function) => {
const contractType: CodingContractType = CodingContractTypes[this.type];
const popupId: string = `coding-contract-prompt-popup-${this.fn}`;
const title: HTMLElement = createElement("h1", {
innerHTML: this.type,
});
const txt: HTMLElement = createElement("p", {
innerHTML: ["You are attempting to solve a Coding Contract. You have",
`${this.getMaxNumTries() - this.tries} tries remaining,`,
"after which the contract will self-destruct.<br><br>",
`${contractType.desc(this.data).replace(/\n/g, "<br>")}`].join(" "),
});
let answerInput: HTMLInputElement;
let solveBtn: HTMLElement;
let cancelBtn: HTMLElement;
answerInput = createElement("input", {
onkeydown: (e: any) => {
if (e.keyCode === KEY.ENTER && answerInput.value !== "") {
e.preventDefault();
solveBtn.click();
} else if (e.keyCode === KEY.ESC) {
e.preventDefault();
cancelBtn.click();
}
const popupId = `coding-contract-prompt-popup-${this.fn}`;
return new Promise<CodingContractResult>((resolve, reject) => {
let popup = new CodingContractPopup({
c: this,
popupId: popupId,
onClose: () => {
resolve(CodingContractResult.Cancelled);
removePopup(popupId);
},
placeholder: "Enter Solution here",
width: "50%",
}) as HTMLInputElement;
solveBtn = createElement("a", {
class: "a-link-button",
clickListener: () => {
const answer: string = answerInput.value;
if (this.isSolution(answer)) {
onAttempt: (val: string) => {
console.log(`top; ${val}`);
if (this.isSolution(val)) {
resolve(CodingContractResult.Success);
} else {
resolve(CodingContractResult.Failure);
}
removeElementById(popupId);
},
innerText: "Solve",
removePopup(popupId);
}
});
cancelBtn = createElement("a", {
class: "a-link-button",
clickListener: () => {
resolve(CodingContractResult.Cancelled);
removeElementById(popupId);
},
innerText: "Cancel",
});
const lineBreak: HTMLElement = createElement("br");
createPopup(popupId, [title, lineBreak, txt, lineBreak, lineBreak, answerInput, solveBtn, cancelBtn]);
answerInput.focus();
createPopup(popupId, CodingContractPopup, popup.props);
});
}
@@ -239,6 +202,14 @@ export class CodingContract {
toJSON(): any {
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;

View File

@@ -6,7 +6,7 @@ import { Reviver } from "../../utils/JSONReviver";
export let Companies: IMap<Company> = {};
function addCompany(params: IConstructorParams) {
function addCompany(params: IConstructorParams): void {
if (Companies[params.name] != null) {
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
// Called when creating new game or after a prestige/reset
export function initCompanies() {
export function initCompanies(): void {
// Save Old Company data for 'favor'
const oldCompanies = Companies;
@@ -40,11 +40,11 @@ export function initCompanies() {
}
// Used to load Companies map from a save
export function loadCompanies(saveString: string) {
export function loadCompanies(saveString: string): void {
Companies = JSON.parse(saveString, Reviver);
}
// 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);
}

View File

@@ -25,12 +25,6 @@ const DefaultConstructorParams: IConstructorParams = {
}
export class Company {
/**
* Initiatizes a Company from a JSON save state.
*/
static fromJSON(value: any): Company {
return Generic_fromJSON(Company, value.data);
}
/**
* Company name
@@ -136,7 +130,7 @@ export class Company {
gainFavor(): void {
if (this.favor == null) { this.favor = 0; }
if (this.rolloverRep == null) { this.rolloverRep = 0; }
var res = this.getFavorGain();
const res = this.getFavorGain();
if (res.length != 2) {
console.error("Invalid result from getFavorGain() function");
return;
@@ -170,6 +164,14 @@ export class Company {
toJSON(): any {
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;

View File

@@ -5,7 +5,7 @@ import { IMap } from "../types";
export const CompanyPositions: IMap<CompanyPosition> = {};
function addCompanyPosition(params: IConstructorParams) {
function addCompanyPosition(params: IConstructorParams): void {
if (CompanyPositions[params.name] != null) {
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
*/
export function getJobRequirementText(company: Company, pos: CompanyPosition, tooltiptext: boolean = false): string {
let reqText: string = "";
export function getJobRequirementText(company: Company, pos: CompanyPosition, tooltiptext = false): string {
let reqText = "";
const offset: number = company.jobStatReqOffset;
const reqHacking: number = pos.requiredHacking > 0 ? pos.requiredHacking+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({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
AllSecurityPositions,
),
expMultiplier: 3,
salaryMultiplier: 3,
@@ -107,7 +107,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
AllSecurityPositions,
),
expMultiplier: 3,
salaryMultiplier: 3,
@@ -119,7 +119,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
AllSecurityPositions,
),
expMultiplier: 2.6,
salaryMultiplier: 2.6,
@@ -131,7 +131,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
AllSecurityPositions,
),
expMultiplier: 2.75,
salaryMultiplier: 2.75,
@@ -143,7 +143,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
AllSecurityPositions,
),
expMultiplier: 2.75,
salaryMultiplier: 2.75,
@@ -155,7 +155,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
AllSecurityPositions,
),
expMultiplier: 2.25,
salaryMultiplier: 2.25,
@@ -167,7 +167,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
AllSecurityPositions,
),
expMultiplier: 2.25,
salaryMultiplier: 2.25,
@@ -179,7 +179,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
AllSecurityPositions,
),
expMultiplier: 2.5,
salaryMultiplier: 2.5,
@@ -191,7 +191,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSecurityPositions
AllSecurityPositions,
),
expMultiplier: 2.2,
salaryMultiplier: 2.2,
@@ -202,7 +202,7 @@ export const companiesMetadata: IConstructorParams[] = [
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions
AllBusinessPositions,
),
expMultiplier: 2,
salaryMultiplier: 2,
@@ -214,7 +214,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
AllTechnologyPositions,
AllSoftwareConsultantPositions,
AllBusinessPositions
AllBusinessPositions,
),
expMultiplier: 1.8,
salaryMultiplier: 1.8,
@@ -226,7 +226,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
CEOOnly,
AllTechnologyPositions,
AllSoftwareConsultantPositions
AllSoftwareConsultantPositions,
),
expMultiplier: 1.75,
salaryMultiplier: 1.75,
@@ -238,7 +238,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
CEOOnly,
AllTechnologyPositions,
AllSoftwareConsultantPositions
AllSoftwareConsultantPositions,
),
expMultiplier: 1.8,
salaryMultiplier: 1.8,
@@ -250,7 +250,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSoftwareConsultantPositions
AllSoftwareConsultantPositions,
),
expMultiplier: 1.8,
salaryMultiplier: 1.8,
@@ -262,7 +262,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSoftwareConsultantPositions
AllSoftwareConsultantPositions,
),
expMultiplier: 1.9,
salaryMultiplier: 1.9,
@@ -274,7 +274,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSoftwareConsultantPositions
AllSoftwareConsultantPositions,
),
expMultiplier: 2,
salaryMultiplier: 2,
@@ -286,7 +286,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
AllTechnologyPositions,
AllBusinessPositions,
AllSoftwareConsultantPositions
AllSoftwareConsultantPositions,
),
expMultiplier: 1.9,
salaryMultiplier: 1.9,
@@ -299,7 +299,7 @@ export const companiesMetadata: IConstructorParams[] = [
CEOOnly,
OperationsManagerOnly,
AllTechnologyPositions,
AllSecurityPositions
AllSecurityPositions,
),
expMultiplier: 1.7,
salaryMultiplier: 1.7,
@@ -351,7 +351,7 @@ export const companiesMetadata: IConstructorParams[] = [
AllTechnologyPositions,
AllBusinessPositions,
AllSoftwareConsultantPositions,
AllSecurityPositions
AllSecurityPositions,
),
expMultiplier: 1.8,
salaryMultiplier: 1.8,
@@ -364,7 +364,7 @@ export const companiesMetadata: IConstructorParams[] = [
AllTechnologyPositions,
AllBusinessPositions,
AllSoftwareConsultantPositions,
AllSecurityPositions
AllSecurityPositions,
),
expMultiplier: 1.75,
salaryMultiplier: 1.75,
@@ -379,7 +379,7 @@ export const companiesMetadata: IConstructorParams[] = [
SecurityEngineerPositions,
AllITPositions,
AllSecurityPositions,
AllAgentPositions
AllAgentPositions,
),
expMultiplier: 2,
salaryMultiplier: 2,
@@ -394,7 +394,7 @@ export const companiesMetadata: IConstructorParams[] = [
SecurityEngineerPositions,
AllITPositions,
AllSecurityPositions,
AllAgentPositions
AllAgentPositions,
),
expMultiplier: 2,
salaryMultiplier: 2,
@@ -409,7 +409,7 @@ export const companiesMetadata: IConstructorParams[] = [
AllITPositions,
AllSecurityPositions,
AllAgentPositions,
AllSoftwareConsultantPositions
AllSoftwareConsultantPositions,
),
expMultiplier: 1.5,
salaryMultiplier: 1.5,
@@ -422,7 +422,7 @@ export const companiesMetadata: IConstructorParams[] = [
AllTechnologyPositions,
AllSoftwareConsultantPositions,
AllBusinessPositions,
AllSecurityPositions
AllSecurityPositions,
),
expMultiplier: 1.4,
salaryMultiplier: 1.4,
@@ -433,7 +433,7 @@ export const companiesMetadata: IConstructorParams[] = [
info: "",
companyPositions: Object.assign({},
SoftwarePositionsUpToLeadDeveloper,
BusinessPositionsUpToOperationsManager
BusinessPositionsUpToOperationsManager,
),
expMultiplier: 1.3,
salaryMultiplier: 1.3,
@@ -445,7 +445,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
SoftwarePositionsUpToLeadDeveloper,
BusinessPositionsUpToOperationsManager,
AllSoftwareConsultantPositions
AllSoftwareConsultantPositions,
),
expMultiplier: 1.5,
salaryMultiplier: 1.5,
@@ -456,7 +456,7 @@ export const companiesMetadata: IConstructorParams[] = [
info: "",
companyPositions: Object.assign({},
AllSecurityPositions,
SoftwarePositionsUpToLeadDeveloper
SoftwarePositionsUpToLeadDeveloper,
),
expMultiplier: 1.3,
salaryMultiplier: 1.3,
@@ -466,7 +466,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.VolhavenSysCoreSecurities,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions
AllTechnologyPositions,
),
expMultiplier: 1.3,
salaryMultiplier: 1.3,
@@ -476,7 +476,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.VolhavenCompuTek,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions
AllTechnologyPositions,
),
expMultiplier: 1.2,
salaryMultiplier: 1.2,
@@ -486,7 +486,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.AevumNetLinkTechnologies,
info: "",
companyPositions: Object.assign({},
AllTechnologyPositions
AllTechnologyPositions,
),
expMultiplier: 1.2,
salaryMultiplier: 1.2,
@@ -509,7 +509,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.Sector12FoodNStuff,
info: "",
companyPositions: Object.assign({},
EmployeeOnly, PartTimeEmployeeOnly
EmployeeOnly, PartTimeEmployeeOnly,
),
expMultiplier: 1,
salaryMultiplier: 1,
@@ -519,7 +519,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.Sector12JoesGuns,
info: "",
companyPositions: Object.assign({},
EmployeeOnly, PartTimeEmployeeOnly
EmployeeOnly, PartTimeEmployeeOnly,
),
expMultiplier: 1,
salaryMultiplier: 1,
@@ -531,7 +531,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({},
AllSoftwarePositions,
AllSoftwareConsultantPositions,
AllITPositions
AllITPositions,
),
expMultiplier: 1.1,
salaryMultiplier: 1.1,
@@ -541,7 +541,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.NewTokyoNoodleBar,
info: "",
companyPositions: Object.assign({},
WaiterOnly, PartTimeWaiterOnly
WaiterOnly, PartTimeWaiterOnly,
),
expMultiplier: 1,
salaryMultiplier: 1,

View File

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

View File

@@ -5,8 +5,8 @@
*/
import { IMap } from "./types";
export let CONSTANTS: IMap<any> = {
Version: "0.51.6",
export const CONSTANTS: IMap<any> = {
Version: "0.51.9",
/** 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
@@ -228,42 +228,50 @@ export let CONSTANTS: IMap<any> = {
LatestUpdate:
`
v0.51.6 - 2021-04-28 Backdoor! (Community)
v0.51.9 - 2021-05-17 offline progress and exports!
-------
Backdoor
* a new terminal command, backdoor, has been added to help differentiate
between the terminal hack command and the netscript hack function. (@dewint)
Alias
* several commands can be included in 1 alias. Recursive alias now work to
a depth of 10. (@Dawe)
Milestones
* A new tab under the Help menu has been added to guide players through the
game.
Offline
Casino
* Blackjack has been added (@BigD)
* Offline money gain has been reworked (it is more generous)
* If you're not working anywhere and go offline the game will work for you
at all your factions evenly.
Netscript
* 'prompt' now converts input to JSON.
* 'getRunningScript' is a new netscript function that returns a bunch of
data related to a running script.
Export
* Exporting now gives +1 favor to all joined factions every 24h.
Coding contracts
* trivial puzzles should no longer appear.
Corp
* Self-fund with an invalid name no longer takes away 150b anyway.
* Can no longer export negative amount
Infiltration
* All numbers are formatted like the rest of the game.
Bladeburner
* No longer waste overflowing time.
Text Editors
* All settings will now be saved and loaded correctly.
Terminal
* 'scan' now works for servers that are more than 21 character long.
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)
`
* ls now correctly lists all files.
* importing auto save+reloads (@Dawe)
* Fix a bug where .fconf could not be created
* Fix formatting inconsistencies for some logs of netscript functions.
* Fix a bug where Cashroot starter kit would appear as [object Object] in
confirmation dialog.
* Fix some ram not displayed as 0.00GB
* Fix error message throw undefined variable error
* City hall now has some generic text if you can't create a corp yet.
* Deleting a file without extension now returns an appropriate error message.
* Fixed an issue where bladeburner would miscalculate the cost of hospitalization.
* It is now possible to suppress bladeburner "action stopped" popup.
* Updated several dependencies (big who cares, I know)
* ls no longer prints lingering newline.
* Money earned/spent by sleeves is now tracked under Character>Money
`,
}

View File

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

View File

@@ -4,8 +4,6 @@ import { getBaseResearchTreeCopy,
import { numeralWrapper } from "../ui/numeralFormat";
import { Reviver } from "../../utils/JSONReviver";
interface IIndustryMap<T> {
Energy: 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
// ResearchTree object
export let IndustryResearchTrees: IIndustryMap<ResearchTree> = {
export const IndustryResearchTrees: IIndustryMap<ResearchTree> = {
Energy: getBaseResearchTreeCopy(),
Utilities: getBaseResearchTreeCopy(),
Agriculture: getBaseResearchTreeCopy(),
@@ -124,7 +122,7 @@ export let IndustryResearchTrees: IIndustryMap<ResearchTree> = {
RealEstate: getProductIndustryResearchTreeCopy(),
}
export function resetIndustryResearchTrees() {
export function resetIndustryResearchTrees(): void {
IndustryResearchTrees.Energy = getBaseResearchTreeCopy();
IndustryResearchTrees.Utilities = 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 " +
"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 " +
"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 {
// Initiatizes a Material object from a JSON save state.
static fromJSON(value: any): Material {
return Generic_fromJSON(Material, value.data);
}
// Name of material
name: string = "InitName";
name = "InitName";
// Amount of material owned
qty: number = 0;
qty = 0;
// Material's "quality". Unbounded
qlt: number = 0;
qlt = 0;
// How much demand the Material has in the market, and the range of possible
// values for this "demand"
dmd: number = 0;
dmd = 0;
dmdR: number[] = [0, 0];
// How much competition there is for this Material in the market, and the range
// of possible values for this "competition"
cmp: number = 0;
cmp = 0;
cmpR: number[] = [0, 0];
// Maximum volatility of this Materials stats
mv: number = 0;
mv = 0;
// Markup. Determines how high of a price you can charge on the material
// compared to the market price without suffering loss in # of sales
// 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
mku: number = 0;
mku = 0;
// How much of this material is being bought, sold, imported and produced every second
buy: number = 0;
sll: number = 0;
prd: number = 0;
imp: number = 0;
buy = 0;
sll = 0;
prd = 0;
imp = 0;
// Exports of this material to another warehouse/industry
exp: any[] = [];
// Total amount of this material exported in the last cycle
totalExp: number = 0;
totalExp = 0;
// Cost / sec to buy this material. AKA Market Price
bCost: number = 0;
bCost = 0;
// 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
// [Whether production/sale is limited, limit amount]
@@ -64,9 +60,9 @@ export class Material {
sllman: any[] = [false, 0]; // Sale
// Flags that signal whether automatic sale pricing through Market TA is enabled
marketTa1: boolean = false;
marketTa2: boolean = false;
marketTa2Price: number = 0;
marketTa1 = false;
marketTa2 = false;
marketTa2Price = 0;
constructor(params: IConstructorParams = {}) {
if (params.name) { this.name = params.name; }
@@ -166,7 +162,7 @@ export class Material {
const compChange: number = 1 + compVolatility;
if (Math.random() < 0.5) {
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
} else {
this.cmp *= (1 / compChange);
@@ -192,6 +188,12 @@ export class Material {
toJSON(): any {
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;

View File

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

View File

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

View File

@@ -16,25 +16,25 @@ export interface IConstructorParams {
export class Research {
// 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
cost: number = 0;
cost = 0;
// Description of what the Research does
desc: string = "";
desc = "";
// All possible generic upgrades for the company, in the form of multipliers
advertisingMult: number = 1;
employeeChaMult: number = 1;
employeeCreMult: number = 1;
employeeEffMult: number = 1;
employeeIntMult: number = 1;
productionMult: number = 1;
productProductionMult: number = 1;
salesMult: number = 1;
sciResearchMult: number = 1;
storageMult: number = 1;
advertisingMult = 1;
employeeChaMult = 1;
employeeCreMult = 1;
employeeEffMult = 1;
employeeIntMult = 1;
productionMult = 1;
productProductionMult = 1;
salesMult = 1;
sciResearchMult = 1;
storageMult = 1;
constructor(p: IConstructorParams={name: "", cost: 0, desc: ""}) {
this.name = p.name;

View File

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

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