mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-26 01:23:49 +01:00
merge v0.56.0
This commit is contained in:
commit
87c63cde59
@ -99,7 +99,6 @@ module.exports = {
|
||||
"no-catch-shadow": ["error"],
|
||||
"no-class-assign": ["error"],
|
||||
"no-compare-neg-zero": ["error"],
|
||||
"no-cond-assign": ["off", "except-parens"],
|
||||
"no-confusing-arrow": ["error"],
|
||||
"no-console": ["off"],
|
||||
"no-const-assign": ["error"],
|
||||
|
@ -84,6 +84,28 @@ changes are okay to contribute:
|
||||
- Changes that directly affect the game's balance
|
||||
- New gameplay mechanics
|
||||
|
||||
### How to setup fork properly
|
||||
|
||||
Fork and clone the repo
|
||||
|
||||
```
|
||||
# This will add the game original code as a repo in your local copy
|
||||
$ git remote add danielyxie git@github.com:danielyxie/bitburner.git
|
||||
|
||||
# You can verify you did this right by doing the following command
|
||||
$ git remote show
|
||||
danielyxie
|
||||
origin
|
||||
|
||||
# Then download all the branches from the game. (there might be more branches)
|
||||
$ git fetch danielyxie
|
||||
From github.com:danielyxie/bitburner
|
||||
* [new branch] dev -> danielyxie/dev
|
||||
* [new branch] master -> danielyxie/master
|
||||
|
||||
# Makes sure you always start from `danielyxie/dev` to avoid merge conflicts.
|
||||
```
|
||||
|
||||
#### Submitting a Pull Request
|
||||
|
||||
When submitting a pull request with your code contributions, please abide by
|
||||
|
60
dist/vendor.bundle.js
vendored
60
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@ -1,6 +1,6 @@
|
||||
.. _gameplay_sourcefiles:
|
||||
|
||||
.. warning:: This page contains spoilers regarding the game's story/plot-line.
|
||||
.. warning:: This page contains spoilers for the game
|
||||
|
||||
Source-Files
|
||||
============
|
||||
|
@ -3,6 +3,109 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
v0.56.0 - 2021-10-11 Trimming the backlog (hydroflame & community)
|
||||
-------------------------------------------
|
||||
|
||||
** BREAKING **
|
||||
|
||||
* The 'write' function is now async. This helps when making scripts that write scripts.
|
||||
|
||||
** Terminal **
|
||||
|
||||
* 'grow' and 'weaken' have been added as terminal command. This should help player transition
|
||||
from commands to scripts. The tutorial also talks about it.
|
||||
* 'cp' command added
|
||||
* Improved performance by rate limiting refresh.
|
||||
|
||||
** IP vs Hostname **
|
||||
|
||||
* The game now uses hostname as primary key for it's servers (yeah believe it or not IPs were
|
||||
used until then). This has caused some issues with purchased servers (they couldn't be sold).
|
||||
You might need to soft reset for the game to fully convert itself.
|
||||
|
||||
** Sleeve **
|
||||
|
||||
* Fixed bug where they couldn't train at Volhaven.
|
||||
* No longer consume all bonus time at once, making it look buggy.
|
||||
|
||||
** SF9 **
|
||||
|
||||
* Now boosts hacknet production by 8/12/14%
|
||||
|
||||
** Hacknet Servers **
|
||||
|
||||
* production nerfed by 10%
|
||||
* Max money increase gets weaker above 10t max money
|
||||
|
||||
** Corporation **
|
||||
|
||||
* Warehouse tooltip now also displays the amount of space taken by products.
|
||||
* Changed research box completely to avoid dependency on Treant (Treant is a pita)
|
||||
* All textbox should accept MAX/MP case insensitive.
|
||||
* Fixed export popup not refreshing dropdowns correctly.
|
||||
* Fixed product mku becoming zero
|
||||
* Increased scaling of Wilson to avoid feedback loop.
|
||||
* Can no longer get in debt by buying real estate
|
||||
* Bonus time is consumed faster.
|
||||
|
||||
** Netscript **
|
||||
|
||||
* isBusy takes bitverse and infiltration into account
|
||||
* hospitalize can't be called when in infiltration.
|
||||
* setToCommitCrime now accepts crime rough name instead of perfect name.
|
||||
* disableLog All now works for bladeburner functions.
|
||||
* Fixed netscript port for ns1.
|
||||
|
||||
** Augmentation **
|
||||
|
||||
* Added augmentation to Ti Di Hui that removes penalty for being unfocused.
|
||||
* Neuroflux no longer appears in special factions.
|
||||
|
||||
** Script Editor **
|
||||
|
||||
* Ram check is debounced instead of refreshed every second.
|
||||
* Added the vscode extension documentation to the game (it doesn't work well, thought)
|
||||
* Fixed issue where autocomplete list would grow forever
|
||||
* Added semi-monokai as theme.
|
||||
* Fixed issue where modifying filename would mess it up.
|
||||
* Font size can be changed now.
|
||||
|
||||
** Infiltration **
|
||||
|
||||
* Fixed issue where game controls would become unfocused.
|
||||
|
||||
** Misc. **
|
||||
|
||||
* Fixed loader incorrectly assuming some null values are incorrect.
|
||||
* installBackdoor trigger Bitverse sequence
|
||||
* Some improvements to the theme editor
|
||||
* Improved documentation about where to learn javascript.
|
||||
* Added some instructions for contributors.
|
||||
* Fixed typo in corporation sell shares modal (@Saynt_Garmo)
|
||||
* Fixed pagination being black on black in Active Scripts
|
||||
* Create Script tab renamed to Script Editor
|
||||
* Fixed an issue where corp some textbox wouldn't update when changing city.
|
||||
* Fixed an issue where hacknet online time was always 0.
|
||||
* Netscript function prompt fixed.
|
||||
* Fixed miscalculation in growth.
|
||||
* Script with syntax errors will try to be a tad more helpful.
|
||||
* Corporations can no longer bribe bladeburners.
|
||||
* Augmentation Graphene Branchiblade renamed to Brachi, like the rest of them.
|
||||
* All ram is displayed in GB/TB/PB now.
|
||||
* Game now saves when saving a file, this can be turned off.
|
||||
* Several improvement to log window.
|
||||
* Bladeburner current action returns General type instead of the name of the action.
|
||||
* Bladeburner travel and Sleeve travel respect disable ASCII.
|
||||
* Tutorial fits on small screens.
|
||||
* Import is much slower but more consistent now.
|
||||
* Fix intelligence not updating properly.
|
||||
* Added SF -1: Time Compression
|
||||
* ReadTheDoc theme now matches the game.
|
||||
* Logbox should wrap text better
|
||||
* Logbox behavior should feel better.
|
||||
* Fix font for AutoLink.exe
|
||||
* nerf noodle bar
|
||||
|
||||
v0.55.0 - 2021-09-20 Material UI (hydroflame & community)
|
||||
-------------------------------------------
|
||||
|
||||
|
@ -64,9 +64,9 @@ documentation_title = '{0} Documentation'.format(project)
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.55'
|
||||
version = '0.56'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.55.0'
|
||||
release = '0.56.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@ -189,3 +189,4 @@ intersphinx_mapping = {'https://docs.python.org/': None}
|
||||
def setup(app):
|
||||
print("Initializing (setup())");
|
||||
app.add_stylesheet('maxwidthoverride.css')
|
||||
app.add_stylesheet('dark_theme.css')
|
||||
|
@ -6,8 +6,6 @@ getServer() Netscript Function
|
||||
:RAM cost: 2 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.
|
||||
|
||||
This function is meant to be used in conjunction with the :doc:`formulas API<../netscriptformulasapi>`.
|
||||
|
||||
Returns an object with the Server's stats. The object has the following properties::
|
||||
|
@ -1,12 +1,13 @@
|
||||
growthAnalyze() Netscript Function
|
||||
==================================
|
||||
|
||||
.. js:function:: growthAnalyze(hostname, growthAmount)
|
||||
.. js:function:: growthAnalyze(hostname, growthAmount[, cores])
|
||||
|
||||
:RAM cost: 1 GB
|
||||
:param string hostname: Hostname of server to analyze.
|
||||
:param number growthAmount: Multiplicative factor by which the server is
|
||||
grown. Decimal form. Must be >= 1.
|
||||
:param number cores: Amount of cores on the server that would run the growth, defaults to 1
|
||||
:returns: The amount of :doc:`grow<grow>` threads needed to grow the specified
|
||||
server by the specified amount.
|
||||
|
||||
|
@ -15,6 +15,7 @@ help you learn some basic programming concepts.
|
||||
Here are some good tutorials for learning programming/JavaScript as a beginner:
|
||||
|
||||
* `Learn-JS <http://www.learn-js.org/en/Welcome>`_
|
||||
* `programiz <https://www.programiz.com/javascript/get-started>`_
|
||||
* `Speaking JavaScript <http://speakingjs.com/es5/index.html>`_
|
||||
This is a bit on the longer side. You can skip all of the historical
|
||||
background stuff. Recommended chapters: 1, 7-18
|
||||
|
453
doc/source/ystatic/dark_theme.css
Normal file
453
doc/source/ystatic/dark_theme.css
Normal file
@ -0,0 +1,453 @@
|
||||
:root {
|
||||
--dark-text-color: #0c0;
|
||||
--dark-link-color: #090;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.wy-nav-content-wrap {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.wy-nav-content {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.section {
|
||||
color: var(--dark-text-color);
|
||||
}
|
||||
|
||||
.rst-content .highlighted {
|
||||
background: #333;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background-color: #17181c;
|
||||
}
|
||||
|
||||
.highlight .nn {
|
||||
color: var(--dark-text-color);
|
||||
}
|
||||
|
||||
.highlight .nb {
|
||||
color: #8bb8df;
|
||||
}
|
||||
|
||||
.highlight .kn,
|
||||
.highlight .kc,
|
||||
.highlight .k {
|
||||
color: #41c2ea;
|
||||
}
|
||||
|
||||
.highlight .s1,
|
||||
.highlight .s2 {
|
||||
color: #b3e87f;
|
||||
}
|
||||
|
||||
.highlight .nt {
|
||||
color: #ccb350;
|
||||
}
|
||||
|
||||
.highlight .c1 {
|
||||
color: #686868;
|
||||
}
|
||||
|
||||
.rst-content div[class^="highlight"] {
|
||||
border-color: #1a1a1a;
|
||||
}
|
||||
|
||||
.icon,
|
||||
.icon-home {
|
||||
color: var(--dark-link-color);
|
||||
}
|
||||
|
||||
.wy-nav-content a,
|
||||
.wy-nav-content a:visited {
|
||||
color: var(--dark-link-color) !important;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.btn-neutral {
|
||||
background-color: #17181c !important;
|
||||
}
|
||||
|
||||
.btn-neutral:hover {
|
||||
background-color: #101114 !important;
|
||||
}
|
||||
|
||||
.btn-neutral:visited {
|
||||
color: #c1c1c1 !important;
|
||||
}
|
||||
|
||||
.btn {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
footer {
|
||||
color: #bdbdbd;
|
||||
}
|
||||
|
||||
.wy-nav-side {
|
||||
background-color: #000;
|
||||
border: 1px solid #333;
|
||||
}
|
||||
|
||||
.wy-menu-vertical > a {
|
||||
color: var(--dark-text-color);
|
||||
}
|
||||
|
||||
.wy-menu-vertical li.current {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.wy-menu-vertical li.current > a,
|
||||
.wy-menu-vertical li.on a {
|
||||
background-color: #000;
|
||||
color: var(--dark-text-color);
|
||||
}
|
||||
|
||||
.wy-menu-vertical li.toctree-l1.current > a,
|
||||
.wy-menu-vertical li.current a {
|
||||
border-color: #000;
|
||||
}
|
||||
|
||||
.wy-menu-vertical header,
|
||||
.wy-menu-vertical p.caption {
|
||||
color: var(--dark-text-color);
|
||||
}
|
||||
|
||||
html.writer-html4 .rst-content dl:not(.docutils) > dt,
|
||||
html.writer-html5
|
||||
.rst-content
|
||||
dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)
|
||||
> dt {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.wy-menu-vertical li.current a {
|
||||
color: #090;
|
||||
}
|
||||
.wy-menu-vertical a {
|
||||
color: var(--dark-text-color);
|
||||
}
|
||||
|
||||
.wy-menu-vertical li.current a:hover {
|
||||
background-color: #222;
|
||||
}
|
||||
|
||||
.wy-menu-vertical a:hover,
|
||||
.wy-menu-vertical li.current > a:hover,
|
||||
.wy-menu-vertical li.on a:hover {
|
||||
background-color: #000;
|
||||
color: var(--dark-text-color);
|
||||
}
|
||||
|
||||
.wy-menu-vertical li.toctree-l2.current > a,
|
||||
.wy-menu-vertical li.toctree-l2.current li.toctree-l3 > a {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.wy-side-nav-search {
|
||||
background-color: #000;
|
||||
color: var(--dark-text-color);
|
||||
}
|
||||
|
||||
.wy-side-nav-search .wy-dropdown > a,
|
||||
.wy-side-nav-search > a {
|
||||
color: var(--dark-text-color);
|
||||
}
|
||||
|
||||
.wy-side-nav-search input[type="text"] {
|
||||
border-left: 0px;
|
||||
border-right: 0px;
|
||||
border-top: 0px;
|
||||
border-radius: 0px;
|
||||
box-shadow: none;
|
||||
border-bottom-color: #0c0;
|
||||
background-color: #333;
|
||||
color: var(--dark-text-color);
|
||||
}
|
||||
|
||||
.theme-switcher {
|
||||
background-color: #0b0c0d;
|
||||
color: var(--dark-text-color);
|
||||
}
|
||||
|
||||
writer-html4 .rst-content dl:not(.docutils) > dt,
|
||||
writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) > dt {
|
||||
background-color: #0b0b0b;
|
||||
color: #007dce;
|
||||
border-color: #282828;
|
||||
}
|
||||
|
||||
.rst-content code,
|
||||
.rst-content tt {
|
||||
color: var(--dark-text-color);
|
||||
}
|
||||
|
||||
writer-html4 .rst-content dl:not(.docutils) dl:not(.field-list) > dt,
|
||||
writer-html5
|
||||
.rst-content
|
||||
dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple)
|
||||
dl:not(.field-list)
|
||||
> dt {
|
||||
background-color: #0f0f0f;
|
||||
color: #959595;
|
||||
border-color: #2b2b2b;
|
||||
}
|
||||
|
||||
.rst-content code,
|
||||
.rst-content tt,
|
||||
code {
|
||||
background-color: #2d2d2d;
|
||||
border-color: #1c1c1c;
|
||||
}
|
||||
|
||||
.rst-content code.xref,
|
||||
.rst-content tt.xref,
|
||||
a .rst-content code,
|
||||
a .rst-content tt {
|
||||
color: #cecece;
|
||||
}
|
||||
|
||||
.rst-content .hint,
|
||||
.rst-content .important,
|
||||
.rst-content .tip,
|
||||
.rst-content .wy-alert-success.admonition,
|
||||
.rst-content .wy-alert-success.admonition-todo,
|
||||
.rst-content .wy-alert-success.attention,
|
||||
.rst-content .wy-alert-success.caution,
|
||||
.rst-content .wy-alert-success.danger,
|
||||
.rst-content .wy-alert-success.error,
|
||||
.rst-content .wy-alert-success.note,
|
||||
.rst-content .wy-alert-success.seealso,
|
||||
.rst-content .wy-alert-success.warning,
|
||||
.wy-alert.wy-alert-success {
|
||||
background-color: #00392e;
|
||||
}
|
||||
|
||||
.rst-content .hint .admonition-title,
|
||||
.rst-content .hint .wy-alert-title,
|
||||
.rst-content .important .admonition-title,
|
||||
.rst-content .important .wy-alert-title,
|
||||
.rst-content .tip .admonition-title,
|
||||
.rst-content .tip .wy-alert-title,
|
||||
.rst-content .wy-alert-success.admonition-todo .admonition-title,
|
||||
.rst-content .wy-alert-success.admonition-todo .wy-alert-title,
|
||||
.rst-content .wy-alert-success.admonition .admonition-title,
|
||||
.rst-content .wy-alert-success.admonition .wy-alert-title,
|
||||
.rst-content .wy-alert-success.attention .admonition-title,
|
||||
.rst-content .wy-alert-success.attention .wy-alert-title,
|
||||
.rst-content .wy-alert-success.caution .admonition-title,
|
||||
.rst-content .wy-alert-success.caution .wy-alert-title,
|
||||
.rst-content .wy-alert-success.danger .admonition-title,
|
||||
.rst-content .wy-alert-success.danger .wy-alert-title,
|
||||
.rst-content .wy-alert-success.error .admonition-title,
|
||||
.rst-content .wy-alert-success.error .wy-alert-title,
|
||||
.rst-content .wy-alert-success.note .admonition-title,
|
||||
.rst-content .wy-alert-success.note .wy-alert-title,
|
||||
.rst-content .wy-alert-success.seealso .admonition-title,
|
||||
.rst-content .wy-alert-success.seealso .wy-alert-title,
|
||||
.rst-content .wy-alert-success.warning .admonition-title,
|
||||
.rst-content .wy-alert-success.warning .wy-alert-title,
|
||||
.rst-content .wy-alert.wy-alert-success .admonition-title,
|
||||
.wy-alert.wy-alert-success .rst-content .admonition-title,
|
||||
.wy-alert.wy-alert-success .wy-alert-title {
|
||||
background-color: #006a56;
|
||||
}
|
||||
|
||||
.rst-content .note,
|
||||
.rst-content .seealso,
|
||||
.rst-content .wy-alert-info.admonition,
|
||||
.rst-content .wy-alert-info.admonition-todo,
|
||||
.rst-content .wy-alert-info.attention,
|
||||
.rst-content .wy-alert-info.caution,
|
||||
.rst-content .wy-alert-info.danger,
|
||||
.rst-content .wy-alert-info.error,
|
||||
.rst-content .wy-alert-info.hint,
|
||||
.rst-content .wy-alert-info.important,
|
||||
.rst-content .wy-alert-info.tip,
|
||||
.rst-content .wy-alert-info.warning,
|
||||
.wy-alert.wy-alert-info {
|
||||
background-color: #002c4d;
|
||||
}
|
||||
|
||||
.rst-content .note .admonition-title,
|
||||
.rst-content .note .wy-alert-title,
|
||||
.rst-content .seealso .admonition-title,
|
||||
.rst-content .seealso .wy-alert-title,
|
||||
.rst-content .wy-alert-info.admonition-todo .admonition-title,
|
||||
.rst-content .wy-alert-info.admonition-todo .wy-alert-title,
|
||||
.rst-content .wy-alert-info.admonition .admonition-title,
|
||||
.rst-content .wy-alert-info.admonition .wy-alert-title,
|
||||
.rst-content .wy-alert-info.attention .admonition-title,
|
||||
.rst-content .wy-alert-info.attention .wy-alert-title,
|
||||
.rst-content .wy-alert-info.caution .admonition-title,
|
||||
.rst-content .wy-alert-info.caution .wy-alert-title,
|
||||
.rst-content .wy-alert-info.danger .admonition-title,
|
||||
.rst-content .wy-alert-info.danger .wy-alert-title,
|
||||
.rst-content .wy-alert-info.error .admonition-title,
|
||||
.rst-content .wy-alert-info.error .wy-alert-title,
|
||||
.rst-content .wy-alert-info.hint .admonition-title,
|
||||
.rst-content .wy-alert-info.hint .wy-alert-title,
|
||||
.rst-content .wy-alert-info.important .admonition-title,
|
||||
.rst-content .wy-alert-info.important .wy-alert-title,
|
||||
.rst-content .wy-alert-info.tip .admonition-title,
|
||||
.rst-content .wy-alert-info.tip .wy-alert-title,
|
||||
.rst-content .wy-alert-info.warning .admonition-title,
|
||||
.rst-content .wy-alert-info.warning .wy-alert-title,
|
||||
.rst-content .wy-alert.wy-alert-info .admonition-title,
|
||||
.wy-alert.wy-alert-info .rst-content .admonition-title,
|
||||
.wy-alert.wy-alert-info .wy-alert-title {
|
||||
background-color: #004a7b;
|
||||
}
|
||||
|
||||
.rst-content dl:not(.docutils) dt {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.rst-content {
|
||||
color: var(--dark-text-color);
|
||||
}
|
||||
|
||||
.rst-content .admonition-todo,
|
||||
.rst-content .attention,
|
||||
.rst-content .caution,
|
||||
.rst-content .warning,
|
||||
.rst-content .wy-alert-warning.admonition,
|
||||
.rst-content .wy-alert-warning.danger,
|
||||
.rst-content .wy-alert-warning.error,
|
||||
.rst-content .wy-alert-warning.hint,
|
||||
.rst-content .wy-alert-warning.important,
|
||||
.rst-content .wy-alert-warning.note,
|
||||
.rst-content .wy-alert-warning.seealso,
|
||||
.rst-content .wy-alert-warning.tip,
|
||||
.wy-alert.wy-alert-warning {
|
||||
background-color: #533500;
|
||||
}
|
||||
|
||||
.rst-content .admonition-todo .admonition-title,
|
||||
.rst-content .admonition-todo .wy-alert-title,
|
||||
.rst-content .attention .admonition-title,
|
||||
.rst-content .attention .wy-alert-title,
|
||||
.rst-content .caution .admonition-title,
|
||||
.rst-content .caution .wy-alert-title,
|
||||
.rst-content .warning .admonition-title,
|
||||
.rst-content .warning .wy-alert-title,
|
||||
.rst-content .wy-alert-warning.admonition .admonition-title,
|
||||
.rst-content .wy-alert-warning.admonition .wy-alert-title,
|
||||
.rst-content .wy-alert-warning.danger .admonition-title,
|
||||
.rst-content .wy-alert-warning.danger .wy-alert-title,
|
||||
.rst-content .wy-alert-warning.error .admonition-title,
|
||||
.rst-content .wy-alert-warning.error .wy-alert-title,
|
||||
.rst-content .wy-alert-warning.hint .admonition-title,
|
||||
.rst-content .wy-alert-warning.hint .wy-alert-title,
|
||||
.rst-content .wy-alert-warning.important .admonition-title,
|
||||
.rst-content .wy-alert-warning.important .wy-alert-title,
|
||||
.rst-content .wy-alert-warning.note .admonition-title,
|
||||
.rst-content .wy-alert-warning.note .wy-alert-title,
|
||||
.rst-content .wy-alert-warning.seealso .admonition-title,
|
||||
.rst-content .wy-alert-warning.seealso .wy-alert-title,
|
||||
.rst-content .wy-alert-warning.tip .admonition-title,
|
||||
.rst-content .wy-alert-warning.tip .wy-alert-title,
|
||||
.rst-content .wy-alert.wy-alert-warning .admonition-title,
|
||||
.wy-alert.wy-alert-warning .rst-content .admonition-title,
|
||||
.wy-alert.wy-alert-warning .wy-alert-title {
|
||||
background-color: #803b00;
|
||||
}
|
||||
|
||||
.rst-content .danger,
|
||||
.rst-content .error,
|
||||
.rst-content .wy-alert-danger.admonition,
|
||||
.rst-content .wy-alert-danger.admonition-todo,
|
||||
.rst-content .wy-alert-danger.attention,
|
||||
.rst-content .wy-alert-danger.caution,
|
||||
.rst-content .wy-alert-danger.hint,
|
||||
.rst-content .wy-alert-danger.important,
|
||||
.rst-content .wy-alert-danger.note,
|
||||
.rst-content .wy-alert-danger.seealso,
|
||||
.rst-content .wy-alert-danger.tip,
|
||||
.rst-content .wy-alert-danger.warning,
|
||||
.wy-alert.wy-alert-danger {
|
||||
background-color: #82231a;
|
||||
}
|
||||
|
||||
.rst-content .danger .admonition-title,
|
||||
.rst-content .danger .wy-alert-title,
|
||||
.rst-content .error .admonition-title,
|
||||
.rst-content .error .wy-alert-title,
|
||||
.rst-content .wy-alert-danger.admonition-todo .admonition-title,
|
||||
.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,
|
||||
.rst-content .wy-alert-danger.admonition .admonition-title,
|
||||
.rst-content .wy-alert-danger.admonition .wy-alert-title,
|
||||
.rst-content .wy-alert-danger.attention .admonition-title,
|
||||
.rst-content .wy-alert-danger.attention .wy-alert-title,
|
||||
.rst-content .wy-alert-danger.caution .admonition-title,
|
||||
.rst-content .wy-alert-danger.caution .wy-alert-title,
|
||||
.rst-content .wy-alert-danger.hint .admonition-title,
|
||||
.rst-content .wy-alert-danger.hint .wy-alert-title,
|
||||
.rst-content .wy-alert-danger.important .admonition-title,
|
||||
.rst-content .wy-alert-danger.important .wy-alert-title,
|
||||
.rst-content .wy-alert-danger.note .admonition-title,
|
||||
.rst-content .wy-alert-danger.note .wy-alert-title,
|
||||
.rst-content .wy-alert-danger.seealso .admonition-title,
|
||||
.rst-content .wy-alert-danger.seealso .wy-alert-title,
|
||||
.rst-content .wy-alert-danger.tip .admonition-title,
|
||||
.rst-content .wy-alert-danger.tip .wy-alert-title,
|
||||
.rst-content .wy-alert-danger.warning .admonition-title,
|
||||
.rst-content .wy-alert-danger.warning .wy-alert-title,
|
||||
.rst-content .wy-alert.wy-alert-danger .admonition-title,
|
||||
.wy-alert.wy-alert-danger .rst-content .admonition-title,
|
||||
.wy-alert.wy-alert-danger .wy-alert-title {
|
||||
background-color: #b9372b;
|
||||
}
|
||||
|
||||
.wy-nav-top {
|
||||
background-color: #0b152d;
|
||||
}
|
||||
|
||||
.rst-content table.docutils thead,
|
||||
.rst-content table.field-list thead,
|
||||
.wy-table thead {
|
||||
color: var(--dark-text-color);
|
||||
}
|
||||
|
||||
.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,
|
||||
.wy-table-backed,
|
||||
.wy-table-odd td,
|
||||
.wy-table-striped tr:nth-child(2n-1) td {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.rst-content table.docutils:not(.field-list) tr:nth-child(2n) td,
|
||||
.wy-table-backed,
|
||||
.wy-table-odd td,
|
||||
.wy-table-striped tr:nth-child(2n) td {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
.rst-content table.docutils td,
|
||||
.wy-table-bordered-all td,
|
||||
writer-html5 .rst-content table.docutils th,
|
||||
.rst-content table.docutils,
|
||||
.wy-table-bordered-all {
|
||||
border-color: #262626;
|
||||
}
|
||||
|
||||
.rst-content table.docutils caption,
|
||||
.rst-content table.field-list caption,
|
||||
.wy-table caption {
|
||||
color: var(--dark-text-color);
|
||||
}
|
||||
|
||||
.wy-menu-vertical li.toctree-l3.current > a,
|
||||
.wy-menu-vertical li.toctree-l3.current li.toctree-l4 > a {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.wy-side-nav-search > div.version {
|
||||
color: var(--dark-text-color);
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "bitburner",
|
||||
"license": "SEE LICENSE IN license.txt",
|
||||
"version": "0.53.0",
|
||||
"version": "0.56.0",
|
||||
"main": "electron-main.js",
|
||||
"author": {
|
||||
"name": "Daniel Xie"
|
||||
|
@ -2,25 +2,25 @@ const numSpaces = 4;
|
||||
const maxLineLength = 160;
|
||||
|
||||
module.exports = {
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true
|
||||
env: {
|
||||
es6: true,
|
||||
node: true,
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"parserOptions": {
|
||||
"ecmaFeatures": {
|
||||
"experimentalObjectRestSpread": true
|
||||
extends: "eslint:recommended",
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
experimentalObjectRestSpread: true,
|
||||
},
|
||||
"ecmaVersion": 8,
|
||||
"sourceType": "module"
|
||||
ecmaVersion: 8,
|
||||
sourceType: "module",
|
||||
},
|
||||
"rules": {
|
||||
rules: {
|
||||
"accessor-pairs": [
|
||||
"error",
|
||||
{
|
||||
"getWithoutSet": false,
|
||||
"setWithoutGet": true
|
||||
}
|
||||
getWithoutSet: false,
|
||||
setWithoutGet: true,
|
||||
},
|
||||
],
|
||||
"array-bracket-newline": ["error"],
|
||||
"array-bracket-spacing": ["error"],
|
||||
@ -33,50 +33,35 @@ module.exports = {
|
||||
"block-spacing": ["error"],
|
||||
"brace-style": ["error"],
|
||||
"callback-return": ["error"],
|
||||
"camelcase": ["error"],
|
||||
camelcase: ["error"],
|
||||
"capitalized-comments": ["error"],
|
||||
"class-methods-use-this": ["error"],
|
||||
"comma-dangle": ["error"],
|
||||
"comma-spacing": ["error"],
|
||||
"comma-style": [
|
||||
"error",
|
||||
"last"
|
||||
],
|
||||
"complexity": ["error"],
|
||||
"computed-property-spacing": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"comma-style": ["error", "last"],
|
||||
complexity: ["error"],
|
||||
"computed-property-spacing": ["error", "never"],
|
||||
"consistent-return": ["error"],
|
||||
"consistent-this": ["error"],
|
||||
"constructor-super": ["error"],
|
||||
"curly": ["error"],
|
||||
curly: ["error"],
|
||||
"default-case": ["error"],
|
||||
"dot-location": [
|
||||
"error",
|
||||
"property"
|
||||
],
|
||||
"dot-location": ["error", "property"],
|
||||
"dot-notation": ["error"],
|
||||
"eol-last": ["error"],
|
||||
"eqeqeq": ["error"],
|
||||
eqeqeq: ["error"],
|
||||
"for-direction": ["error"],
|
||||
"func-call-spacing": ["error"],
|
||||
"func-name-matching": ["error"],
|
||||
"func-names": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"func-names": ["error", "never"],
|
||||
"func-style": ["error"],
|
||||
"function-paren-newline": ["error"],
|
||||
"generator-star-spacing": [
|
||||
"error",
|
||||
"before"
|
||||
],
|
||||
"generator-star-spacing": ["error", "before"],
|
||||
"getter-return": [
|
||||
"error",
|
||||
{
|
||||
"allowImplicit": false
|
||||
}
|
||||
allowImplicit: false,
|
||||
},
|
||||
],
|
||||
"global-require": ["error"],
|
||||
"guard-for-in": ["error"],
|
||||
@ -84,52 +69,37 @@ module.exports = {
|
||||
"id-blacklist": ["error"],
|
||||
"id-length": ["error"],
|
||||
"id-match": ["error"],
|
||||
"implicit-arrow-linebreak": [
|
||||
"error",
|
||||
"beside"
|
||||
],
|
||||
"indent": [
|
||||
"implicit-arrow-linebreak": ["error", "beside"],
|
||||
indent: [
|
||||
"error",
|
||||
numSpaces,
|
||||
{
|
||||
"SwitchCase": 1
|
||||
}
|
||||
SwitchCase: 1,
|
||||
},
|
||||
],
|
||||
"init-declarations": ["error"],
|
||||
"jsx-quotes": ["error"],
|
||||
"key-spacing": ["error"],
|
||||
"keyword-spacing": ["error"],
|
||||
"line-comment-position": ["error"],
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"windows"
|
||||
],
|
||||
"linebreak-style": ["error", "windows"],
|
||||
"lines-around-comment": ["error"],
|
||||
"lines-between-class-members": ["error"],
|
||||
"max-depth": ["error"],
|
||||
"max-len": [
|
||||
"error",
|
||||
maxLineLength
|
||||
],
|
||||
"max-len": ["error", maxLineLength],
|
||||
"max-lines": [
|
||||
"error",
|
||||
{
|
||||
"skipBlankLines": true,
|
||||
"skipComments": true
|
||||
}
|
||||
skipBlankLines: true,
|
||||
skipComments: true,
|
||||
},
|
||||
],
|
||||
"max-nested-callbacks": ["error"],
|
||||
"max-params": ["error"],
|
||||
"max-statements": ["error"],
|
||||
"max-statements-per-line": ["error"],
|
||||
"multiline-comment-style": [
|
||||
"off",
|
||||
"starred-block"
|
||||
],
|
||||
"multiline-ternary": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"multiline-comment-style": ["off", "starred-block"],
|
||||
"multiline-ternary": ["error", "never"],
|
||||
"new-cap": ["error"],
|
||||
"new-parens": ["error"],
|
||||
// TODO: configure this...
|
||||
@ -145,18 +115,15 @@ module.exports = {
|
||||
"no-catch-shadow": ["error"],
|
||||
"no-class-assign": ["error"],
|
||||
"no-compare-neg-zero": ["error"],
|
||||
"no-cond-assign": [
|
||||
"error",
|
||||
"except-parens"
|
||||
],
|
||||
"no-cond-assign": ["error", "except-parens"],
|
||||
"no-confusing-arrow": ["error"],
|
||||
"no-console": ["error"],
|
||||
"no-const-assign": ["error"],
|
||||
"no-constant-condition": [
|
||||
"error",
|
||||
{
|
||||
"checkLoops": false
|
||||
}
|
||||
checkLoops: false,
|
||||
},
|
||||
],
|
||||
"no-continue": ["off"],
|
||||
"no-control-regex": ["error"],
|
||||
@ -170,15 +137,15 @@ module.exports = {
|
||||
"no-duplicate-imports": [
|
||||
"error",
|
||||
{
|
||||
"includeExports": true
|
||||
}
|
||||
includeExports: true,
|
||||
},
|
||||
],
|
||||
"no-else-return": ["error"],
|
||||
"no-empty": [
|
||||
"error",
|
||||
{
|
||||
"allowEmptyCatch": false
|
||||
}
|
||||
allowEmptyCatch: false,
|
||||
},
|
||||
],
|
||||
"no-empty-character-class": ["error"],
|
||||
"no-empty-function": ["error"],
|
||||
@ -194,8 +161,8 @@ module.exports = {
|
||||
"error",
|
||||
"all",
|
||||
{
|
||||
"conditionalAssign": false
|
||||
}
|
||||
conditionalAssign: false,
|
||||
},
|
||||
],
|
||||
"no-extra-semi": ["error"],
|
||||
"no-fallthrough": ["error"],
|
||||
@ -206,20 +173,17 @@ module.exports = {
|
||||
"no-implicit-globals": ["error"],
|
||||
"no-implied-eval": ["error"],
|
||||
"no-inline-comments": ["error"],
|
||||
"no-inner-declarations": [
|
||||
"error",
|
||||
"both"
|
||||
],
|
||||
"no-inner-declarations": ["error", "both"],
|
||||
"no-invalid-regexp": ["error"],
|
||||
"no-invalid-this": ["error"],
|
||||
"no-irregular-whitespace": [
|
||||
"error",
|
||||
{
|
||||
"skipComments": false,
|
||||
"skipRegExps": false,
|
||||
"skipStrings": false,
|
||||
"skipTemplates": false
|
||||
}
|
||||
skipComments: false,
|
||||
skipRegExps: false,
|
||||
skipStrings: false,
|
||||
skipTemplates: false,
|
||||
},
|
||||
],
|
||||
"no-iterator": ["error"],
|
||||
"no-label-var": ["error"],
|
||||
@ -230,13 +194,9 @@ module.exports = {
|
||||
"no-magic-numbers": [
|
||||
"error",
|
||||
{
|
||||
"ignore": [
|
||||
-1,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"ignoreArrayIndexes": true
|
||||
}
|
||||
ignore: [-1, 0, 1],
|
||||
ignoreArrayIndexes: true,
|
||||
},
|
||||
],
|
||||
"no-mixed-operators": ["error"],
|
||||
"no-mixed-requires": ["error"],
|
||||
@ -247,8 +207,8 @@ module.exports = {
|
||||
"no-multiple-empty-lines": [
|
||||
"error",
|
||||
{
|
||||
"max": 1
|
||||
}
|
||||
max: 1,
|
||||
},
|
||||
],
|
||||
"no-native-reassign": ["error"],
|
||||
"no-negated-condition": ["error"],
|
||||
@ -268,8 +228,8 @@ module.exports = {
|
||||
"no-plusplus": [
|
||||
"error",
|
||||
{
|
||||
"allowForLoopAfterthoughts": true
|
||||
}
|
||||
allowForLoopAfterthoughts: true,
|
||||
},
|
||||
],
|
||||
"no-process-env": ["error"],
|
||||
"no-process-exit": ["error"],
|
||||
@ -283,10 +243,10 @@ module.exports = {
|
||||
"no-restricted-properties": [
|
||||
"error",
|
||||
{
|
||||
"message": "'log' is too general, use an appropriate level when logging.",
|
||||
"object": "console",
|
||||
"property": "log"
|
||||
}
|
||||
message: "'log' is too general, use an appropriate level when logging.",
|
||||
object: "console",
|
||||
property: "log",
|
||||
},
|
||||
],
|
||||
"no-restricted-syntax": ["error"],
|
||||
"no-return-assign": ["error"],
|
||||
@ -295,8 +255,8 @@ module.exports = {
|
||||
"no-self-assign": [
|
||||
"error",
|
||||
{
|
||||
"props": false
|
||||
}
|
||||
props: false,
|
||||
},
|
||||
],
|
||||
"no-self-compare": ["error"],
|
||||
"no-sequences": ["error"],
|
||||
@ -333,10 +293,10 @@ module.exports = {
|
||||
"no-useless-rename": [
|
||||
"error",
|
||||
{
|
||||
"ignoreDestructuring": false,
|
||||
"ignoreExport": false,
|
||||
"ignoreImport": false
|
||||
}
|
||||
ignoreDestructuring: false,
|
||||
ignoreExport: false,
|
||||
ignoreImport: false,
|
||||
},
|
||||
],
|
||||
"no-useless-return": ["error"],
|
||||
"no-var": ["error"],
|
||||
@ -344,10 +304,7 @@ module.exports = {
|
||||
"no-warning-comments": ["error"],
|
||||
"no-whitespace-before-property": ["error"],
|
||||
"no-with": ["error"],
|
||||
"nonblock-statement-body-position": [
|
||||
"error",
|
||||
"below"
|
||||
],
|
||||
"nonblock-statement-body-position": ["error", "below"],
|
||||
"object-curly-newline": ["error"],
|
||||
"object-curly-spacing": ["error"],
|
||||
"object-property-newline": ["error"],
|
||||
@ -355,10 +312,7 @@ module.exports = {
|
||||
"one-var": ["off"],
|
||||
"one-var-declaration-per-line": ["error"],
|
||||
"operator-assignment": ["error"],
|
||||
"operator-linebreak": [
|
||||
"error",
|
||||
"none"
|
||||
],
|
||||
"operator-linebreak": ["error", "none"],
|
||||
"padded-blocks": ["off"],
|
||||
"padding-line-between-statements": ["error"],
|
||||
"prefer-arrow-callback": ["error"],
|
||||
@ -371,24 +325,15 @@ module.exports = {
|
||||
"prefer-spread": ["error"],
|
||||
"prefer-template": ["error"],
|
||||
"quote-props": ["error"],
|
||||
"quotes": ["error"],
|
||||
"radix": [
|
||||
"error",
|
||||
"as-needed"
|
||||
],
|
||||
quotes: ["error"],
|
||||
radix: ["error", "as-needed"],
|
||||
"require-await": ["error"],
|
||||
"require-jsdoc": ["off"],
|
||||
"require-yield": ["error"],
|
||||
"rest-spread-spacing": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"semi": ["error"],
|
||||
"rest-spread-spacing": ["error", "never"],
|
||||
semi: ["error"],
|
||||
"semi-spacing": ["error"],
|
||||
"semi-style": [
|
||||
"error",
|
||||
"last"
|
||||
],
|
||||
"semi-style": ["error", "last"],
|
||||
"sort-imports": ["error"],
|
||||
"sort-keys": ["error"],
|
||||
"sort-vars": ["error"],
|
||||
@ -398,37 +343,25 @@ module.exports = {
|
||||
"space-infix-ops": ["error"],
|
||||
"space-unary-ops": ["error"],
|
||||
"spaced-comment": ["error"],
|
||||
"strict": ["error"],
|
||||
strict: ["error"],
|
||||
"switch-colon-spacing": [
|
||||
"error",
|
||||
{
|
||||
"after": true,
|
||||
"before": false
|
||||
}
|
||||
after: true,
|
||||
before: false,
|
||||
},
|
||||
],
|
||||
"symbol-description": ["error"],
|
||||
"template-curly-spacing": ["error"],
|
||||
"template-tag-spacing": ["error"],
|
||||
"unicode-bom": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"unicode-bom": ["error", "never"],
|
||||
"use-isnan": ["error"],
|
||||
"valid-jsdoc": ["error"],
|
||||
"valid-typeof": ["error"],
|
||||
"vars-on-top": ["error"],
|
||||
"wrap-iife": [
|
||||
"error",
|
||||
"any"
|
||||
],
|
||||
"wrap-iife": ["error", "any"],
|
||||
"wrap-regex": ["error"],
|
||||
"yield-star-spacing": [
|
||||
"error",
|
||||
"before"
|
||||
],
|
||||
"yoda": [
|
||||
"error",
|
||||
"never"
|
||||
]
|
||||
}
|
||||
"yield-star-spacing": ["error", "before"],
|
||||
yoda: ["error", "never"],
|
||||
},
|
||||
};
|
||||
|
@ -8,16 +8,18 @@ const path = require("path");
|
||||
const exec = require("child_process").exec;
|
||||
const semver = require("./semver");
|
||||
|
||||
const getPackageJson = () => new Promise((resolve, reject) => {
|
||||
const getPackageJson = () =>
|
||||
new Promise((resolve, reject) => {
|
||||
try {
|
||||
/* eslint-disable-next-line global-require */
|
||||
resolve(require(path.resolve(process.cwd(), "package.json")));
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const getEngines = (data) => new Promise((resolve, reject) => {
|
||||
const getEngines = (data) =>
|
||||
new Promise((resolve, reject) => {
|
||||
let versions = null;
|
||||
|
||||
if (data.engines) {
|
||||
@ -29,9 +31,10 @@ const getEngines = (data) => new Promise((resolve, reject) => {
|
||||
} else {
|
||||
reject("Missing or improper 'engines' property in 'package.json'");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const checkNpmVersion = (engines) => new Promise((resolve, reject) => {
|
||||
const checkNpmVersion = (engines) =>
|
||||
new Promise((resolve, reject) => {
|
||||
exec("npm -v", (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
reject(`Unable to find NPM version\n${stderr}`);
|
||||
@ -43,20 +46,25 @@ const checkNpmVersion = (engines) => new Promise((resolve, reject) => {
|
||||
if (semver.satisfies(npmVersion, engineVersion)) {
|
||||
resolve();
|
||||
} else {
|
||||
reject(`Incorrect npm version\n'package.json' specifies "${engineVersion}", you are currently running "${npmVersion}".`);
|
||||
reject(
|
||||
`Incorrect npm version\n'package.json' specifies "${engineVersion}", you are currently running "${npmVersion}".`,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const checkNodeVersion = (engines) => new Promise((resolve, reject) => {
|
||||
const checkNodeVersion = (engines) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const nodeVersion = process.version.substring(1);
|
||||
|
||||
if (semver.satisfies(nodeVersion, engines.node)) {
|
||||
resolve(engines);
|
||||
} else {
|
||||
reject(`Incorrect node version\n'package.json' specifies "${engines.node}", you are currently running "${process.version}".`);
|
||||
reject(
|
||||
`Incorrect node version\n'package.json' specifies "${engines.node}", you are currently running "${process.version}".`,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
getPackageJson()
|
||||
.then(getEngines)
|
||||
@ -69,5 +77,5 @@ getPackageJson()
|
||||
/* eslint-disable no-console, no-process-exit */
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
@ -444,7 +444,6 @@ function parseComparator(comp, loose) {
|
||||
}
|
||||
|
||||
class SemVer {
|
||||
|
||||
/**
|
||||
* A semantic version.
|
||||
* @param {string} version The version.
|
||||
@ -488,7 +487,7 @@ class SemVer {
|
||||
// Numberify any prerelease numeric ids
|
||||
if (matches[4]) {
|
||||
this.prerelease = matches[4].split(".").map((id) => {
|
||||
if ((/^[0-9]+$/).test(id)) {
|
||||
if (/^[0-9]+$/.test(id)) {
|
||||
const num = Number(id);
|
||||
if (num >= 0 && num < MAX_SAFE_INTEGER) {
|
||||
return num;
|
||||
@ -532,7 +531,9 @@ class SemVer {
|
||||
}
|
||||
|
||||
return (
|
||||
compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || compareIdentifiers(this.patch, other.patch)
|
||||
compareIdentifiers(this.major, other.major) ||
|
||||
compareIdentifiers(this.minor, other.minor) ||
|
||||
compareIdentifiers(this.patch, other.patch)
|
||||
);
|
||||
}
|
||||
|
||||
@ -572,7 +573,8 @@ class SemVer {
|
||||
}
|
||||
}
|
||||
|
||||
const compare = (leftVersion, rightVersion, loose) => new SemVer(leftVersion, loose).compare(new SemVer(rightVersion, loose));
|
||||
const compare = (leftVersion, rightVersion, loose) =>
|
||||
new SemVer(leftVersion, loose).compare(new SemVer(rightVersion, loose));
|
||||
const gt = (leftVersion, rightVersion, loose) => compare(leftVersion, rightVersion, loose) > 0;
|
||||
const lt = (leftVersion, rightVersion, loose) => compare(leftVersion, rightVersion, loose) < 0;
|
||||
const eq = (leftVersion, rightVersion, loose) => compare(leftVersion, rightVersion, loose) === 0;
|
||||
|
@ -533,6 +533,7 @@ export class Augmentation {
|
||||
console.warn(`Invalid Faction object in addToAllFactions(). Key value: ${fac}`);
|
||||
continue;
|
||||
}
|
||||
if (facObj.getInfo().special) continue;
|
||||
facObj.augmentations.push(this.name);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,118 @@
|
||||
import { IMap } from "../../types";
|
||||
|
||||
export const AugmentationNames: IMap<string> = {
|
||||
export const AugmentationNames: {
|
||||
Targeting1: string;
|
||||
Targeting2: string;
|
||||
Targeting3: string;
|
||||
SyntheticHeart: string;
|
||||
SynfibrilMuscle: string;
|
||||
CombatRib1: string;
|
||||
CombatRib2: string;
|
||||
CombatRib3: string;
|
||||
NanofiberWeave: string;
|
||||
SubdermalArmor: string;
|
||||
WiredReflexes: string;
|
||||
GrapheneBoneLacings: string;
|
||||
BionicSpine: string;
|
||||
GrapheneBionicSpine: string;
|
||||
BionicLegs: string;
|
||||
GrapheneBionicLegs: string;
|
||||
SpeechProcessor: string;
|
||||
TITN41Injection: string;
|
||||
EnhancedSocialInteractionImplant: string;
|
||||
BitWire: string;
|
||||
ArtificialBioNeuralNetwork: string;
|
||||
ArtificialSynapticPotentiation: string;
|
||||
EnhancedMyelinSheathing: string;
|
||||
SynapticEnhancement: string;
|
||||
NeuralRetentionEnhancement: string;
|
||||
DataJack: string;
|
||||
ENM: string;
|
||||
ENMCore: string;
|
||||
ENMCoreV2: string;
|
||||
ENMCoreV3: string;
|
||||
ENMAnalyzeEngine: string;
|
||||
ENMDMA: string;
|
||||
Neuralstimulator: string;
|
||||
NeuralAccelerator: string;
|
||||
CranialSignalProcessorsG1: string;
|
||||
CranialSignalProcessorsG2: string;
|
||||
CranialSignalProcessorsG3: string;
|
||||
CranialSignalProcessorsG4: string;
|
||||
CranialSignalProcessorsG5: string;
|
||||
NeuronalDensification: string;
|
||||
NeuroreceptorManager: string;
|
||||
NuoptimalInjectorImplant: string;
|
||||
SpeechEnhancement: string;
|
||||
FocusWire: string;
|
||||
PCDNI: string;
|
||||
PCDNIOptimizer: string;
|
||||
PCDNINeuralNetwork: string;
|
||||
PCMatrix: string;
|
||||
ADRPheromone1: string;
|
||||
ADRPheromone2: string;
|
||||
ShadowsSimulacrum: string;
|
||||
HacknetNodeCPUUpload: string;
|
||||
HacknetNodeCacheUpload: string;
|
||||
HacknetNodeNICUpload: string;
|
||||
HacknetNodeKernelDNI: string;
|
||||
HacknetNodeCoreDNI: string;
|
||||
NeuroFluxGovernor: string;
|
||||
Neurotrainer1: string;
|
||||
Neurotrainer2: string;
|
||||
Neurotrainer3: string;
|
||||
Hypersight: string;
|
||||
LuminCloaking1: string;
|
||||
LuminCloaking2: string;
|
||||
HemoRecirculator: string;
|
||||
SmartSonar: string;
|
||||
PowerRecirculator: string;
|
||||
QLink: string;
|
||||
TheRedPill: string;
|
||||
SPTN97: string;
|
||||
HiveMind: string;
|
||||
CordiARCReactor: string;
|
||||
SmartJaw: string;
|
||||
Neotra: string;
|
||||
Xanipher: string;
|
||||
nextSENS: string;
|
||||
OmniTekInfoLoad: string;
|
||||
PhotosyntheticCells: string;
|
||||
Neurolink: string;
|
||||
TheBlackHand: string;
|
||||
UnstableCircadianModulator: string;
|
||||
CRTX42AA: string;
|
||||
Neuregen: string;
|
||||
CashRoot: string;
|
||||
NutriGen: string;
|
||||
INFRARet: string;
|
||||
DermaForce: string;
|
||||
GrapheneBrachiBlades: string;
|
||||
GrapheneBionicArms: string;
|
||||
BrachiBlades: string;
|
||||
BionicArms: string;
|
||||
SNA: string;
|
||||
HydroflameLeftArm: string;
|
||||
EsperEyewear: string;
|
||||
EMS4Recombination: string;
|
||||
OrionShoulder: string;
|
||||
HyperionV1: string;
|
||||
HyperionV2: string;
|
||||
GolemSerum: string;
|
||||
VangelisVirus: string;
|
||||
VangelisVirus3: string;
|
||||
INTERLINKED: string;
|
||||
BladeRunner: string;
|
||||
BladeArmor: string;
|
||||
BladeArmorPowerCells: string;
|
||||
BladeArmorEnergyShielding: string;
|
||||
BladeArmorUnibeam: string;
|
||||
BladeArmorOmnibeam: string;
|
||||
BladeArmorIPU: string;
|
||||
BladesSimulacrum: string;
|
||||
StaneksGift1: string;
|
||||
StaneksGift2: string;
|
||||
StaneksGift3: string;
|
||||
StaneksGift4: string;
|
||||
} = {
|
||||
Targeting1: "Augmented Targeting I",
|
||||
Targeting2: "Augmented Targeting II",
|
||||
Targeting3: "Augmented Targeting III",
|
||||
@ -87,7 +199,7 @@ export const AugmentationNames: IMap<string> = {
|
||||
NutriGen: "NutriGen Implant",
|
||||
INFRARet: "INFRARET Enhancement",
|
||||
DermaForce: "DermaForce Particle Barrier",
|
||||
GrapheneBrachiBlades: "Graphene BranchiBlades Upgrade",
|
||||
GrapheneBrachiBlades: "Graphene BrachiBlades Upgrade",
|
||||
GrapheneBionicArms: "Graphene Bionic Arms Upgrade",
|
||||
BrachiBlades: "BrachiBlades",
|
||||
BionicArms: "Bionic Arms",
|
||||
|
@ -1960,6 +1960,18 @@ export class Bladeburner implements IBladeburner {
|
||||
break;
|
||||
}
|
||||
}
|
||||
const gen = [
|
||||
"Training",
|
||||
"Recruitment",
|
||||
"FieldAnalysis",
|
||||
"Field Analysis",
|
||||
"Diplomacy",
|
||||
"Hyperbolic Regeneration Chamber",
|
||||
];
|
||||
if (gen.includes(res.type)) {
|
||||
res.type = "General";
|
||||
}
|
||||
|
||||
if (res.type == null) {
|
||||
res.type = "Idle";
|
||||
}
|
||||
|
116
src/Constants.ts
116
src/Constants.ts
@ -114,7 +114,7 @@ export const CONSTANTS: {
|
||||
TotalNumBitNodes: number;
|
||||
LatestUpdate: string;
|
||||
} = {
|
||||
Version: "0.55.0",
|
||||
Version: "0.56.0",
|
||||
|
||||
// Speed (in ms) at which the main loop is updated
|
||||
_idleSpeed: 200,
|
||||
@ -281,31 +281,107 @@ export const CONSTANTS: {
|
||||
TotalNumBitNodes: 24,
|
||||
|
||||
LatestUpdate: `
|
||||
v0.55.0 - 2021-09-20 Material UI (hydroflame & community)
|
||||
v0.56.0 - 2021-10-11 Trimming the backlog (hydroflame & community)
|
||||
-------------------------------------------
|
||||
|
||||
** Global **
|
||||
** BREAKING **
|
||||
|
||||
* The game is now 100% in typescript, react, and Material-UI
|
||||
* The 'write' function is now async. This helps when making scripts that write scripts.
|
||||
|
||||
** Terminal **
|
||||
|
||||
* 'grow' and 'weaken' have been added as terminal command. This should help player transition
|
||||
from commands to scripts. The tutorial also talks about it.
|
||||
* 'cp' command added
|
||||
* Improved performance by rate limiting refresh.
|
||||
|
||||
** IP vs Hostname **
|
||||
|
||||
* The game now uses hostname as primary key for it's servers (yeah believe it or not IPs were
|
||||
used until then). This has caused some issues with purchased servers (they couldn't be sold).
|
||||
You might need to soft reset for the game to fully convert itself.
|
||||
|
||||
** Sleeve **
|
||||
|
||||
* Fixed bug where they couldn't train at Volhaven.
|
||||
* No longer consume all bonus time at once, making it look buggy.
|
||||
|
||||
** SF9 **
|
||||
|
||||
* Now boosts hacknet production by 8/12/14%
|
||||
|
||||
** Hacknet Servers **
|
||||
|
||||
* production nerfed by 10%
|
||||
* Max money increase gets weaker above 10t max money
|
||||
|
||||
** Corporation **
|
||||
|
||||
* Warehouse tooltip now also displays the amount of space taken by products.
|
||||
* Changed research box completely to avoid dependency on Treant (Treant is a pita)
|
||||
* All textbox should accept MAX/MP case insensitive.
|
||||
* Fixed export popup not refreshing dropdowns correctly.
|
||||
* Fixed product mku becoming zero
|
||||
* Increased scaling of Wilson to avoid feedback loop.
|
||||
* Can no longer get in debt by buying real estate
|
||||
* Bonus time is consumed faster.
|
||||
|
||||
** Netscript **
|
||||
|
||||
* isBusy takes bitverse and infiltration into account
|
||||
* hospitalize can't be called when in infiltration.
|
||||
* setToCommitCrime now accepts crime rough name instead of perfect name.
|
||||
* disableLog All now works for bladeburner functions.
|
||||
* Fixed netscript port for ns1.
|
||||
|
||||
** Augmentation **
|
||||
|
||||
* Added augmentation to Ti Di Hui that removes penalty for being unfocused.
|
||||
* Neuroflux no longer appears in special factions.
|
||||
|
||||
** Script Editor **
|
||||
|
||||
* Ram check is debounced instead of refreshed every second.
|
||||
* Added the vscode extension documentation to the game (it doesn't work well, thought)
|
||||
* Fixed issue where autocomplete list would grow forever
|
||||
* Added semi-monokai as theme.
|
||||
* Fixed issue where modifying filename would mess it up.
|
||||
* Font size can be changed now.
|
||||
|
||||
** Infiltration **
|
||||
|
||||
* Fixed issue where game controls would become unfocused.
|
||||
|
||||
** Misc. **
|
||||
|
||||
* Corporations can no longer bribe special factions
|
||||
* Infiltration can no longer lose focus of the keyboard.
|
||||
* Fix terminal line limit
|
||||
* Added theme editor
|
||||
* Theme applies on game load (@Nolshine)
|
||||
* Sleeves no longer consume all bonus time for some actions
|
||||
* Fix a bug where the autocomlete list would get duplicates
|
||||
* Fix tutorial not scaling properly on small screens
|
||||
* Import should be more consistent
|
||||
* Typo with 'help' command
|
||||
* Fix infinite loop in casino
|
||||
* Fixed loader incorrectly assuming some null values are incorrect.
|
||||
* installBackdoor trigger Bitverse sequence
|
||||
* Some improvements to the theme editor
|
||||
* Improved documentation about where to learn javascript.
|
||||
* Added some instructions for contributors.
|
||||
* Fixed typo in corporation sell shares modal (@Saynt_Garmo)
|
||||
* Fixed pagination being black on black in Active Scripts
|
||||
* Create Script tab renamed to Script Editor
|
||||
* Fixed an issue where corp some textbox wouldn't update when changing city.
|
||||
* Fixed an issue where hacknet online time was always 0.
|
||||
* Netscript function prompt fixed.
|
||||
* Fixed miscalculation in growth.
|
||||
* Script with syntax errors will try to be a tad more helpful.
|
||||
* Corporations can no longer bribe bladeburners.
|
||||
* Augmentation Graphene Branchiblade renamed to Brachi, like the rest of them.
|
||||
* All ram is displayed in GB/TB/PB now.
|
||||
* Game now saves when saving a file, this can be turned off.
|
||||
* Several improvement to log window.
|
||||
* Bladeburner current action returns General type instead of the name of the action.
|
||||
* Bladeburner travel and Sleeve travel respect disable ASCII.
|
||||
* Tutorial fits on small screens.
|
||||
* Import is much slower but more consistent now.
|
||||
* Fix intelligence not updating properly.
|
||||
* Added SF -1: Time Compression
|
||||
* ReadTheDoc theme now matches the game.
|
||||
* Logbox should wrap text better
|
||||
* Logbox behavior should feel better.
|
||||
* Fix font for AutoLink.exe
|
||||
* nerf noodle bar
|
||||
`,
|
||||
|
||||
/*
|
||||
|
||||
|
||||
*/
|
||||
};
|
||||
|
@ -105,6 +105,7 @@ export function SellMaterial(mat: Material, amt: string, price: string): void {
|
||||
}
|
||||
|
||||
//Parse quantity
|
||||
amt = amt.toUpperCase();
|
||||
if (amt.includes("MAX") || amt.includes("PROD")) {
|
||||
let q = amt.replace(/\s+/g, "");
|
||||
q = q.replace(/[^-()\d/*+.MAXPROD]/g, "");
|
||||
@ -168,6 +169,7 @@ export function SellProduct(product: Product, city: string, amt: string, price:
|
||||
const cities = Object.keys(Cities);
|
||||
|
||||
// Parse quantity
|
||||
amt = amt.toUpperCase();
|
||||
if (amt.includes("MAX") || amt.includes("PROD")) {
|
||||
//Dynamically evaluated quantity. First test to make sure its valid
|
||||
let qty = amt.replace(/\s+/g, "");
|
||||
@ -372,7 +374,7 @@ export function Research(division: IIndustry, researchName: string): void {
|
||||
|
||||
export function ExportMaterial(divisionName: string, cityName: string, material: Material, amt: string): void {
|
||||
// Sanitize amt
|
||||
let sanitizedAmt = amt.replace(/\s+/g, "");
|
||||
let sanitizedAmt = amt.replace(/\s+/g, "").toUpperCase();
|
||||
sanitizedAmt = sanitizedAmt.replace(/[^-()\d/*+.MAX]/g, "");
|
||||
let temp = sanitizedAmt.replace(/MAX/g, "1");
|
||||
try {
|
||||
|
@ -564,7 +564,7 @@ export class Industry implements IIndustry {
|
||||
buyAmt = mat.buy * CorporationConstants.SecsPerMarketCycle * marketCycles;
|
||||
|
||||
if (matName == "RealEstate") {
|
||||
maxAmt = buyAmt;
|
||||
maxAmt = corporation.funds.toNumber() / mat.bCost;
|
||||
} else {
|
||||
maxAmt = Math.floor((warehouse.size - warehouse.sizeUsed) / MaterialSizes[matName]);
|
||||
}
|
||||
@ -840,7 +840,7 @@ export class Industry implements IIndustry {
|
||||
let sellAmt;
|
||||
if (isString(mat.sllman[1])) {
|
||||
//Dynamically evaluated
|
||||
let tmp = (mat.sllman[1] as string).replace(/MAX/g, maxSell + "");
|
||||
let tmp = (mat.sllman[1] as string).replace(/MAX/g, (maxSell + "").toUpperCase());
|
||||
tmp = tmp.replace(/PROD/g, mat.prd + "");
|
||||
try {
|
||||
sellAmt = eval(tmp);
|
||||
@ -893,7 +893,7 @@ export class Industry implements IIndustry {
|
||||
const exp = mat.exp[expI];
|
||||
const amtStr = exp.amt.replace(
|
||||
/MAX/g,
|
||||
mat.qty / (CorporationConstants.SecsPerMarketCycle * marketCycles) + "",
|
||||
(mat.qty / (CorporationConstants.SecsPerMarketCycle * marketCycles) + "").toUpperCase(),
|
||||
);
|
||||
let amt = 0;
|
||||
try {
|
||||
@ -1201,7 +1201,7 @@ export class Industry implements IIndustry {
|
||||
let sellAmt;
|
||||
if (product.sllman[city][0] && isString(product.sllman[city][1])) {
|
||||
//Sell amount is dynamically evaluated
|
||||
let tmp = product.sllman[city][1].replace(/MAX/g, maxSell);
|
||||
let tmp = product.sllman[city][1].replace(/MAX/g, (maxSell + "").toUpperCase());
|
||||
tmp = tmp.replace(/PROD/g, product.data[city][1]);
|
||||
try {
|
||||
tmp = eval(tmp);
|
||||
|
@ -185,11 +185,12 @@ export class Product {
|
||||
0.05 * employeeProd[EmployeePositions.Business]);
|
||||
this.calculateRating(industry);
|
||||
const advMult = 1 + Math.pow(this.advCost, 0.1) / 100;
|
||||
this.mku = 100 / (advMult * Math.pow(this.qlt + 0.001, 0.65) * (busRatio + mgmtRatio));
|
||||
const busmgtgRatio = Math.max(busRatio + mgmtRatio, 1 / employeeProd["total"]);
|
||||
this.mku = 100 / (advMult * Math.pow(this.qlt + 0.001, 0.65) * busmgtgRatio);
|
||||
|
||||
// I actually don't understand well enough to know if this is right.
|
||||
// I'm adding this to prevent a crash.
|
||||
if (this.mku === 0) this.mku = 1;
|
||||
if (this.mku === 0 || !isFinite(this.mku)) this.mku = 1;
|
||||
|
||||
this.dmd =
|
||||
industry.awareness === 0 ? 20 : Math.min(100, advMult * (100 * (industry.popularity / industry.awareness)));
|
||||
|
@ -47,7 +47,7 @@ export const CorporationUpgrades: IMap<CorporationUpgrade> = {
|
||||
"3": [
|
||||
3,
|
||||
4e9,
|
||||
1.12,
|
||||
1.5,
|
||||
0.005,
|
||||
"Wilson Analytics",
|
||||
"Purchase data and analysis from Wilson, a marketing research " +
|
||||
|
@ -80,10 +80,20 @@ export function ExpandIndustryTab(props: IProps): React.ReactElement {
|
||||
<Typography>Division name:</Typography>
|
||||
|
||||
<Box display="flex" alignItems="center">
|
||||
<TextField autoFocus={true} value={name} onChange={onNameChange} onKeyDown={onKeyDown} type="text" />
|
||||
<TextField
|
||||
autoFocus={true}
|
||||
value={name}
|
||||
onChange={onNameChange}
|
||||
onKeyDown={onKeyDown}
|
||||
type="text"
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<Button disabled={disabled} sx={{ mx: 1 }} onClick={newIndustry}>
|
||||
Create Division
|
||||
Expand
|
||||
</Button>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
|
@ -43,16 +43,21 @@ export function ExpandNewCity(props: IProps): React.ReactElement {
|
||||
Would you like to expand into a new city by opening an office? This would cost{" "}
|
||||
<MoneyCost money={CorporationConstants.OfficeInitialCost} corp={corp} />
|
||||
</Typography>
|
||||
<Select value={city} onChange={onCityChange}>
|
||||
<Select
|
||||
endAdornment={
|
||||
<Button onClick={expand} disabled={disabled}>
|
||||
Confirm
|
||||
</Button>
|
||||
}
|
||||
value={city}
|
||||
onChange={onCityChange}
|
||||
>
|
||||
{possibleCities.map((cityName: string) => (
|
||||
<MenuItem key={cityName} value={cityName}>
|
||||
{cityName}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
<Button onClick={expand} disabled={disabled}>
|
||||
Confirm
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -39,7 +39,9 @@ export function ExportModal(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function onIndustryChange(event: SelectChangeEvent<string>): void {
|
||||
setIndustry(event.target.value);
|
||||
const div = event.target.value;
|
||||
setIndustry(div);
|
||||
setCity(Object.keys(corp.divisions[0].warehouses)[0]);
|
||||
}
|
||||
|
||||
function onAmtChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
|
@ -30,8 +30,7 @@ export function Augmentations(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function queueAllAugs(): void {
|
||||
for (const i in AugmentationNames) {
|
||||
const augName = AugmentationNames[i];
|
||||
for (const augName of Object.keys(AugmentationNames)) {
|
||||
props.player.queueAugmentation(augName);
|
||||
}
|
||||
}
|
||||
|
@ -2,13 +2,14 @@ import React from "react";
|
||||
import { use } from "../ui/Context";
|
||||
import { Exploit } from "./Exploit";
|
||||
|
||||
const getComputedStyle = window.getComputedStyle;
|
||||
export function Unclickable(): React.ReactElement {
|
||||
const player = use.Player();
|
||||
|
||||
function unclickable(event: React.MouseEvent<HTMLDivElement>): void {
|
||||
if (!event.target || !(event.target instanceof Element)) return;
|
||||
const display = window.getComputedStyle(event.target as Element).display;
|
||||
const visibility = window.getComputedStyle(event.target as Element).visibility;
|
||||
const display = getComputedStyle(event.target as Element).display;
|
||||
const visibility = getComputedStyle(event.target as Element).visibility;
|
||||
if (display === "none" && visibility === "hidden" && event.isTrusted) player.giveExploit(Exploit.Unclickable);
|
||||
}
|
||||
|
||||
|
@ -24,9 +24,9 @@ function timeCompression(): void {
|
||||
return;
|
||||
}
|
||||
last = now;
|
||||
setTimeout(minute, 1000);
|
||||
window.setTimeout(minute, 1000);
|
||||
}
|
||||
setTimeout(minute, 1000);
|
||||
window.setTimeout(minute, 1000);
|
||||
}
|
||||
|
||||
export function startExploits(): void {
|
||||
|
@ -50,6 +50,11 @@ export class FactionInfo {
|
||||
*/
|
||||
keep: boolean;
|
||||
|
||||
/**
|
||||
* Special faction
|
||||
*/
|
||||
special: boolean;
|
||||
|
||||
constructor(
|
||||
infoText: JSX.Element,
|
||||
enemies: string[],
|
||||
@ -57,6 +62,7 @@ export class FactionInfo {
|
||||
offerHackingWork: boolean,
|
||||
offerFieldWork: boolean,
|
||||
offerSecurityWork: boolean,
|
||||
special: boolean,
|
||||
keep: boolean,
|
||||
) {
|
||||
this.infoText = infoText;
|
||||
@ -70,6 +76,7 @@ export class FactionInfo {
|
||||
this.augmentationPriceMult = 1;
|
||||
this.augmentationRepRequirementMult = 1;
|
||||
this.keep = keep;
|
||||
this.special = special;
|
||||
}
|
||||
|
||||
offersWork(): boolean {
|
||||
@ -96,6 +103,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
|
||||
Daedalus: new FactionInfo(
|
||||
@ -106,6 +114,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
|
||||
"The Covenant": new FactionInfo(
|
||||
@ -124,6 +133,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
|
||||
// Megacorporations, each forms its own faction
|
||||
@ -139,6 +149,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
),
|
||||
|
||||
@ -158,6 +169,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
),
|
||||
|
||||
@ -175,10 +187,11 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
),
|
||||
|
||||
"Blade Industries": new FactionInfo(<>Augmentation is Salvation.</>, [], true, true, true, true, true),
|
||||
"Blade Industries": new FactionInfo(<>Augmentation is Salvation.</>, [], true, true, true, true, false, true),
|
||||
|
||||
NWO: new FactionInfo(
|
||||
(
|
||||
@ -193,10 +206,20 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
),
|
||||
|
||||
"Clarke Incorporated": new FactionInfo(<>The Power of the Genome - Unlocked.</>, [], true, true, true, true, true),
|
||||
"Clarke Incorporated": new FactionInfo(
|
||||
<>The Power of the Genome - Unlocked.</>,
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
),
|
||||
|
||||
"OmniTek Incorporated": new FactionInfo(
|
||||
<>Simply put, our mission is to design and build robots that make a difference.</>,
|
||||
@ -205,6 +228,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
),
|
||||
|
||||
@ -220,10 +244,20 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
),
|
||||
|
||||
"KuaiGong International": new FactionInfo(<>Dream big. Work hard. Make history.</>, [], true, true, true, true, true),
|
||||
"KuaiGong International": new FactionInfo(
|
||||
<>Dream big. Work hard. Make history.</>,
|
||||
[],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
),
|
||||
|
||||
// Other Corporations
|
||||
"Fulcrum Secret Technologies": new FactionInfo(
|
||||
@ -238,6 +272,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
),
|
||||
|
||||
@ -261,6 +296,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
|
||||
"The Black Hand": new FactionInfo(
|
||||
@ -280,6 +316,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
|
||||
// prettier-ignore
|
||||
@ -325,6 +362,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
|
||||
// City factions, essentially governments
|
||||
@ -336,8 +374,18 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
Chongqing: new FactionInfo(
|
||||
<>Serve the People.</>,
|
||||
["Sector-12", "Aevum", "Volhaven"],
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
Chongqing: new FactionInfo(<>Serve the People.</>, ["Sector-12", "Aevum", "Volhaven"], true, true, true, true, false),
|
||||
Ishima: new FactionInfo(
|
||||
<>The East Asian Order of the Future.</>,
|
||||
["Sector-12", "Aevum", "Volhaven"],
|
||||
@ -346,6 +394,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
"New Tokyo": new FactionInfo(
|
||||
<>Asia's World City.</>,
|
||||
@ -355,6 +404,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
"Sector-12": new FactionInfo(
|
||||
<>The City of the Future.</>,
|
||||
@ -364,6 +414,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
Volhaven: new FactionInfo(
|
||||
<>Benefit, Honor, and Glory.</>,
|
||||
@ -373,6 +424,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
|
||||
// Criminal Organizations/Gangs
|
||||
@ -384,6 +436,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
|
||||
"The Dark Army": new FactionInfo(
|
||||
@ -394,9 +447,10 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
|
||||
"The Syndicate": new FactionInfo(<>Honor holds you back.</>, [], true, true, true, true, false),
|
||||
"The Syndicate": new FactionInfo(<>Honor holds you back.</>, [], true, true, true, true, false, false),
|
||||
|
||||
Silhouette: new FactionInfo(
|
||||
(
|
||||
@ -415,6 +469,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
|
||||
Tetrads: new FactionInfo(
|
||||
@ -425,14 +480,15 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
|
||||
"Slum Snakes": new FactionInfo(<>Slum Snakes rule!</>, [], false, false, true, true, false),
|
||||
"Slum Snakes": new FactionInfo(<>Slum Snakes rule!</>, [], false, false, true, true, false, false),
|
||||
|
||||
// Earlygame factions - factions the player will prestige with early on that don't belong in other categories.
|
||||
Netburners: new FactionInfo(<>{"~~//*>H4CK||3T 8URN3R5**>?>\\~~"}</>, [], true, true, false, false, false),
|
||||
Netburners: new FactionInfo(<>{"~~//*>H4CK||3T 8URN3R5**>?>\\~~"}</>, [], true, true, false, false, false, false),
|
||||
|
||||
"Tian Di Hui": new FactionInfo(<>Obey Heaven and work righteously.</>, [], true, true, false, true, false),
|
||||
"Tian Di Hui": new FactionInfo(<>Obey Heaven and work righteously.</>, [], true, true, false, true, false, false),
|
||||
|
||||
CyberSec: new FactionInfo(
|
||||
(
|
||||
@ -448,6 +504,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
|
||||
// Special Factions
|
||||
@ -466,6 +523,7 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
),
|
||||
|
||||
@ -509,5 +567,6 @@ export const FactionInfos: IMap<FactionInfo> = {
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
),
|
||||
};
|
||||
|
@ -41,6 +41,7 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
||||
if (isPlayersGang) {
|
||||
const augs: string[] = [];
|
||||
for (const augName in Augmentations) {
|
||||
if (augName === AugmentationNames.NeuroFluxGovernor) continue;
|
||||
const aug = Augmentations[augName];
|
||||
if (!aug.isSpecial) {
|
||||
augs.push(augName);
|
||||
|
@ -510,7 +510,9 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
||||
}
|
||||
if (!(target instanceof Server)) throw new Error(`'${upgTarget}' is not a normal server.`);
|
||||
|
||||
target.changeMaximumMoney(upg.value, true);
|
||||
const old = target.moneyMax;
|
||||
target.changeMaximumMoney(upg.value);
|
||||
console.log(target.moneyMax / old);
|
||||
} catch (e) {
|
||||
player.hashManager.refundUpgrade(upgName);
|
||||
return false;
|
||||
|
@ -28,6 +28,7 @@ import { TableCell } from "../../ui/React/Table";
|
||||
import TableBody from "@mui/material/TableBody";
|
||||
import Table from "@mui/material/Table";
|
||||
import TableRow from "@mui/material/TableRow";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
|
||||
interface IProps {
|
||||
node: HacknetNode;
|
||||
@ -163,7 +164,7 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
|
||||
<Typography>RAM:</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography>{node.ram}GB</Typography>
|
||||
<Typography>{numeralWrapper.formatRAM(node.ram)}</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Button onClick={upgradeRamOnClick}>{upgradeRamContent}</Button>
|
||||
|
@ -31,6 +31,7 @@ import { TableCell } from "../../ui/React/Table";
|
||||
import TableBody from "@mui/material/TableBody";
|
||||
import Table from "@mui/material/Table";
|
||||
import TableRow from "@mui/material/TableRow";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
|
||||
interface IProps {
|
||||
node: HacknetServer;
|
||||
@ -213,7 +214,7 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
<Typography>RAM:</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography>{node.maxRam}GB</Typography>
|
||||
<Typography>{numeralWrapper.formatRAM(node.maxRam)}</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Button onClick={upgradeRamOnClick}>{upgradeRamContent}</Button>
|
||||
|
@ -64,13 +64,21 @@ export function HacknetUpgradeElem(props: IProps): React.ReactElement {
|
||||
</Typography>
|
||||
|
||||
<Typography>{upg.desc}</Typography>
|
||||
{!upg.hasTargetServer && (
|
||||
<Button onClick={purchase} disabled={!canPurchase}>
|
||||
Purchase
|
||||
Buy
|
||||
</Button>
|
||||
{level > 0 && effect && <Typography>{effect}</Typography>}
|
||||
{upg.hasTargetServer && (
|
||||
<ServerDropdown value={selectedServer} serverType={ServerType.Foreign} onChange={changeTargetServer} />
|
||||
)}
|
||||
{upg.hasTargetServer && (
|
||||
<ServerDropdown
|
||||
purchase={purchase}
|
||||
canPurchase={canPurchase}
|
||||
value={selectedServer}
|
||||
serverType={ServerType.Foreign}
|
||||
onChange={changeTargetServer}
|
||||
/>
|
||||
)}
|
||||
{level > 0 && effect && <Typography>{effect}</Typography>}
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import { purchaseRamForHomeComputer } from "../../Server/ServerPurchases";
|
||||
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { MathComponent } from "mathjax-react";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
@ -31,7 +32,8 @@ export function RamButton(props: IProps): React.ReactElement {
|
||||
<Tooltip title={<MathComponent tex={String.raw`\large{cost = 3.2 \times 10^3 \times 1.58^{log_2{(ram)}}}`} />}>
|
||||
<span>
|
||||
<Button disabled={!props.p.canAfford(cost)} onClick={buy}>
|
||||
Upgrade 'home' RAM ({homeComputer.maxRam}GB -> {homeComputer.maxRam * 2}GB) -
|
||||
Upgrade 'home' RAM ({numeralWrapper.formatRAM(homeComputer.maxRam)} ->
|
||||
{numeralWrapper.formatRAM(homeComputer.maxRam * 2)}) -
|
||||
<Money money={cost} player={props.p} />
|
||||
</Button>
|
||||
</span>
|
||||
|
@ -17,6 +17,7 @@ import { getPurchaseServerCost } from "../../Server/ServerPurchases";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { use } from "../../ui/Context";
|
||||
import { PurchaseServerModal } from "./PurchaseServerModal";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
|
||||
interface IServerProps {
|
||||
ram: number;
|
||||
@ -30,7 +31,7 @@ function ServerButton(props: IServerProps): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
<Button onClick={() => setOpen(true)} disabled={!player.canAfford(cost)}>
|
||||
Purchase {props.ram}GB Server -
|
||||
Purchase {numeralWrapper.formatRAM(props.ram)} Server -
|
||||
<Money money={cost} player={player} />
|
||||
</Button>
|
||||
<PurchaseServerModal
|
||||
|
@ -10,7 +10,6 @@ import { RunningScript } from "../Script/RunningScript";
|
||||
import { GetServer } from "../Server/AllServers";
|
||||
|
||||
import { compareArrays } from "../utils/helpers/compareArrays";
|
||||
import { roundToTwo } from "../utils/helpers/roundToTwo";
|
||||
|
||||
export function killWorkerScript(runningScriptObj: RunningScript, hostname: string, rerenderUi?: boolean): boolean;
|
||||
export function killWorkerScript(workerScript: WorkerScript): boolean;
|
||||
@ -90,15 +89,6 @@ function removeWorkerScript(workerScript: WorkerScript, rerenderUi = true): void
|
||||
return;
|
||||
}
|
||||
|
||||
// Recalculate ram used on that server
|
||||
server.ramUsed = roundToTwo(server.ramUsed - workerScript.ramUsage);
|
||||
if (server.ramUsed < 0) {
|
||||
console.warn(
|
||||
`Server (${server.hostname}) RAM usage went negative (if it's due to floating pt imprecision, it's okay): ${server.ramUsed}`,
|
||||
);
|
||||
server.ramUsed = 0;
|
||||
}
|
||||
|
||||
// Delete the RunningScript object from that server
|
||||
for (let i = 0; i < server.runningScripts.length; ++i) {
|
||||
const runningScript = server.runningScripts[i];
|
||||
@ -108,6 +98,10 @@ function removeWorkerScript(workerScript: WorkerScript, rerenderUi = true): void
|
||||
}
|
||||
}
|
||||
|
||||
// Recalculate ram used on that server
|
||||
server.ramUsed = 0;
|
||||
for (const rs of server.runningScripts) server.ramUsed += rs.ramUsage * rs.threads;
|
||||
|
||||
// Delete script from global pool (workerScripts)
|
||||
const res = workerScripts.delete(workerScript.pid);
|
||||
if (!res) {
|
||||
|
@ -13,13 +13,12 @@ export function netscriptDelay(time: number, workerScript: WorkerScript): Promis
|
||||
}
|
||||
|
||||
export function makeRuntimeRejectMsg(workerScript: WorkerScript, msg: string): string {
|
||||
const lineNum = "";
|
||||
const server = GetServer(workerScript.hostname);
|
||||
if (server == null) {
|
||||
throw new Error(`WorkerScript constructed with invalid server ip: ${workerScript.hostname}`);
|
||||
}
|
||||
|
||||
return "|" + server.hostname + "|" + workerScript.name + "|" + msg + lineNum;
|
||||
return "|" + server.hostname + "|" + workerScript.name + "|" + msg;
|
||||
}
|
||||
|
||||
export function resolveNetscriptRequestedThreads(
|
||||
|
@ -122,6 +122,7 @@ import { Router } from "./ui/GameRoot";
|
||||
import { numeralWrapper } from "./ui/numeralFormat";
|
||||
import { is2DArray } from "./utils/helpers/is2DArray";
|
||||
import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions";
|
||||
import { SpecialServers } from "./Server/data/SpecialServers";
|
||||
|
||||
import { LogBoxEvents } from "./ui/React/LogBoxManager";
|
||||
import { arrayToString } from "./utils/helpers/arrayToString";
|
||||
@ -136,6 +137,7 @@ import { IIndustry } from "./Corporation/IIndustry";
|
||||
|
||||
import { Faction } from "./Faction/Faction";
|
||||
import { Augmentation } from "./Augmentation/Augmentation";
|
||||
import { Page } from "./ui/Router";
|
||||
|
||||
import { CodingContract } from "./CodingContracts";
|
||||
import { Stock } from "./StockMarket/Stock";
|
||||
@ -724,7 +726,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
|
||||
const gang = NetscriptGang(Player, workerScript, helper);
|
||||
const sleeve = NetscriptSleeve(Player, workerScript, helper);
|
||||
const extra = NetscriptExtra(Player, workerScript, helper);
|
||||
const extra = NetscriptExtra(Player, workerScript);
|
||||
const hacknet = NetscriptHacknet(Player, workerScript, helper);
|
||||
const stanek = NetscriptStanek(Player, workerScript, helper);
|
||||
|
||||
@ -732,7 +734,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
hacknet: hacknet,
|
||||
sprintf: sprintf,
|
||||
vsprintf: vsprintf,
|
||||
scan: function (ip: any = workerScript.hostname, hostnames: any = true): any {
|
||||
scan: function (ip: any = workerScript.hostname): any {
|
||||
updateDynamicRam("scan", getRamCost("scan"));
|
||||
const server = GetServer(ip);
|
||||
if (server == null) {
|
||||
@ -740,14 +742,9 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
}
|
||||
const out = [];
|
||||
for (let i = 0; i < server.serversOnNetwork.length; i++) {
|
||||
let entry;
|
||||
const s = getServerOnNetwork(server, i);
|
||||
if (s === null) continue;
|
||||
if (hostnames) {
|
||||
entry = s.hostname;
|
||||
} else {
|
||||
entry = s.hostname;
|
||||
}
|
||||
const entry = s.hostname;
|
||||
if (entry == null) {
|
||||
continue;
|
||||
}
|
||||
@ -874,7 +871,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
return Promise.resolve(moneyAfter / moneyBefore);
|
||||
});
|
||||
},
|
||||
growthAnalyze: function (ip: any, growth: any): any {
|
||||
growthAnalyze: function (ip: any, growth: any, cores: any = 1): any {
|
||||
updateDynamicRam("growthAnalyze", getRamCost("growthAnalyze"));
|
||||
|
||||
// Check argument validity
|
||||
@ -887,7 +884,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
throw makeRuntimeErrorMsg("growthAnalyze", `Invalid argument: growth must be numeric and >= 1, is ${growth}.`);
|
||||
}
|
||||
|
||||
return numCycleForGrowth(server, Number(growth), Player, 1);
|
||||
return numCycleForGrowth(server, Number(growth), Player, cores);
|
||||
},
|
||||
weaken: function (ip: any, { threads: requestedThreads }: any = {}): any {
|
||||
updateDynamicRam("weaken", getRamCost("weaken"));
|
||||
@ -1596,9 +1593,6 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
},
|
||||
getServer: function (ip: any): any {
|
||||
updateDynamicRam("getServer", getRamCost("getServer"));
|
||||
if (SourceFileFlags[5] <= 0 && Player.bitNodeN !== 5) {
|
||||
throw makeRuntimeErrorMsg("getServer", "Requires Source-File 5 to run.");
|
||||
}
|
||||
const server = safeGetServer(ip, "getServer");
|
||||
const copy = Object.assign({}, server);
|
||||
// These fields should be hidden.
|
||||
@ -2333,17 +2327,16 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
// Create a new script
|
||||
script = new Script(fn, data, server.hostname, server.scripts);
|
||||
server.scripts.push(script);
|
||||
return true;
|
||||
return script.updateRamUsage(server.scripts);
|
||||
}
|
||||
mode === "w" ? (script.code = data) : (script.code += data);
|
||||
script.updateRamUsage(server.scripts);
|
||||
script.markUpdated();
|
||||
return script.updateRamUsage(server.scripts);
|
||||
} else {
|
||||
// Write to text file
|
||||
const txtFile = getTextFile(fn, server);
|
||||
if (txtFile == null) {
|
||||
createTextFile(fn, data, server);
|
||||
return true;
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (mode === "w") {
|
||||
txtFile.write(data);
|
||||
@ -2351,7 +2344,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
txtFile.append(data);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
throw makeRuntimeErrorMsg("write", `Invalid argument: ${port}`);
|
||||
}
|
||||
@ -3097,6 +3090,10 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
workerScript.log("installBackdoor", `Successfully installed backdoor on '${server.hostname}'`);
|
||||
|
||||
server.backdoorInstalled = true;
|
||||
|
||||
if (SpecialServers.WorldDaemon === server.hostname) {
|
||||
Router.toBitVerse(false, false);
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
},
|
||||
@ -3260,12 +3257,16 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
hospitalize: function (): any {
|
||||
updateDynamicRam("hospitalize", getRamCost("hospitalize"));
|
||||
checkSingularityAccess("hospitalize", 1);
|
||||
if (Player.isWorking || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse) {
|
||||
workerScript.log("hospitalize", "Cannot go to the hospital because the player is busy.");
|
||||
return;
|
||||
}
|
||||
return Player.hospitalize();
|
||||
},
|
||||
isBusy: function (): any {
|
||||
updateDynamicRam("isBusy", getRamCost("isBusy"));
|
||||
checkSingularityAccess("isBusy", 1);
|
||||
return Player.isWorking;
|
||||
return Player.isWorking || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse;
|
||||
},
|
||||
stopAction: function (): any {
|
||||
updateDynamicRam("stopAction", getRamCost("stopAction"));
|
||||
@ -3301,7 +3302,9 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
|
||||
workerScript.log(
|
||||
"upgradeHomeRam",
|
||||
`Purchased additional RAM for home computer! It now has ${homeComputer.maxRam}GB of RAM.`,
|
||||
`Purchased additional RAM for home computer! It now has ${numeralWrapper.formatRAM(
|
||||
homeComputer.maxRam,
|
||||
)} of RAM.`,
|
||||
);
|
||||
return true;
|
||||
},
|
||||
@ -4191,9 +4194,6 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
},
|
||||
joinBladeburnerDivision: function (): any {
|
||||
updateDynamicRam("joinBladeburnerDivision", getRamCost("bladeburner", "joinBladeburnerDivision"));
|
||||
checkBladeburnerAccess("joinBladeburnerDivision", true);
|
||||
const bladeburner = Player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
if (Player.bitNodeN === 7 || SourceFileFlags[7] > 0) {
|
||||
if (Player.bitNodeN === 8) {
|
||||
return false;
|
||||
@ -4209,12 +4209,6 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
Player.bladeburner = new Bladeburner(Player);
|
||||
workerScript.log("joinBladeburnerDivision", "You have been accepted into the Bladeburner division");
|
||||
|
||||
const worldHeader = document.getElementById("world-menu-header");
|
||||
if (worldHeader instanceof HTMLElement) {
|
||||
worldHeader.click();
|
||||
worldHeader.click();
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
workerScript.log(
|
||||
@ -4634,19 +4628,19 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
...extra,
|
||||
};
|
||||
|
||||
function getFunctionNames(obj: NS): string[] {
|
||||
function getFunctionNames(obj: NS, prefix: string): string[] {
|
||||
const functionNames: string[] = [];
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
if (typeof value == "function") {
|
||||
functionNames.push(key);
|
||||
functionNames.push(prefix + key);
|
||||
} else if (typeof value == "object") {
|
||||
functionNames.push(...getFunctionNames(value));
|
||||
functionNames.push(...getFunctionNames(value, key + "."));
|
||||
}
|
||||
}
|
||||
return functionNames;
|
||||
}
|
||||
|
||||
const possibleLogs = Object.fromEntries([...getFunctionNames(functions)].map((a) => [a, true]));
|
||||
const possibleLogs = Object.fromEntries([...getFunctionNames(functions, "")].map((a) => [a, true]));
|
||||
|
||||
return functions;
|
||||
} // End NetscriptFunction()
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Exploit } from "../Exploits/Exploit";
|
||||
@ -11,7 +10,7 @@ export interface INetscriptExtra {
|
||||
bypass(doc: Document): void;
|
||||
}
|
||||
|
||||
export function NetscriptExtra(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): INetscriptExtra {
|
||||
export function NetscriptExtra(player: IPlayer, workerScript: WorkerScript): INetscriptExtra {
|
||||
return {
|
||||
heart: {
|
||||
// Easter egg function
|
||||
|
@ -8,6 +8,7 @@ import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { findSleevePurchasableAugs } from "../PersonObjects/Sleeve/SleeveHelpers";
|
||||
import { Augmentations } from "../Augmentation/Augmentations";
|
||||
import { CityName } from "../Locations/data/CityNames";
|
||||
import { findCrime } from "../Crime/CrimeHelpers";
|
||||
|
||||
export interface INetscriptSleeve {
|
||||
getNumSleeves(): number;
|
||||
@ -87,13 +88,17 @@ export function NetscriptSleeve(
|
||||
checkSleeveNumber("setToSynchronize", sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].synchronize(player);
|
||||
},
|
||||
setToCommitCrime: function (asleeveNumber: any = 0, acrimeName: any = ""): boolean {
|
||||
setToCommitCrime: function (asleeveNumber: any = 0, aCrimeRoughName: any = ""): boolean {
|
||||
const sleeveNumber = helper.number("setToCommitCrime", "sleeveNumber", asleeveNumber);
|
||||
const crimeName = helper.string("setToUniversityCourse", "crimeName", acrimeName);
|
||||
const crimeRoughName = helper.string("setToCommitCrime", "crimeName", aCrimeRoughName);
|
||||
helper.updateDynamicRam("setToCommitCrime", getRamCost("sleeve", "setToCommitCrime"));
|
||||
checkSleeveAPIAccess("setToCommitCrime");
|
||||
checkSleeveNumber("setToCommitCrime", sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].commitCrime(player, crimeName);
|
||||
const crime = findCrime(crimeRoughName);
|
||||
if (crime === null) {
|
||||
return false;
|
||||
}
|
||||
return player.sleeves[sleeveNumber].commitCrime(player, crime.name);
|
||||
},
|
||||
setToUniversityCourse: function (asleeveNumber: any = 0, auniversityName: any = "", aclassName: any = ""): boolean {
|
||||
const sleeveNumber = helper.number("setToUniversityCourse", "sleeveNumber", asleeveNumber);
|
||||
|
@ -125,10 +125,14 @@ function startNetscript2Script(workerScript: WorkerScript): Promise<WorkerScript
|
||||
.catch((e) => reject(e));
|
||||
}).catch((e) => {
|
||||
if (e instanceof Error) {
|
||||
if (e instanceof SyntaxError) {
|
||||
workerScript.errorMessage = makeRuntimeRejectMsg(workerScript, e.message + " (sorry we can't be more helpful)");
|
||||
} else {
|
||||
workerScript.errorMessage = makeRuntimeRejectMsg(
|
||||
workerScript,
|
||||
e.message + ((e.stack && "\nstack:\n" + e.stack.toString()) || ""),
|
||||
);
|
||||
}
|
||||
throw workerScript;
|
||||
} else if (isScriptErrorMessage(e)) {
|
||||
workerScript.errorMessage = e;
|
||||
@ -190,7 +194,8 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<WorkerScript
|
||||
cb(res);
|
||||
})
|
||||
.catch(function (err: any) {
|
||||
console.error(err);
|
||||
// workerscript is when you cancel a delay
|
||||
if (!(err instanceof WorkerScript)) console.error(err);
|
||||
});
|
||||
};
|
||||
int.setProperty(scope, name, int.createAsyncFunction(tempWrapper));
|
||||
|
@ -201,6 +201,7 @@ export interface IPlayer {
|
||||
inGang(): boolean;
|
||||
isQualified(company: Company, position: CompanyPosition): boolean;
|
||||
loseMoney(money: number): void;
|
||||
process(router: IRouter, numCycles?: number): void;
|
||||
reapplyAllAugmentations(resetMultipliers?: boolean): void;
|
||||
reapplyAllSourceFiles(): void;
|
||||
regenerateHp(amt: number): void;
|
||||
|
@ -245,6 +245,7 @@ export class PlayerObject implements IPlayer {
|
||||
getIntelligenceBonus: (weight: number) => number;
|
||||
getCasinoWinnings: () => number;
|
||||
quitJob: (company: string) => void;
|
||||
process: (router: IRouter, numCycles?: number) => void;
|
||||
createHacknetServer: () => HacknetServer;
|
||||
startCreateProgramWork: (router: IRouter, programName: string, time: number, reqLevel: number) => void;
|
||||
queueAugmentation: (augmentationName: string) => void;
|
||||
@ -507,6 +508,7 @@ export class PlayerObject implements IPlayer {
|
||||
this.getWorkAgiExpGain = generalMethods.getWorkAgiExpGain;
|
||||
this.getWorkChaExpGain = generalMethods.getWorkChaExpGain;
|
||||
this.getWorkRepGain = generalMethods.getWorkRepGain;
|
||||
this.process = generalMethods.process;
|
||||
this.startCreateProgramWork = generalMethods.startCreateProgramWork;
|
||||
this.createProgramWork = generalMethods.createProgramWork;
|
||||
this.finishCreateProgramWork = generalMethods.finishCreateProgramWork;
|
||||
|
@ -77,7 +77,6 @@ export function init(this: IPlayer): void {
|
||||
}
|
||||
|
||||
export function prestigeAugmentation(this: IPlayer): void {
|
||||
const homeComp = this.getHomeComputer();
|
||||
this.currentServer = SpecialServers.Home;
|
||||
|
||||
this.numPeopleKilled = 0;
|
||||
@ -453,6 +452,8 @@ export function gainIntelligenceExp(this: IPlayer, exp: number): void {
|
||||
if (SourceFileFlags[5] > 0 || this.intelligence > 0) {
|
||||
this.intelligence_exp += exp;
|
||||
}
|
||||
|
||||
this.intelligence = Math.floor(this.calculateSkill(this.intelligence_exp));
|
||||
}
|
||||
|
||||
//Given a string expression like "str" or "strength", returns the given stat
|
||||
@ -574,6 +575,37 @@ export function startWork(this: IPlayer, router: IRouter, companyName: string):
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
export function process(this: IPlayer, router: IRouter, numCycles = 1): void {
|
||||
// Working
|
||||
if (this.isWorking) {
|
||||
if (this.workType == CONSTANTS.WorkTypeFaction) {
|
||||
if (this.workForFaction(numCycles)) {
|
||||
router.toFaction();
|
||||
}
|
||||
} else if (this.workType == CONSTANTS.WorkTypeCreateProgram) {
|
||||
if (this.createProgramWork(numCycles)) {
|
||||
router.toTerminal();
|
||||
}
|
||||
} else if (this.workType == CONSTANTS.WorkTypeStudyClass) {
|
||||
if (this.takeClass(numCycles)) {
|
||||
router.toCity();
|
||||
}
|
||||
} else if (this.workType == CONSTANTS.WorkTypeCrime) {
|
||||
if (this.commitCrime(numCycles)) {
|
||||
router.toLocation(Locations[LocationName.Slums]);
|
||||
}
|
||||
} else if (this.workType == CONSTANTS.WorkTypeCompanyPartTime) {
|
||||
if (this.workPartTime(numCycles)) {
|
||||
router.toCity();
|
||||
}
|
||||
} else {
|
||||
if (this.work(numCycles)) {
|
||||
router.toCity();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function cancelationPenalty(this: IPlayer): number {
|
||||
const server = GetServer(this.companyName);
|
||||
if (server instanceof Server) {
|
||||
|
@ -476,9 +476,9 @@ export class Sleeve extends Person {
|
||||
return null;
|
||||
}
|
||||
|
||||
let time = this.storedCycles * CONSTANTS.MilliPerCycle;
|
||||
let cyclesUsed = this.storedCycles;
|
||||
cyclesUsed = Math.min(cyclesUsed, 15);
|
||||
let time = cyclesUsed * CONSTANTS.MilliPerCycle;
|
||||
if (this.currentTaskMaxTime !== 0 && this.currentTaskTime + time > this.currentTaskMaxTime) {
|
||||
time = this.currentTaskMaxTime - this.currentTaskTime;
|
||||
cyclesUsed = Math.floor(time / CONSTANTS.MilliPerCycle);
|
||||
@ -489,6 +489,7 @@ export class Sleeve extends Person {
|
||||
cyclesUsed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
this.currentTaskTime += time;
|
||||
|
||||
// Shock gradually goes towards 100
|
||||
@ -846,7 +847,6 @@ export class Sleeve extends Person {
|
||||
|
||||
this.currentTaskLocation = companyName;
|
||||
this.currentTask = SleeveTaskType.Company;
|
||||
this.currentTaskMaxTime = CONSTANTS.MillisecondsPer8Hours;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -906,7 +906,6 @@ export class Sleeve extends Person {
|
||||
|
||||
this.currentTaskLocation = factionName;
|
||||
this.currentTask = SleeveTaskType.Faction;
|
||||
this.currentTaskMaxTime = CONSTANTS.MillisecondsPer20Hours;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -29,4 +29,5 @@ export function loadPlayer(saveString: string): void {
|
||||
}
|
||||
|
||||
Player.exploits = sanitizeExploits(Player.exploits);
|
||||
console.log(Player.bladeburner);
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ function prestigeAugmentation(): void {
|
||||
}
|
||||
}
|
||||
|
||||
if (augmentationExists(AugmentationNames.StaneksGift) && Augmentations[AugmentationNames.StaneksGift].owned) {
|
||||
if (augmentationExists(AugmentationNames.StaneksGift1) && Augmentations[AugmentationNames.StaneksGift1].owned) {
|
||||
// TODO(hydroflame): refactor faction names so we don't have to hard
|
||||
// code strings.
|
||||
joinFaction(Factions["Church of the Machine God"]);
|
||||
|
@ -144,6 +144,18 @@ function evaluateVersionCompatibility(ver: string): void {
|
||||
|
||||
delete anyPlayer.companyPosition;
|
||||
}
|
||||
if (ver < "0.56.0") {
|
||||
for (const q of anyPlayer.queuedAugmentations) {
|
||||
if (q.name === "Graphene BranchiBlades Upgrade") {
|
||||
q.name = "Graphene BrachiBlades Upgrade";
|
||||
}
|
||||
}
|
||||
for (const q of anyPlayer.augmentations) {
|
||||
if (q.name === "Graphene BranchiBlades Upgrade") {
|
||||
q.name = "Graphene BrachiBlades Upgrade";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadGame(saveString: string): boolean {
|
||||
|
@ -109,6 +109,7 @@ export class Script {
|
||||
if (res > 0) {
|
||||
this.ramUsage = roundToTwo(res);
|
||||
}
|
||||
this.markUpdated();
|
||||
}
|
||||
|
||||
// Serialize the current object to a JSON save state
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -44,6 +44,7 @@ export function OptionsModal(props: IProps): React.ReactElement {
|
||||
<Select onChange={(event) => setTheme(event.target.value)} defaultValue={props.options.theme}>
|
||||
<MenuItem value="vs-dark">dark</MenuItem>
|
||||
<MenuItem value="light">light</MenuItem>
|
||||
<MenuItem value="monokai">monokai</MenuItem>
|
||||
</Select>
|
||||
</Box>
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import React, { useState, useEffect, useRef, useMemo } from "react";
|
||||
import Editor from "@monaco-editor/react";
|
||||
import * as monaco from "monaco-editor";
|
||||
type IStandaloneCodeEditor = monaco.editor.IStandaloneCodeEditor;
|
||||
@ -21,6 +21,8 @@ import { NetscriptFunctions } from "../../NetscriptFunctions";
|
||||
import { WorkerScript } from "../../Netscript/WorkerScript";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { iTutorialNextStep, ITutorial, iTutorialSteps } from "../../InteractiveTutorial";
|
||||
import { debounce } from "lodash";
|
||||
import { saveObject } from "../../SaveObject";
|
||||
|
||||
import Button from "@mui/material/Button";
|
||||
import Typography from "@mui/material/Typography";
|
||||
@ -30,6 +32,7 @@ import TextField from "@mui/material/TextField";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import SettingsIcon from "@mui/icons-material/Settings";
|
||||
|
||||
let symbolsLoaded = false;
|
||||
let symbols: string[] = [];
|
||||
export function SetupTextEditor(): void {
|
||||
const ns = NetscriptFunctions({} as WorkerScript);
|
||||
@ -83,6 +86,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
const [filename, setFilename] = useState(props.filename ? props.filename : lastFilename);
|
||||
const [code, setCode] = useState<string>(props.filename ? props.code : lastCode);
|
||||
const [ram, setRAM] = useState("RAM: ???");
|
||||
const [updatingRam, setUpdatingRam] = useState(false);
|
||||
const [optionsOpen, setOptionsOpen] = useState(false);
|
||||
const [options, setOptions] = useState<Options>({
|
||||
theme: Settings.MonacoTheme,
|
||||
@ -90,6 +94,15 @@ export function Root(props: IProps): React.ReactElement {
|
||||
fontSize: Settings.MonacoFontSize,
|
||||
});
|
||||
|
||||
const debouncedSetRAM = useMemo(
|
||||
() =>
|
||||
debounce((s) => {
|
||||
setRAM(s);
|
||||
setUpdatingRam(false);
|
||||
}, 300),
|
||||
[],
|
||||
);
|
||||
|
||||
// store the last known state in case we need to restart without nano.
|
||||
useEffect(() => {
|
||||
if (props.filename === undefined) return;
|
||||
@ -164,6 +177,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
for (let i = 0; i < server.scripts.length; i++) {
|
||||
if (filename == server.scripts[i].filename) {
|
||||
server.scripts[i].saveScript(filename, code, props.player.currentServer, server.scripts);
|
||||
if (Settings.SaveGameOnFileSave) saveObject.saveGame();
|
||||
props.router.toTerminal();
|
||||
return;
|
||||
}
|
||||
@ -177,6 +191,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
for (let i = 0; i < server.textFiles.length; ++i) {
|
||||
if (server.textFiles[i].fn === filename) {
|
||||
server.textFiles[i].write(code);
|
||||
if (Settings.SaveGameOnFileSave) saveObject.saveGame();
|
||||
props.router.toTerminal();
|
||||
return;
|
||||
}
|
||||
@ -187,6 +202,8 @@ export function Root(props: IProps): React.ReactElement {
|
||||
dialogBoxCreate("Invalid filename. Must be either a script (.script, .js, or .ns) or " + " or text file (.txt)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Settings.SaveGameOnFileSave) saveObject.saveGame();
|
||||
props.router.toTerminal();
|
||||
}
|
||||
|
||||
@ -212,38 +229,40 @@ export function Root(props: IProps): React.ReactElement {
|
||||
lastPosition = editorRef.current.getPosition();
|
||||
}
|
||||
setCode(newCode);
|
||||
updateRAM(newCode);
|
||||
}
|
||||
|
||||
async function updateRAM(): Promise<void> {
|
||||
const codeCopy = code + "";
|
||||
// calculate it once the first time the file is loaded.
|
||||
useEffect(() => {
|
||||
updateRAM(code);
|
||||
}, []);
|
||||
|
||||
async function updateRAM(newCode: string): Promise<void> {
|
||||
setUpdatingRam(true);
|
||||
const codeCopy = newCode + "";
|
||||
const ramUsage = await calculateRamUsage(codeCopy, props.player.getCurrentServer().scripts);
|
||||
if (ramUsage > 0) {
|
||||
setRAM("RAM: " + numeralWrapper.formatRAM(ramUsage));
|
||||
debouncedSetRAM("RAM: " + numeralWrapper.formatRAM(ramUsage));
|
||||
return;
|
||||
}
|
||||
switch (ramUsage) {
|
||||
case RamCalculationErrorCode.ImportError: {
|
||||
setRAM("RAM: Import Error");
|
||||
debouncedSetRAM("RAM: Import Error");
|
||||
break;
|
||||
}
|
||||
case RamCalculationErrorCode.URLImportError: {
|
||||
setRAM("RAM: HTTP Import Error");
|
||||
debouncedSetRAM("RAM: HTTP Import Error");
|
||||
break;
|
||||
}
|
||||
case RamCalculationErrorCode.SyntaxError:
|
||||
default: {
|
||||
setRAM("RAM: Syntax Error");
|
||||
debouncedSetRAM("RAM: Syntax Error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new Promise<void>(() => undefined);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(updateRAM, 1000);
|
||||
return () => clearInterval(id);
|
||||
}, [code]);
|
||||
|
||||
useEffect(() => {
|
||||
function maybeSave(event: KeyboardEvent): void {
|
||||
if (Settings.DisableHotkeys) return;
|
||||
@ -275,6 +294,8 @@ export function Root(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
function beforeMount(monaco: any): void {
|
||||
if (symbolsLoaded) return;
|
||||
symbolsLoaded = true;
|
||||
monaco.languages.registerCompletionItemProvider("javascript", {
|
||||
provideCompletionItems: () => {
|
||||
const suggestions = [];
|
||||
@ -323,7 +344,9 @@ export function Root(props: IProps): React.ReactElement {
|
||||
/>
|
||||
<Box display="flex" flexDirection="row" sx={{ m: 1 }} alignItems="center">
|
||||
<Button onClick={beautify}>Beautify</Button>
|
||||
<Typography sx={{ mx: 1 }}>{ram}</Typography>
|
||||
<Typography color={updatingRam ? "secondary" : "primary"} sx={{ mx: 1 }}>
|
||||
{ram}
|
||||
</Typography>
|
||||
<Button onClick={save}>Save & Close (Ctrl/Cmd + b)</Button>
|
||||
<Link sx={{ mx: 1 }} target="_blank" href="https://bitburner.readthedocs.io/en/latest/index.html">
|
||||
<Typography> Netscript Documentation</Typography>
|
||||
|
51
src/ScriptEditor/ui/themes.ts
Normal file
51
src/ScriptEditor/ui/themes.ts
Normal file
@ -0,0 +1,51 @@
|
||||
export async function loadThemes(monaco: { editor: any }): Promise<void> {
|
||||
monaco.editor.defineTheme("monokai", {
|
||||
base: "vs-dark",
|
||||
inherit: true,
|
||||
rules: [
|
||||
{
|
||||
background: "272822",
|
||||
token: "",
|
||||
},
|
||||
{
|
||||
foreground: "75715e",
|
||||
token: "comment",
|
||||
},
|
||||
{
|
||||
foreground: "e6db74",
|
||||
token: "string",
|
||||
},
|
||||
{
|
||||
token: "number",
|
||||
foreground: "ae81ff",
|
||||
},
|
||||
{
|
||||
foreground: "ae81ff",
|
||||
token: "function",
|
||||
},
|
||||
{
|
||||
foreground: "f92672",
|
||||
token: "keyword",
|
||||
},
|
||||
{
|
||||
token: "storage.type.function.js",
|
||||
foreground: "ae81ff",
|
||||
},
|
||||
|
||||
// {
|
||||
// foreground: "ae81ff",
|
||||
// token: "entity.name.function",
|
||||
// },
|
||||
],
|
||||
colors: {
|
||||
"editor.foreground": "#F8F8F2",
|
||||
"editor.background": "#272822",
|
||||
"editor.selectionBackground": "#49483E",
|
||||
"editor.lineHighlightBackground": "#3E3D32",
|
||||
"editorCursor.foreground": "#F8F8F0",
|
||||
"editorWhitespace.foreground": "#3B3A32",
|
||||
"editorIndentGuide.activeBackground": "#9D550FB0",
|
||||
"editor.selectionHighlightBorder": "#222218",
|
||||
},
|
||||
});
|
||||
}
|
@ -125,14 +125,16 @@ export class Server extends BaseServer {
|
||||
/**
|
||||
* Change this server's maximum money
|
||||
* @param n - Value by which to change the server's maximum money
|
||||
* @param perc - Whether it should be changed by a percentage, or a flat value
|
||||
*/
|
||||
changeMaximumMoney(n: number, perc = false): void {
|
||||
if (perc) {
|
||||
this.moneyMax *= n;
|
||||
} else {
|
||||
this.moneyMax += n;
|
||||
changeMaximumMoney(n: number): void {
|
||||
const softCap = 10e12;
|
||||
if (this.moneyMax > softCap) {
|
||||
const aboveCap = this.moneyMax - softCap;
|
||||
n = 1 + (n - 1) / Math.log(aboveCap) / Math.log(8);
|
||||
}
|
||||
console.log(n);
|
||||
|
||||
this.moneyMax *= n;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,6 +68,11 @@ interface IDefaultSettings {
|
||||
*/
|
||||
MaxTerminalCapacity: number;
|
||||
|
||||
/**
|
||||
* Save the game when you save any file.
|
||||
*/
|
||||
SaveGameOnFileSave: boolean;
|
||||
|
||||
/**
|
||||
* Whether the player should be asked to confirm purchasing each and every augmentation.
|
||||
*/
|
||||
@ -168,6 +173,7 @@ export const defaultSettings: IDefaultSettings = {
|
||||
MaxLogCapacity: 50,
|
||||
MaxPortCapacity: 50,
|
||||
MaxTerminalCapacity: 200,
|
||||
SaveGameOnFileSave: true,
|
||||
SuppressBuyAugmentationConfirmation: false,
|
||||
SuppressFactionInvites: false,
|
||||
SuppressHospitalizationPopup: false,
|
||||
@ -226,6 +232,7 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
|
||||
MaxTerminalCapacity: defaultSettings.MaxTerminalCapacity,
|
||||
OwnedAugmentationsOrder: OwnedAugmentationsOrderSetting.AcquirementTime,
|
||||
PurchaseAugmentationsOrder: PurchaseAugmentationsOrderSetting.Default,
|
||||
SaveGameOnFileSave: defaultSettings.SaveGameOnFileSave,
|
||||
SuppressBuyAugmentationConfirmation: defaultSettings.SuppressBuyAugmentationConfirmation,
|
||||
SuppressFactionInvites: defaultSettings.SuppressFactionInvites,
|
||||
SuppressHospitalizationPopup: defaultSettings.SuppressHospitalizationPopup,
|
||||
@ -234,7 +241,7 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
|
||||
SuppressBladeburnerPopup: defaultSettings.SuppressBladeburnerPopup,
|
||||
MonacoTheme: "vs-dark",
|
||||
MonacoInsertSpaces: false,
|
||||
MonacoFontSize: 10,
|
||||
MonacoFontSize: 20,
|
||||
|
||||
theme: {
|
||||
primarylight: defaultSettings.theme.primarylight,
|
||||
|
@ -14,6 +14,7 @@ export const TerminalHelpText: string[] = [
|
||||
"clear Clear all text on the terminal ",
|
||||
"cls See 'clear' command ",
|
||||
"connect [hostname] Connects to a remote server",
|
||||
"cp [src] [dst]: Copy a file",
|
||||
"download [script/text file] Downloads scripts or text files to your computer",
|
||||
"expr [math expression] Evaluate a mathematical expression",
|
||||
"free Check the machine's memory (RAM) usage",
|
||||
@ -158,6 +159,7 @@ export const HelpTexts: IMap<string[]> = {
|
||||
"to this command. Note that only servers that are immediately adjacent to the current server in the network can be connected to. To ",
|
||||
"see which servers can be connected to, use the 'scan' command.",
|
||||
],
|
||||
cp: ["cp [src] [dst]", " ", "Copy a file on this server. To copy a file to another server use scp."],
|
||||
download: [
|
||||
"download [script/text file]",
|
||||
" ",
|
||||
|
@ -41,6 +41,7 @@ import { cat } from "./commands/cat";
|
||||
import { cd } from "./commands/cd";
|
||||
import { check } from "./commands/check";
|
||||
import { connect } from "./commands/connect";
|
||||
import { cp } from "./commands/cp";
|
||||
import { download } from "./commands/download";
|
||||
import { expr } from "./commands/expr";
|
||||
import { free } from "./commands/free";
|
||||
@ -729,6 +730,7 @@ export class Terminal implements ITerminal {
|
||||
clear: () => this.clear(),
|
||||
cls: () => this.clear(),
|
||||
connect: connect,
|
||||
cp: cp,
|
||||
download: download,
|
||||
expr: expr,
|
||||
free: free,
|
||||
|
92
src/Terminal/commands/cp.ts
Normal file
92
src/Terminal/commands/cp.ts
Normal file
@ -0,0 +1,92 @@
|
||||
import { ITerminal } from "../ITerminal";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { BaseServer } from "../../Server/BaseServer";
|
||||
import { isScriptFilename } from "../../Script/isScriptFilename";
|
||||
|
||||
export function cp(
|
||||
terminal: ITerminal,
|
||||
router: IRouter,
|
||||
player: IPlayer,
|
||||
server: BaseServer,
|
||||
args: (string | number)[],
|
||||
): void {
|
||||
try {
|
||||
if (args.length !== 2) {
|
||||
terminal.error("Incorrect usage of cp command. Usage: cp [src] [dst]");
|
||||
return;
|
||||
}
|
||||
const src = args[0] + "";
|
||||
const dst = args[1] + "";
|
||||
if (src === dst) {
|
||||
terminal.error("src and dst cannot be the same");
|
||||
return;
|
||||
}
|
||||
const srcExt = src.slice(src.lastIndexOf("."));
|
||||
const dstExt = dst.slice(dst.lastIndexOf("."));
|
||||
if (srcExt !== dstExt) {
|
||||
terminal.error("src and dst must have the same extension.");
|
||||
return;
|
||||
}
|
||||
const filename = terminal.getFilepath(src);
|
||||
if (!isScriptFilename(filename) && !filename.endsWith(".txt")) {
|
||||
terminal.error("cp only works for scripts and .txt files");
|
||||
return;
|
||||
}
|
||||
|
||||
// Scp for txt files
|
||||
if (filename.endsWith(".txt")) {
|
||||
let txtFile = null;
|
||||
for (let i = 0; i < server.textFiles.length; ++i) {
|
||||
if (server.textFiles[i].fn === filename) {
|
||||
txtFile = server.textFiles[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (txtFile === null) {
|
||||
return terminal.error("No such file exists!");
|
||||
}
|
||||
|
||||
const tRes = server.writeToTextFile(dst, txtFile.text);
|
||||
if (!tRes.success) {
|
||||
terminal.error("scp failed");
|
||||
return;
|
||||
}
|
||||
if (tRes.overwritten) {
|
||||
terminal.print(`WARNING: ${dst} already exists and will be overwriten`);
|
||||
terminal.print(`${dst} overwritten`);
|
||||
return;
|
||||
}
|
||||
terminal.print(`${dst} copied`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the current script
|
||||
let sourceScript = null;
|
||||
for (let i = 0; i < server.scripts.length; ++i) {
|
||||
if (filename == server.scripts[i].filename) {
|
||||
sourceScript = server.scripts[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sourceScript == null) {
|
||||
terminal.error("cp() failed. No such script exists");
|
||||
return;
|
||||
}
|
||||
|
||||
const sRes = server.writeToScriptFile(dst, sourceScript.code);
|
||||
if (!sRes.success) {
|
||||
terminal.error(`scp failed`);
|
||||
return;
|
||||
}
|
||||
if (sRes.overwritten) {
|
||||
terminal.print(`WARNING: ${dst} already exists and will be overwritten`);
|
||||
terminal.print(`${dst} overwritten`);
|
||||
return;
|
||||
}
|
||||
terminal.print(`${dst} copied`);
|
||||
} catch (e) {
|
||||
terminal.error(e + "");
|
||||
}
|
||||
}
|
@ -24,7 +24,10 @@ export function nano(
|
||||
if (script == null) {
|
||||
let code = "";
|
||||
if (filename.endsWith(".ns") || filename.endsWith(".js")) {
|
||||
code = `export async function main(ns) {
|
||||
code = `/**
|
||||
* @param {NS} ns
|
||||
**/
|
||||
export async function main(ns) {
|
||||
|
||||
}`;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import { startWorkerScript } from "../../NetscriptWorker";
|
||||
import { RunningScript } from "../../Script/RunningScript";
|
||||
import { findRunningScript } from "../../Script/ScriptHelpers";
|
||||
import * as libarg from "arg";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
|
||||
export function runScript(
|
||||
terminal: ITerminal,
|
||||
@ -64,8 +65,8 @@ export function runScript(
|
||||
"This machine does not have enough RAM to run this script with " +
|
||||
numThreads +
|
||||
" threads. Script requires " +
|
||||
ramUsage +
|
||||
"GB of RAM",
|
||||
numeralWrapper.formatRAM(ramUsage) +
|
||||
" of RAM",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ const commands = [
|
||||
"clear",
|
||||
"cls",
|
||||
"connect",
|
||||
"cp",
|
||||
"download",
|
||||
"expr",
|
||||
"free",
|
||||
@ -239,6 +240,13 @@ export function determineAllPossibilitiesForTabCompletion(
|
||||
return allPos;
|
||||
}
|
||||
|
||||
if (isCommand("cp") && index === 0) {
|
||||
addAllScripts();
|
||||
addAllTextFiles();
|
||||
addAllDirectories();
|
||||
return allPos;
|
||||
}
|
||||
|
||||
if (isCommand("connect")) {
|
||||
// All network connections
|
||||
for (let i = 0; i < currServ.serversOnNetwork.length; ++i) {
|
||||
|
@ -35,8 +35,6 @@ import { updateSourceFileFlags } from "./SourceFile/SourceFileFlags";
|
||||
import { initSymbolToStockMap, processStockPrices } from "./StockMarket/StockMarket";
|
||||
import { Terminal } from "./Terminal";
|
||||
import { Sleeve } from "./PersonObjects/Sleeve/Sleeve";
|
||||
import { Locations } from "./Locations/Locations";
|
||||
import { LocationName } from "./Locations/data/LocationNames";
|
||||
|
||||
import { Money } from "./ui/React/Money";
|
||||
import { Hashes } from "./ui/React/Hashes";
|
||||
@ -92,34 +90,7 @@ const Engine: {
|
||||
|
||||
Terminal.process(Router, Player, numCycles);
|
||||
|
||||
// Working
|
||||
if (Player.isWorking) {
|
||||
if (Player.workType == CONSTANTS.WorkTypeFaction) {
|
||||
if (Player.workForFaction(numCycles)) {
|
||||
Router.toFaction();
|
||||
}
|
||||
} else if (Player.workType == CONSTANTS.WorkTypeCreateProgram) {
|
||||
if (Player.createProgramWork(numCycles)) {
|
||||
Router.toTerminal();
|
||||
}
|
||||
} else if (Player.workType == CONSTANTS.WorkTypeStudyClass) {
|
||||
if (Player.takeClass(numCycles)) {
|
||||
Router.toCity();
|
||||
}
|
||||
} else if (Player.workType == CONSTANTS.WorkTypeCrime) {
|
||||
if (Player.commitCrime(numCycles)) {
|
||||
Router.toLocation(Locations[LocationName.Slums]);
|
||||
}
|
||||
} else if (Player.workType == CONSTANTS.WorkTypeCompanyPartTime) {
|
||||
if (Player.workPartTime(numCycles)) {
|
||||
Router.toCity();
|
||||
}
|
||||
} else {
|
||||
if (Player.work(numCycles)) {
|
||||
Router.toCity();
|
||||
}
|
||||
}
|
||||
}
|
||||
Player.process(Router, numCycles);
|
||||
|
||||
// Update stock prices
|
||||
if (Player.hasWseAccount) {
|
||||
|
@ -77,6 +77,7 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
const [disableTextEffects, setDisableTextEffects] = useState(Settings.DisableTextEffects);
|
||||
const [enableBashHotkeys, setEnableBashHotkeys] = useState(Settings.EnableBashHotkeys);
|
||||
const [enableTimestamps, setEnableTimestamps] = useState(Settings.EnableTimestamps);
|
||||
const [saveGameOnFileSave, setSaveGameOnFileSave] = useState(Settings.SaveGameOnFileSave);
|
||||
|
||||
const [locale, setLocale] = useState(Settings.Locale);
|
||||
const [diagnosticOpen, setDiagnosticOpen] = useState(false);
|
||||
@ -165,6 +166,10 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
setEnableTimestamps(event.target.checked);
|
||||
Settings.EnableTimestamps = event.target.checked;
|
||||
}
|
||||
function handleSaveGameOnFile(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
setSaveGameOnFileSave(event.target.checked);
|
||||
Settings.SaveGameOnFileSave = event.target.checked;
|
||||
}
|
||||
|
||||
function startImport(): void {
|
||||
if (!window.File || !window.FileReader || !window.FileList || !window.Blob) return;
|
||||
@ -505,6 +510,19 @@ export function GameOptionsRoot(props: IProps): React.ReactElement {
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<ListItem>
|
||||
<FormControlLabel
|
||||
control={<Switch checked={saveGameOnFileSave} onChange={handleSaveGameOnFile} />}
|
||||
label={
|
||||
<Tooltip
|
||||
title={<Typography>Save your game any time a file is saved in the script editor.</Typography>}
|
||||
>
|
||||
<Typography>Save game on file save</Typography>
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
|
||||
<ListItem>
|
||||
<Tooltip title={<Typography>Sets the locale for displaying numbers.</Typography>}>
|
||||
<Typography>Locale </Typography>
|
||||
|
@ -11,6 +11,7 @@ import { BaseServer } from "../../Server/BaseServer";
|
||||
import { HacknetServer } from "../../Hacknet/HacknetServer";
|
||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import Button from "@mui/material/Button";
|
||||
|
||||
// TODO make this an enum when this gets converted to TypeScript
|
||||
export const ServerType = {
|
||||
@ -21,6 +22,8 @@ export const ServerType = {
|
||||
};
|
||||
|
||||
interface IProps {
|
||||
purchase: () => void;
|
||||
canPurchase: boolean;
|
||||
serverType: number;
|
||||
onChange: (event: SelectChangeEvent<string>) => void;
|
||||
value: string;
|
||||
@ -61,7 +64,16 @@ export function ServerDropdown(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
return (
|
||||
<Select sx={{ mx: 1 }} value={props.value} onChange={props.onChange}>
|
||||
<Select
|
||||
startAdornment={
|
||||
<Button onClick={props.purchase} disabled={!props.canPurchase}>
|
||||
Buy
|
||||
</Button>
|
||||
}
|
||||
sx={{ mx: 1 }}
|
||||
value={props.value}
|
||||
onChange={props.onChange}
|
||||
>
|
||||
{servers}
|
||||
</Select>
|
||||
);
|
||||
|
@ -36,24 +36,16 @@ export function TablePaginationActionsAll(props: TablePaginationActionsProps): R
|
||||
|
||||
return (
|
||||
<Box sx={{ flexShrink: 0, ml: 2.5 }}>
|
||||
<IconButton onClick={handleFirstPageButtonClick} disabled={page === 0} aria-label="first page">
|
||||
<IconButton onClick={handleFirstPageButtonClick} disabled={page === 0}>
|
||||
{theme.direction === "rtl" ? <LastPageIcon /> : <FirstPageIcon />}
|
||||
</IconButton>
|
||||
<IconButton onClick={handleBackButtonClick} disabled={page === 0} aria-label="previous page">
|
||||
<IconButton onClick={handleBackButtonClick} disabled={page === 0}>
|
||||
{theme.direction === "rtl" ? <KeyboardArrowRight /> : <KeyboardArrowLeft />}
|
||||
</IconButton>
|
||||
<IconButton
|
||||
onClick={handleNextButtonClick}
|
||||
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
|
||||
aria-label="next page"
|
||||
>
|
||||
<IconButton onClick={handleNextButtonClick} disabled={page >= Math.ceil(count / rowsPerPage) - 1}>
|
||||
{theme.direction === "rtl" ? <KeyboardArrowLeft /> : <KeyboardArrowRight />}
|
||||
</IconButton>
|
||||
<IconButton
|
||||
onClick={handleLastPageButtonClick}
|
||||
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
|
||||
aria-label="last page"
|
||||
>
|
||||
<IconButton onClick={handleLastPageButtonClick} disabled={page >= Math.ceil(count / rowsPerPage) - 1}>
|
||||
{theme.direction === "rtl" ? <FirstPageIcon /> : <LastPageIcon />}
|
||||
</IconButton>
|
||||
</Box>
|
||||
|
@ -276,6 +276,12 @@ export function refreshTheme(): void {
|
||||
select: {
|
||||
color: Settings.theme.primary,
|
||||
},
|
||||
selectLabel: {
|
||||
color: Settings.theme.primary,
|
||||
},
|
||||
displayedRows: {
|
||||
color: Settings.theme.primary,
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiTab: {
|
||||
|
@ -2,6 +2,8 @@ import React, { useState } from "react";
|
||||
import { Modal } from "./Modal";
|
||||
import Button from "@mui/material/Button";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import ReplyIcon from "@mui/icons-material/Reply";
|
||||
@ -87,17 +89,22 @@ export function ThemeEditorModal(props: IProps): React.ReactElement {
|
||||
|
||||
return (
|
||||
<Modal open={props.open} onClose={props.onClose}>
|
||||
<Button color="primary">primary</Button>
|
||||
<Button color="secondary">secondary</Button>
|
||||
<Button color="warning">warning</Button>
|
||||
<Button color="info">info</Button>
|
||||
<Button color="error">error</Button>
|
||||
<Typography color="primary">primary</Typography>
|
||||
<Typography color="secondary">secondary</Typography>
|
||||
<Typography color="warning">warning</Typography>
|
||||
<Typography color="info">info</Typography>
|
||||
<Typography color="error">error</Typography>
|
||||
<Paper>
|
||||
<Tooltip open={true} placement={"top"} title={<Typography>Example tooltip</Typography>}>
|
||||
<Button color="primary">primary button</Button>
|
||||
</Tooltip>
|
||||
<Button color="secondary">secondary button</Button>
|
||||
<Button color="warning">warning button</Button>
|
||||
<Button color="info">info button</Button>
|
||||
<Button color="error">error button</Button>
|
||||
<Button disabled>disabled button</Button>
|
||||
<Typography color="primary">text with primary color</Typography>
|
||||
<Typography color="secondary">text with secondary color</Typography>
|
||||
<Typography color="error">text with error color</Typography>
|
||||
<TextField value={"Text field"} />
|
||||
</Paper>
|
||||
<br />
|
||||
<Typography>Warning: Editing the theme is very slow.</Typography>
|
||||
<ColorEditor
|
||||
name="primarylight"
|
||||
onColorChange={onColorChange}
|
||||
|
@ -106,6 +106,10 @@ class NumeralFormatter {
|
||||
}
|
||||
|
||||
formatRAM(n: number): string {
|
||||
if (n < 1e3) return this.format(n, "0.00") + "GB";
|
||||
if (n < 1e6) return this.format(n / 1e3, "0.00") + "TB";
|
||||
if (n < 1e9) return this.format(n / 1e6, "0.00") + "PB";
|
||||
if (n < 1e12) return this.format(n / 1e9, "0.00") + "EB";
|
||||
return this.format(n, "0.00") + "GB";
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,7 @@ export interface IReviverValue {
|
||||
// off to that `fromJSON` fuunction, passing in the value.
|
||||
export function Reviver(key: string, value: IReviverValue | null): any {
|
||||
if (value == null) {
|
||||
console.log("Reviver WRONGLY called with key: " + key + ", and value: " + value);
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof value === "object" && typeof value.ctor === "string" && typeof value.data !== "undefined") {
|
||||
|
Loading…
Reference in New Issue
Block a user