mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-16 14:28:36 +02:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db2bf79e3b | ||
|
|
6f330efc44 | ||
|
|
708c73fa0f | ||
|
|
c7febd5551 | ||
|
|
ddbdf66d00 | ||
|
|
e572c6dad8 | ||
|
|
ff097db1e2 | ||
|
|
ad12f0e551 | ||
|
|
93f8785ec6 | ||
|
|
69124e7146 | ||
|
|
8a42f6e49c | ||
|
|
2ac4cd41bb | ||
|
|
28584c8461 | ||
|
|
1eddddd14f | ||
|
|
42e9a368b4 | ||
|
|
40713a4112 | ||
|
|
8e79658e67 | ||
|
|
6efc3ec75e | ||
|
|
9840e1f4eb | ||
|
|
7cdca5e813 | ||
|
|
d170693da4 | ||
|
|
31a9c041b4 | ||
|
|
ce7c2c309c | ||
|
|
29abffd464 | ||
|
|
ae4b8228f7 | ||
|
|
04bc2bebdd | ||
|
|
8f30e60d08 | ||
|
|
e8aa1851c5 | ||
|
|
7232a786ed | ||
|
|
2507899762 | ||
|
|
26149d5a01 | ||
|
|
670394ca2f | ||
|
|
e0745d7757 | ||
|
|
dc79f7a940 | ||
|
|
bf4d841f88 | ||
|
|
4c30f107e3 | ||
|
|
c9fe8d9b65 | ||
|
|
29ea1281e0 | ||
|
|
3ec54bcdd8 | ||
|
|
4892f0bd79 | ||
|
|
62c571ef3a | ||
|
|
6c57d548ec | ||
|
|
6c0b5b3ed9 | ||
|
|
f288d982db | ||
|
|
101834fcaf | ||
|
|
642c7a107a | ||
|
|
63da8d709a | ||
|
|
753a1f1193 | ||
|
|
726c36f276 | ||
|
|
640795dbe9 | ||
|
|
802f28082d |
10
README_contribution.md
Normal file
10
README_contribution.md
Normal file
@@ -0,0 +1,10 @@
|
||||
Deploying a new version
|
||||
-----------------------
|
||||
|
||||
Update the following
|
||||
- `src/Constants.ts` `Version` and `LatestUpdate`
|
||||
- `package.json` `version`
|
||||
- `doc/source/conf.py` `version` and `release`
|
||||
- `doc/source/changelog.rst`
|
||||
- post to discord
|
||||
- post to reddit.com/r/Bitburner
|
||||
@@ -184,5 +184,4 @@
|
||||
|
||||
#infiltration-buttons .a-link-button {
|
||||
display: inline;
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
@@ -356,10 +356,27 @@ a:visited {
|
||||
color: $my-stat-cha-color;
|
||||
}
|
||||
|
||||
.reputation {
|
||||
color: $light-yellow;
|
||||
}
|
||||
|
||||
.smallfont {
|
||||
font-size: $defaultFontSize * 0.8125;
|
||||
}
|
||||
|
||||
.samefont {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.noscrollbar {
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
|
||||
.noscrollbar::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
input[type=checkbox] {
|
||||
filter: invert(1) sepia(1) hue-rotate(41deg) brightness(100%) saturate(10);
|
||||
}
|
||||
@@ -395,4 +412,12 @@ input[type=checkbox] {
|
||||
height: 10px;
|
||||
background: var(--my-font-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.noselect {
|
||||
-moz-user-select: -moz-none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
@@ -85,3 +85,45 @@
|
||||
.tooltip:hover .tooltiptextlow {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.copy_tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.copy_tooltip_copied {
|
||||
color: #fff;
|
||||
transition: color 0.3s;
|
||||
}
|
||||
|
||||
.copy_tooltip .copy_tooltip_text {
|
||||
visibility: hidden;
|
||||
font-size: 15px;
|
||||
padding: 5px;
|
||||
background-color: var(--my-background-color);
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 120%;
|
||||
left: 5%;
|
||||
opacity: 0;
|
||||
border: 2px solid var(--my-highlight-color);
|
||||
}
|
||||
|
||||
.copy_tooltip .copy_tooltip_text::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
left: 50%;
|
||||
margin-left: -6px;
|
||||
border-width: 8px;
|
||||
border-style: solid;
|
||||
border-color: transparent transparent white transparent;
|
||||
}
|
||||
|
||||
.copy_tooltip .copy_tooltip_text_visible {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
4
dist/engine.bundle.js
vendored
4
dist/engine.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/engineStyle.bundle.js
vendored
2
dist/engineStyle.bundle.js
vendored
@@ -1,2 +1,2 @@
|
||||
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([377,0]),o()}({320:function(n,t,o){},322:function(n,t,o){},324:function(n,t,o){},326:function(n,t,o){},328:function(n,t,o){},330:function(n,t,o){},332:function(n,t,o){},334:function(n,t,o){},336:function(n,t,o){},338:function(n,t,o){},340:function(n,t,o){},342:function(n,t,o){},344:function(n,t,o){},346:function(n,t,o){},348:function(n,t,o){},350:function(n,t,o){},352:function(n,t,o){},354:function(n,t,o){},356:function(n,t,o){},358:function(n,t,o){},360:function(n,t,o){},362:function(n,t,o){},364:function(n,t,o){},366:function(n,t,o){},368:function(n,t,o){},370:function(n,t,o){},372:function(n,t,o){},374:function(n,t,o){},377:function(n,t,o){"use strict";o.r(t);o(376),o(374),o(372),o(370),o(368),o(366),o(364),o(362),o(360),o(358),o(356),o(354),o(352),o(350),o(348),o(346),o(344),o(342),o(340),o(338),o(336),o(334),o(332),o(330),o(328),o(326),o(324),o(322),o(320)}});
|
||||
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([396,0]),o()}({339:function(n,t,o){},341:function(n,t,o){},343:function(n,t,o){},345:function(n,t,o){},347:function(n,t,o){},349:function(n,t,o){},351:function(n,t,o){},353:function(n,t,o){},355:function(n,t,o){},357:function(n,t,o){},359:function(n,t,o){},361:function(n,t,o){},363:function(n,t,o){},365:function(n,t,o){},367:function(n,t,o){},369:function(n,t,o){},371:function(n,t,o){},373:function(n,t,o){},375:function(n,t,o){},377:function(n,t,o){},379:function(n,t,o){},381:function(n,t,o){},383:function(n,t,o){},385:function(n,t,o){},387:function(n,t,o){},389:function(n,t,o){},391:function(n,t,o){},393:function(n,t,o){},396:function(n,t,o){"use strict";o.r(t);o(395),o(393),o(391),o(389),o(387),o(385),o(383),o(381),o(379),o(377),o(375),o(373),o(371),o(369),o(367),o(365),o(363),o(361),o(359),o(357),o(355),o(353),o(351),o(349),o(347),o(345),o(343),o(341),o(339)}});
|
||||
//# sourceMappingURL=engineStyle.bundle.js.map
|
||||
62
dist/engineStyle.css
vendored
62
dist/engineStyle.css
vendored
@@ -353,9 +353,24 @@ a:visited {
|
||||
.charisma-purple {
|
||||
color: #a671d1; }
|
||||
|
||||
.reputation {
|
||||
color: #faffdf; }
|
||||
|
||||
.smallfont {
|
||||
font-size: 13px; }
|
||||
|
||||
.samefont {
|
||||
font-size: inherit; }
|
||||
|
||||
.noscrollbar {
|
||||
-ms-overflow-style: none;
|
||||
/* IE and Edge */
|
||||
scrollbar-width: none;
|
||||
/* Firefox */ }
|
||||
|
||||
.noscrollbar::-webkit-scrollbar {
|
||||
display: none; }
|
||||
|
||||
input[type=checkbox] {
|
||||
filter: invert(1) sepia(1) hue-rotate(41deg) brightness(100%) saturate(10); }
|
||||
|
||||
@@ -387,6 +402,13 @@ input[type=checkbox] {
|
||||
background: var(--my-font-color);
|
||||
cursor: pointer; }
|
||||
|
||||
.noselect {
|
||||
-moz-user-select: -moz-none;
|
||||
-khtml-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none; }
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
/* Styling for tooltip-style elements */
|
||||
@@ -460,6 +482,43 @@ input[type=checkbox] {
|
||||
.tooltip:hover .tooltiptextlow {
|
||||
visibility: visible; }
|
||||
|
||||
.copy_tooltip {
|
||||
position: relative;
|
||||
display: inline-block; }
|
||||
|
||||
.copy_tooltip_copied {
|
||||
color: #fff;
|
||||
transition: color 0.3s; }
|
||||
|
||||
.copy_tooltip .copy_tooltip_text {
|
||||
visibility: hidden;
|
||||
font-size: 15px;
|
||||
padding: 5px;
|
||||
background-color: var(--my-background-color);
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: 120%;
|
||||
left: 5%;
|
||||
opacity: 0;
|
||||
border: 2px solid var(--my-highlight-color); }
|
||||
|
||||
.copy_tooltip .copy_tooltip_text::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
left: 50%;
|
||||
margin-left: -6px;
|
||||
border-width: 8px;
|
||||
border-style: solid;
|
||||
border-color: transparent transparent white transparent; }
|
||||
|
||||
.copy_tooltip .copy_tooltip_text_visible {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transition: opacity 0.3s; }
|
||||
|
||||
/* COLORS */
|
||||
/* Attributes */
|
||||
/**
|
||||
@@ -1315,8 +1374,7 @@ button {
|
||||
margin-top: 20px; }
|
||||
|
||||
#infiltration-buttons .a-link-button {
|
||||
display: inline;
|
||||
width: 25%; }
|
||||
display: inline; }
|
||||
|
||||
/**
|
||||
* Styling for the Augmentations UI. This is the page that displays all of the
|
||||
|
||||
34
dist/vendor.bundle.js
vendored
34
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@@ -3,39 +3,156 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
v0.51.1 - 2021-04-06 Bugfixes because the author of the last patch sucks (it's hydroflame)
|
||||
------------------------------------------------------------------------------------------
|
||||
|
||||
**Netscript**
|
||||
* 'getPlayer' returns players faction and tor
|
||||
* 'hospitalization' is a new singularity function.
|
||||
* 'gang.getMemberInformation' now returns more information.
|
||||
* 'hacknet.hashCapacity' is a new hacknet function that returns the maximum hash capacity.
|
||||
|
||||
**Hospitalization**
|
||||
* Now only cost at most 10% of your money.
|
||||
|
||||
**Bugfix**
|
||||
* confirmation dialog box no longer use previous text
|
||||
|
||||
**Accessibility**
|
||||
* The game is a little easier to handle for screen readers (yes, there's an
|
||||
absolute legend playing this game with a screen reader)
|
||||
* Infiltration use buttons instead of a-links
|
||||
* New option to disable ASCII art. This will make the metro map and world
|
||||
map display as a list of buttons.
|
||||
|
||||
**Misc.**
|
||||
* 'fl1ght.exe' will no longer suggest the combat path. Related faction
|
||||
requirements unchanged.
|
||||
|
||||
v0.51.0 - 2021-03-31 Formulas (hydroflame)
|
||||
------------------------------------------
|
||||
|
||||
**Formulas API**
|
||||
|
||||
* A new API is introduced, this gives players access to various formulas used in the game.
|
||||
It'll help you make more informed decisions.
|
||||
|
||||
**Netscript**
|
||||
|
||||
* 'getServer' is a new function meant to be used with the formulas API.
|
||||
* 'getPlayer' is a new function meant to be used with the formulas API.
|
||||
* 'getStats' and 'getCharacterInformation' are deprecated in favor of 'getPlayer'
|
||||
* 'getCurrentServer' is a new function that returns the server the player is currently connected.
|
||||
|
||||
**Display**
|
||||
|
||||
* All money should now consistently be orange.
|
||||
* All rep should now consistently be light-yellow.
|
||||
* Most numbers should display consistently now (aka all money is formatted the same).
|
||||
|
||||
**Click to copy**
|
||||
|
||||
* Certain UI elements are now 'click-to-copy'
|
||||
|
||||
v0.50.2 - 2021-03-25 Everyone asked for this one. (hydroflame)
|
||||
--------------------------------------------------------------
|
||||
|
||||
**BitNodeMultipliers**
|
||||
|
||||
* 'GangKarmaRequirements': a new multipler that influences how much karma is required to make a gang different bitnodes.
|
||||
|
||||
**Netscript**
|
||||
|
||||
* 'connect': a new singularity function that connects you to a server. (like the terminal command)
|
||||
* 'manualHack': a new singularity function that performs a manual hack on the players current server.
|
||||
* ns2 stack trace works on Firefox now.
|
||||
|
||||
**Misc.**
|
||||
|
||||
* New shortcut, Alt + b, brings you to bladeburner
|
||||
* New shortcut, Alt + g, brings you to gang
|
||||
|
||||
v0.50.1 - 2021-03-22 (hydroflame)
|
||||
---------------------------------
|
||||
**Netscript**
|
||||
|
||||
* getTaskStats works
|
||||
|
||||
**Source-File -1**
|
||||
|
||||
* Added a new Exploit
|
||||
|
||||
**Factions**
|
||||
|
||||
* Augmentations offered by a Faction but already bought are in a separate list at the bottom of the page.
|
||||
|
||||
**Bug fixed**
|
||||
|
||||
* Fixed a bug where completing a maxed non-repeatable BitNode would make its color on the BitVerse like level 1.
|
||||
|
||||
**Misc.**
|
||||
|
||||
* Minor spacing in stats tables.
|
||||
|
||||
v0.50.0 - 2021-03-20 Intelligence (hydroflame)
|
||||
----------------------------------------------
|
||||
|
||||
**Intelligence**
|
||||
|
||||
* int exp gain and effect has been reworked. It is now much more easy to
|
||||
acquire and far more powerful. The goal here is to feel like players have
|
||||
another tool in their arsenal.
|
||||
|
||||
**Factions**
|
||||
|
||||
* Hacking factions no longer have hacking level requirements since their associated servers do.
|
||||
|
||||
**Misc.**
|
||||
|
||||
* Sleeve styling.
|
||||
* number formatting
|
||||
* remove wiki button in Hacking Missions.
|
||||
* Fix NaN displayed when very very large numbers are reached.
|
||||
|
||||
v0.49.2 - 2021-03-13 (hydroflame)
|
||||
-------
|
||||
---------------------------------
|
||||
|
||||
**BN8**
|
||||
|
||||
BN8
|
||||
* A new bitnode multipler has been added, it lets you reduce money from a
|
||||
server without gaining actually any money. This is important for BN8 where
|
||||
hack/grow can influence the stock market. No money can be gained from
|
||||
hacking but server money can still be reduced.
|
||||
|
||||
Documentation
|
||||
**Documentation**
|
||||
|
||||
* readthedocs should now be more consistent and many examples were added.
|
||||
|
||||
Netscript
|
||||
**Netscript**
|
||||
|
||||
* Ace editor will now correctly highlight all functions.
|
||||
* 'tFormat' is a new netscript function that returns a human readable
|
||||
representation of milliseconds. eg. "2 hours 15 minute 43 seconds"
|
||||
|
||||
Gang
|
||||
**Gang**
|
||||
|
||||
* style improvements
|
||||
|
||||
Bladeburner
|
||||
**Bladeburner**
|
||||
|
||||
* style improvements
|
||||
* fix bug where 'skill list SKILL' would crash if skill is level 0.
|
||||
|
||||
Sleeve
|
||||
**Sleeve**
|
||||
|
||||
* karma gain now scales with sync.
|
||||
|
||||
Misc.
|
||||
Fix issue where the effective stats under Character>Stats were being calculated.
|
||||
**Misc.**
|
||||
|
||||
* Fix issue where the effective stats under Character>Stats were being calculated.
|
||||
|
||||
v0.49.0 - 2021-03-11 Source-File -1 (hydroflame)
|
||||
-------
|
||||
------------------------------------------------
|
||||
|
||||
**Source-File -1**
|
||||
|
||||
@@ -63,7 +180,7 @@ v0.49.0 - 2021-03-11 Source-File -1 (hydroflame)
|
||||
|
||||
|
||||
v0.48.0 - ASCII - 2021-03-07 (hydroflame)
|
||||
-------
|
||||
-----------------------------------------
|
||||
|
||||
**ASCII**
|
||||
|
||||
@@ -135,7 +252,7 @@ v0.47.2 - 7/15/2019
|
||||
* Added 'Solarized Dark' theme to CodeMirror editor
|
||||
* After Infiltration, you will now return to the company page rather than the city page
|
||||
* Bug fix: Stock Market UI should no longer crash for certain locale settings
|
||||
* Bug fix: You can now properly remove unfinished programs (the *.exe-N%-INC files)
|
||||
* Bug fix: You can now properly remove unfinished programs (the `*.exe-N%-INC` files)
|
||||
* Bug fix: Fixed an issue that allowed you to increase money on servers with a 'maxMoney' of 0 (like CSEC)
|
||||
* Bug fix: Scripts no longer persist if they were started with syntax/import errors
|
||||
* Bug fix: 'hack' and 'analyze' Terminal commands are now blocking
|
||||
|
||||
@@ -64,9 +64,9 @@ documentation_title = '{0} Documentation'.format(project)
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.47'
|
||||
version = '0.51'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.47.0'
|
||||
release = '0.51.1'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
@@ -860,7 +860,7 @@ Random Tips
|
||||
.. Substitution definitions
|
||||
.. |Alpha Enterprises| replace:: :code:`Alpha Enterprises`
|
||||
.. |Augmentations tab| replace:: :code:`Augmentations` tab
|
||||
.. |AutoLink| replace:: :code:`NUKE.exe`
|
||||
.. |AutoLink| replace:: :code:`AutoLink.exe`
|
||||
.. |BruteSSH| replace:: :code:`BruteSSH.exe`
|
||||
.. |City tab| replace:: :code:`City` tab
|
||||
.. |CyberSec| replace:: :code:`CyberSec`
|
||||
|
||||
@@ -30,4 +30,5 @@ to reach out to the developer!
|
||||
Gang API <netscript/netscriptgangapi>
|
||||
Coding Contract API <netscript/netscriptcodingcontractapi>
|
||||
Sleeve API <netscript/netscriptsleeveapi>
|
||||
Formulas API <netscript/netscriptformulasapi>
|
||||
Miscellaneous <netscript/netscriptmisc>
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
getHackTime(), getGrowTime(), & getWeakenTime()
|
||||
===============================================
|
||||
|
||||
The :js:func:`getHackTime`, :js:func:`getGrowTime`, and :js:func:`getWeakenTime`
|
||||
all take an additional third optional parameter for specifying a specific intelligence
|
||||
level to see how that would affect the hack/grow/weaken times. This parameter
|
||||
defaults to your current intelligence level.
|
||||
|
||||
(Intelligence is unlocked after obtaining Source-File 5).
|
||||
|
||||
The function signatures are then::
|
||||
|
||||
getHackTime(hostname/ip[, hackLvl=current level, intLvl=current level])
|
||||
getGrowTime(hostname/ip[, hackLvl=current level, intLvl=current level])
|
||||
getWeakenTime(hostname/ip[, hackLvl=current level, intLvl=current level])
|
||||
39
doc/source/netscript/advancedfunctions/getServer.rst
Normal file
39
doc/source/netscript/advancedfunctions/getServer.rst
Normal file
@@ -0,0 +1,39 @@
|
||||
getServer() Netscript Function
|
||||
==========================================
|
||||
|
||||
.. js:function:: getServer()
|
||||
|
||||
:RAM cost: 4 GB
|
||||
|
||||
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::
|
||||
|
||||
{
|
||||
cpuCores
|
||||
ftpPortOpen
|
||||
hasAdminRights
|
||||
hostname
|
||||
httpPortOpen
|
||||
ip
|
||||
isConnectedTo
|
||||
maxRam
|
||||
organizationName
|
||||
ramUsed
|
||||
smtpPortOpen
|
||||
sqlPortOpen
|
||||
sshPortOpen
|
||||
baseDifficulty
|
||||
hackDifficulty
|
||||
manuallyHacked
|
||||
minDifficulty
|
||||
moneyAvailable
|
||||
moneyMax
|
||||
numOpenPortsRequired
|
||||
openPortCount
|
||||
purchasedByPlayer
|
||||
requiredHackingSkill
|
||||
serverGrowth
|
||||
}
|
||||
22
doc/source/netscript/formulasapi/basic/calculateExp.rst
Normal file
22
doc/source/netscript/formulasapi/basic/calculateExp.rst
Normal file
@@ -0,0 +1,22 @@
|
||||
calculateExp() Netscript Function
|
||||
=================================
|
||||
|
||||
.. js:function:: calculateExp(skillLevel[, mult])
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param number skillLevel: ``skillLevel`` to convert to exp.
|
||||
:param number mult: Assume a specific skill multipler.
|
||||
:returns: number of exp required to reach given ``skillLevel`` with that multiplier.
|
||||
|
||||
You must have Source-File 5-1 in order to use this function.
|
||||
|
||||
This function calculates the amount of experience needed to reach level the given ``skillLevel``.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
nextHacking = getStats().hacking+1;
|
||||
nextExp = formulas.basic.calculateExp(nextHacking);
|
||||
missingExp = nextExp - getCharacterInformation().hackingExp;
|
||||
tprint("Missing " + missingExp + " to reach next hacking level");
|
||||
20
doc/source/netscript/formulasapi/basic/calculateSkill.rst
Normal file
20
doc/source/netscript/formulasapi/basic/calculateSkill.rst
Normal file
@@ -0,0 +1,20 @@
|
||||
calculateSkill() Netscript Function
|
||||
===================================
|
||||
|
||||
.. js:function:: calculateSkill(exp[, mult])
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param number exp: ``exp`` to convert to skillLevel.
|
||||
:param number mult: Assume a specific skill multipler.
|
||||
:returns: skillLevel that ``exp`` would reach with that multiplier.
|
||||
|
||||
You must have Source-File 5-1 in order to use this function.
|
||||
|
||||
This function calculates the skillLevel that the given amount of ``exp`` would reach.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
skillLevel = formulas.basic.calculateSkill(1000);
|
||||
tprint("1000 exp would reach level " + skillLevel);
|
||||
23
doc/source/netscript/formulasapi/basic/growPercent.rst
Normal file
23
doc/source/netscript/formulasapi/basic/growPercent.rst
Normal file
@@ -0,0 +1,23 @@
|
||||
growPercent() Netscript Function
|
||||
=================================
|
||||
|
||||
.. js:function:: growPercent(server, threads, player)
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param server server: The server that receives the growth.
|
||||
:param number threads: The number of thread that would be used.
|
||||
:param player player: The player.
|
||||
:returns: The percentage growth this server would receive with these parameters.
|
||||
|
||||
You must have Source-File 5-1 in order to use this function.
|
||||
|
||||
Server can be acquired with the :doc:`getServer<../../advancedfunctions/getServer>` function.
|
||||
Player can be acquired with the :doc:`getPlayer<../../singularityfunctions/getPlayer>` function.
|
||||
|
||||
This function calculates percentage of growth a server would receive with these parameters.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
tprint(growPercent(getServer(), 50, getPlayer()))
|
||||
24
doc/source/netscript/formulasapi/basic/growTime.rst
Normal file
24
doc/source/netscript/formulasapi/basic/growTime.rst
Normal file
@@ -0,0 +1,24 @@
|
||||
growTime() Netscript Function
|
||||
=================================
|
||||
|
||||
.. js:function:: growTime(server, player)
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param server server: The server to grow.
|
||||
:param player player: The player.
|
||||
:returns: The time it takes to grow this server. In seconds.
|
||||
|
||||
You must have Source-File 5-1 in order to use this function.
|
||||
|
||||
Server can be acquired with the :doc:`getServer<../../advancedfunctions/getServer>` function.
|
||||
Player can be acquired with the :doc:`getPlayer<../../singularityfunctions/getPlayer>` function.
|
||||
|
||||
This function calculates the amount of time it takes to grow a server.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
server = getServer();
|
||||
server.hackDifficulty = server.minDifficulty;
|
||||
tprint(growTime(server, getPlayer()));
|
||||
24
doc/source/netscript/formulasapi/basic/hackChance.rst
Normal file
24
doc/source/netscript/formulasapi/basic/hackChance.rst
Normal file
@@ -0,0 +1,24 @@
|
||||
hackChance() Netscript Function
|
||||
=================================
|
||||
|
||||
.. js:function:: hackChance(server, player)
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param server server: The server to hack.
|
||||
:param player player: The player.
|
||||
:returns: The change to hack that server. between 0 and 1.
|
||||
|
||||
You must have Source-File 5-1 in order to use this function.
|
||||
|
||||
Server can be acquired with the :doc:`getServer<../../advancedfunctions/getServer>` function.
|
||||
Player can be acquired with the :doc:`getPlayer<../../singularityfunctions/getPlayer>` function.
|
||||
|
||||
This function calculates percentage chance to hack a server.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
server = getServer();
|
||||
server.hackDifficulty = server.minDifficulty;
|
||||
tprint(hackChance(server, getPlayer()));
|
||||
24
doc/source/netscript/formulasapi/basic/hackExp.rst
Normal file
24
doc/source/netscript/formulasapi/basic/hackExp.rst
Normal file
@@ -0,0 +1,24 @@
|
||||
hackExp() Netscript Function
|
||||
=================================
|
||||
|
||||
.. js:function:: hackExp(server, player)
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param server server: The server to hack.
|
||||
:param player player: The player.
|
||||
:returns: The amount of exp that would be acquired if this server were to be hacked.
|
||||
|
||||
You must have Source-File 5-1 in order to use this function.
|
||||
|
||||
Server can be acquired with the :doc:`getServer<../../advancedfunctions/getServer>` function.
|
||||
Player can be acquired with the :doc:`getPlayer<../../singularityfunctions/getPlayer>` function.
|
||||
|
||||
This function calculates the amount of exp obtained by hacking a server.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
server = getServer();
|
||||
server.hackDifficulty = 99.9;
|
||||
tprint(hackExp(server, getPlayer()));
|
||||
25
doc/source/netscript/formulasapi/basic/hackPercent.rst
Normal file
25
doc/source/netscript/formulasapi/basic/hackPercent.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
hackPercent() Netscript Function
|
||||
=================================
|
||||
|
||||
.. js:function:: hackPercent(server, player)
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param server server: The server to hack.
|
||||
:param player player: The player.
|
||||
:returns: The percentage of money hacked from a servers maximum money.
|
||||
|
||||
You must have Source-File 5-1 in order to use this function.
|
||||
|
||||
Server can be acquired with the :doc:`getServer<../../advancedfunctions/getServer>` function.
|
||||
Player can be acquired with the :doc:`getPlayer<../../singularityfunctions/getPlayer>` function.
|
||||
|
||||
This function calculates the percentage of maximum money hacked from a server.
|
||||
Multiply this by thread count to know calculate the percentage for more than 1 thread.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
server = getServer();
|
||||
server.hackDifficulty = server.minDifficulty;
|
||||
tprint(hackPercent(server, getPlayer()));
|
||||
24
doc/source/netscript/formulasapi/basic/hackTime.rst
Normal file
24
doc/source/netscript/formulasapi/basic/hackTime.rst
Normal file
@@ -0,0 +1,24 @@
|
||||
hackTime() Netscript Function
|
||||
=================================
|
||||
|
||||
.. js:function:: hackTime(server, player)
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param server server: The server to hack.
|
||||
:param player player: The player.
|
||||
:returns: The time it takes to hack this server. In seconds.
|
||||
|
||||
You must have Source-File 5-1 in order to use this function.
|
||||
|
||||
Server can be acquired with the :doc:`getServer<../../advancedfunctions/getServer>` function.
|
||||
Player can be acquired with the :doc:`getPlayer<../../singularityfunctions/getPlayer>` function.
|
||||
|
||||
This function calculates the amount of time it takes to hack a server.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
server = getServer();
|
||||
server.hackDifficulty = server.minDifficulty;
|
||||
tprint(hackTime(server, getPlayer()));
|
||||
24
doc/source/netscript/formulasapi/basic/weakenTime.rst
Normal file
24
doc/source/netscript/formulasapi/basic/weakenTime.rst
Normal file
@@ -0,0 +1,24 @@
|
||||
weakenTime() Netscript Function
|
||||
=================================
|
||||
|
||||
.. js:function:: weakenTime(server, player)
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param server server: The server to weaken.
|
||||
:param player player: The player.
|
||||
:returns: The time it takes to weaken this server. In seconds.
|
||||
|
||||
You must have Source-File 5-1 in order to use this function.
|
||||
|
||||
Server can be acquired with the :doc:`getServer<../../advancedfunctions/getServer>` function.
|
||||
Player can be acquired with the :doc:`getPlayer<../../singularityfunctions/getPlayer>` function.
|
||||
|
||||
This function calculates the amount of time it takes to weaken a server.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
server = getServer();
|
||||
server.hackDifficulty = server.minDifficulty;
|
||||
tprint(weakenTime(server, getPlayer()));
|
||||
26
doc/source/netscript/formulasapi/hacknetNodes/constants.rst
Normal file
26
doc/source/netscript/formulasapi/hacknetNodes/constants.rst
Normal file
@@ -0,0 +1,26 @@
|
||||
constants() Netscript Function
|
||||
==============================
|
||||
|
||||
.. js:function:: constants()
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:returns: A structure with various constants related to hacknet nodes.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
MoneyGainPerLevel
|
||||
BaseCost
|
||||
LevelBaseCost
|
||||
RamBaseCost
|
||||
CoreBaseCost
|
||||
PurchaseNextMult
|
||||
UpgradeLevelMult
|
||||
UpgradeRamMult
|
||||
UpgradeCoreMult
|
||||
MaxLevel
|
||||
MaxRam
|
||||
MaxCores
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
coreUpgradeCost() Netscript Function
|
||||
=============================================
|
||||
|
||||
.. js:function:: coreUpgradeCost(startingCores[, extraCores[, costMult]])
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param number startingCores: Number of core at the start the calculation.
|
||||
:param number extraCores: Extra number of cores you want to buy. Default to ``1``.
|
||||
:param number costMult: Aug multiplier that reduces cost. Defaults to ``1``.
|
||||
:returns: Money required to go from ``startingCores`` to ``startingCores+extraCores``.
|
||||
|
||||
You must have Source-File 5-1 in order to use this function.
|
||||
|
||||
This function calculates the cost of upgrading cores from any level to any level.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
formulas.hacknetNodes.coreUpgradeCost(1, 5); // returns: 6355000
|
||||
@@ -0,0 +1,19 @@
|
||||
hacknetNodeCost() Netscript Function
|
||||
=============================================
|
||||
|
||||
.. js:function:: hacknetNodeCost(nodeN[, costMult]])
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param number nodeN: Number of the new node.
|
||||
:param number costMult: Aug multiplier that reduces cost. Defaults to ``1``.
|
||||
:returns: Money required to buy your ``nodeN`` th node.
|
||||
|
||||
You must have Source-File 5-1 in order to use this function.
|
||||
|
||||
This function calculates the cost purchasing a hacknet node.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
formulas.hacknetNodes.hacknetNodeCost(2); // returns: 1800
|
||||
@@ -0,0 +1,20 @@
|
||||
levelUpgradeCost() Netscript Function
|
||||
==============================================
|
||||
|
||||
.. js:function:: levelUpgradeCost(startingLevel[, extraLevels[, costMult]])
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param number startingLevel: Number of level at the start the calculation.
|
||||
:param number extraLevels: Extra number of levels you want to buy. Default to ``1``.
|
||||
:param number costMult: Aug multiplier that reduces cost. Defaults to ``1``.
|
||||
:returns: Money required to go from ``startingLevel`` to ``startingLevel+extraLevels``.
|
||||
|
||||
You must have Source-File 5-1 in order to use this function.
|
||||
|
||||
This function calculates the cost of upgrading levels from any level to any level.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
formulas.hacknetNodes.levelUpgradeCost(1, 5); // returns: 2816
|
||||
@@ -0,0 +1,24 @@
|
||||
moneyGainRate() Netscript Function
|
||||
===========================================
|
||||
|
||||
.. js:function:: moneyGainRate(level, ram, core[, mult])
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param number level: level of the node.
|
||||
:param number ram: ram of the node.
|
||||
:param number core: cores of the node.
|
||||
:returns: Money per second that a node with those stats would gain per second.
|
||||
|
||||
You must have Source-File 5-1 in order to use this function.
|
||||
|
||||
This function calculates the money rate of a node with the given stats.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
node = hacknet.getNodeStats(1);
|
||||
currentRate = formulas.hacknetNodes.moneyGainRate(node.level, node.ram, node.cores);
|
||||
levelRate = formulas.hacknetNodes.moneyGainRate(node.level+1, node.ram, node.cores);
|
||||
ramRate = formulas.hacknetNodes.moneyGainRate(node.level, node.ram*2, node.cores);
|
||||
coresRate = formulas.hacknetNodes.moneyGainRate(node.level, node.ram, node.cores+1);
|
||||
@@ -0,0 +1,22 @@
|
||||
ramUpgradeCost() Netscript Function
|
||||
============================================
|
||||
|
||||
.. js:function:: ramUpgradeCost(startingRam[, extraRamLevels[, costMult]])
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param number startingRam: Amount of RAM at the start the calculation.
|
||||
:param number extraRamLevels: Extra number of levels you want to buy. Default to ``1``.
|
||||
:param number costMult: Aug multiplier that reduces cost. Defaults to ``1``.
|
||||
:returns: Money required to go from ``startingRam`` to ``startingRam+extraRamLevels``.
|
||||
|
||||
..note:: ``startingRam`` is the actual amount of ram, not the amount of levels of ram.
|
||||
|
||||
You must have Source-File 5-1 in order to use this function.
|
||||
|
||||
This function calculates the cost of upgrading levels from any level to any level.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
formulas.hacknetNodes.ramUpgradeCost(1, 5); // returns: 2095000
|
||||
@@ -0,0 +1,20 @@
|
||||
cacheUpgradeCost() Netscript Function
|
||||
==============================================
|
||||
|
||||
.. js:function:: cacheUpgradeCost(startingCache[, extraCacheLevels[, costMult]])
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param number startingCache: Cache level at the start the calculation.
|
||||
:param number extraCacheLevels: Extra number of cache level you want to buy. Default to ``1``.
|
||||
:param number costMult: Aug multiplier that reduces cost. Defaults to ``1``.
|
||||
:returns: Money required to go from ``startingLevel`` to ``startingLevel+extraLevels``.
|
||||
|
||||
You must have Source-File 5-1 and Source-File 9-1 in order to use this function.
|
||||
|
||||
This function calculates the cost of upgrading cache from any level to any level.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
formulas.hacknetServers.cacheUpgradeCost(1, 5); // returns: 243170000
|
||||
@@ -0,0 +1,29 @@
|
||||
constants() Netscript Function
|
||||
=============================================
|
||||
|
||||
.. js:function:: constants()
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:returns: A structure with various constants related to hacknet servers.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
{
|
||||
HashesPerLevel
|
||||
BaseCost
|
||||
RamBaseCost
|
||||
CoreBaseCost
|
||||
CacheBaseCost
|
||||
PurchaseMult
|
||||
UpgradeLevelMult
|
||||
UpgradeRamMult
|
||||
UpgradeCoreMult
|
||||
UpgradeCacheMult
|
||||
MaxServers
|
||||
MaxLevel
|
||||
MaxRam
|
||||
MaxCores
|
||||
MaxCache
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
coreUpgradeCost() Netscript Function
|
||||
=============================================
|
||||
|
||||
.. js:function:: coreUpgradeCost(startingCores[, extraCores[, costMult]])
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param number startingCores: Number of core at the start the calculation.
|
||||
:param number extraCores: Extra number of cores you want to buy. Default to ``1``.
|
||||
:param number costMult: Aug multiplier that reduces cost. Defaults to ``1``.
|
||||
:returns: Money required to go from ``startingCores`` to ``startingCores+extraCores``.
|
||||
|
||||
You must have Source-File 5-1 and Source-File 9-1 in order to use this function.
|
||||
|
||||
This function calculates the cost of upgrading cores from any level to any level.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
formulas.hacknetServers.coreUpgradeCost(1, 5); // returns: 12015000
|
||||
@@ -0,0 +1,19 @@
|
||||
hacknetServerCost() Netscript Function
|
||||
===============================================
|
||||
|
||||
.. js:function:: hacknetServerCost(serverN[, costMult]])
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param number serverN: Number of the new node.
|
||||
:param number costMult: Aug multiplier that reduces cost. Defaults to ``1``.
|
||||
:returns: Money required to buy your ``serverN`` th node.
|
||||
|
||||
You must have Source-File 5-1 and Source-File 9-1 in order to use this function.
|
||||
|
||||
This function calculates the cost purchasing a hacknet node.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
formulas.hacknetNodes.hacknetServerCost(2); // returns: 1800000
|
||||
@@ -0,0 +1,24 @@
|
||||
hashGainRate() Netscript Function
|
||||
==========================================
|
||||
|
||||
.. js:function:: hashGainRate(level, ram, core[, mult])
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param number level: level of the server.
|
||||
:param number ram: ram of the server.
|
||||
:param number core: cores of the server.
|
||||
:returns: Money per second that a server with those stats would gain per second.
|
||||
|
||||
You must have Source-File 5-1 and Source-File 9-1 in order to use this function.
|
||||
|
||||
This function calculates the hash rate of a server with the given stats.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
server = hacknet.getNodeStats(1);
|
||||
currentRate = formulas.hacknetNodes.hashGainRate(server.level, server.ram, server.cores);
|
||||
levelRate = formulas.hacknetNodes.hashGainRate(server.level+1, server.ram, server.cores);
|
||||
ramRate = formulas.hacknetNodes.hashGainRate(server.level, server.ram*2, server.cores);
|
||||
coresRate = formulas.hacknetNodes.hashGainRate(server.level, server.ram, server.cores+1);
|
||||
@@ -0,0 +1,19 @@
|
||||
hashUpgradeCost() Netscript Function
|
||||
=============================================
|
||||
|
||||
.. js:function:: hashUpgradeCost(upgName, level)
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param string upgName: Name of the Hash upgrade.
|
||||
:param number level: Level of the upgrade.
|
||||
:returns: Amount of Hash.
|
||||
|
||||
You must have Source-File 5-1 and Source-File 9-1 in order to use this function.
|
||||
|
||||
This function calculates amount of Hash require to buy level ``level`` of upgrade ``upgName``.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
formulas.hacknetServers.hashUpgradeCost("Increase Maximum Money", 5); // returns: 250
|
||||
@@ -0,0 +1,20 @@
|
||||
levelUpgradeCost() Netscript Function
|
||||
=============================================
|
||||
|
||||
.. js:function:: levelUpgradeCost(startingLevel[, extraLevels[, costMult]])
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param number startingLevel: Number of level at the start the calculation.
|
||||
:param number extraLevels: Extra number of levels you want to buy. Default to ``1``.
|
||||
:param number costMult: Aug multiplier that reduces cost. Defaults to ``1``.
|
||||
:returns: Money required to go from ``startingLevel`` to ``startingLevel+extraLevels``.
|
||||
|
||||
You must have Source-File 5-1 and Source-File 9-1 in order to use this function.
|
||||
|
||||
This function calculates the cost of upgrading levels from any level to any level.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
formulas.hacknetServers.levelUpgradeCost(1, 5); // returns: 2792000
|
||||
@@ -0,0 +1,22 @@
|
||||
ramUpgradeCost() Netscript Function
|
||||
=============================================
|
||||
|
||||
.. js:function:: ramUpgradeCost(startingRam[, extraRamLevels[, costMult]])
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param number startingRam: Amount of RAM at the start the calculation.
|
||||
:param number extraRamLevels: Extra number of levels you want to buy. Default to ``1``.
|
||||
:param number costMult: Aug multiplier that reduces cost. Defaults to ``1``.
|
||||
:returns: Money required to go from ``startingRam`` to ``startingRam+extraRamLevels``.
|
||||
|
||||
..note:: ``startingRam`` is the actual amount of ram, not the amount of levels of ram.
|
||||
|
||||
You must have Source-File 5-1 and Source-File 9-1 in order to use this function.
|
||||
|
||||
This function calculates the cost of upgrading levels from any level to any level.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
formulas.hacknetServers.ramUpgradeCost(1, 5); // returns: 15810000
|
||||
18
doc/source/netscript/hacknetnodeapi/getHashUpgradeLevel.rst
Normal file
18
doc/source/netscript/hacknetnodeapi/getHashUpgradeLevel.rst
Normal file
@@ -0,0 +1,18 @@
|
||||
getHashUpgradeLevel() Netscript Function
|
||||
========================================
|
||||
|
||||
.. js:function:: getHashUpgradeLevel(upgName)
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param string upgName: Name of upgrade to spend hashes on. Must be an exact match.
|
||||
:returns: level of the upgrade.
|
||||
|
||||
.. note:: This function is only applicable for Hacknet Servers (the upgraded version
|
||||
of a Hacknet Node).
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
hacknet.getHashUpgradeLevel("Sell for Money"); // returns: 5
|
||||
// "Sell for Money" was bought 5 times.
|
||||
13
doc/source/netscript/hacknetnodeapi/getStudyMult.rst
Normal file
13
doc/source/netscript/hacknetnodeapi/getStudyMult.rst
Normal file
@@ -0,0 +1,13 @@
|
||||
getStudyMult() Netscript Function
|
||||
=================================
|
||||
|
||||
.. js:function:: getStudyMult()
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:returns: The multiplier to studying that hash upgrades provide to the player.
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
hacknet.getStudyMult(); // return: 1.4
|
||||
13
doc/source/netscript/hacknetnodeapi/getTrainingMult.rst
Normal file
13
doc/source/netscript/hacknetnodeapi/getTrainingMult.rst
Normal file
@@ -0,0 +1,13 @@
|
||||
getTrainingMul() Netscript Function
|
||||
===================================
|
||||
|
||||
.. js:function:: getTrainingMul()
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:returns: The multiplier to training that hash upgrades provide to the player.
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
hacknet.getTrainingMult(); // return: 1.4
|
||||
12
doc/source/netscript/hacknetnodeapi/hashCapacity.rst
Normal file
12
doc/source/netscript/hacknetnodeapi/hashCapacity.rst
Normal file
@@ -0,0 +1,12 @@
|
||||
hashCapacity() Netscript Function
|
||||
=================================
|
||||
|
||||
.. warning:: This page contains spoilers for the game
|
||||
|
||||
.. js:function:: hashCapacity()
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:returns: The players maximum hash capacity.
|
||||
|
||||
.. note:: This function is only applicable for Hacknet Servers (the upgraded version of
|
||||
a Hacknet Node).
|
||||
@@ -9,4 +9,4 @@ they contain spoilers for the game.
|
||||
.. toctree::
|
||||
|
||||
getBitNodeMultipliers() <advancedfunctions/getBitNodeMultipliers>
|
||||
getHackTime(), getGrowTime(), & getWeakenTime() <advancedfunctions/getHackGrowWeakenTimes>
|
||||
getServer() <advancedfunctions/getServer>
|
||||
|
||||
61
doc/source/netscript/netscriptformulasapi.rst
Normal file
61
doc/source/netscript/netscriptformulasapi.rst
Normal file
@@ -0,0 +1,61 @@
|
||||
.. _netscriptformulas:
|
||||
|
||||
Netscript Formulas Functions
|
||||
============================
|
||||
|
||||
.. warning:: This page contains spoilers for the game.
|
||||
|
||||
The formulas API allow you to gain insight into the inner workings of the game.
|
||||
These functions will allow you to make more informed decision.
|
||||
|
||||
All of these function cost 0 GB of ram to use. All these function require
|
||||
Source-File 5-1 but some additionally need another source file level 1 to use.
|
||||
|
||||
|
||||
basic formulas
|
||||
--------------
|
||||
|
||||
These functions are under the ``formulas.basic.`` name space and available as
|
||||
soon as you acquire Source-File 5-1
|
||||
|
||||
.. toctree::
|
||||
calculateSkill() <formulasapi/basic/calculateSkill>
|
||||
calculateExp() <formulasapi/basic/calculateExp>
|
||||
growTime() <formulasapi/basic/growTime>
|
||||
hackTime() <formulasapi/basic/hackTime>
|
||||
weakenTime() <formulasapi/basic/weakenTime>
|
||||
growPercent() <formulasapi/basic/growPercent>
|
||||
hackPercent() <formulasapi/basic/hackPercent>
|
||||
hackChance() <formulasapi/basic/hackChance>
|
||||
hackExp() <formulasapi/basic/hackExp>
|
||||
|
||||
|
||||
hacknetNodes formulas
|
||||
---------------------
|
||||
|
||||
These functions are under the ``formulas.hacknetNodes.`` namespace and available as
|
||||
soon as you acquire Source-File 5-1.
|
||||
|
||||
.. toctree::
|
||||
hacknetNodeCost() <formulasapi/hacknetNodes/hacknetNodeCost>
|
||||
moneyGainRate() <formulasapi/hacknetNodes/moneyGainRate>
|
||||
levelUpgradeCost() <formulasapi/hacknetNodes/levelUpgradeCost>
|
||||
ramUpgradeCost() <formulasapi/hacknetNodes/ramUpgradeCost>
|
||||
coreUpgradeCost() <formulasapi/hacknetNodes/coreUpgradeCost>
|
||||
constants() <formulasapi/hacknetNodes/constants>
|
||||
|
||||
hacknetServers formulas
|
||||
-----------------------
|
||||
|
||||
These functions are under the ``formulas.hacknetServers.`` namespace.
|
||||
These functions require Source-File 5-1 and Source-File 9-1 to be invoked.
|
||||
|
||||
.. toctree::
|
||||
hacknetServerCost() <formulasapi/hacknetServers/hacknetServerCost>
|
||||
hashGainRate() <formulasapi/hacknetServers/hashGainRate>
|
||||
levelUpgradeCost() <formulasapi/hacknetServers/levelUpgradeCost>
|
||||
ramUpgradeCost() <formulasapi/hacknetServers/ramUpgradeCost>
|
||||
coreUpgradeCost() <formulasapi/hacknetServers/coreUpgradeCost>
|
||||
cacheUpgradeCost() <formulasapi/hacknetServers/cacheUpgradeCost>
|
||||
hashUpgradeCost() <formulasapi/hacknetServers/hashUpgradeCost>
|
||||
constants() <formulasapi/hacknetServers/constants>
|
||||
@@ -84,6 +84,7 @@ This includes information such as function signatures, what they do, and their r
|
||||
sprintf() <basicfunctions/sprintf>
|
||||
vsprintf() <basicfunctions/vsprintf>
|
||||
nFormat() <basicfunctions/nFormat>
|
||||
tFormat() <basicfunctions/tFormat>
|
||||
prompt() <basicfunctions/prompt>
|
||||
wget() <basicfunctions/wget>
|
||||
getFavorToDonate() <basicfunctions/getFavorToDonate>
|
||||
|
||||
@@ -26,7 +26,7 @@ In :ref:`netscriptjs`::
|
||||
ns.hacknet.getNodeStats(3).level;
|
||||
|
||||
.. toctree::
|
||||
:caption: API Functions:
|
||||
:caption: Hacknet Nodes API Functions:
|
||||
|
||||
numNodes() <hacknetnodeapi/numNodes>
|
||||
maxNumNodes() <hacknetnodeapi/maxNumNodes>
|
||||
@@ -36,14 +36,22 @@ In :ref:`netscriptjs`::
|
||||
upgradeLevel() <hacknetnodeapi/upgradeLevel>
|
||||
upgradeRam() <hacknetnodeapi/upgradeRam>
|
||||
upgradeCore() <hacknetnodeapi/upgradeCore>
|
||||
upgradeCache() <hacknetnodeapi/upgradeCache>
|
||||
getLevelUpgradeCost() <hacknetnodeapi/getLevelUpgradeCost>
|
||||
getRamUpgradeCost() <hacknetnodeapi/getRamUpgradeCost>
|
||||
getCoreUpgradeCost() <hacknetnodeapi/getCoreUpgradeCost>
|
||||
|
||||
.. toctree::
|
||||
:caption: Hacknet Servers API Functions:
|
||||
|
||||
upgradeCache() <hacknetnodeapi/upgradeCache>
|
||||
getCacheUpgradeCost() <hacknetnodeapi/getCacheUpgradeCost>
|
||||
numHashes() <hacknetnodeapi/numHashes>
|
||||
hashCapacity() <hacknetnodeapi/hashCapacity>
|
||||
hashCost() <hacknetnodeapi/hashCost>
|
||||
spendHashes() <hacknetnodeapi/spendHashes>
|
||||
getHashUpgradeLevel() <hacknetnodeapi/getHashUpgradeLevel>
|
||||
getTrainingMult() <hacknetnodeapi/getTrainingMult>
|
||||
getStudyMult() <hacknetnodeapi/getStudyMult>
|
||||
|
||||
.. _netscript_hacknetnodeapi_referencingahacknetnode:
|
||||
|
||||
|
||||
@@ -24,8 +24,11 @@ level 3, then you will be able to access all of the Singularity Functions.
|
||||
travelToCity() <singularityfunctions/travelToCity>
|
||||
purchaseTor() <singularityfunctions/purchaseTor>
|
||||
purchaseProgram() <singularityfunctions/purchaseProgram>
|
||||
getStats() <singularityfunctions/getStats>
|
||||
getCharacterInformation() <singularityfunctions/getCharacterInformation>
|
||||
getCurrentServer() <singularityfunctions/getCurrentServer>
|
||||
connect() <singularityfunctions/connect>
|
||||
manualHack() <singularityfunctions/manualHack>
|
||||
getPlayer() <singularityfunctions/getPlayer>
|
||||
hospitalize() <singularityfunctions/hospitalize>
|
||||
isBusy() <singularityfunctions/isBusy>
|
||||
stopAction() <singularityfunctions/stopAction>
|
||||
upgradeHomeRam() <singularityfunctions/upgradeHomeRam>
|
||||
@@ -55,3 +58,10 @@ level 3, then you will be able to access all of the Singularity Functions.
|
||||
purchaseAugmentation() <singularityfunctions/purchaseAugmentation>
|
||||
installAugmentations() <singularityfunctions/installAugmentations>
|
||||
softReset() <singularityfunctions/softReset>
|
||||
|
||||
|
||||
.. toctree::
|
||||
:caption: Deprecated:
|
||||
|
||||
getStats() <singularityfunctions/getStats>
|
||||
getCharacterInformation() <singularityfunctions/getCharacterInformation>
|
||||
20
doc/source/netscript/singularityfunctions/connect.rst
Normal file
20
doc/source/netscript/singularityfunctions/connect.rst
Normal file
@@ -0,0 +1,20 @@
|
||||
connect() Netscript Function
|
||||
============================
|
||||
|
||||
.. js:function:: connect(hostname)
|
||||
|
||||
:RAM cost: 2 GB
|
||||
:param string hostname: hostname of the server to connect.
|
||||
:returns: ``true`` if the connection was a success.
|
||||
|
||||
If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to use this function.
|
||||
|
||||
This function will connect you to the specified server if it's directly connected to the current server.
|
||||
You can also pass in 'home' to return to your home server from anywhere.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
connect("joesguns");
|
||||
connect("CSEC");
|
||||
@@ -9,8 +9,12 @@ getAugmentationStats() Netscript Function
|
||||
|
||||
If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.
|
||||
|
||||
ns.getAugmentationStats("Synfibril Muscle")
|
||||
{
|
||||
strength_mult: 1.3,
|
||||
defense_mult: 1.3,
|
||||
}
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
ns.getAugmentationStats("Synfibril Muscle")
|
||||
{
|
||||
strength_mult: 1.3,
|
||||
defense_mult: 1.3,
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ getCharacterInformation() Netscript Function
|
||||
|
||||
.. js:function:: getCharacterInformation()
|
||||
|
||||
.. warning:: This function is deprecated.
|
||||
|
||||
:RAM cost: 0.5 GB
|
||||
|
||||
If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to run this function.
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
getCurrentServer() Netscript Function
|
||||
=====================================
|
||||
|
||||
.. js:function:: getCurrentServer()
|
||||
|
||||
:RAM cost: 2 GB
|
||||
:returns: The hostname of the server the player is currently connected to.
|
||||
|
||||
If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.
|
||||
|
||||
103
doc/source/netscript/singularityfunctions/getPlayer.rst
Normal file
103
doc/source/netscript/singularityfunctions/getPlayer.rst
Normal file
@@ -0,0 +1,103 @@
|
||||
getPlayer() Netscript Function
|
||||
==============================
|
||||
|
||||
.. js:function:: getPlayer()
|
||||
|
||||
:RAM cost: 0.5 GB
|
||||
|
||||
If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to run this function.
|
||||
|
||||
The result of this function can be passed to the :doc:`formulas API<../netscriptformulasapi>`.
|
||||
|
||||
Returns an object with the Player's stats. The object has the following properties::
|
||||
|
||||
{
|
||||
hacking_skill
|
||||
hp
|
||||
max_hp
|
||||
strength
|
||||
defense
|
||||
dexterity
|
||||
agility
|
||||
charisma
|
||||
intelligence
|
||||
hacking_chance_mult
|
||||
hacking_speed_mult
|
||||
hacking_money_mult
|
||||
hacking_grow_mult
|
||||
hacking_exp
|
||||
strength_exp
|
||||
defense_exp
|
||||
dexterity_exp
|
||||
agility_exp
|
||||
charisma_exp
|
||||
hacking_mult
|
||||
strength_mult
|
||||
defense_mult
|
||||
dexterity_mult
|
||||
agility_mult
|
||||
charisma_mult
|
||||
hacking_exp_mult
|
||||
strength_exp_mult
|
||||
defense_exp_mult
|
||||
dexterity_exp_mult
|
||||
agility_exp_mult
|
||||
charisma_exp_mult
|
||||
company_rep_mult
|
||||
faction_rep_mult
|
||||
money
|
||||
city
|
||||
location
|
||||
crime_money_mult
|
||||
crime_success_mult
|
||||
isWorking
|
||||
workType
|
||||
currentWorkFactionName
|
||||
currentWorkFactionDescription
|
||||
workHackExpGainRate
|
||||
workStrExpGainRate
|
||||
workDefExpGainRate
|
||||
workDexExpGainRate
|
||||
workAgiExpGainRate
|
||||
workChaExpGainRate
|
||||
workRepGainRate
|
||||
workMoneyGainRate
|
||||
workMoneyLossRate
|
||||
workHackExpGained
|
||||
workStrExpGained
|
||||
workDefExpGained
|
||||
workDexExpGained
|
||||
workAgiExpGained
|
||||
workChaExpGained
|
||||
workRepGained
|
||||
workMoneyGained
|
||||
createProgramName
|
||||
createProgramReqLvl
|
||||
className
|
||||
crimeType
|
||||
work_money_mult
|
||||
hacknet_node_money_mult
|
||||
hacknet_node_purchase_cost_mult
|
||||
hacknet_node_ram_cost_mult
|
||||
hacknet_node_core_cost_mult
|
||||
hacknet_node_level_cost_mult
|
||||
hasWseAccount
|
||||
hasTixApiAccess
|
||||
has4SData
|
||||
has4SDataTixApi
|
||||
bladeburner_max_stamina_mult
|
||||
bladeburner_stamina_gain_mult
|
||||
bladeburner_success_chance_mult
|
||||
bitNodeN
|
||||
totalPlaytime
|
||||
playtimeSinceLastAug
|
||||
playtimeSinceLastBitnode
|
||||
jobs
|
||||
factions
|
||||
tor
|
||||
}
|
||||
|
||||
Example::
|
||||
|
||||
player = getPlayer();
|
||||
print('My charisma level is: ' + player.charisma);
|
||||
@@ -3,6 +3,8 @@ getStats() Netscript Function
|
||||
|
||||
.. js:function:: getStats()
|
||||
|
||||
.. warning:: This function is deprecated.
|
||||
|
||||
:RAM cost: 0.5 GB
|
||||
|
||||
If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to run this function.
|
||||
|
||||
11
doc/source/netscript/singularityfunctions/hospitalize.rst
Normal file
11
doc/source/netscript/singularityfunctions/hospitalize.rst
Normal file
@@ -0,0 +1,11 @@
|
||||
hospitalize() Netscript Function
|
||||
===================================
|
||||
|
||||
.. js:function:: hospitalize()
|
||||
|
||||
:RAM cost: 1 GB
|
||||
:returns: The cost of your visit to the hospital.
|
||||
|
||||
If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to use this function.
|
||||
|
||||
Hospitalize yourself. Recovering all lost hp.
|
||||
24
doc/source/netscript/singularityfunctions/manualHack.rst
Normal file
24
doc/source/netscript/singularityfunctions/manualHack.rst
Normal file
@@ -0,0 +1,24 @@
|
||||
manualHack() Netscript Function
|
||||
===============================
|
||||
|
||||
.. js:function:: manualHack()
|
||||
|
||||
:RAM cost: 2 GB
|
||||
:returns: The amount of money stolen if the hack is successful, and zero otherwise
|
||||
|
||||
If you are not in BitNode-4, then you must have Level 1 of Source-File 4 in order to use this function.
|
||||
|
||||
This function will perform a manual hack on the server you are currently connected to.
|
||||
This is typically required to join factions.
|
||||
|
||||
Examples:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
connect("CSEC");
|
||||
manualHack();
|
||||
|
||||
.. warning::
|
||||
For NS2 users:
|
||||
|
||||
This function is async.
|
||||
@@ -3,6 +3,8 @@ softReset() Netscript Function
|
||||
|
||||
.. js:function:: softReset()
|
||||
|
||||
:RAM cost: 5 GB
|
||||
|
||||
If you are not in BitNode-4, then you must have Level 3 of Source-File 4 in order to use this function.
|
||||
|
||||
This function will perform a reset even if you don't have any augmentation installed.
|
||||
|
||||
@@ -31,6 +31,8 @@ Alt + f Switch to 'Factions' page
|
||||
Alt + a Switch to 'Augmentations' page
|
||||
Alt + u Switch to 'Tutorial' page
|
||||
Alt + o Switch to 'Options' page
|
||||
Alt + g Switch to 'Gang' page
|
||||
Alt + b Switch to 'Bladeburner' page
|
||||
========== ===========================================================================
|
||||
|
||||
Script Editor
|
||||
|
||||
36
index.html
36
index.html
@@ -30,7 +30,7 @@
|
||||
<div id="entire-game-container" style="visibility:hidden;">
|
||||
<div id="mainmenu-container">
|
||||
<!-- Main menu -->
|
||||
<ul id="mainmenu" class="mainmenu">
|
||||
<ul id="mainmenu" class="mainmenu noscrollbar">
|
||||
<!-- Hacking dropdown -->
|
||||
<li id="hacking-menu-header-li">
|
||||
<button id="hacking-menu-header" class="mainmenu-accordion-header"> Hacking </button>
|
||||
@@ -261,16 +261,16 @@
|
||||
<div id="infiltration-left-panel">
|
||||
<p id="infiltration-level-text"> </p>
|
||||
<div id="infiltration-buttons">
|
||||
<a class="a-link-button tooltip" id="infiltration-kill"> </a>
|
||||
<a class="a-link-button tooltip" id="infiltration-knockout"> </a>
|
||||
<a class="a-link-button tooltip" id="infiltration-stealthknockout"> </a>
|
||||
<a class="a-link-button tooltip" id="infiltration-assassinate"> </a>
|
||||
<a class="a-link-button tooltip" id="infiltration-hacksecurity"> </a>
|
||||
<a class="a-link-button tooltip" id="infiltration-destroysecurity"> </a>
|
||||
<a class="a-link-button tooltip" id="infiltration-sneak"> </a>
|
||||
<a class="a-link-button tooltip" id="infiltration-pickdoor"> </a>
|
||||
<a class="a-link-button tooltip" id="infiltration-bribe"> </a>
|
||||
<a class="a-link-button tooltip" id="infiltration-escape"> </a>
|
||||
<button class="a-link-button tooltip" id="infiltration-kill"> </button>
|
||||
<button class="a-link-button tooltip" id="infiltration-knockout"> </button>
|
||||
<button class="a-link-button tooltip" id="infiltration-stealthknockout"> </button>
|
||||
<button class="a-link-button tooltip" id="infiltration-assassinate"> </button>
|
||||
<button class="a-link-button tooltip" id="infiltration-hacksecurity"> </button>
|
||||
<button class="a-link-button tooltip" id="infiltration-destroysecurity"> </button>
|
||||
<button class="a-link-button tooltip" id="infiltration-sneak"> </button>
|
||||
<button class="a-link-button tooltip" id="infiltration-pickdoor"> </button>
|
||||
<button class="a-link-button tooltip" id="infiltration-bribe"> </button>
|
||||
<button class="a-link-button tooltip" id="infiltration-escape"> </button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="infiltration-right-panel">
|
||||
@@ -387,7 +387,7 @@
|
||||
<!-- Game Options -->
|
||||
<div id="game-options-container" class="popup-box-container">
|
||||
<div id="game-options-content" class="game-options-box">
|
||||
<button id="game-options-close-button">×</button>
|
||||
<button id="game-options-close-button" aria-label="close options dialog">×</button>
|
||||
<h1> Game Options </h1>
|
||||
<br/>
|
||||
<div id="game-options-left-panel">
|
||||
@@ -511,6 +511,16 @@
|
||||
<input class="optionCheckbox" type="checkbox" name="settingsDisableHotkeys" id="settingsDisableHotkeys">
|
||||
</fieldset>
|
||||
|
||||
<!-- View city as list of buttons instead of ASCII art. -->
|
||||
<fieldset>
|
||||
<label for="settingsDisableASCIIArt" class="tooltip">Disable ASCII art:
|
||||
<span class="tooltiptexthigh">
|
||||
If this is set all ASCII art will be disabled.
|
||||
</span>
|
||||
</label>
|
||||
<input class="optionCheckbox" type="checkbox" name="settingsDisableASCIIArt" id="settingsDisableASCIIArt">
|
||||
</fieldset>
|
||||
|
||||
<!-- Locale for displaying numbers -->
|
||||
<fieldset>
|
||||
<label for="settingsLocale" class="tooltip">Locale:
|
||||
@@ -590,6 +600,8 @@
|
||||
<p>If the game fails to load, consider <a href="?noScripts">killing all scripts</a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="unclickable" style="display: none">Click on this to upgrade your Source-File -1!</div>
|
||||
<script type="text/javascript" src="dist/vendor.bundle.js"></script><script type="text/javascript" src="dist/engine.bundle.js"></script><script type="text/javascript" src="dist/engineStyle.bundle.js"></script></body>
|
||||
|
||||
<!-- Misc Scripts -->
|
||||
|
||||
70
package-lock.json
generated
70
package-lock.json
generated
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "bitburner",
|
||||
"version": "0.47.3",
|
||||
"version": "0.49.2",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"version": "0.47.3",
|
||||
"version": "0.49.2",
|
||||
"hasInstallScript": true,
|
||||
"license": "SEE LICENSE IN license.txt",
|
||||
"dependencies": {
|
||||
@@ -38,6 +38,7 @@
|
||||
"numeral": "2.0.6",
|
||||
"react": "^16.8.3",
|
||||
"react-dom": "^16.8.3",
|
||||
"react-modal": "^3.12.1",
|
||||
"sprintf-js": "^1.1.1",
|
||||
"tapable": "^1.0.0",
|
||||
"uuid": "^3.2.1",
|
||||
@@ -4571,6 +4572,11 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/exenv": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
|
||||
"integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50="
|
||||
},
|
||||
"node_modules/exit": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
|
||||
@@ -11779,6 +11785,29 @@
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.3.tgz",
|
||||
"integrity": "sha512-Y4rC1ZJmsxxkkPuMLwvKvlL1Zfpbcu+Bf4ZigkHup3v9EfdYhAlWAaVyA19olXq2o2mGn0w+dFKvk3pVVlYcIA=="
|
||||
},
|
||||
"node_modules/react-lifecycles-compat": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"node_modules/react-modal": {
|
||||
"version": "3.12.1",
|
||||
"resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.12.1.tgz",
|
||||
"integrity": "sha512-WGuXn7Fq31PbFJwtWmOk+jFtGC7E9tJVbFX0lts8ZoS5EPi9+WWylUJWLKKVm3H4GlQ7ZxY7R6tLlbSIBQ5oZA==",
|
||||
"dependencies": {
|
||||
"exenv": "^1.2.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"react-lifecycles-compat": "^3.0.0",
|
||||
"warning": "^4.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^0.14.0 || ^15.0.0 || ^16 || ^17",
|
||||
"react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz",
|
||||
@@ -15999,6 +16028,14 @@
|
||||
"xml-name-validator": "3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/warning": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
|
||||
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/watchpack": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
|
||||
@@ -21422,6 +21459,11 @@
|
||||
"clone-regexp": "1.0.1"
|
||||
}
|
||||
},
|
||||
"exenv": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
|
||||
"integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50="
|
||||
},
|
||||
"exit": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
|
||||
@@ -27426,6 +27468,22 @@
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.3.tgz",
|
||||
"integrity": "sha512-Y4rC1ZJmsxxkkPuMLwvKvlL1Zfpbcu+Bf4ZigkHup3v9EfdYhAlWAaVyA19olXq2o2mGn0w+dFKvk3pVVlYcIA=="
|
||||
},
|
||||
"react-lifecycles-compat": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
||||
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
||||
},
|
||||
"react-modal": {
|
||||
"version": "3.12.1",
|
||||
"resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.12.1.tgz",
|
||||
"integrity": "sha512-WGuXn7Fq31PbFJwtWmOk+jFtGC7E9tJVbFX0lts8ZoS5EPi9+WWylUJWLKKVm3H4GlQ7ZxY7R6tLlbSIBQ5oZA==",
|
||||
"requires": {
|
||||
"exenv": "^1.2.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"react-lifecycles-compat": "^3.0.0",
|
||||
"warning": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz",
|
||||
@@ -31040,6 +31098,14 @@
|
||||
"xml-name-validator": "3.0.0"
|
||||
}
|
||||
},
|
||||
"warning": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
|
||||
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"watchpack": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
"numeral": "2.0.6",
|
||||
"react": "^16.8.3",
|
||||
"react-dom": "^16.8.3",
|
||||
"react-modal": "^3.12.1",
|
||||
"sprintf-js": "^1.1.1",
|
||||
"tapable": "^1.0.0",
|
||||
"uuid": "^3.2.1",
|
||||
@@ -120,5 +121,5 @@
|
||||
"watch": "webpack --watch --mode production",
|
||||
"watch:dev": "webpack --watch --mode development"
|
||||
},
|
||||
"version": "0.49.2"
|
||||
"version": "0.51.1"
|
||||
}
|
||||
|
||||
@@ -274,6 +274,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.InfiltrationMoney = 3;
|
||||
BitNodeMultipliers.FactionWorkRepGain = 0.5;
|
||||
BitNodeMultipliers.FactionPassiveRepGain = 0;
|
||||
BitNodeMultipliers.GangKarmaRequirement = 0;
|
||||
break;
|
||||
case 3: // Corporatocracy
|
||||
BitNodeMultipliers.HackingLevelMultiplier = 0.8;
|
||||
@@ -289,6 +290,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.HacknetNodeMoney = 0.25;
|
||||
BitNodeMultipliers.HomeComputerRamCost = 1.5;
|
||||
BitNodeMultipliers.PurchasedServerCost = 2;
|
||||
BitNodeMultipliers.GangKarmaRequirement = 3;
|
||||
break;
|
||||
case 4: // The Singularity
|
||||
BitNodeMultipliers.ServerMaxMoney = 0.15;
|
||||
@@ -331,6 +333,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.FactionPassiveRepGain = 0;
|
||||
BitNodeMultipliers.HackExpGain = 0.25;
|
||||
BitNodeMultipliers.DaedalusAugsRequirement = 1.166; // Results in 35 Augs needed
|
||||
BitNodeMultipliers.GangKarmaRequirement = 5;
|
||||
break;
|
||||
case 7: // Bladeburner 2079
|
||||
BitNodeMultipliers.BladeburnerRank = 0.6;
|
||||
@@ -351,6 +354,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.FourSigmaMarketDataCost = 2;
|
||||
BitNodeMultipliers.FourSigmaMarketDataApiCost = 2;
|
||||
BitNodeMultipliers.DaedalusAugsRequirement = 1.166; // Results in 35 Augs needed
|
||||
BitNodeMultipliers.GangKarmaRequirement = 5;
|
||||
break;
|
||||
case 8: // Ghost of Wall Street
|
||||
BitNodeMultipliers.ScriptHackMoney = 0.3;
|
||||
@@ -363,6 +367,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.RepToDonateToFaction = 0;
|
||||
BitNodeMultipliers.CorporationValuation = 0;
|
||||
BitNodeMultipliers.CodingContractMoney = 0;
|
||||
BitNodeMultipliers.GangKarmaRequirement = 10;
|
||||
break;
|
||||
case 9: // Hacktocracy
|
||||
BitNodeMultipliers.HackingLevelMultiplier = 0.4;
|
||||
@@ -384,6 +389,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.FourSigmaMarketDataApiCost = 4;
|
||||
BitNodeMultipliers.BladeburnerRank = 0.9;
|
||||
BitNodeMultipliers.BladeburnerSkillCost = 1.2;
|
||||
BitNodeMultipliers.GangKarmaRequirement = 3;
|
||||
break;
|
||||
case 10: // Digital Carbon
|
||||
BitNodeMultipliers.HackingLevelMultiplier = 0.2;
|
||||
@@ -407,6 +413,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.PurchasedServerLimit = 0.6;
|
||||
BitNodeMultipliers.PurchasedServerMaxRam = 0.5;
|
||||
BitNodeMultipliers.BladeburnerRank = 0.8;
|
||||
BitNodeMultipliers.GangKarmaRequirement = 3;
|
||||
break;
|
||||
case 11: //The Big Crash
|
||||
BitNodeMultipliers.HackingLevelMultiplier = 0.5;
|
||||
|
||||
@@ -109,6 +109,11 @@ interface IBitNodeMultipliers {
|
||||
*/
|
||||
FourSigmaMarketDataCost: number;
|
||||
|
||||
/**
|
||||
* Influences how much negative karma is required to create a gang in this bitnode.
|
||||
*/
|
||||
GangKarmaRequirement: number;
|
||||
|
||||
/**
|
||||
* Influences the experienced gained when hacking a server.
|
||||
*/
|
||||
@@ -268,4 +273,5 @@ export const BitNodeMultipliers: IBitNodeMultipliers = {
|
||||
BladeburnerSkillCost: 1,
|
||||
|
||||
DaedalusAugsRequirement: 1,
|
||||
GangKarmaRequirement: 1,
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@ import { Factions, factionExists } from "./Faction/Factions";
|
||||
import { joinFaction, displayFactionContent } from "./Faction/FactionHelpers";
|
||||
import { Player } from "./Player";
|
||||
import { hackWorldDaemon, redPillFlag } from "./RedPill";
|
||||
import { calculateHospitalizationCost } from "./Hospital/Hospital";
|
||||
|
||||
import { Page, routing } from "./ui/navigationTracking";
|
||||
import { numeralWrapper } from "./ui/numeralFormat";
|
||||
@@ -50,6 +51,12 @@ import { createPopup } from "../utils/uiHelpers/createPopup";
|
||||
import { removeElement } from "../utils/uiHelpers/removeElement";
|
||||
import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
||||
|
||||
import { StatsTable } from "./ui/React/StatsTable";
|
||||
import { CopyableText } from "./ui/React/CopyableText";
|
||||
import { Money } from "./ui/React/Money";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
|
||||
const stealthIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="0 0 166 132" style="fill:#adff2f;"><g><path d="M132.658-0.18l-24.321,24.321c-7.915-2.71-16.342-4.392-25.087-4.392c-45.84,0-83,46-83,46 s14.1,17.44,35.635,30.844L12.32,120.158l12.021,12.021L144.68,11.841L132.658-0.18z M52.033,80.445 c-2.104-4.458-3.283-9.438-3.283-14.695c0-19.054,15.446-34.5,34.5-34.5c5.258,0,10.237,1.179,14.695,3.284L52.033,80.445z"/><path d="M134.865,37.656l-18.482,18.482c0.884,3.052,1.367,6.275,1.367,9.612c0,19.055-15.446,34.5-34.5,34.5 c-3.337,0-6.56-0.483-9.611-1.367l-10.124,10.124c6.326,1.725,12.934,2.743,19.735,2.743c45.84,0,83-46,83-46 S153.987,50.575,134.865,37.656z"/></g></svg> `
|
||||
const killIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="16px" height="16px" viewBox="-22 0 511 511.99561" style="fill:#adff2f;"><path d="m.496094 466.242188 39.902344-39.902344 45.753906 45.753906-39.898438 39.902344zm0 0"/><path d="m468.421875 89.832031-1.675781-89.832031-300.265625 300.265625 45.753906 45.753906zm0 0"/><path d="m95.210938 316.785156 16.84375 16.847656h.003906l83.65625 83.65625 22.753906-22.753906-100.503906-100.503906zm0 0"/><path d="m101.445312 365.300781-39.902343 39.902344 45.753906 45.753906 39.902344-39.902343-39.90625-39.902344zm0 0"/></svg>`
|
||||
|
||||
@@ -706,7 +713,7 @@ Bladeburner.prototype.completeAction = function() {
|
||||
if (isOperation && this.logging.ops) {
|
||||
this.log(action.name + " successfully completed! Gained " + formatNumber(gain, 3) + " rank");
|
||||
} else if (!isOperation && this.logging.contracts) {
|
||||
this.log(action.name + " contract successfully completed! Gained " + formatNumber(gain, 3) + " rank and " + numeralWrapper.format(moneyGain, "$0.000a"));
|
||||
this.log(action.name + " contract successfully completed! Gained " + formatNumber(gain, 3) + " rank and " + numeralWrapper.formatMoney(moneyGain));
|
||||
}
|
||||
}
|
||||
isOperation ? this.completeOperation(true) : this.completeContract(true);
|
||||
@@ -722,9 +729,10 @@ Bladeburner.prototype.completeAction = function() {
|
||||
damage = action.hpLoss * difficultyMultiplier;
|
||||
damage = Math.ceil(addOffset(damage, 10));
|
||||
this.hpLost += damage;
|
||||
const cost = calculateHospitalizationCost(Player, damage);
|
||||
if (Player.takeDamage(damage)) {
|
||||
++this.numHosp;
|
||||
this.moneyLost += (CONSTANTS.HospitalCostPerHp * Player.max_hp);
|
||||
this.moneyLost += cost;
|
||||
}
|
||||
}
|
||||
var logLossText = "";
|
||||
@@ -794,9 +802,10 @@ Bladeburner.prototype.completeAction = function() {
|
||||
if (action.hpLoss) {
|
||||
damage = action.hpLoss * difficultyMultiplier;
|
||||
damage = Math.ceil(addOffset(damage, 10));
|
||||
const cost = calculateHospitalizationCost(Player, damage);
|
||||
if (Player.takeDamage(damage)) {
|
||||
++this.numHosp;
|
||||
this.moneyLost += (CONSTANTS.HospitalCostPerHp * Player.max_hp);
|
||||
this.moneyLost += cost;
|
||||
}
|
||||
}
|
||||
teamLossMax = Math.floor(teamCount);
|
||||
@@ -899,7 +908,7 @@ Bladeburner.prototype.completeAction = function() {
|
||||
this.stamina = Math.min(this.maxStamina, this.stamina + staminaGain);
|
||||
this.startAction(this.action);
|
||||
if (this.logging.general) {
|
||||
this.log(`Rested in Hyperbolic Regeneration Chamber. Restored ${BladeburnerConstants.HrcHpGain} HP and gained ${numeralWrapper.format(staminaGain, "0.0")} stamina`);
|
||||
this.log(`Rested in Hyperbolic Regeneration Chamber. Restored ${BladeburnerConstants.HrcHpGain} HP and gained ${numeralWrapper.formatStamina(staminaGain)} stamina`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1211,10 +1220,7 @@ Bladeburner.prototype.initializeDomElementRefs = function() {
|
||||
overviewChaos: null,
|
||||
overviewSkillPoints: null,
|
||||
overviewBonusTime: null,
|
||||
overviewAugSuccessMult: null,
|
||||
overviewAugMaxStaminaMult: null,
|
||||
overviewAugStaminaGainMult: null,
|
||||
overviewAugAnalysisMult: null,
|
||||
overviewAugMults: null,
|
||||
|
||||
// Actions and Skills Content
|
||||
actionsAndSkillsDesc: null,
|
||||
@@ -1256,7 +1262,7 @@ Bladeburner.prototype.createContent = function() {
|
||||
// Console
|
||||
DomElems.consoleDiv = createElement("div", {
|
||||
class:"bladeburner-console-div",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
if (DomElems.consoleInput instanceof Element) {
|
||||
DomElems.consoleInput.focus();
|
||||
}
|
||||
@@ -1264,12 +1270,12 @@ Bladeburner.prototype.createContent = function() {
|
||||
}
|
||||
});
|
||||
DomElems.consoleTable = createElement("table", {class:"bladeburner-console-table"});
|
||||
DomElems.consoleInputRow = createElement("tr", {class:"bladeburner-console-input-row", id:"bladeubrner-console-input-row"});
|
||||
DomElems.consoleInputRow = createElement("tr", {class:"bladeburner-console-input-row", id:"bladeburner-console-input-row"});
|
||||
DomElems.consoleInputCell = createElement("td", {class:"bladeburner-console-input-cell"});
|
||||
DomElems.consoleInputHeader = createElement("pre", {innerText:"> "});
|
||||
DomElems.consoleInput = createElement("input", {
|
||||
type:"text", class:"bladeburner-console-input", tabIndex:1,
|
||||
onfocus:()=>{DomElems.consoleInput.value = DomElems.consoleInput.value}
|
||||
onfocus:() => {DomElems.consoleInput.value = DomElems.consoleInput.value}
|
||||
});
|
||||
|
||||
DomElems.consoleInputCell.appendChild(DomElems.consoleInputHeader);
|
||||
@@ -1330,7 +1336,7 @@ Bladeburner.prototype.createOverviewContent = function() {
|
||||
DomElems.overviewStaminaHelpTip = createElement("div", {
|
||||
class:"help-tip",
|
||||
innerText:"?",
|
||||
clickListener: ()=> {
|
||||
clickListener: () => {
|
||||
dialogBoxCreate("Performing actions will use up your stamina.<br><br>" +
|
||||
"Your max stamina is determined primarily by your agility stat.<br><br>" +
|
||||
"Your stamina gain rate is determined by both your agility and your " +
|
||||
@@ -1358,7 +1364,7 @@ Bladeburner.prototype.createOverviewContent = function() {
|
||||
|
||||
DomElems.overviewEstPopHelpTip = createElement("div", {
|
||||
innerText:"?", class:"help-tip",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
dialogBoxCreate("The success rate of your contracts/operations depends on " +
|
||||
"the population of Synthoids in your current city. " +
|
||||
"The success rate that is shown to you is only an estimate, " +
|
||||
@@ -1397,10 +1403,7 @@ Bladeburner.prototype.createOverviewContent = function() {
|
||||
DomElems.overviewSkillPoints = createElement("p", {display:"block"});
|
||||
|
||||
|
||||
DomElems.overviewAugSuccessMult = createElement("p", {display:"block"});
|
||||
DomElems.overviewAugMaxStaminaMult = createElement("p", {display:"block"});
|
||||
DomElems.overviewAugStaminaGainMult = createElement("p", {display:"block"});
|
||||
DomElems.overviewAugAnalysisMult = createElement("p", {display:"block"});
|
||||
DomElems.overviewAugMults = createElement("div", {display:"block"});
|
||||
|
||||
|
||||
DomElems.overviewDiv.appendChild(DomElems.overviewRank);
|
||||
@@ -1418,21 +1421,18 @@ Bladeburner.prototype.createOverviewContent = function() {
|
||||
DomElems.overviewDiv.appendChild(DomElems.overviewBonusTime);
|
||||
DomElems.overviewDiv.appendChild(DomElems.overviewSkillPoints);
|
||||
appendLineBreaks(DomElems.overviewDiv, 1);
|
||||
DomElems.overviewDiv.appendChild(DomElems.overviewAugSuccessMult);
|
||||
DomElems.overviewDiv.appendChild(DomElems.overviewAugMaxStaminaMult);
|
||||
DomElems.overviewDiv.appendChild(DomElems.overviewAugStaminaGainMult);
|
||||
DomElems.overviewDiv.appendChild(DomElems.overviewAugAnalysisMult);
|
||||
DomElems.overviewDiv.appendChild(DomElems.overviewAugMults);
|
||||
|
||||
// Travel to new city button
|
||||
appendLineBreaks(DomElems.overviewDiv, 1);
|
||||
DomElems.overviewDiv.appendChild(createElement("a", {
|
||||
innerHTML:"Travel", class:"a-link-button", display:"inline-block",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
var popupId = "bladeburner-travel-popup-cancel-btn";
|
||||
var popupArguments = [];
|
||||
popupArguments.push(createElement("a", { // Cancel Button
|
||||
innerText:"Cancel", class:"a-link-button",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
removeElementById(popupId); return false;
|
||||
}
|
||||
}))
|
||||
@@ -1451,7 +1451,7 @@ Bladeburner.prototype.createOverviewContent = function() {
|
||||
*/
|
||||
class:"cmpy-mgmt-find-employee-option",
|
||||
innerText:BladeburnerConstants.CityNames[i],
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
inst.city = BladeburnerConstants.CityNames[i];
|
||||
removeElementById(popupId);
|
||||
inst.updateOverviewContent();
|
||||
@@ -1474,7 +1474,7 @@ Bladeburner.prototype.createOverviewContent = function() {
|
||||
DomElems.overviewDiv.appendChild(createElement("a", {
|
||||
innerText:"Faction", class:"a-link-button", display:"inline-block",
|
||||
tooltip:"Apply to the Bladeburner Faction, or go to the faction page if you are already a member",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
if (bladeburnerFac.isMember) {
|
||||
Engine.loadFactionContent();
|
||||
displayFactionContent(bladeburnersFactionName);
|
||||
@@ -1518,7 +1518,7 @@ Bladeburner.prototype.createActionAndSkillsContent = function() {
|
||||
DomElems.actionAndSkillsDiv.appendChild(createElement("a", {
|
||||
innerText:buttons[i],
|
||||
class:currTab === buttons[i].toLowerCase() ? "bladeburner-nav-button-inactive" : "bladeburner-nav-button",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
DomElems.currentTab = buttons[i].toLowerCase();
|
||||
inst.createActionAndSkillsContent();
|
||||
return false;
|
||||
@@ -1770,23 +1770,26 @@ Bladeburner.prototype.updateOverviewContent = function() {
|
||||
if (!routing.isOn(Page.Bladeburner)) {return;}
|
||||
DomElems.overviewRank.childNodes[0].nodeValue = "Rank: " + formatNumber(this.rank, 2);
|
||||
DomElems.overviewStamina.innerText = "Stamina: " + formatNumber(this.stamina, 3) + " / " + formatNumber(this.maxStamina, 3);
|
||||
DomElems.overviewGen1.innerHTML =
|
||||
"Stamina Penalty: " + formatNumber((1-this.calculateStaminaPenalty())*100, 1) + "%<br><br>" +
|
||||
"Team Size: " + formatNumber(this.teamSize, 0) + "<br>" +
|
||||
"Team Members Lost: " + formatNumber(this.teamLost, 0) + "<br><br>" +
|
||||
"Num Times Hospitalized: " + this.numHosp + "<br>" +
|
||||
"Money Lost From Hospitalizations: " + numeralWrapper.format(this.moneyLost, "$0.000a") + "<br><br>" +
|
||||
"Current City: " + this.city + "<br>";
|
||||
ReactDOM.render(<>
|
||||
Stamina Penalty: {formatNumber((1-this.calculateStaminaPenalty())*100, 1)}%<br /><br />
|
||||
Team Size: {formatNumber(this.teamSize, 0)}<br />
|
||||
Team Members Lost: {formatNumber(this.teamLost, 0)}<br /><br />
|
||||
Num Times Hospitalized: {this.numHosp}<br />
|
||||
Money Lost From Hospitalizations: {Money(this.moneyLost)}<br /><br />
|
||||
Current City: {this.city}<br />
|
||||
</>, DomElems.overviewGen1);
|
||||
|
||||
DomElems.overviewEstPop.childNodes[0].nodeValue = "Est. Synthoid Population: " + numeralWrapper.format(this.getCurrentCity().popEst, "0.000a");
|
||||
DomElems.overviewEstPop.childNodes[0].nodeValue = "Est. Synthoid Population: " + numeralWrapper.formatPopulation(this.getCurrentCity().popEst);
|
||||
DomElems.overviewEstComms.childNodes[0].nodeValue = "Est. Synthoid Communities: " + formatNumber(this.getCurrentCity().comms, 0);
|
||||
DomElems.overviewChaos.childNodes[0].nodeValue = "City Chaos: " + formatNumber(this.getCurrentCity().chaos);
|
||||
DomElems.overviewSkillPoints.innerText = "Skill Points: " + formatNumber(this.skillPoints, 0);
|
||||
DomElems.overviewBonusTime.childNodes[0].nodeValue = "Bonus time: " + convertTimeMsToTimeElapsedString(this.storedCycles/BladeburnerConstants.CyclesPerSecond*1000);
|
||||
DomElems.overviewAugSuccessMult.innerText = "Aug. Success Chance Mult: " + formatNumber(Player.bladeburner_success_chance_mult*100, 1) + "%";
|
||||
DomElems.overviewAugMaxStaminaMult.innerText = "Aug. Max Stamina Mult: " + formatNumber(Player.bladeburner_max_stamina_mult*100, 1) + "%";
|
||||
DomElems.overviewAugStaminaGainMult.innerText = "Aug. Stamina Gain Mult: " + formatNumber(Player.bladeburner_stamina_gain_mult*100, 1) + "%";
|
||||
DomElems.overviewAugAnalysisMult.innerText = "Aug. Field Analysis Mult: " + formatNumber(Player.bladeburner_analysis_mult*100, 1) + "%";
|
||||
ReactDOM.render(StatsTable([
|
||||
["Aug. Success Chance mult: ", formatNumber(Player.bladeburner_success_chance_mult*100, 1) + "%"],
|
||||
["Aug. Max Stamina mult: ", formatNumber(Player.bladeburner_max_stamina_mult*100, 1) + "%"],
|
||||
["Aug. Stamina Gain mult: ", formatNumber(Player.bladeburner_stamina_gain_mult*100, 1) + "%"],
|
||||
["Aug. Field Analysis mult: ", formatNumber(Player.bladeburner_analysis_mult*100, 1) + "%"],
|
||||
]), DomElems.overviewAugMults);
|
||||
}
|
||||
|
||||
Bladeburner.prototype.updateActionAndSkillsContent = function() {
|
||||
@@ -1902,7 +1905,7 @@ Bladeburner.prototype.updateGeneralActionsUIElement = function(el, action) {
|
||||
el.appendChild(createElement("a", {
|
||||
innerText:"Start", class: "a-link-button",
|
||||
margin:"3px", padding:"3px",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
this.action.type = ActionTypes[action.name];
|
||||
this.action.name = action.name;
|
||||
this.startAction(this.action);
|
||||
@@ -1943,7 +1946,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
|
||||
el.appendChild(createElement("a", {
|
||||
innerText:"Start", class: "a-link-button",
|
||||
padding:"3px", margin:"3px",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
this.action.type = ActionTypes.Contract;
|
||||
this.action.name = action.name;
|
||||
this.startAction(this.action);
|
||||
@@ -1967,7 +1970,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
|
||||
padding:"2px", margin:"2px",
|
||||
tooltip: isActive ? "WARNING: changing the level will restart the contract" : "",
|
||||
display:"inline",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
++action.level;
|
||||
if (isActive) {this.startAction(this.action);} // Restart Action
|
||||
this.updateContractsUIElement(el, action);
|
||||
@@ -1979,7 +1982,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
|
||||
padding:"2px", margin:"2px",
|
||||
tooltip: isActive ? "WARNING: changing the level will restart the contract" : "",
|
||||
display:"inline",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
--action.level;
|
||||
if (isActive) {this.startAction(this.action);} // Restart Action
|
||||
this.updateContractsUIElement(el, action);
|
||||
@@ -1993,8 +1996,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
|
||||
display:"inline-block",
|
||||
innerHTML:action.desc + "\n\n" +
|
||||
`Estimated success chance: ${formatNumber(estimatedSuccessChance*100, 1)}% ${action.isStealth?stealthIcon:''}${action.isKill?killIcon:''}\n` +
|
||||
|
||||
"Time Required (s): " + formatNumber(actionTime, 0) + "\n" +
|
||||
"Time Required: " + convertTimeMsToTimeElapsedString(actionTime*1000) + "\n" +
|
||||
"Contracts remaining: " + Math.floor(action.count) + "\n" +
|
||||
"Successes: " + action.successes + "\n" +
|
||||
"Failures: " + action.failures,
|
||||
@@ -2042,7 +2044,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
|
||||
el.appendChild(createElement("a", {
|
||||
innerText:"Start", class: "a-link-button",
|
||||
margin:"3px", padding:"3px",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
this.action.type = ActionTypes.Operation;
|
||||
this.action.name = action.name;
|
||||
this.startAction(this.action);
|
||||
@@ -2053,7 +2055,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
|
||||
el.appendChild(createElement("a", {
|
||||
innerText:"Set Team Size (Curr Size: " + formatNumber(action.teamCount, 0) + ")", class:"a-link-button",
|
||||
margin:"3px", padding:"3px",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
var popupId = "bladeburner-operation-set-team-size-popup";
|
||||
var txt = createElement("p", {
|
||||
innerText:"Enter the amount of team members you would like to take on these " +
|
||||
@@ -2067,7 +2069,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
|
||||
});
|
||||
var setBtn = createElement("a", {
|
||||
innerText:"Confirm", class:"a-link-button",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
var num = Math.round(parseFloat(input.value));
|
||||
if (isNaN(num)) {
|
||||
dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric)")
|
||||
@@ -2081,7 +2083,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
|
||||
});
|
||||
var cancelBtn = createElement("a", {
|
||||
innerText:"Cancel", class:"a-link-button",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
removeElementById(popupId);
|
||||
return false;
|
||||
}
|
||||
@@ -2105,7 +2107,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
|
||||
padding:"2px", margin:"2px",
|
||||
tooltip: isActive ? "WARNING: changing the level will restart the Operation" : "",
|
||||
display:"inline",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
++action.level;
|
||||
if (isActive) {this.startAction(this.action);} // Restart Action
|
||||
this.updateOperationsUIElement(el, action);
|
||||
@@ -2117,7 +2119,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
|
||||
padding:"2px", margin:"2px",
|
||||
tooltip: isActive ? "WARNING: changing the level will restart the Operation" : "",
|
||||
display:"inline",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
--action.level;
|
||||
if (isActive) {this.startAction(this.action);} // Restart Action
|
||||
this.updateOperationsUIElement(el, action);
|
||||
@@ -2133,7 +2135,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
|
||||
display:"inline-block",
|
||||
innerHTML:action.desc + "\n\n" +
|
||||
`Estimated success chance: ${formatNumber(estimatedSuccessChance*100, 1)}% ${action.isStealth?stealthIcon:''}${action.isKill?killIcon:''}\n` +
|
||||
"Time Required(s): " + formatNumber(actionTime, 0) + "\n" +
|
||||
"Time Required: " + convertTimeMsToTimeElapsedString(actionTime*1000) + "\n" +
|
||||
"Operations remaining: " + Math.floor(action.count) + "\n" +
|
||||
"Successes: " + action.successes + "\n" +
|
||||
"Failures: " + action.failures,
|
||||
@@ -2194,7 +2196,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
|
||||
el.appendChild(createElement("a", { // Start button
|
||||
innerText:"Start", margin:"3px", padding:"3px",
|
||||
class:hasReqdRank ? "a-link-button" : "a-link-button-inactive",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
this.action.type = ActionTypes.BlackOperation;
|
||||
this.action.name = action.name;
|
||||
this.startAction(this.action);
|
||||
@@ -2205,7 +2207,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
|
||||
el.appendChild(createElement("a", { // Set Team Size Button
|
||||
innerText:"Set Team Size (Curr Size: " + formatNumber(action.teamCount, 0) + ")", class:"a-link-button",
|
||||
margin:"3px", padding:"3px",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
var popupId = "bladeburner-operation-set-team-size-popup";
|
||||
var txt = createElement("p", {
|
||||
innerText:"Enter the amount of team members you would like to take on this " +
|
||||
@@ -2219,7 +2221,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
|
||||
});
|
||||
var setBtn = createElement("a", {
|
||||
innerText:"Confirm", class:"a-link-button",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
var num = Math.round(parseFloat(input.value));
|
||||
if (isNaN(num)) {
|
||||
dialogBoxCreate("Invalid value entered for number of Team Members (must be numeric)")
|
||||
@@ -2233,7 +2235,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
|
||||
});
|
||||
var cancelBtn = createElement("a", {
|
||||
innerText:"Cancel", class:"a-link-button",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
removeElementById(popupId);
|
||||
return false;
|
||||
}
|
||||
@@ -2256,7 +2258,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
|
||||
el.appendChild(createElement("p", {
|
||||
display:"inline-block",
|
||||
innerHTML:`Estimated Success Chance: ${formatNumber(estimatedSuccessChance*100, 1)}% ${action.isStealth?stealthIcon:''}${action.isKill?killIcon:''}\n` +
|
||||
"Time Required(s): " + formatNumber(actionTime, 0),
|
||||
"Time Required: " + convertTimeMsToTimeElapsedString(actionTime*1000),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -2269,9 +2271,15 @@ Bladeburner.prototype.updateSkillsUIElement = function(el, skill) {
|
||||
}
|
||||
var pointCost = skill.calculateCost(currentLevel);
|
||||
|
||||
el.appendChild(createElement("h2", { // Header
|
||||
innerText:skill.name + " (Lvl " + currentLevel + ")", display:"inline-block"
|
||||
}));
|
||||
const nameDiv = createElement("div");
|
||||
ReactDOM.render(React.createElement(CopyableText, {value: skill.name}, null), nameDiv);
|
||||
el.appendChild(nameDiv)
|
||||
|
||||
const h2 = createElement("h2", { // Header
|
||||
display:"inline-block",
|
||||
});
|
||||
h2.appendChild(nameDiv);
|
||||
el.appendChild(h2);
|
||||
|
||||
var canLevel = this.skillPoints >= pointCost;
|
||||
var maxLvl = skill.maxLvl ? currentLevel >= skill.maxLvl : false;
|
||||
@@ -2279,7 +2287,7 @@ Bladeburner.prototype.updateSkillsUIElement = function(el, skill) {
|
||||
innerText:"Level", display:"inline-block",
|
||||
class: canLevel && !maxLvl ? "a-link-button" : "a-link-button-inactive",
|
||||
margin:"3px", padding:"3px",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
if (this.skillPoints < pointCost) {return;}
|
||||
this.skillPoints -= pointCost;
|
||||
this.upgradeSkill(skill);
|
||||
@@ -2288,6 +2296,10 @@ Bladeburner.prototype.updateSkillsUIElement = function(el, skill) {
|
||||
}
|
||||
}));
|
||||
appendLineBreaks(el, 2);
|
||||
el.appendChild(createElement("p", {
|
||||
display:"block",
|
||||
innerText:`Level: ${currentLevel}`,
|
||||
}));
|
||||
if (maxLvl) {
|
||||
el.appendChild(createElement("p", {
|
||||
color:"red", display:"block",
|
||||
@@ -2315,7 +2327,7 @@ Bladeburner.prototype.postToConsole = function(input, saveToLogs=true) {
|
||||
}
|
||||
|
||||
if (input == null || DomElems.consoleDiv == null) {return;}
|
||||
$("#bladeubrner-console-input-row").before('<tr><td class="bladeburner-console-line" style="color: var(--my-font-color); white-space:pre-wrap;">' + input + '</td></tr>');
|
||||
$("#bladeburner-console-input-row").before('<tr><td class="bladeburner-console-line" style="color: var(--my-font-color); white-space:pre-wrap;">' + input + '</td></tr>');
|
||||
|
||||
if (DomElems.consoleTable.childNodes.length > MaxConsoleEntries) {
|
||||
DomElems.consoleTable.removeChild(DomElems.consoleTable.firstChild);
|
||||
@@ -214,6 +214,7 @@ export class Action {
|
||||
competence += (this.weights[stat] * Math.pow(effMultiplier*playerStatLvl, this.decays[stat]));
|
||||
}
|
||||
}
|
||||
competence *= Player.getIntelligenceBonus(0.75);
|
||||
competence *= inst.calculateStaminaPenalty();
|
||||
|
||||
competence *= this.getTeamSuccessBonus(inst);
|
||||
|
||||
@@ -60,7 +60,7 @@ export const BladeburnerConstants: {
|
||||
ChaosThreshold: 50, // City chaos level after which it starts making tasks harder
|
||||
|
||||
BaseStatGain: 1, // Base stat gain per second
|
||||
BaseIntGain: 0.001, // Base intelligence stat gain
|
||||
BaseIntGain: 0.003, // Base intelligence stat gain
|
||||
|
||||
ActionCountGrowthPeriod: 480, // Time (s) it takes for action count to grow by its specified value
|
||||
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
import {
|
||||
CodingContract,
|
||||
CodingContractRewardType,
|
||||
CodingContractTypes
|
||||
CodingContractTypes,
|
||||
ICodingContractReward
|
||||
} from "./CodingContracts";
|
||||
import { Factions } from "./Faction/Factions";
|
||||
import { Player } from "./Player";
|
||||
import { AllServers } from "./Server/AllServers";
|
||||
import { GetServerByHostname } from "./Server/ServerHelpers";
|
||||
import { SpecialServerNames } from "./Server/SpecialServerIps";
|
||||
import { Server } from "./Server/Server";
|
||||
import { HacknetServer } from "./Hacknet/HacknetServer";
|
||||
|
||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||
|
||||
|
||||
export function generateRandomContract() {
|
||||
// First select a random problem type
|
||||
let problemType = getRandomProblemType();
|
||||
const problemType = getRandomProblemType();
|
||||
|
||||
// Then select a random reward type. 'Money' will always be the last reward type
|
||||
const reward = getRandomReward();
|
||||
@@ -22,15 +25,15 @@ export function generateRandomContract() {
|
||||
// Choose random server
|
||||
const randServer = getRandomServer();
|
||||
|
||||
let contractFn = getRandomFilename(randServer, reward);
|
||||
let contract = new CodingContract(contractFn, problemType, reward);
|
||||
const contractFn = getRandomFilename(randServer, reward);
|
||||
const contract = new CodingContract(contractFn, problemType, reward);
|
||||
|
||||
randServer.addContract(contract);
|
||||
}
|
||||
|
||||
export function generateRandomContractOnHome() {
|
||||
// First select a random problem type
|
||||
let problemType = getRandomProblemType();
|
||||
const problemType = getRandomProblemType();
|
||||
|
||||
// Then select a random reward type. 'Money' will always be the last reward type
|
||||
const reward = getRandomReward();
|
||||
@@ -38,13 +41,19 @@ export function generateRandomContractOnHome() {
|
||||
// Choose random server
|
||||
const serv = Player.getHomeComputer();
|
||||
|
||||
let contractFn = getRandomFilename(serv, reward);
|
||||
let contract = new CodingContract(contractFn, problemType, reward);
|
||||
const contractFn = getRandomFilename(serv, reward);
|
||||
const contract = new CodingContract(contractFn, problemType, reward);
|
||||
|
||||
serv.addContract(contract);
|
||||
}
|
||||
|
||||
export function generateContract(params) {
|
||||
export interface IGenerateContractParams {
|
||||
problemType?: string;
|
||||
server?: string;
|
||||
fn?: string;
|
||||
}
|
||||
|
||||
export function generateContract(params: IGenerateContractParams) {
|
||||
// Problem Type
|
||||
let problemType;
|
||||
const problemTypes = Object.keys(CodingContractTypes);
|
||||
@@ -62,7 +71,7 @@ export function generateContract(params) {
|
||||
if (params.server != null) {
|
||||
server = GetServerByHostname(params.server);
|
||||
if (server == null) {
|
||||
server = AllServers[param.server];
|
||||
server = AllServers[params.server];
|
||||
}
|
||||
if (server == null) {
|
||||
server = getRandomServer();
|
||||
@@ -84,7 +93,7 @@ export function generateContract(params) {
|
||||
}
|
||||
|
||||
// Ensures that a contract's reward type is valid
|
||||
function sanitizeRewardType(rewardType) {
|
||||
function sanitizeRewardType(rewardType: CodingContractRewardType): CodingContractRewardType {
|
||||
let type = rewardType; // Create copy
|
||||
|
||||
const factionsThatAllowHacking = Player.factions.filter((fac) => {
|
||||
@@ -115,9 +124,11 @@ function getRandomProblemType() {
|
||||
return problemTypes[randIndex];
|
||||
}
|
||||
|
||||
function getRandomReward() {
|
||||
let reward = {};
|
||||
reward.type = getRandomInt(0, CodingContractRewardType.Money);
|
||||
function getRandomReward(): ICodingContractReward {
|
||||
let reward: ICodingContractReward = {
|
||||
name: "",
|
||||
type: getRandomInt(0, CodingContractRewardType.Money),
|
||||
};
|
||||
reward.type = sanitizeRewardType(reward.type);
|
||||
|
||||
// Add additional information based on the reward type
|
||||
@@ -155,7 +166,7 @@ function getRandomReward() {
|
||||
return reward;
|
||||
}
|
||||
|
||||
function getRandomServer() {
|
||||
function getRandomServer(): Server | HacknetServer {
|
||||
const servers = Object.keys(AllServers);
|
||||
let randIndex = getRandomInt(0, servers.length - 1);
|
||||
let randServer = AllServers[servers[randIndex]];
|
||||
@@ -163,7 +174,7 @@ function getRandomServer() {
|
||||
// An infinite loop shouldn't ever happen, but to be safe we'll use
|
||||
// a for loop with a limited number of tries
|
||||
for (let i = 0; i < 200; ++i) {
|
||||
if (!randServer.purchasedByPlayer && randServer.hostname !== SpecialServerNames.WorldDaemon) {
|
||||
if (randServer instanceof Server && !randServer.purchasedByPlayer && randServer.hostname !== SpecialServerNames.WorldDaemon) {
|
||||
break;
|
||||
}
|
||||
randIndex = getRandomInt(0, servers.length - 1);
|
||||
@@ -173,11 +184,11 @@ function getRandomServer() {
|
||||
return randServer;
|
||||
}
|
||||
|
||||
function getRandomFilename(server, reward) {
|
||||
function getRandomFilename(server: Server | HacknetServer, reward: ICodingContractReward): string {
|
||||
let contractFn = `contract-${getRandomInt(0, 1e6)}`;
|
||||
|
||||
for (let i = 0; i < 1000; ++i) {
|
||||
if (server.contracts.filter((c) => {return c.fn === contractFn}).length <= 0) { break; }
|
||||
if (server.contracts.filter((c: CodingContract) => {return c.fn === contractFn}).length <= 0) { break; }
|
||||
contractFn = `contract-${getRandomInt(0, 1e6)}`;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { IMap } from "./types";
|
||||
|
||||
export let CONSTANTS: IMap<any> = {
|
||||
Version: "0.49.0",
|
||||
Version: "0.51.1",
|
||||
|
||||
/** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
|
||||
* and the skill level formula in Player.js. Note that all this means it that when experience hits MAX_INT, then
|
||||
@@ -75,14 +75,14 @@ export let CONSTANTS: IMap<any> = {
|
||||
HospitalCostPerHp: 100e3,
|
||||
|
||||
// Intelligence-related constants
|
||||
IntelligenceCrimeWeight: 0.05, // Weight for how much int affects crime success rates
|
||||
IntelligenceCrimeWeight: 0.025, // Weight for how much int affects crime success rates
|
||||
IntelligenceInfiltrationWeight: 0.1, // Weight for how much int affects infiltration success rates
|
||||
IntelligenceCrimeBaseExpGain: 0.001,
|
||||
IntelligenceProgramBaseExpGain: 500, // Program required hack level divided by this to determine int exp gain
|
||||
IntelligenceCrimeBaseExpGain: 0.05,
|
||||
IntelligenceProgramBaseExpGain: 2.5, // Program required hack level divided by this to determine int exp gain
|
||||
IntelligenceTerminalHackBaseExpGain: 200, // Hacking exp divided by this to determine int exp gain
|
||||
IntelligenceSingFnBaseExpGain: 0.002,
|
||||
IntelligenceClassBaseExpGain: 0.000001,
|
||||
IntelligenceHackingMissionBaseExpGain: 0.03, // Hacking Mission difficulty multiplied by this to get exp gain
|
||||
IntelligenceSingFnBaseExpGain: 1.5,
|
||||
IntelligenceClassBaseExpGain: 0.01,
|
||||
IntelligenceHackingMissionBaseExpGain: 3, // Hacking Mission difficulty multiplied by this to get exp gain
|
||||
|
||||
// Hacking Missions
|
||||
// TODO Move this into Hacking Mission implementation
|
||||
@@ -228,34 +228,30 @@ export let CONSTANTS: IMap<any> = {
|
||||
|
||||
LatestUpdate:
|
||||
`
|
||||
v0.49.2 - 2021-03-13
|
||||
v0.51.1 - 2021-04-06 Bugfixes because the author of the last patch sucks (it's hydroflame)
|
||||
-------
|
||||
|
||||
BN8
|
||||
* A new bitnode multipler has been added, it lets you reduce money from a
|
||||
server without gaining actually any money. This is important for BN8 where
|
||||
hack/grow can influence the stock market. No money can be gained from
|
||||
hacking but server money can still be reduced.
|
||||
|
||||
Documentation
|
||||
* readthedocs should now be more consistent and many examples were added.
|
||||
|
||||
Netscript
|
||||
* Ace editor will now correctly highlight all functions.
|
||||
* 'tFormat' is a new netscript function that returns a human readable
|
||||
representation of milliseconds. eg. "2 hours 15 minute 43 seconds"
|
||||
* 'getPlayer' returns players faction and tor
|
||||
* 'hospitalization' is a new singularity function.
|
||||
* 'gang.getMemberInformation' now returns more information.
|
||||
* 'hacknet.hashCapacity' is a new hacknet function that returns the maximum hash capacity.
|
||||
|
||||
Gang
|
||||
* style improvements
|
||||
Hospitalization
|
||||
* Now only cost at most 10% of your money.
|
||||
|
||||
Bladeburner
|
||||
* style improvements
|
||||
* fix bug where 'skill list SKILL' would crash if skill is level 0.
|
||||
Bugfix
|
||||
* confirmation dialog box no longer use previous text
|
||||
|
||||
Sleeve
|
||||
* karma gain now scales with sync.
|
||||
Accessibility
|
||||
* The game is a little easier to handle for screen readers (yes, there's an
|
||||
absolute legend playing this game with a screen reader)
|
||||
* Infiltration use buttons instead of a-links
|
||||
* New option to disable ASCII art. This will make the metro map and world
|
||||
map display as a list of buttons.
|
||||
|
||||
Misc.
|
||||
Fix issue where the effective stats under Character>Stats were being calculated.
|
||||
* 'fl1ght.exe' will no longer suggest the combat path. Related faction
|
||||
requirements unchanged.
|
||||
`
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@ import { Warehouse } from "./Warehouse";
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { Factions } from "../Faction/Factions";
|
||||
import { showLiterature } from "../Literature";
|
||||
import { showLiterature } from "../Literature/LiteratureHelpers";
|
||||
import { LiteratureNames } from "../Literature/data/LiteratureNames";
|
||||
import { createCityMap } from "../Locations/Cities";
|
||||
import { CityName } from "../Locations/data/CityNames";
|
||||
import { Player } from "../Player";
|
||||
@@ -1795,7 +1796,7 @@ OfficeSpace.prototype.findEmployees = function(parentRefs) {
|
||||
"Creativity: " + formatNumber(employee.cre, 1) + "<br>" +
|
||||
"Efficiency: " + formatNumber(employee.eff, 1) + "<br>" +
|
||||
"Salary: " + numeralWrapper.format(employee.sal, '$0.000a') + " \ s<br>",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
office.hireEmployee(employee, parentRefs);
|
||||
removeElementById("cmpy-mgmt-hire-employee-popup");
|
||||
return false;
|
||||
@@ -1808,7 +1809,7 @@ OfficeSpace.prototype.findEmployees = function(parentRefs) {
|
||||
class:"a-link-button",
|
||||
innerText:"Cancel",
|
||||
float:"right",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
removeElementById("cmpy-mgmt-hire-employee-popup");
|
||||
return false;
|
||||
}
|
||||
@@ -1842,7 +1843,7 @@ OfficeSpace.prototype.hireEmployee = function(employee, parentRefs) {
|
||||
company.rerender();
|
||||
return yesNoTxtInpBoxClose();
|
||||
});
|
||||
noBtn.addEventListener("click", ()=>{
|
||||
noBtn.addEventListener("click", () => {
|
||||
return yesNoTxtInpBoxClose();
|
||||
});
|
||||
yesNoTxtInpBoxCreate("Give your employee a nickname!");
|
||||
@@ -2075,14 +2076,14 @@ Corporation.prototype.getInvestment = function() {
|
||||
noBtn = yesNoBoxGetNoButton();
|
||||
yesBtn.innerHTML = "Accept";
|
||||
noBtn.innerHML = "Reject";
|
||||
yesBtn.addEventListener("click", ()=>{
|
||||
yesBtn.addEventListener("click", () => {
|
||||
++this.fundingRound;
|
||||
this.funds = this.funds.plus(funding);
|
||||
this.numShares -= investShares;
|
||||
this.rerender();
|
||||
return yesNoBoxClose();
|
||||
});
|
||||
noBtn.addEventListener("click", ()=>{
|
||||
noBtn.addEventListener("click", () => {
|
||||
return yesNoBoxClose();
|
||||
});
|
||||
yesNoBoxCreate("An investment firm has offered you " + numeralWrapper.format(funding, '$0.000a') +
|
||||
@@ -2107,7 +2108,7 @@ Corporation.prototype.goPublic = function() {
|
||||
var input = createElement("input", {
|
||||
type:"number",
|
||||
placeholder: "Shares to issue",
|
||||
onkeyup:(e)=>{
|
||||
onkeyup:(e) => {
|
||||
e.preventDefault();
|
||||
if (e.keyCode === KEY.ENTER) {yesBtn.click();}
|
||||
}
|
||||
@@ -2116,7 +2117,7 @@ Corporation.prototype.goPublic = function() {
|
||||
yesBtn = createElement("a", {
|
||||
class:"a-link-button",
|
||||
innerText:"Go Public",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
var numShares = Math.round(input.value);
|
||||
var initialSharePrice = this.determineValuation() / (this.totalShares);
|
||||
if (isNaN(numShares)) {
|
||||
@@ -2142,7 +2143,7 @@ Corporation.prototype.goPublic = function() {
|
||||
var noBtn = createElement("a", {
|
||||
class:"a-link-button",
|
||||
innerText:"Cancel",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
removeElementById(goPublicPopupId);
|
||||
return false;
|
||||
}
|
||||
@@ -2330,7 +2331,7 @@ Corporation.prototype.getStarterGuide = function() {
|
||||
// Check if player already has Corporation Handbook
|
||||
let homeComp = Player.getHomeComputer(),
|
||||
hasHandbook = false,
|
||||
handbookFn = "corporation-management-handbook.lit";
|
||||
handbookFn = LiteratureNames.CorporationManagementHandbook;
|
||||
for (let i = 0; i < homeComp.messages.length; ++i) {
|
||||
if (isString(homeComp.messages[i]) && homeComp.messages[i] === handbookFn) {
|
||||
hasHandbook = true;
|
||||
|
||||
@@ -120,6 +120,7 @@ export class Crime {
|
||||
chance /= CONSTANTS.MaxSkillLevel;
|
||||
chance /= this.difficulty;
|
||||
chance *= p.crime_success_mult;
|
||||
chance *= p.getIntelligenceBonus(1);
|
||||
|
||||
return Math.min(chance, 1);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ export const Crimes: IMap<Crime> = {
|
||||
dexterity_success_weight: 2,
|
||||
agility_success_weight: 1,
|
||||
|
||||
intelligence_exp: 0.25 * CONSTANTS.IntelligenceCrimeBaseExpGain,
|
||||
intelligence_exp: 7.5 * CONSTANTS.IntelligenceCrimeBaseExpGain,
|
||||
}),
|
||||
|
||||
Mug: new Crime("Mug", CONSTANTS.CrimeMug, 4e3, 36e3, 1/5, 0.25, {
|
||||
@@ -45,7 +45,7 @@ export const Crimes: IMap<Crime> = {
|
||||
dexterity_success_weight: 1,
|
||||
agility_success_weight: 1,
|
||||
|
||||
intelligence_exp: 0.5 * CONSTANTS.IntelligenceCrimeBaseExpGain,
|
||||
intelligence_exp: 15 * CONSTANTS.IntelligenceCrimeBaseExpGain,
|
||||
}),
|
||||
|
||||
DealDrugs: new Crime("Deal Drugs", CONSTANTS.CrimeDrugs, 10e3, 120e3, 1, 0.5, {
|
||||
@@ -66,7 +66,7 @@ export const Crimes: IMap<Crime> = {
|
||||
hacking_success_weight: 0.05,
|
||||
dexterity_success_weight: 1.25,
|
||||
|
||||
intelligence_exp: 2 * CONSTANTS.IntelligenceCrimeBaseExpGain,
|
||||
intelligence_exp: 60 * CONSTANTS.IntelligenceCrimeBaseExpGain,
|
||||
}),
|
||||
|
||||
TraffickArms: new Crime("Traffick Arms", CONSTANTS.CrimeTraffickArms, 40e3, 600e3, 2, 1, {
|
||||
@@ -110,7 +110,7 @@ export const Crimes: IMap<Crime> = {
|
||||
agility_success_weight: 2,
|
||||
charisma_success_weight: 2,
|
||||
|
||||
intelligence_exp: CONSTANTS.IntelligenceCrimeBaseExpGain,
|
||||
intelligence_exp: 16 * CONSTANTS.IntelligenceCrimeBaseExpGain,
|
||||
}),
|
||||
|
||||
Kidnap: new Crime("Kidnap", CONSTANTS.CrimeKidnap, 120e3, 3.6e6, 5, 6, {
|
||||
@@ -125,7 +125,7 @@ export const Crimes: IMap<Crime> = {
|
||||
dexterity_success_weight: 1,
|
||||
agility_success_weight: 1,
|
||||
|
||||
intelligence_exp: 2 * CONSTANTS.IntelligenceCrimeBaseExpGain,
|
||||
intelligence_exp: 26 * CONSTANTS.IntelligenceCrimeBaseExpGain,
|
||||
}),
|
||||
|
||||
Assassination: new Crime("Assassination", CONSTANTS.CrimeAssassination, 300e3, 12e6, 8, 10, {
|
||||
@@ -138,7 +138,7 @@ export const Crimes: IMap<Crime> = {
|
||||
dexterity_success_weight: 2,
|
||||
agility_success_weight: 1,
|
||||
|
||||
intelligence_exp: 5 * CONSTANTS.IntelligenceCrimeBaseExpGain,
|
||||
intelligence_exp: 65 * CONSTANTS.IntelligenceCrimeBaseExpGain,
|
||||
|
||||
kills: 1,
|
||||
}),
|
||||
@@ -158,6 +158,6 @@ export const Crimes: IMap<Crime> = {
|
||||
agility_success_weight: 1,
|
||||
charisma_success_weight: 1,
|
||||
|
||||
intelligence_exp: 10 * CONSTANTS.IntelligenceCrimeBaseExpGain,
|
||||
intelligence_exp: 130 * CONSTANTS.IntelligenceCrimeBaseExpGain,
|
||||
}),
|
||||
};
|
||||
|
||||
39
src/Crime/formulas/crime.ts
Normal file
39
src/Crime/formulas/crime.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { calculateIntelligenceBonus } from "../../PersonObjects/formulas/intelligence";
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
|
||||
export interface ICrime {
|
||||
hacking_success_weight: number;
|
||||
strength_success_weight: number;
|
||||
defense_success_weight: number;
|
||||
dexterity_success_weight: number;
|
||||
agility_success_weight: number;
|
||||
charisma_success_weight: number;
|
||||
difficulty: number;
|
||||
}
|
||||
|
||||
export interface IPerson {
|
||||
hacking_skill: number;
|
||||
strength: number;
|
||||
defense: number;
|
||||
dexterity: number;
|
||||
agility: number;
|
||||
charisma: number;
|
||||
intelligence: number;
|
||||
crime_success_mult: number;
|
||||
}
|
||||
|
||||
export function calculateCrimeSuccessChance(crime: ICrime, person: IPerson) {
|
||||
let chance: number = (crime.hacking_success_weight * person.hacking_skill +
|
||||
crime.strength_success_weight * person.strength +
|
||||
crime.defense_success_weight * person.defense +
|
||||
crime.dexterity_success_weight * person.dexterity +
|
||||
crime.agility_success_weight * person.agility +
|
||||
crime.charisma_success_weight * person.charisma +
|
||||
CONSTANTS.IntelligenceCrimeWeight * person.intelligence);
|
||||
chance /= CONSTANTS.MaxSkillLevel;
|
||||
chance /= crime.difficulty;
|
||||
chance *= person.crime_success_mult;
|
||||
chance *= calculateIntelligenceBonus(person.intelligence);
|
||||
|
||||
return Math.min(chance, 1);
|
||||
}
|
||||
@@ -1,21 +1,24 @@
|
||||
import * as React from "react";
|
||||
import { DarkWebItems } from "./DarkWebItems";
|
||||
|
||||
import { Player } from "../Player";
|
||||
import { SpecialServerIps } from "../Server/SpecialServerIps";
|
||||
import { post } from "../ui/postToTerminal";
|
||||
import { post, postElement } from "../ui/postToTerminal";
|
||||
import { Money } from "../ui/React/Money";
|
||||
|
||||
import { isValidIPAddress } from "../../utils/helpers/isValidIPAddress";
|
||||
import { formatNumber } from "../../utils/StringHelperFunctions";
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
|
||||
//Posts a "help" message if connected to DarkWeb
|
||||
export function checkIfConnectedToDarkweb() {
|
||||
export function checkIfConnectedToDarkweb(): void {
|
||||
if (SpecialServerIps.hasOwnProperty("Darkweb Server")) {
|
||||
var darkwebIp = SpecialServerIps["Darkweb Server"];
|
||||
const darkwebIp = SpecialServerIps.getIp("Darkweb Server");
|
||||
if (!isValidIPAddress(darkwebIp)) {return;}
|
||||
if (darkwebIp == Player.getCurrentServer().ip) {
|
||||
post("You are now connected to the dark web. From the dark web you can purchase illegal items. " +
|
||||
"Use the 'buy -l' command to display a list of all the items you can buy. Use 'buy [item-name] " +
|
||||
"to purchase an item");
|
||||
"to purchase an item.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +26,7 @@ export function checkIfConnectedToDarkweb() {
|
||||
//Handler for dark web commands. The terminal's executeCommand() function will pass
|
||||
//dark web-specific commands into this. It will pass in the raw split command array
|
||||
//rather than the command string
|
||||
export function executeDarkwebTerminalCommand(commandArray) {
|
||||
export function executeDarkwebTerminalCommand(commandArray: string[]): void {
|
||||
if (commandArray.length == 0) {return;}
|
||||
switch (commandArray[0]) {
|
||||
case "buy":
|
||||
@@ -49,11 +52,11 @@ export function executeDarkwebTerminalCommand(commandArray) {
|
||||
function listAllDarkwebItems() {
|
||||
for(const key in DarkWebItems) {
|
||||
const item = DarkWebItems[key];
|
||||
post(item.toString());
|
||||
postElement(<>{item.program} - {Money(item.price)} - {item.description}</>);
|
||||
}
|
||||
}
|
||||
|
||||
function buyDarkwebItem(itemName) {
|
||||
function buyDarkwebItem(itemName: string): void {
|
||||
itemName = itemName.toLowerCase();
|
||||
|
||||
// find the program that matches, if any
|
||||
@@ -1,4 +1,4 @@
|
||||
import { formatNumber } from "../../utils/StringHelperFunctions";
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
|
||||
export class DarkWebItem {
|
||||
program: string;
|
||||
@@ -10,9 +10,4 @@ export class DarkWebItem {
|
||||
this.price = price;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
// Formats the item to print out to terminal (e.g. BruteSSH.exe -$500,000 - Opens up SSH Ports)
|
||||
toString(): string {
|
||||
return [this.program, "$" + formatNumber(this.price, 0), this.description].join(' - ');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import { createElement } from "../utils/uiHelpers/createElement";
|
||||
import { createOptionElement } from "../utils/uiHelpers/createOptionElement";
|
||||
import { getSelectText } from "../utils/uiHelpers/getSelectData";
|
||||
import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
||||
import { Money } from "./ui/React/Money";
|
||||
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
@@ -611,12 +612,16 @@ class DevMenuComponent extends Component {
|
||||
}
|
||||
|
||||
viewStockCaps() {
|
||||
let text = "<table><tbody><tr><th>Stock</th><th>Price cap</th></tr>";
|
||||
let stocks = [];
|
||||
this.processStocks((stock) => {
|
||||
text += `<tr><td>${stock.symbol}</td><td style="text-align:right;">${numeralWrapper.format(stock.cap, '$0.000a')}</td></tr>`;
|
||||
stocks.push(<tr key={stock.symbol}>
|
||||
<td>{stock.symbol}</td>
|
||||
<td style={{'textAlign':'right'}}>{Money(stock.cap)}</td>
|
||||
</tr>);
|
||||
});
|
||||
text += "</tbody></table>";
|
||||
dialogBoxCreate(text);
|
||||
dialogBoxCreate(<table><tbody><tr><th>Stock</th><th>Price cap</th></tr>
|
||||
{stocks}
|
||||
</tbody></table>);
|
||||
}
|
||||
|
||||
sleeveMaxAllShock() {
|
||||
|
||||
@@ -12,10 +12,11 @@ Source-File minus 1 is extremely weak because it can be fully level up quickly.
|
||||
|
||||
export enum Exploit {
|
||||
UndocumentedFunctionCall = 'UndocumentedFunctionCall',
|
||||
Unclickable = 'Unclickable',
|
||||
PrototypeTampering = 'PrototypeTampering',
|
||||
// To the players reading this. Yes you're supposed to add EditSaveFile by
|
||||
// editing your save file, yes you could add them all, no we don't care
|
||||
// that's not the point
|
||||
// that's not the point.
|
||||
EditSaveFile = 'EditSaveFile'
|
||||
}
|
||||
|
||||
@@ -25,6 +26,7 @@ const names: {
|
||||
'UndocumentedFunctionCall': 'by looking beyond the documentation.',
|
||||
'EditSaveFile': 'by editing your save file.',
|
||||
'PrototypeTampering': 'by tampering with Numbers prototype.',
|
||||
'Unclickable': 'by clicking the unclickable.',
|
||||
}
|
||||
|
||||
|
||||
|
||||
24
src/Exploits/unclickable.ts
Normal file
24
src/Exploits/unclickable.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Player } from "../Player";
|
||||
import { Exploit } from "./Exploit";
|
||||
|
||||
(function() {
|
||||
function clickTheUnclickable(event: MouseEvent) {
|
||||
if(!event.target || !(event.target instanceof Element)) return;
|
||||
const display = window.getComputedStyle(event.target as Element).display;
|
||||
if(display === 'none' && event.isTrusted)
|
||||
Player.giveExploit(Exploit.Unclickable);
|
||||
}
|
||||
|
||||
|
||||
function targetElement() {
|
||||
const elem = document.getElementById('unclickable');
|
||||
if(elem == null) {
|
||||
console.error('Could not find the unclickable elem for the related exploit.');
|
||||
return;
|
||||
}
|
||||
elem.addEventListener("click", clickTheUnclickable);
|
||||
document.removeEventListener('DOMContentLoaded', targetElement);
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', targetElement);
|
||||
})();
|
||||
@@ -25,6 +25,8 @@ import {
|
||||
Generic_fromJSON
|
||||
} from "../../utils/JSONReviver";
|
||||
import { formatNumber } from "../../utils/StringHelperFunctions";
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
import { Money } from "../ui/React/Money";
|
||||
import {
|
||||
yesNoBoxCreate,
|
||||
yesNoBoxGetYesButton,
|
||||
@@ -108,10 +110,12 @@ export function purchaseAugmentationBoxCreate(aug, fac) {
|
||||
yesNoBoxClose();
|
||||
});
|
||||
|
||||
yesNoBoxCreate("<h2>" + aug.name + "</h2><br>" +
|
||||
aug.info + "<br><br>" +
|
||||
"<br>Would you like to purchase the " + aug.name + " Augmentation for $" +
|
||||
formatNumber(aug.baseCost * factionInfo.augmentationPriceMult, 2) + "?");
|
||||
yesNoBoxCreate(<>
|
||||
<h2>{aug.name}</h2><br />
|
||||
<div dangerouslySetInnerHTML={{__html: aug.info}}></div><br /><br />
|
||||
<br />Would you like to purchase the {aug.name} Augmentation for
|
||||
{Money(aug.baseCost * factionInfo.augmentationPriceMult)}?
|
||||
</>);
|
||||
}
|
||||
|
||||
//Returns a boolean indicating whether the player has the prerequisites for the
|
||||
|
||||
@@ -6,6 +6,7 @@ import * as React from "react";
|
||||
import { PurchaseableAugmentation } from "./PurchaseableAugmentation";
|
||||
|
||||
import { Augmentations } from "../../Augmentation/Augmentations";
|
||||
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
||||
import { Faction } from "../../Faction/Faction";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { PurchaseAugmentationsOrderSetting } from "../../Settings/SettingEnums";
|
||||
@@ -44,7 +45,7 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
|
||||
this.rerender = this.rerender.bind(this);
|
||||
}
|
||||
|
||||
getAugs() {
|
||||
getAugs(): string[] {
|
||||
if (this.isPlayersGang) {
|
||||
const augs: string[] = [];
|
||||
for (const augName in Augmentations) {
|
||||
@@ -60,7 +61,7 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
|
||||
}
|
||||
}
|
||||
|
||||
getAugsSorted() {
|
||||
getAugsSorted(): string[] {
|
||||
switch (Settings.PurchaseAugmentationsOrder) {
|
||||
case PurchaseAugmentationsOrderSetting.Cost: {
|
||||
return this.getAugsSortedByCost();
|
||||
@@ -73,7 +74,7 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
|
||||
}
|
||||
}
|
||||
|
||||
getAugsSortedByCost() {
|
||||
getAugsSortedByCost(): string[] {
|
||||
const augs = this.getAugs();
|
||||
augs.sort((augName1, augName2)=>{
|
||||
var aug1 = Augmentations[augName1], aug2 = Augmentations[augName2];
|
||||
@@ -87,7 +88,7 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
|
||||
return augs;
|
||||
}
|
||||
|
||||
getAugsSortedByReputation() {
|
||||
getAugsSortedByReputation(): string[] {
|
||||
const augs = this.getAugs();
|
||||
augs.sort((augName1, augName2)=>{
|
||||
var aug1 = Augmentations[augName1], aug2 = Augmentations[augName2];
|
||||
@@ -100,16 +101,16 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
|
||||
return augs;
|
||||
}
|
||||
|
||||
getAugsSortedByDefault() {
|
||||
getAugsSortedByDefault(): string[] {
|
||||
return this.getAugs();
|
||||
}
|
||||
|
||||
switchSortOrder(newOrder: PurchaseAugmentationsOrderSetting) {
|
||||
switchSortOrder(newOrder: PurchaseAugmentationsOrderSetting): void {
|
||||
Settings.PurchaseAugmentationsOrder = newOrder;
|
||||
this.rerender();
|
||||
}
|
||||
|
||||
rerender() {
|
||||
rerender(): void {
|
||||
this.setState((prevState) => {
|
||||
return {
|
||||
rerenderFlag: !prevState.rerenderFlag,
|
||||
@@ -119,17 +120,39 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
|
||||
|
||||
render() {
|
||||
const augs = this.getAugsSorted();
|
||||
const augList = augs.map((aug) => {
|
||||
const purchasable = augs.filter((aug: string) =>
|
||||
aug === AugmentationNames.NeuroFluxGovernor ||
|
||||
(!this.props.p.augmentations.some(a => a.name === aug) &&
|
||||
!this.props.p.queuedAugmentations.some(a => a.name === aug))
|
||||
)
|
||||
|
||||
const parent = this;
|
||||
function purchaseableAugmentation(aug: string) {
|
||||
return (
|
||||
<PurchaseableAugmentation
|
||||
augName={aug}
|
||||
faction={this.props.faction}
|
||||
faction={parent.props.faction}
|
||||
key={aug}
|
||||
p={this.props.p}
|
||||
rerender={this.rerender}
|
||||
p={parent.props.p}
|
||||
rerender={parent.rerender}
|
||||
/>
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
const augListElems = purchasable.map(aug => purchaseableAugmentation(aug));
|
||||
|
||||
let ownedElem = <></>
|
||||
const owned = augs.filter((aug: string) => !purchasable.includes(aug));
|
||||
if (owned.length !== 0) {
|
||||
ownedElem = <>
|
||||
<br />
|
||||
<h2>Purchased Augmentations</h2>
|
||||
<p style={infoStyleMarkup}>
|
||||
This factions also offers these augmentations but you already own them.
|
||||
</p>
|
||||
{owned.map(aug => purchaseableAugmentation(aug))}
|
||||
</>
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -156,7 +179,8 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
|
||||
text={"Sort by Default Order"}
|
||||
/>
|
||||
<br />
|
||||
{augList}
|
||||
{augListElems}
|
||||
{ownedElem}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import { Faction } from "../../Faction/Faction";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { Reputation } from "../../ui/React/Reputation";
|
||||
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
|
||||
@@ -21,7 +23,7 @@ type IProps = {
|
||||
|
||||
type IState = {
|
||||
donateAmt: number;
|
||||
statusTxt: string;
|
||||
status: JSX.Element;
|
||||
}
|
||||
|
||||
const inputStyleMarkup = {
|
||||
@@ -37,7 +39,7 @@ export class DonateOption extends React.Component<IProps, IState> {
|
||||
|
||||
this.state = {
|
||||
donateAmt: 0,
|
||||
statusTxt: "",
|
||||
status: <></>,
|
||||
}
|
||||
|
||||
this.calculateRepGain = this.calculateRepGain.bind(this);
|
||||
@@ -61,8 +63,9 @@ export class DonateOption extends React.Component<IProps, IState> {
|
||||
this.props.p.loseMoney(amt);
|
||||
const repGain = this.calculateRepGain(amt);
|
||||
this.props.faction.playerReputation += repGain;
|
||||
dialogBoxCreate(`You just donated ${numeralWrapper.formatMoney(amt)} to ${fac.name} to gain ` +
|
||||
`${numeralWrapper.format(repGain, "0,0.000")} reputation`);
|
||||
dialogBoxCreate(<>
|
||||
You just donated {Money(amt)} to {fac.name} to gain {Reputation(repGain)} reputation
|
||||
</>);
|
||||
this.props.rerender();
|
||||
}
|
||||
}
|
||||
@@ -73,13 +76,13 @@ export class DonateOption extends React.Component<IProps, IState> {
|
||||
if (isNaN(amt)) {
|
||||
this.setState({
|
||||
donateAmt: 0,
|
||||
statusTxt: "Invalid donate amount entered!",
|
||||
status: <>Invalid donate amount entered!</>,
|
||||
});
|
||||
} else {
|
||||
const repGain = this.calculateRepGain(amt);
|
||||
this.setState({
|
||||
donateAmt: amt,
|
||||
statusTxt: `This donation will result in ${numeralWrapper.format(repGain, "0,0.000")} reputation gain`,
|
||||
status: <>This donation will result in {Reputation(repGain)} reputation gain</>,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -93,7 +96,7 @@ export class DonateOption extends React.Component<IProps, IState> {
|
||||
onClick={this.donate}
|
||||
text={"Donate Money"}
|
||||
/>
|
||||
<p style={this.blockStyle}>{this.state.statusTxt}</p>
|
||||
<p style={this.blockStyle}>{this.state.status}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -10,6 +10,8 @@ import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
|
||||
import { AutoupdatingParagraph } from "../../ui/React/AutoupdatingParagraph";
|
||||
import { ParagraphWithTooltip } from "../../ui/React/ParagraphWithTooltip";
|
||||
import { Reputation } from "../../ui/React/Reputation";
|
||||
import { Favor } from "../../ui/React/Favor";
|
||||
|
||||
type IProps = {
|
||||
faction: Faction;
|
||||
@@ -33,18 +35,17 @@ export class Info extends React.Component<IProps, any> {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.getFavorGainText = this.getFavorGainText.bind(this);
|
||||
this.getReputationText = this.getReputationText.bind(this);
|
||||
this.getFavorGainContent = this.getFavorGainContent.bind(this);
|
||||
this.getReputationContent = this.getReputationContent.bind(this);
|
||||
}
|
||||
|
||||
getFavorGainText(): string {
|
||||
getFavorGainContent(): JSX.Element {
|
||||
const favorGain = this.props.faction.getFavorGain()[0];
|
||||
return `You will earn ${numeralWrapper.format(favorGain, "0,0")} faction favor upon resetting after installing an Augmentation`
|
||||
return <>You will earn {Favor(favorGain)} faction favor upon resetting after installing an Augmentation</>
|
||||
}
|
||||
|
||||
getReputationText(): string {
|
||||
const formattedRep = numeralWrapper.format(this.props.faction.playerReputation, "0.000a");
|
||||
return `Reputation: ${formattedRep}`
|
||||
getReputationContent(): JSX.Element {
|
||||
return <>Reputation: {Reputation(this.props.faction.playerReputation)}</>
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -65,12 +66,12 @@ export class Info extends React.Component<IProps, any> {
|
||||
<p style={blockStyleMarkup}>-------------------------</p>
|
||||
<AutoupdatingParagraph
|
||||
intervalTime={5e3}
|
||||
getText={this.getReputationText}
|
||||
getTooltip={this.getFavorGainText}
|
||||
getContent={this.getReputationContent}
|
||||
getTooltip={this.getFavorGainContent}
|
||||
/>
|
||||
<p style={blockStyleMarkup}>-------------------------</p>
|
||||
<ParagraphWithTooltip
|
||||
text={`Faction Favor: ${numeralWrapper.format(this.props.faction.favor, "0,0")}`}
|
||||
content={<>Faction Favor: {Favor(this.props.faction.favor)}</>}
|
||||
tooltip={favorTooltip}
|
||||
/>
|
||||
<p style={blockStyleMarkup}>-------------------------</p>
|
||||
|
||||
@@ -18,9 +18,12 @@ import { Faction } from "../../Faction/Faction";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { Reputation } from "../../ui/React/Reputation";
|
||||
import { IMap } from "../../types";
|
||||
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { Augmentation as AugFormat } from "../../ui/React/Augmentation";
|
||||
|
||||
type IProps = {
|
||||
augName: string;
|
||||
@@ -106,20 +109,19 @@ export class PurchaseableAugmentation extends React.Component<IProps, any> {
|
||||
|
||||
// Determine UI properties
|
||||
let disabled: boolean = false;
|
||||
let statusTxt: string = "";
|
||||
let status: JSX.Element = <></>;
|
||||
let color: string = "";
|
||||
if (!this.hasPrereqs()) {
|
||||
disabled = true;
|
||||
statusTxt = `LOCKED (Requires ${this.aug.prereqs.join(",")} as prerequisite(s))`;
|
||||
status = <>LOCKED (Requires {this.aug.prereqs.map(aug => AugFormat(aug))} as prerequisite)</>;
|
||||
color = "red";
|
||||
} else if (this.aug.name !== AugmentationNames.NeuroFluxGovernor && (this.aug.owned || this.owned())) {
|
||||
disabled = true;
|
||||
statusTxt = "ALREADY OWNED";
|
||||
} else if (this.hasReputation()) {
|
||||
statusTxt = `UNLOCKED - ${numeralWrapper.formatMoney(moneyCost)}`;
|
||||
status = <>UNLOCKED - {Money(moneyCost)}</>;
|
||||
} else {
|
||||
disabled = true;
|
||||
statusTxt = `LOCKED (Requires ${numeralWrapper.format(repCost, "0,0.0")} faction reputation - ${numeralWrapper.formatMoney(moneyCost)})`;
|
||||
status = <>LOCKED (Requires {Reputation(repCost)} faction reputation - {Money(moneyCost)})</>;
|
||||
color = "red";
|
||||
}
|
||||
|
||||
@@ -144,7 +146,7 @@ export class PurchaseableAugmentation extends React.Component<IProps, any> {
|
||||
text={btnTxt}
|
||||
tooltip={this.aug.info}
|
||||
/>
|
||||
<p style={txtStyle}>{statusTxt}</p>
|
||||
<p style={txtStyle}>{status}</p>
|
||||
</span>
|
||||
</li>
|
||||
)
|
||||
|
||||
@@ -35,6 +35,14 @@ import { removeElement } from "../utils/uiHelpers/removeElement";
|
||||
import { removeElementById } from "../utils/uiHelpers/removeElementById";
|
||||
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
||||
|
||||
import { StatsTable } from "./ui/React/StatsTable";
|
||||
import { Money } from "./ui/React/Money";
|
||||
import { MoneyRate } from "./ui/React/MoneyRate";
|
||||
import { Reputation } from "./ui/React/Reputation";
|
||||
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { renderToStaticMarkup } from "react-dom/server"
|
||||
|
||||
// Constants
|
||||
const GangRespectToReputationRatio = 5; // Respect is divided by this to get rep gain
|
||||
@@ -492,15 +500,15 @@ Gang.prototype.ascendMember = function(memberObj, workerScript) {
|
||||
if (workerScript == null) {
|
||||
dialogBoxCreate([`You ascended ${memberObj.name}!`,
|
||||
"",
|
||||
`Your gang lost ${numeralWrapper.format(res.respect, "0.000a")} respect`,
|
||||
`Your gang lost ${numeralWrapper.formatRespect(res.respect)} respect`,
|
||||
"",
|
||||
`${memberObj.name} gained the following stat multipliers for ascending:`,
|
||||
`Hacking: ${numeralWrapper.format(res.hack, "0.000%")}`,
|
||||
`Strength: ${numeralWrapper.format(res.str, "0.000%")}`,
|
||||
`Defense: ${numeralWrapper.format(res.def, "0.000%")}`,
|
||||
`Dexterity: ${numeralWrapper.format(res.dex, "0.000%")}`,
|
||||
`Agility: ${numeralWrapper.format(res.agi, "0.000%")}`,
|
||||
`Charisma: ${numeralWrapper.format(res.cha, "0.000%")}`].join("<br>"));
|
||||
`Hacking: ${numeralWrapper.formatPercentage(res.hack, 3)}`,
|
||||
`Strength: ${numeralWrapper.formatPercentage(res.str, 3)}`,
|
||||
`Defense: ${numeralWrapper.formatPercentage(res.def, 3)}`,
|
||||
`Dexterity: ${numeralWrapper.formatPercentage(res.dex, 3)}`,
|
||||
`Agility: ${numeralWrapper.formatPercentage(res.agi, 3)}`,
|
||||
`Charisma: ${numeralWrapper.formatPercentage(res.cha, 3)}`].join("<br>"));
|
||||
} else {
|
||||
workerScript.log(`Ascended Gang member ${memberObj.name}`);
|
||||
}
|
||||
@@ -1044,14 +1052,14 @@ Gang.prototype.createGangMemberUpgradeBox = function(player, initialFilter="") {
|
||||
type:"text", placeholder:"Filter gang members",
|
||||
class: "text-input",
|
||||
value:initialFilter,
|
||||
onkeyup:()=>{
|
||||
onkeyup:() => {
|
||||
var filterValue = UIElems.gangMemberUpgradeBoxFilter.value.toString();
|
||||
this.createGangMemberUpgradeBox(player, filterValue);
|
||||
}
|
||||
});
|
||||
|
||||
UIElems.gangMemberUpgradeBoxDiscount = createElement("p", {
|
||||
innerText: "Discount: -" + numeralWrapper.format(1 - 1 / this.getDiscount(), "0.00%"),
|
||||
innerText: "Discount: -" + numeralWrapper.formatPercentage(1 - 1 / this.getDiscount()),
|
||||
marginLeft: "6px",
|
||||
tooltip: "You get a discount on equipment and upgrades based on your gang's " +
|
||||
"respect and power. More respect and power leads to more discounts."
|
||||
@@ -1178,10 +1186,10 @@ GangMember.prototype.createGangMemberUpgradePanel = function(gangObj, player) {
|
||||
let upg = upgradeArray[j];
|
||||
(function (upg, div, memberObj, i, gang) {
|
||||
let createElementParams = {
|
||||
innerText: upg.name + " - " + numeralWrapper.format(upg.getCost(gang), "$0.000a"),
|
||||
innerHTML: `${upg.name} - ${renderToStaticMarkup(Money(upg.getCost(gang)))}`,
|
||||
class: "a-link-button", margin:"2px", padding:"2px", display:"block",
|
||||
fontSize:"11px",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
memberObj.buyUpgrade(upg, player, gangObj);
|
||||
return false;
|
||||
}
|
||||
@@ -1266,7 +1274,7 @@ Gang.prototype.displayGangContent = function(player) {
|
||||
// Back button
|
||||
UIElems.gangContainer.appendChild(createElement("a", {
|
||||
class:"a-link-button", display:"inline-block", innerText:"Back",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
Engine.loadFactionContent();
|
||||
displayFactionContent(facName);
|
||||
return false;
|
||||
@@ -1277,7 +1285,7 @@ Gang.prototype.displayGangContent = function(player) {
|
||||
UIElems.managementButton = createElement("a", {
|
||||
id:"gang-management-subpage-button", class:"a-link-button-inactive",
|
||||
display:"inline-block", innerHTML: "Gang Management (Alt+1)",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
UIElems.gangManagementSubpage.style.display = "block";
|
||||
UIElems.gangTerritorySubpage.style.display = "none";
|
||||
UIElems.managementButton.classList.toggle("a-link-button-inactive");
|
||||
@@ -1340,7 +1348,7 @@ Gang.prototype.displayGangContent = function(player) {
|
||||
UIElems.gangRecruitMemberButton = createElement("a", {
|
||||
id: "gang-management-recruit-member-btn", class:"a-link-button-inactive",
|
||||
innerHTML:"Recruit Gang Member", display:"inline-block", margin:"10px",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
const popupId = "recruit-gang-member-popup";
|
||||
|
||||
let yesBtn;
|
||||
@@ -1408,7 +1416,7 @@ Gang.prototype.displayGangContent = function(player) {
|
||||
UIElems.gangExpandAllButton = createElement("a", {
|
||||
class:"a-link-button", display:"inline-block",
|
||||
innerHTML:"Expand All",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
var allHeaders = UIElems.gangManagementSubpage.getElementsByClassName("accordion-header");
|
||||
for (var i = 0; i < allHeaders.length; ++i) {
|
||||
var hdr = allHeaders[i];
|
||||
@@ -1422,7 +1430,7 @@ Gang.prototype.displayGangContent = function(player) {
|
||||
UIElems.gangCollapseAllButton = createElement("a", {
|
||||
class:"a-link-button", display:"inline-block",
|
||||
innerHTML:"Collapse All",
|
||||
clickListener:()=>{
|
||||
clickListener:() => {
|
||||
var allHeaders = UIElems.gangManagementSubpage.getElementsByClassName("accordion-header");
|
||||
for (var i = 0; i < allHeaders.length; ++i) {
|
||||
var hdr = allHeaders[i];
|
||||
@@ -1436,7 +1444,7 @@ Gang.prototype.displayGangContent = function(player) {
|
||||
UIElems.gangMemberFilter = createElement("input", {
|
||||
type:"text", placeholder:"Filter gang members", margin:"5px", padding:"5px",
|
||||
class:"text-input",
|
||||
onkeyup:()=>{
|
||||
onkeyup:() => {
|
||||
this.displayGangMemberList();
|
||||
}
|
||||
});
|
||||
@@ -1584,13 +1592,13 @@ Gang.prototype.updateGangContent = function() {
|
||||
|
||||
if (UIElems.gangMemberUpgradeBoxOpened) {
|
||||
UIElems.gangMemberUpgradeBoxDiscount.childNodes[0].nodeValue =
|
||||
"Discount: -" + numeralWrapper.format(1 - 1 / this.getDiscount(), "0.00%");
|
||||
"Discount: -" + numeralWrapper.formatPercentage(1 - 1 / this.getDiscount());
|
||||
}
|
||||
|
||||
if (UIElems.gangTerritorySubpage.style.display === "block") {
|
||||
// Territory Warfare Clash Chance
|
||||
UIElems.gangTerritoryWarfareClashChance.innerText =
|
||||
`Territory Clash Chance: ${numeralWrapper.format(this.territoryClashChance, '0.000%')}`;
|
||||
`Territory Clash Chance: ${numeralWrapper.formatPercentage(this.territoryClashChance, 3)}`;
|
||||
|
||||
// Engaged in Territory Warfare checkbox
|
||||
UIElems.gangTerritoryWarfareCheckbox.checked = this.territoryWarfareEngaged;
|
||||
@@ -1623,7 +1631,7 @@ Gang.prototype.updateGangContent = function() {
|
||||
const clashVictoryChance = playerPower / (gangTerritoryInfo.power + playerPower);
|
||||
let newHTML = `<u>${gangname}</u><br>Power: ${formatNumber(gangTerritoryInfo.power, 6)}<br>`;
|
||||
newHTML += `Territory: ${displayNumber}%<br>`;
|
||||
newHTML += `Chance to win clash with this gang: ${numeralWrapper.format(clashVictoryChance, "0.000%")}<br><br>`;
|
||||
newHTML += `Chance to win clash with this gang: ${numeralWrapper.formatPercentage(clashVictoryChance, 3)}<br><br>`;
|
||||
UIElems.gangTerritoryInfoText.innerHTML += newHTML;
|
||||
}
|
||||
}
|
||||
@@ -1641,8 +1649,8 @@ Gang.prototype.updateGangContent = function() {
|
||||
removeChildrenFromElement(UIElems.gangInfo);
|
||||
UIElems.gangInfo.appendChild(createElement("p", { // Respect
|
||||
display: "inline-block",
|
||||
innerText: "Respect: " + numeralWrapper.format(this.respect, '0.00000a') +
|
||||
" (" + numeralWrapper.format(5*this.respectGainRate, '0.00000a') + " / sec)",
|
||||
innerText: "Respect: " + numeralWrapper.formatRespect(this.respect) +
|
||||
" (" + numeralWrapper.formatRespect(5*this.respectGainRate) + " / sec)",
|
||||
tooltip: "Represents the amount of respect your gang has from other gangs and criminal " +
|
||||
"organizations. Your respect affects the amount of money " +
|
||||
"your gang members will earn, and also determines how much " +
|
||||
@@ -1652,8 +1660,8 @@ Gang.prototype.updateGangContent = function() {
|
||||
|
||||
UIElems.gangInfo.appendChild(createElement("p", { // Wanted level
|
||||
display: "inline-block",
|
||||
innerText: "Wanted Level: " + numeralWrapper.format(this.wanted, '0.00000a') +
|
||||
" (" + numeralWrapper.format(5*this.wantedGainRate, '0.00000a') + " / sec)",
|
||||
innerText: "Wanted Level: " + numeralWrapper.formatWanted(this.wanted) +
|
||||
" (" + numeralWrapper.formatWanted(5*this.wantedGainRate) + " / sec)",
|
||||
tooltip: "Represents how much the gang is wanted by law enforcement. The higher " +
|
||||
"your gang's wanted level, the harder it will be for your gang members " +
|
||||
"to make money and earn respect. Note that the minimum wanted level is 1."
|
||||
@@ -1669,10 +1677,9 @@ Gang.prototype.updateGangContent = function() {
|
||||
}));
|
||||
UIElems.gangInfo.appendChild(createElement("br"));
|
||||
|
||||
UIElems.gangInfo.appendChild(createElement("p", { // Money gain rate
|
||||
display: "inline-block",
|
||||
innerText: `Money gain rate: ${numeralWrapper.format(5 * this.moneyGainRate, "$0.000a")} / sec`,
|
||||
}));
|
||||
const d0 = createElement("div");
|
||||
ReactDOM.render(<p style={{'display': 'inline-block'}}>Money gain rate: {MoneyRate(5 * this.moneyGainRate)}</p>, d0);
|
||||
UIElems.gangInfo.appendChild(d0);
|
||||
UIElems.gangInfo.appendChild(createElement("br"));
|
||||
|
||||
// Fix some rounding issues graphically
|
||||
@@ -1692,10 +1699,9 @@ Gang.prototype.updateGangContent = function() {
|
||||
}));
|
||||
UIElems.gangInfo.appendChild(createElement("br"));
|
||||
|
||||
UIElems.gangInfo.appendChild(createElement("p", { // Faction reputation
|
||||
display:"inline-block",
|
||||
innerText:"Faction reputation: " + numeralWrapper.format(rep, '0.000a')
|
||||
}));
|
||||
const d1 = createElement("div");
|
||||
ReactDOM.render(<p style={{'display': 'inline-block'}}>Faction reputation: {Reputation(rep)}</p>, d1);
|
||||
UIElems.gangInfo.appendChild(d1);
|
||||
UIElems.gangInfo.appendChild(createElement("br"));
|
||||
|
||||
const CyclesPerSecond = 1000 / Engine._idleSpeed;
|
||||
@@ -1761,12 +1767,12 @@ Gang.prototype.createGangMemberDisplayElement = function(memberObj) {
|
||||
const statsDiv = createElement("div", {
|
||||
class: "gang-member-info-div",
|
||||
id: name + "gang-member-stats",
|
||||
tooltipsmall: [`Hk: x${numeralWrapper.format(memberObj.hack_mult * memberObj.hack_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.hack_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.hack_asc_mult, "0,0.00")} Asc)`,
|
||||
`St: x${numeralWrapper.format(memberObj.str_mult * memberObj.str_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.str_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.str_asc_mult, "0,0.00")} Asc)`,
|
||||
`Df: x${numeralWrapper.format(memberObj.def_mult * memberObj.def_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.def_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.def_asc_mult, "0,0.00")} Asc)`,
|
||||
`Dx: x${numeralWrapper.format(memberObj.dex_mult * memberObj.dex_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.dex_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.dex_asc_mult, "0,0.00")} Asc)`,
|
||||
`Ag: x${numeralWrapper.format(memberObj.agi_mult * memberObj.agi_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.agi_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.agi_asc_mult, "0,0.00")} Asc)`,
|
||||
`Ch: x${numeralWrapper.format(memberObj.cha_mult * memberObj.cha_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.cha_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.cha_asc_mult, "0,0.00")} Asc)`].join("<br>"),
|
||||
tooltipsmall: [`Hk: x${numeralWrapper.formatMultiplier(memberObj.hack_mult * memberObj.hack_asc_mult)}(x${numeralWrapper.formatMultiplier(memberObj.hack_mult)} Eq, x${numeralWrapper.formatMultiplier(memberObj.hack_asc_mult)} Asc)`,
|
||||
`St: x${numeralWrapper.formatMultiplier(memberObj.str_mult * memberObj.str_asc_mult)}(x${numeralWrapper.formatMultiplier(memberObj.str_mult)} Eq, x${numeralWrapper.formatMultiplier(memberObj.str_asc_mult)} Asc)`,
|
||||
`Df: x${numeralWrapper.formatMultiplier(memberObj.def_mult * memberObj.def_asc_mult)}(x${numeralWrapper.formatMultiplier(memberObj.def_mult)} Eq, x${numeralWrapper.formatMultiplier(memberObj.def_asc_mult)} Asc)`,
|
||||
`Dx: x${numeralWrapper.formatMultiplier(memberObj.dex_mult * memberObj.dex_asc_mult)}(x${numeralWrapper.formatMultiplier(memberObj.dex_mult)} Eq, x${numeralWrapper.formatMultiplier(memberObj.dex_asc_mult)} Asc)`,
|
||||
`Ag: x${numeralWrapper.formatMultiplier(memberObj.agi_mult * memberObj.agi_asc_mult)}(x${numeralWrapper.formatMultiplier(memberObj.agi_mult)} Eq, x${numeralWrapper.formatMultiplier(memberObj.agi_asc_mult)} Asc)`,
|
||||
`Ch: x${numeralWrapper.formatMultiplier(memberObj.cha_mult * memberObj.cha_asc_mult)}(x${numeralWrapper.formatMultiplier(memberObj.cha_mult)} Eq, x${numeralWrapper.formatMultiplier(memberObj.cha_asc_mult)} Asc)`].join("<br>"),
|
||||
});
|
||||
UIElems.gangMemberPanels[name]["statsDiv"] = statsDiv;
|
||||
const statsP = createElement("pre", {
|
||||
@@ -1784,15 +1790,15 @@ Gang.prototype.createGangMemberDisplayElement = function(memberObj) {
|
||||
innerText: ["Are you sure you want to ascend this member? They will lose all of",
|
||||
"their non-Augmentation upgrades and their stats will reset back to 1.",
|
||||
"",
|
||||
`Furthermore, your gang will lose ${numeralWrapper.format(memberObj.earnedRespect, "0.000a")} respect`,
|
||||
`Furthermore, your gang will lose ${numeralWrapper.formatRespect(memberObj.earnedRespect)} respect`,
|
||||
"",
|
||||
"In return, they will gain the following permanent boost to stat multipliers:\n",
|
||||
`Hacking: +${numeralWrapper.format(ascendBenefits.hack, "0.00%")}`,
|
||||
`Strength: +${numeralWrapper.format(ascendBenefits.str, "0.00%")}`,
|
||||
`Defense: +${numeralWrapper.format(ascendBenefits.def, "0.00%")}`,
|
||||
`Dexterity: +${numeralWrapper.format(ascendBenefits.dex, "0.00%")}`,
|
||||
`Agility: +${numeralWrapper.format(ascendBenefits.agi, "0.00%")}`,
|
||||
`Charisma: +${numeralWrapper.format(ascendBenefits.cha, "0.00%")}`].join("\n"),
|
||||
`Hacking: +${numeralWrapper.formatPercentage(ascendBenefits.hack)}`,
|
||||
`Strength: +${numeralWrapper.formatPercentage(ascendBenefits.str)}`,
|
||||
`Defense: +${numeralWrapper.formatPercentage(ascendBenefits.def)}`,
|
||||
`Dexterity: +${numeralWrapper.formatPercentage(ascendBenefits.dex)}`,
|
||||
`Agility: +${numeralWrapper.formatPercentage(ascendBenefits.agi)}`,
|
||||
`Charisma: +${numeralWrapper.formatPercentage(ascendBenefits.cha)}`].join("\n"),
|
||||
});
|
||||
const confirmBtn = createElement("button", {
|
||||
class: "std-button",
|
||||
@@ -1874,7 +1880,7 @@ Gang.prototype.createGangMemberDisplayElement = function(memberObj) {
|
||||
taskSelector.selectedIndex = taskIndex;
|
||||
}
|
||||
|
||||
var gainInfo = createElement("p", {id:name + "gang-member-gain-info"});
|
||||
var gainInfo = createElement("div", {id:name + "gang-member-gain-info"});
|
||||
taskDiv.appendChild(taskSelector);
|
||||
taskDiv.appendChild(gainInfo);
|
||||
|
||||
@@ -1907,12 +1913,12 @@ Gang.prototype.updateGangMemberDisplayElement = function(memberObj) {
|
||||
var stats = document.getElementById(name + "gang-member-stats-text");
|
||||
if (stats) {
|
||||
stats.innerText =
|
||||
[`Hacking: ${formatNumber(memberObj.hack, 0)} (${numeralWrapper.format(memberObj.hack_exp, '(0.00a)')} exp)`,
|
||||
`Strength: ${formatNumber(memberObj.str, 0)} (${numeralWrapper.format(memberObj.str_exp, '(0.00a)')} exp)`,
|
||||
`Defense: ${formatNumber(memberObj.def, 0)} (${numeralWrapper.format(memberObj.def_exp, '(0.00a)')} exp)`,
|
||||
`Dexterity: ${formatNumber(memberObj.dex, 0)} (${numeralWrapper.format(memberObj.dex_exp, '(0.00a)')} exp)`,
|
||||
`Agility: ${formatNumber(memberObj.agi, 0)} (${numeralWrapper.format(memberObj.agi_exp, '(0.00a)')} exp)`,
|
||||
`Charisma: ${formatNumber(memberObj.cha, 0)} (${numeralWrapper.format(memberObj.cha_exp, '(0.00a)')} exp)`].join("\n");
|
||||
[`Hacking: ${formatNumber(memberObj.hack, 0)} (${numeralWrapper.formatExp(memberObj.hack_exp)} exp)`,
|
||||
`Strength: ${formatNumber(memberObj.str, 0)} (${numeralWrapper.formatExp(memberObj.str_exp)} exp)`,
|
||||
`Defense: ${formatNumber(memberObj.def, 0)} (${numeralWrapper.formatExp(memberObj.def_exp)} exp)`,
|
||||
`Dexterity: ${formatNumber(memberObj.dex, 0)} (${numeralWrapper.formatExp(memberObj.dex_exp)} exp)`,
|
||||
`Agility: ${formatNumber(memberObj.agi, 0)} (${numeralWrapper.formatExp(memberObj.agi_exp)} exp)`,
|
||||
`Charisma: ${formatNumber(memberObj.cha, 0)} (${numeralWrapper.formatExp(memberObj.cha_exp)} exp)`].join("\n");
|
||||
}
|
||||
|
||||
// Update tooltip for stat multipliers
|
||||
@@ -1921,23 +1927,25 @@ Gang.prototype.updateGangMemberDisplayElement = function(memberObj) {
|
||||
const statsDiv = panel["statsDiv"];
|
||||
if (statsDiv) {
|
||||
statsDiv.firstChild.innerHTML =
|
||||
[`Hk: x${numeralWrapper.format(memberObj.hack_mult * memberObj.hack_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.hack_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.hack_asc_mult, "0,0.00")} Asc)`,
|
||||
`St: x${numeralWrapper.format(memberObj.str_mult * memberObj.str_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.str_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.str_asc_mult, "0,0.00")} Asc)`,
|
||||
`Df: x${numeralWrapper.format(memberObj.def_mult * memberObj.def_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.def_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.def_asc_mult, "0,0.00")} Asc)`,
|
||||
`Dx: x${numeralWrapper.format(memberObj.dex_mult * memberObj.dex_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.dex_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.dex_asc_mult, "0,0.00")} Asc)`,
|
||||
`Ag: x${numeralWrapper.format(memberObj.agi_mult * memberObj.agi_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.agi_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.agi_asc_mult, "0,0.00")} Asc)`,
|
||||
`Ch: x${numeralWrapper.format(memberObj.cha_mult * memberObj.cha_asc_mult, "0,0.00")}(x${numeralWrapper.format(memberObj.cha_mult, "0,0.00")} Eq, x${numeralWrapper.format(memberObj.cha_asc_mult, "0,0.00")} Asc)`].join("<br>");
|
||||
[`Hk: x${numeralWrapper.formatMultiplier(memberObj.hack_mult * memberObj.hack_asc_mult)}(x${numeralWrapper.formatMultiplier(memberObj.hack_mult)} Eq, x${numeralWrapper.formatMultiplier(memberObj.hack_asc_mult)} Asc)`,
|
||||
`St: x${numeralWrapper.formatMultiplier(memberObj.str_mult * memberObj.str_asc_mult)}(x${numeralWrapper.formatMultiplier(memberObj.str_mult)} Eq, x${numeralWrapper.formatMultiplier(memberObj.str_asc_mult)} Asc)`,
|
||||
`Df: x${numeralWrapper.formatMultiplier(memberObj.def_mult * memberObj.def_asc_mult)}(x${numeralWrapper.formatMultiplier(memberObj.def_mult)} Eq, x${numeralWrapper.formatMultiplier(memberObj.def_asc_mult)} Asc)`,
|
||||
`Dx: x${numeralWrapper.formatMultiplier(memberObj.dex_mult * memberObj.dex_asc_mult)}(x${numeralWrapper.formatMultiplier(memberObj.dex_mult)} Eq, x${numeralWrapper.formatMultiplier(memberObj.dex_asc_mult)} Asc)`,
|
||||
`Ag: x${numeralWrapper.formatMultiplier(memberObj.agi_mult * memberObj.agi_asc_mult)}(x${numeralWrapper.formatMultiplier(memberObj.agi_mult)} Eq, x${numeralWrapper.formatMultiplier(memberObj.agi_asc_mult)} Asc)`,
|
||||
`Ch: x${numeralWrapper.formatMultiplier(memberObj.cha_mult * memberObj.cha_asc_mult)}(x${numeralWrapper.formatMultiplier(memberObj.cha_mult)} Eq, x${numeralWrapper.formatMultiplier(memberObj.cha_asc_mult)} Asc)`].join("<br>");
|
||||
}
|
||||
}
|
||||
|
||||
// Update info about gang member's earnings/gains
|
||||
var gainInfo = document.getElementById(name + "gang-member-gain-info");
|
||||
if (gainInfo) {
|
||||
gainInfo.innerHTML =
|
||||
[`Money: ${numeralWrapper.format(5*memberObj.calculateMoneyGain(this), '$0.000a')} / sec`,
|
||||
`Respect: ${numeralWrapper.format(5*memberObj.calculateRespectGain(this), '0.00000a')} / sec`,
|
||||
`Wanted Level: ${numeralWrapper.format(5*memberObj.calculateWantedLevelGain(this), '0.00000a')} / sec`,
|
||||
`Total Respect Earned: ${numeralWrapper.format(memberObj.earnedRespect, '0.00000a')}`].join("<br>");
|
||||
const data = [
|
||||
[`Money:`, MoneyRate(5*memberObj.calculateMoneyGain(this))],
|
||||
[`Respect:`, `${numeralWrapper.formatRespect(5*memberObj.calculateRespectGain(this))} / sec`],
|
||||
[`Wanted Level:`, `${numeralWrapper.formatWanted(5*memberObj.calculateWantedLevelGain(this))} / sec`],
|
||||
[`Total Respect:`, `${numeralWrapper.formatRespect(memberObj.earnedRespect)}`],
|
||||
];
|
||||
ReactDOM.render(StatsTable(data), gainInfo);
|
||||
}
|
||||
|
||||
// Update selector to have the correct task
|
||||
@@ -1,17 +1,19 @@
|
||||
import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers";
|
||||
import { Player } from "./Player";
|
||||
import { IPlayer } from "./PersonObjects/IPlayer";
|
||||
import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence";
|
||||
import { Server } from "./Server/Server";
|
||||
import { HacknetServer } from "./Hacknet/HacknetServer";
|
||||
|
||||
/**
|
||||
* Returns the chance the player has to successfully hack a server
|
||||
*/
|
||||
export function calculateHackingChance(server) {
|
||||
export function calculateHackingChance(server: Server, player: IPlayer): number {
|
||||
const hackFactor = 1.75;
|
||||
const intFactor = 0.2;
|
||||
const difficultyMult = (100 - server.hackDifficulty) / 100;
|
||||
const skillMult = (hackFactor * Player.hacking_skill) + (intFactor * Player.intelligence);
|
||||
const skillMult = hackFactor * player.hacking_skill;
|
||||
const skillChance = (skillMult - server.requiredHackingSkill) / skillMult;
|
||||
const chance = skillChance * difficultyMult * Player.hacking_chance_mult;
|
||||
const chance = skillChance * difficultyMult * player.hacking_chance_mult * calculateIntelligenceBonus(player.intelligence, 1);
|
||||
if (chance > 1) { return 1; }
|
||||
if (chance < 0) { return 0; }
|
||||
|
||||
@@ -22,14 +24,14 @@ export function calculateHackingChance(server) {
|
||||
* Returns the amount of hacking experience the player will gain upon
|
||||
* successfully hacking a server
|
||||
*/
|
||||
export function calculateHackingExpGain(server) {
|
||||
export function calculateHackingExpGain(server: Server, player: IPlayer): number {
|
||||
const baseExpGain = 3;
|
||||
const diffFactor = 0.3;
|
||||
if (server.baseDifficulty == null) {
|
||||
server.baseDifficulty = server.hackDifficulty;
|
||||
}
|
||||
var expGain = baseExpGain;
|
||||
expGain += (server.baseDifficulty * Player.hacking_exp_mult * diffFactor);
|
||||
let expGain = baseExpGain;
|
||||
expGain += (server.baseDifficulty * player.hacking_exp_mult * diffFactor);
|
||||
|
||||
return expGain * BitNodeMultipliers.HackExpGain;
|
||||
}
|
||||
@@ -38,13 +40,13 @@ export function calculateHackingExpGain(server) {
|
||||
* Returns the percentage of money that will be stolen from a server if
|
||||
* it is successfully hacked (returns the decimal form, not the actual percent value)
|
||||
*/
|
||||
export function calculatePercentMoneyHacked(server) {
|
||||
export function calculatePercentMoneyHacked(server: Server, player: IPlayer): number {
|
||||
// Adjust if needed for balancing. This is the divisor for the final calculation
|
||||
const balanceFactor = 240;
|
||||
|
||||
const difficultyMult = (100 - server.hackDifficulty) / 100;
|
||||
const skillMult = (Player.hacking_skill - (server.requiredHackingSkill - 1)) / Player.hacking_skill;
|
||||
const percentMoneyHacked = difficultyMult * skillMult * Player.hacking_money_mult / balanceFactor;
|
||||
const skillMult = (player.hacking_skill - (server.requiredHackingSkill - 1)) / player.hacking_skill;
|
||||
const percentMoneyHacked = difficultyMult * skillMult * player.hacking_money_mult / balanceFactor;
|
||||
if (percentMoneyHacked < 0) { return 0; }
|
||||
if (percentMoneyHacked > 1) { return 1; }
|
||||
|
||||
@@ -54,21 +56,18 @@ export function calculatePercentMoneyHacked(server) {
|
||||
/**
|
||||
* Returns time it takes to complete a hack on a server, in seconds
|
||||
*/
|
||||
export function calculateHackingTime(server, hack, int) {
|
||||
export function calculateHackingTime(server: Server, player: IPlayer): number {
|
||||
const difficultyMult = server.requiredHackingSkill * server.hackDifficulty;
|
||||
|
||||
const baseDiff = 500;
|
||||
const baseSkill = 50;
|
||||
const diffFactor = 2.5;
|
||||
const intFactor = 0.1;
|
||||
if (hack == null) {hack = Player.hacking_skill;}
|
||||
if (int == null) {int = Player.intelligence;}
|
||||
var skillFactor = (diffFactor * difficultyMult + baseDiff);
|
||||
let skillFactor = (diffFactor * difficultyMult + baseDiff);
|
||||
// tslint:disable-next-line
|
||||
skillFactor /= (hack + baseSkill + (intFactor * int));
|
||||
skillFactor /= (player.hacking_skill + baseSkill);
|
||||
|
||||
const hackTimeMultiplier = 5;
|
||||
const hackingTime = hackTimeMultiplier * skillFactor / Player.hacking_speed_mult;
|
||||
const hackingTime = hackTimeMultiplier * skillFactor / (player.hacking_speed_mult * calculateIntelligenceBonus(player.intelligence, 1));
|
||||
|
||||
return hackingTime;
|
||||
}
|
||||
@@ -76,17 +75,17 @@ export function calculateHackingTime(server, hack, int) {
|
||||
/**
|
||||
* Returns time it takes to complete a grow operation on a server, in seconds
|
||||
*/
|
||||
export function calculateGrowTime(server, hack, int) {
|
||||
export function calculateGrowTime(server: Server, player: IPlayer): number {
|
||||
const growTimeMultiplier = 3.2; // Relative to hacking time. 16/5 = 3.2
|
||||
|
||||
return growTimeMultiplier * calculateHackingTime(server, hack, int);
|
||||
return growTimeMultiplier * calculateHackingTime(server, player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns time it takes to complete a weaken operation on a server, in seconds
|
||||
*/
|
||||
export function calculateWeakenTime(server, hack, int) {
|
||||
export function calculateWeakenTime(server: Server, player: IPlayer): number {
|
||||
const weakenTimeMultiplier = 4; // Relative to hacking time
|
||||
|
||||
return weakenTimeMultiplier * calculateHackingTime(server, hack, int);
|
||||
return weakenTimeMultiplier * calculateHackingTime(server, player);
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Utility functions for calculating the maximum number of Hacknet upgrades the player
|
||||
* can purchase for a Node with his/her current money
|
||||
*/
|
||||
@@ -8,24 +8,11 @@
|
||||
*
|
||||
* TODO Should probably split the different types of functions into their own modules
|
||||
*/
|
||||
import {
|
||||
HacknetNode,
|
||||
BaseCostForHacknetNode,
|
||||
HacknetNodePurchaseNextMult,
|
||||
HacknetNodeMaxLevel,
|
||||
HacknetNodeMaxRam,
|
||||
HacknetNodeMaxCores
|
||||
} from "./HacknetNode";
|
||||
import {
|
||||
HacknetServer,
|
||||
BaseCostForHacknetServer,
|
||||
HacknetServerPurchaseMult,
|
||||
HacknetServerMaxLevel,
|
||||
HacknetServerMaxRam,
|
||||
HacknetServerMaxCores,
|
||||
HacknetServerMaxCache,
|
||||
MaxNumberHacknetServers
|
||||
} from "./HacknetServer";
|
||||
import { HacknetNode } from "./HacknetNode";
|
||||
import { calculateNodeCost } from "./formulas/HacknetNodes";
|
||||
import { calculateServerCost } from "./formulas/HacknetServers";
|
||||
import { HacknetNodeConstants, HacknetServerConstants } from "./data/Constants";
|
||||
import { HacknetServer } from "./HacknetServer";
|
||||
import { HashManager } from "./HashManager";
|
||||
import { HashUpgrades } from "./HashUpgrades";
|
||||
|
||||
@@ -105,24 +92,15 @@ export function purchaseHacknet() {
|
||||
}
|
||||
|
||||
export function hasMaxNumberHacknetServers() {
|
||||
return hasHacknetServers() && Player.hacknetNodes.length >= MaxNumberHacknetServers;
|
||||
return hasHacknetServers() && Player.hacknetNodes.length >= HacknetServerConstants.MaxServers;
|
||||
}
|
||||
|
||||
export function getCostOfNextHacknetNode() {
|
||||
// Cost increases exponentially based on how many you own
|
||||
const numOwned = Player.hacknetNodes.length;
|
||||
const mult = HacknetNodePurchaseNextMult;
|
||||
|
||||
return BaseCostForHacknetNode * Math.pow(mult, numOwned) * Player.hacknet_node_purchase_cost_mult;
|
||||
return calculateNodeCost(Player.hacknetNodes.length+1, Player.hacknet_node_purchase_cost_mult);
|
||||
}
|
||||
|
||||
export function getCostOfNextHacknetServer() {
|
||||
const numOwned = Player.hacknetNodes.length;
|
||||
const mult = HacknetServerPurchaseMult;
|
||||
|
||||
if (numOwned >= MaxNumberHacknetServers) { return Infinity; }
|
||||
|
||||
return BaseCostForHacknetServer * Math.pow(mult, numOwned) * Player.hacknet_node_purchase_cost_mult;
|
||||
return calculateServerCost(Player.hacknetNodes.length+1, Player.hacknet_node_purchase_cost_mult);
|
||||
}
|
||||
|
||||
// Calculate the maximum number of times the Player can afford to upgrade a Hacknet Node's level
|
||||
@@ -270,14 +248,14 @@ export function purchaseLevelUpgrade(node, levels=1) {
|
||||
const isServer = (node instanceof HacknetServer);
|
||||
|
||||
// If we're at max level, return false
|
||||
if (node.level >= (isServer ? HacknetServerMaxLevel : HacknetNodeMaxLevel)) {
|
||||
if (node.level >= (isServer ? HacknetServerConstants.MaxLevel : HacknetNodeConstants.MaxLevel)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the number of specified upgrades would exceed the max level, calculate
|
||||
// the maximum number of upgrades and use that
|
||||
if (node.level + sanitizedLevels > (isServer ? HacknetServerMaxLevel : HacknetNodeMaxLevel)) {
|
||||
const diff = Math.max(0, (isServer ? HacknetServerMaxLevel : HacknetNodeMaxLevel) - node.level);
|
||||
if (node.level + sanitizedLevels > (isServer ? HacknetServerConstants.MaxLevel : HacknetNodeConstants.MaxLevel)) {
|
||||
const diff = Math.max(0, (isServer ? HacknetServerConstants.MaxLevel : HacknetNodeConstants.MaxLevel) - node.level);
|
||||
return purchaseLevelUpgrade(node, diff);
|
||||
}
|
||||
|
||||
@@ -301,20 +279,20 @@ export function purchaseRamUpgrade(node, levels=1) {
|
||||
const isServer = (node instanceof HacknetServer);
|
||||
|
||||
// Fail if we're already at max
|
||||
if (node.ram >= (isServer ? HacknetServerMaxRam : HacknetNodeMaxRam)) {
|
||||
if (node.ram >= (isServer ? HacknetServerConstants.MaxRam : HacknetNodeConstants.MaxRam)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the number of specified upgrades would exceed the max RAM, calculate the
|
||||
// max possible number of upgrades and use that
|
||||
if (isServer) {
|
||||
if (node.maxRam * Math.pow(2, sanitizedLevels) > HacknetServerMaxRam) {
|
||||
const diff = Math.max(0, Math.log2(Math.round(HacknetServerMaxRam / node.maxRam)));
|
||||
if (node.maxRam * Math.pow(2, sanitizedLevels) > HacknetServerConstants.MaxRam) {
|
||||
const diff = Math.max(0, Math.log2(Math.round(HacknetServerConstants.MaxRam / node.maxRam)));
|
||||
return purchaseRamUpgrade(node, diff);
|
||||
}
|
||||
} else {
|
||||
if (node.ram * Math.pow(2, sanitizedLevels) > HacknetNodeMaxRam) {
|
||||
const diff = Math.max(0, Math.log2(Math.round(HacknetNodeMaxRam / node.ram)));
|
||||
if (node.ram * Math.pow(2, sanitizedLevels) > HacknetNodeConstants.MaxRam) {
|
||||
const diff = Math.max(0, Math.log2(Math.round(HacknetNodeConstants.MaxRam / node.ram)));
|
||||
return purchaseRamUpgrade(node, diff);
|
||||
}
|
||||
}
|
||||
@@ -340,14 +318,14 @@ export function purchaseCoreUpgrade(node, levels=1) {
|
||||
const isServer = (node instanceof HacknetServer);
|
||||
|
||||
// Fail if we're already at max
|
||||
if (node.cores >= (isServer ? HacknetServerMaxCores : HacknetNodeMaxCores)) {
|
||||
if (node.cores >= (isServer ? HacknetServerConstants.MaxCores : HacknetNodeConstants.MaxCores)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the specified number of upgrades would exceed the max Cores, calculate
|
||||
// the max possible number of upgrades and use that
|
||||
if (node.cores + sanitizedLevels > (isServer ? HacknetServerMaxCores : HacknetNodeMaxCores)) {
|
||||
const diff = Math.max(0, (isServer ? HacknetServerMaxCores : HacknetNodeMaxCores) - node.cores);
|
||||
if (node.cores + sanitizedLevels > (isServer ? HacknetServerConstants.MaxCores : HacknetNodeConstants.MaxCores)) {
|
||||
const diff = Math.max(0, (isServer ? HacknetServerConstants.MaxCores : HacknetNodeConstants.MaxCores) - node.cores);
|
||||
return purchaseCoreUpgrade(node, diff);
|
||||
}
|
||||
|
||||
@@ -374,8 +352,8 @@ export function purchaseCacheUpgrade(node, levels=1) {
|
||||
}
|
||||
|
||||
// Fail if we're already at max
|
||||
if (node.cache + sanitizedLevels > HacknetServerMaxCache) {
|
||||
const diff = Math.max(0, HacknetServerMaxCache - node.cache);
|
||||
if (node.cache + sanitizedLevels > HacknetServerConstants.MaxCache) {
|
||||
const diff = Math.max(0, HacknetServerConstants.MaxCache - node.cache);
|
||||
return purchaseCacheUpgrade(node, diff);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,29 +9,19 @@ import { IHacknetNode } from "./IHacknetNode";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import {
|
||||
calculateMoneyGainRate,
|
||||
calculateLevelUpgradeCost,
|
||||
calculateCoreUpgradeCost,
|
||||
calculateRamUpgradeCost,
|
||||
} from "./formulas/HacknetNodes";
|
||||
import { HacknetNodeConstants } from "./data/Constants";
|
||||
|
||||
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||
import { Generic_fromJSON,
|
||||
Generic_toJSON,
|
||||
Reviver } from "../../utils/JSONReviver";
|
||||
|
||||
// Constants for Hacknet Node production
|
||||
export const HacknetNodeMoneyGainPerLevel: number = 1.6; // Base production per level
|
||||
|
||||
// Constants for Hacknet Node purchase/upgrade costs
|
||||
export const BaseCostForHacknetNode: number = 1000;
|
||||
export const BaseCostFor1GBOfRamHacknetNode: number = 30e3;
|
||||
export const BaseCostForHacknetNodeCore: number = 500e3;
|
||||
export const HacknetNodePurchaseNextMult: number = 1.85; // Multiplier when purchasing an additional hacknet node
|
||||
export const HacknetNodeUpgradeLevelMult: number = 1.04; // Multiplier for cost when upgrading level
|
||||
export const HacknetNodeUpgradeRamMult: number = 1.28; // Multiplier for cost when upgrading RAM
|
||||
export const HacknetNodeUpgradeCoreMult: number = 1.48; // Multiplier for cost when buying another core
|
||||
|
||||
// Constants for max upgrade levels for Hacknet Nodes
|
||||
export const HacknetNodeMaxLevel: number = 200;
|
||||
export const HacknetNodeMaxRam: number = 64;
|
||||
export const HacknetNodeMaxCores: number = 16;
|
||||
|
||||
export class HacknetNode implements IHacknetNode {
|
||||
/**
|
||||
* Initiatizes a HacknetNode object from a JSON save state.
|
||||
@@ -69,79 +59,17 @@ export class HacknetNode implements IHacknetNode {
|
||||
|
||||
// Get the cost to upgrade this Node's number of cores
|
||||
calculateCoreUpgradeCost(levels: number=1, costMult: number): number {
|
||||
const sanitizedLevels = Math.round(levels);
|
||||
if (isNaN(sanitizedLevels) || sanitizedLevels < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this.cores >= HacknetNodeMaxCores) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
const coreBaseCost = BaseCostForHacknetNodeCore;
|
||||
const mult = HacknetNodeUpgradeCoreMult;
|
||||
let totalCost = 0;
|
||||
let currentCores = this.cores;
|
||||
for (let i = 0; i < sanitizedLevels; ++i) {
|
||||
totalCost += (coreBaseCost * Math.pow(mult, currentCores-1));
|
||||
++currentCores;
|
||||
}
|
||||
|
||||
totalCost *= costMult;
|
||||
|
||||
return totalCost;
|
||||
return calculateCoreUpgradeCost(this.cores, levels, costMult);
|
||||
}
|
||||
|
||||
// Get the cost to upgrade this Node's level
|
||||
calculateLevelUpgradeCost(levels: number=1, costMult: number): number {
|
||||
const sanitizedLevels = Math.round(levels);
|
||||
if (isNaN(sanitizedLevels) || sanitizedLevels < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this.level >= HacknetNodeMaxLevel) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
const mult = HacknetNodeUpgradeLevelMult;
|
||||
let totalMultiplier = 0;
|
||||
let currLevel = this.level;
|
||||
for (let i = 0; i < sanitizedLevels; ++i) {
|
||||
totalMultiplier += Math.pow(mult, currLevel);
|
||||
++currLevel;
|
||||
}
|
||||
|
||||
return BaseCostForHacknetNode / 2 * totalMultiplier * costMult;
|
||||
return calculateLevelUpgradeCost(this.level, levels, costMult);
|
||||
}
|
||||
|
||||
// Get the cost to upgrade this Node's RAM
|
||||
calculateRamUpgradeCost(levels: number=1, costMult: number): number {
|
||||
const sanitizedLevels = Math.round(levels);
|
||||
if (isNaN(sanitizedLevels) || sanitizedLevels < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this.ram >= HacknetNodeMaxRam) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
let totalCost = 0;
|
||||
let numUpgrades = Math.round(Math.log2(this.ram));
|
||||
let currentRam = this.ram;
|
||||
|
||||
for (let i = 0; i < sanitizedLevels; ++i) {
|
||||
let baseCost = currentRam * BaseCostFor1GBOfRamHacknetNode;
|
||||
let mult = Math.pow(HacknetNodeUpgradeRamMult, numUpgrades);
|
||||
|
||||
totalCost += (baseCost * mult);
|
||||
|
||||
currentRam *= 2;
|
||||
++numUpgrades;
|
||||
}
|
||||
|
||||
totalCost *= costMult;
|
||||
|
||||
return totalCost;
|
||||
return calculateRamUpgradeCost(this.ram, levels, costMult);
|
||||
}
|
||||
|
||||
// Process this Hacknet Node in the game loop.
|
||||
@@ -163,14 +91,14 @@ export class HacknetNode implements IHacknetNode {
|
||||
// Upgrade this Node's number of cores, if possible
|
||||
// Returns a boolean indicating whether new cores were successfully bought
|
||||
upgradeCore(levels: number=1, prodMult: number): void {
|
||||
this.cores = Math.min(HacknetNodeMaxCores, Math.round(this.cores + levels));
|
||||
this.cores = Math.min(HacknetNodeConstants.MaxCores, Math.round(this.cores + levels));
|
||||
this.updateMoneyGainRate(prodMult);
|
||||
}
|
||||
|
||||
// Upgrade this Node's level, if possible
|
||||
// Returns a boolean indicating whether the level was successfully updated
|
||||
upgradeLevel(levels: number=1, prodMult: number): void {
|
||||
this.level = Math.min(HacknetNodeMaxLevel, Math.round(this.level + levels));
|
||||
this.level = Math.min(HacknetNodeConstants.MaxLevel, Math.round(this.level + levels));
|
||||
this.updateMoneyGainRate(prodMult);
|
||||
}
|
||||
|
||||
@@ -186,14 +114,7 @@ export class HacknetNode implements IHacknetNode {
|
||||
|
||||
// Re-calculate this Node's production and update the moneyGainRatePerSecond prop
|
||||
updateMoneyGainRate(prodMult: number): void {
|
||||
//How much extra $/s is gained per level
|
||||
var gainPerLevel = HacknetNodeMoneyGainPerLevel;
|
||||
|
||||
this.moneyGainRatePerSecond = (this.level * gainPerLevel) *
|
||||
Math.pow(1.035, this.ram - 1) *
|
||||
((this.cores + 5) / 6) *
|
||||
prodMult *
|
||||
BitNodeMultipliers.HacknetNodeMoney;
|
||||
this.moneyGainRatePerSecond = calculateMoneyGainRate(this.level, this.ram, this.cores, prodMult);
|
||||
if (isNaN(this.moneyGainRatePerSecond)) {
|
||||
this.moneyGainRatePerSecond = 0;
|
||||
dialogBoxCreate("Error in calculating Hacknet Node production. Please report to game developer", false);
|
||||
|
||||
@@ -8,6 +8,14 @@ import { IHacknetNode } from "./IHacknetNode";
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import { BaseServer } from "../Server/BaseServer";
|
||||
import { RunningScript } from "../Script/RunningScript";
|
||||
import { HacknetServerConstants } from "./data/Constants";
|
||||
import {
|
||||
calculateHashGainRate,
|
||||
calculateLevelUpgradeCost,
|
||||
calculateRamUpgradeCost,
|
||||
calculateCoreUpgradeCost,
|
||||
calculateCacheUpgradeCost,
|
||||
} from "./formulas/HacknetServers";
|
||||
|
||||
import { createRandomIp } from "../../utils/IPAddress";
|
||||
|
||||
@@ -17,29 +25,6 @@ import {
|
||||
Reviver
|
||||
} from "../../utils/JSONReviver";
|
||||
|
||||
// Constants for Hacknet Server stats/production
|
||||
export const HacknetServerHashesPerLevel: number = 0.001;
|
||||
|
||||
// Constants for Hacknet Server purchase/upgrade costs
|
||||
export const BaseCostForHacknetServer: number = 50e3;
|
||||
export const BaseCostFor1GBHacknetServerRam: number = 200e3;
|
||||
export const BaseCostForHacknetServerCore: number = 1e6;
|
||||
export const BaseCostForHacknetServerCache: number = 10e6;
|
||||
|
||||
export const HacknetServerPurchaseMult: number = 3.2; // Multiplier for puchasing an additional Hacknet Server
|
||||
export const HacknetServerUpgradeLevelMult: number = 1.1; // Multiplier for cost when upgrading level
|
||||
export const HacknetServerUpgradeRamMult: number = 1.4; // Multiplier for cost when upgrading RAM
|
||||
export const HacknetServerUpgradeCoreMult: number = 1.55; // Multiplier for cost when buying another core
|
||||
export const HacknetServerUpgradeCacheMult: number = 1.85; // Multiplier for cost when upgrading cache
|
||||
|
||||
export const MaxNumberHacknetServers: number = 20; // Max number of Hacknet Servers you can own
|
||||
|
||||
// Constants for max upgrade levels for Hacknet Server
|
||||
export const HacknetServerMaxLevel: number = 300;
|
||||
export const HacknetServerMaxRam: number = 8192;
|
||||
export const HacknetServerMaxCores: number = 128;
|
||||
export const HacknetServerMaxCache: number = 15;
|
||||
|
||||
interface IConstructorParams {
|
||||
adminRights?: boolean;
|
||||
hostname: string;
|
||||
@@ -73,7 +58,7 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
|
||||
// How long this HacknetServer has existed, in seconds
|
||||
onlineTimeSeconds: number = 0;
|
||||
|
||||
// Total number of hashes earned by this
|
||||
// Total number of hashes earned by this server
|
||||
totalHashesGenerated: number = 0;
|
||||
|
||||
constructor(params: IConstructorParams={ hostname: "", ip: createRandomIp() }) {
|
||||
@@ -84,96 +69,19 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
|
||||
}
|
||||
|
||||
calculateCacheUpgradeCost(levels: number): number {
|
||||
const sanitizedLevels = Math.round(levels);
|
||||
if (isNaN(sanitizedLevels) || sanitizedLevels < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this.cache >= HacknetServerMaxCache) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
const mult = HacknetServerUpgradeCacheMult;
|
||||
let totalCost = 0;
|
||||
let currentCache = this.cache;
|
||||
for (let i = 0; i < sanitizedLevels; ++i) {
|
||||
totalCost += Math.pow(mult, currentCache - 1);
|
||||
++currentCache;
|
||||
}
|
||||
totalCost *= BaseCostForHacknetServerCache;
|
||||
|
||||
return totalCost;
|
||||
return calculateCacheUpgradeCost(this.cache, levels);
|
||||
}
|
||||
|
||||
calculateCoreUpgradeCost(levels: number, costMult: number): number {
|
||||
const sanitizedLevels = Math.round(levels);
|
||||
if (isNaN(sanitizedLevels) || sanitizedLevels < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this.cores >= HacknetServerMaxCores) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
const mult = HacknetServerUpgradeCoreMult;
|
||||
let totalCost = 0;
|
||||
let currentCores = this.cores;
|
||||
for (let i = 0; i < sanitizedLevels; ++i) {
|
||||
totalCost += Math.pow(mult, currentCores-1);
|
||||
++currentCores;
|
||||
}
|
||||
totalCost *= BaseCostForHacknetServerCore;
|
||||
totalCost *= costMult;
|
||||
|
||||
return totalCost;
|
||||
return calculateCoreUpgradeCost(this.cores, levels, costMult);
|
||||
}
|
||||
|
||||
calculateLevelUpgradeCost(levels: number, costMult: number): number {
|
||||
const sanitizedLevels = Math.round(levels);
|
||||
if (isNaN(sanitizedLevels) || sanitizedLevels < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this.level >= HacknetServerMaxLevel) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
const mult = HacknetServerUpgradeLevelMult;
|
||||
let totalMultiplier = 0;
|
||||
let currLevel = this.level;
|
||||
for (let i = 0; i < sanitizedLevels; ++i) {
|
||||
totalMultiplier += Math.pow(mult, currLevel);
|
||||
++currLevel;
|
||||
}
|
||||
|
||||
return 10 * BaseCostForHacknetServer * totalMultiplier * costMult;
|
||||
return calculateLevelUpgradeCost(this.level, levels, costMult);
|
||||
}
|
||||
|
||||
calculateRamUpgradeCost(levels: number, costMult: number): number {
|
||||
const sanitizedLevels = Math.round(levels);
|
||||
if (isNaN(sanitizedLevels) || sanitizedLevels < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this.maxRam >= HacknetServerMaxRam) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
let totalCost = 0;
|
||||
let numUpgrades = Math.round(Math.log2(this.maxRam));
|
||||
let currentRam = this.maxRam;
|
||||
for (let i = 0; i < sanitizedLevels; ++i) {
|
||||
let baseCost = currentRam * BaseCostFor1GBHacknetServerRam;
|
||||
let mult = Math.pow(HacknetServerUpgradeRamMult, numUpgrades);
|
||||
|
||||
totalCost += (baseCost * mult);
|
||||
|
||||
currentRam *= 2;
|
||||
++numUpgrades;
|
||||
}
|
||||
totalCost *= costMult;
|
||||
|
||||
return totalCost;
|
||||
return calculateRamUpgradeCost(this.maxRam, levels, costMult);
|
||||
}
|
||||
|
||||
// Process this Hacknet Server in the game loop. Returns the number of hashes generated
|
||||
@@ -184,17 +92,17 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
|
||||
}
|
||||
|
||||
upgradeCache(levels: number): void {
|
||||
this.cache = Math.min(HacknetServerMaxCache, Math.round(this.cache + levels));
|
||||
this.cache = Math.min(HacknetServerConstants.MaxCache, Math.round(this.cache + levels));
|
||||
this.updateHashCapacity();
|
||||
}
|
||||
|
||||
upgradeCore(levels: number, prodMult: number): void {
|
||||
this.cores = Math.min(HacknetServerMaxCores, Math.round(this.cores + levels));
|
||||
this.cores = Math.min(HacknetServerConstants.MaxCores, Math.round(this.cores + levels));
|
||||
this.updateHashRate(prodMult);
|
||||
}
|
||||
|
||||
upgradeLevel(levels: number, prodMult: number): void {
|
||||
this.level = Math.min(HacknetServerMaxLevel, Math.round(this.level + levels));
|
||||
this.level = Math.min(HacknetServerConstants.MaxLevel, Math.round(this.level + levels));
|
||||
this.updateHashRate(prodMult);
|
||||
}
|
||||
|
||||
@@ -202,7 +110,7 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
|
||||
for (let i = 0; i < levels; ++i) {
|
||||
this.maxRam *= 2;
|
||||
}
|
||||
this.maxRam = Math.min(HacknetServerMaxRam, Math.round(this.maxRam));
|
||||
this.maxRam = Math.min(HacknetServerConstants.MaxRam, Math.round(this.maxRam));
|
||||
this.updateHashRate(prodMult);
|
||||
|
||||
return true;
|
||||
@@ -221,14 +129,7 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
|
||||
}
|
||||
|
||||
updateHashRate(prodMult: number): void {
|
||||
const baseGain = HacknetServerHashesPerLevel * this.level;
|
||||
const ramMultiplier = Math.pow(1.07, Math.log2(this.maxRam));
|
||||
const coreMultiplier = 1 + (this.cores - 1) / 5;
|
||||
const ramRatio = (1 - this.ramUsed / this.maxRam);
|
||||
|
||||
const hashRate = baseGain * ramMultiplier * coreMultiplier * ramRatio;
|
||||
|
||||
this.hashRate = hashRate * prodMult * BitNodeMultipliers.HacknetNodeMoney;
|
||||
this.hashRate = calculateHashGainRate(this.level, this.ramUsed, this.maxRam, this.cores, prodMult)
|
||||
|
||||
if (isNaN(this.hashRate)) {
|
||||
this.hashRate = 0;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* those upgrades
|
||||
*/
|
||||
import { HashUpgrades } from "./HashUpgrades";
|
||||
import { HashUpgrade } from "./HashUpgrade";
|
||||
|
||||
import { IMap } from "../types";
|
||||
import { Generic_fromJSON,
|
||||
@@ -67,11 +68,20 @@ export class HashManager {
|
||||
return this.getMult(upgName);
|
||||
}
|
||||
|
||||
getUpgrade(upgName: string): HashUpgrade | null {
|
||||
const upg = HashUpgrades[upgName];
|
||||
if (!upg) {
|
||||
console.error(`Invalid Upgrade Name given to HashManager.getUpgrade(): ${upgName}`);
|
||||
return null;
|
||||
}
|
||||
return upg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cost (in hashes) of an upgrade
|
||||
*/
|
||||
getUpgradeCost(upgName: string): number {
|
||||
const upg = HashUpgrades[upgName];
|
||||
const upg = this.getUpgrade(upgName);
|
||||
const currLevel = this.upgrades[upgName];
|
||||
if (upg == null || currLevel == null) {
|
||||
console.error(`Invalid Upgrade Name given to HashManager.getUpgradeCost(): ${upgName}`);
|
||||
|
||||
80
src/Hacknet/data/Constants.ts
Normal file
80
src/Hacknet/data/Constants.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
export const HacknetNodeConstants: {
|
||||
// Constants for Hacknet Node production
|
||||
MoneyGainPerLevel: number;
|
||||
|
||||
// Constants for Hacknet Node purchase/upgrade costs
|
||||
BaseCost: number;
|
||||
LevelBaseCost: number;
|
||||
RamBaseCost: number;
|
||||
CoreBaseCost: number;
|
||||
|
||||
PurchaseNextMult: number;
|
||||
UpgradeLevelMult: number;
|
||||
UpgradeRamMult: number;
|
||||
UpgradeCoreMult: number;
|
||||
|
||||
// Constants for max upgrade levels for Hacknet Nodes
|
||||
MaxLevel: number;
|
||||
MaxRam: number;
|
||||
MaxCores: number;
|
||||
} = {
|
||||
MoneyGainPerLevel: 1.6,
|
||||
|
||||
BaseCost: 1000,
|
||||
LevelBaseCost: 1,
|
||||
RamBaseCost: 30e3,
|
||||
CoreBaseCost: 500e3,
|
||||
|
||||
PurchaseNextMult: 1.85,
|
||||
UpgradeLevelMult: 1.04,
|
||||
UpgradeRamMult: 1.28,
|
||||
UpgradeCoreMult: 1.48,
|
||||
|
||||
MaxLevel: 200,
|
||||
MaxRam: 64,
|
||||
MaxCores: 16,
|
||||
}
|
||||
|
||||
export const HacknetServerConstants: {
|
||||
// Constants for Hacknet Server stats/production
|
||||
HashesPerLevel: number;
|
||||
|
||||
// Constants for Hacknet Server purchase/upgrade costs
|
||||
BaseCost: number;
|
||||
RamBaseCost: number;
|
||||
CoreBaseCost: number;
|
||||
CacheBaseCost: number;
|
||||
|
||||
PurchaseMult: number; // Multiplier for puchasing an additional Hacknet Server
|
||||
UpgradeLevelMult: number; // Multiplier for cost when upgrading level
|
||||
UpgradeRamMult: number; // Multiplier for cost when upgrading RAM
|
||||
UpgradeCoreMult: number; // Multiplier for cost when buying another core
|
||||
UpgradeCacheMult: number; // Multiplier for cost when upgrading cache
|
||||
MaxServers: number; // Max number of Hacknet Servers you can own
|
||||
|
||||
// Constants for max upgrade levels for Hacknet Server
|
||||
MaxLevel: number;
|
||||
MaxRam: number;
|
||||
MaxCores: number;
|
||||
MaxCache: number;
|
||||
} = {
|
||||
HashesPerLevel: 0.001,
|
||||
|
||||
BaseCost: 50e3,
|
||||
RamBaseCost: 200e3,
|
||||
CoreBaseCost: 1e6,
|
||||
CacheBaseCost: 10e6,
|
||||
|
||||
PurchaseMult: 3.20,
|
||||
UpgradeLevelMult: 1.10,
|
||||
UpgradeRamMult: 1.40,
|
||||
UpgradeCoreMult: 1.55,
|
||||
UpgradeCacheMult: 1.85,
|
||||
|
||||
MaxServers: 20,
|
||||
|
||||
MaxLevel: 300,
|
||||
MaxRam: 8192,
|
||||
MaxCores: 128,
|
||||
MaxCache: 15,
|
||||
}
|
||||
96
src/Hacknet/formulas/HacknetNodes.ts
Normal file
96
src/Hacknet/formulas/HacknetNodes.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||
import { HacknetNodeConstants } from "../data/Constants";
|
||||
|
||||
export function calculateMoneyGainRate(level: number, ram: number, cores: number, mult: number): number {
|
||||
const gainPerLevel = HacknetNodeConstants.MoneyGainPerLevel;
|
||||
|
||||
const levelMult = (level * gainPerLevel);
|
||||
const ramMult = Math.pow(1.035, ram - 1);
|
||||
const coresMult = ((cores + 5) / 6);
|
||||
return levelMult *
|
||||
ramMult *
|
||||
coresMult *
|
||||
mult *
|
||||
BitNodeMultipliers.HacknetNodeMoney;
|
||||
}
|
||||
|
||||
export function calculateLevelUpgradeCost(startingLevel: number, extraLevels: number=1, costMult: number=1): number {
|
||||
const sanitizedLevels = Math.round(extraLevels);
|
||||
if (isNaN(sanitizedLevels) || sanitizedLevels < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (startingLevel >= HacknetNodeConstants.MaxLevel) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
const mult = HacknetNodeConstants.UpgradeLevelMult;
|
||||
let totalMultiplier = 0;
|
||||
let currLevel = startingLevel;
|
||||
for (let i = 0; i < sanitizedLevels; ++i) {
|
||||
totalMultiplier += (HacknetNodeConstants.LevelBaseCost * Math.pow(mult, currLevel));
|
||||
++currLevel;
|
||||
}
|
||||
|
||||
return HacknetNodeConstants.BaseCost / 2 * totalMultiplier * costMult;
|
||||
}
|
||||
|
||||
export function calculateRamUpgradeCost(startingRam: number, extraLevels: number=1, costMult: number=1): number {
|
||||
const sanitizedLevels = Math.round(extraLevels);
|
||||
if (isNaN(sanitizedLevels) || sanitizedLevels < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (startingRam >= HacknetNodeConstants.MaxRam) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
let totalCost = 0;
|
||||
let numUpgrades = Math.round(Math.log2(startingRam));
|
||||
let currentRam = startingRam;
|
||||
|
||||
for (let i = 0; i < sanitizedLevels; ++i) {
|
||||
const baseCost = currentRam * HacknetNodeConstants.RamBaseCost;
|
||||
const mult = Math.pow(HacknetNodeConstants.UpgradeRamMult, numUpgrades);
|
||||
|
||||
totalCost += (baseCost * mult);
|
||||
|
||||
currentRam *= 2;
|
||||
++numUpgrades;
|
||||
}
|
||||
|
||||
totalCost *= costMult;
|
||||
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
export function calculateCoreUpgradeCost(startingCore: number, extraLevels: number=1, costMult: number=1): number {
|
||||
const sanitizedCores = Math.round(extraLevels);
|
||||
if (isNaN(sanitizedCores) || sanitizedCores < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (startingCore >= HacknetNodeConstants.MaxCores) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
const coreBaseCost = HacknetNodeConstants.CoreBaseCost;
|
||||
const mult = HacknetNodeConstants.UpgradeCoreMult;
|
||||
let totalCost = 0;
|
||||
let currentCores = startingCore;
|
||||
for (let i = 0; i < sanitizedCores; ++i) {
|
||||
totalCost += (coreBaseCost * Math.pow(mult, currentCores-1));
|
||||
++currentCores;
|
||||
}
|
||||
|
||||
totalCost *= costMult;
|
||||
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
export function calculateNodeCost(n: number, mult: number=1): number {
|
||||
if(n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return HacknetNodeConstants.BaseCost * Math.pow(HacknetNodeConstants.PurchaseNextMult, n-1) * mult;
|
||||
}
|
||||
115
src/Hacknet/formulas/HacknetServers.ts
Normal file
115
src/Hacknet/formulas/HacknetServers.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||
import { HacknetServerConstants } from "../data/Constants";
|
||||
|
||||
export function calculateHashGainRate(level: number, ramUsed: number, maxRam: number, cores: number, mult: number): number {
|
||||
const baseGain = HacknetServerConstants.HashesPerLevel * level;
|
||||
const ramMultiplier = Math.pow(1.07, Math.log2(maxRam));
|
||||
const coreMultiplier = 1 + (cores - 1) / 5;
|
||||
const ramRatio = (1 - ramUsed / maxRam);
|
||||
|
||||
return baseGain *
|
||||
ramMultiplier *
|
||||
coreMultiplier *
|
||||
ramRatio *
|
||||
mult *
|
||||
BitNodeMultipliers.HacknetNodeMoney;
|
||||
}
|
||||
|
||||
export function calculateLevelUpgradeCost(startingLevel: number, extraLevels: number=1, costMult: number=1): number {
|
||||
const sanitizedLevels = Math.round(extraLevels);
|
||||
if (isNaN(sanitizedLevels) || sanitizedLevels < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (startingLevel >= HacknetServerConstants.MaxLevel) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
const mult = HacknetServerConstants.UpgradeLevelMult;
|
||||
let totalMultiplier = 0;
|
||||
let currLevel = startingLevel;
|
||||
for (let i = 0; i < sanitizedLevels; ++i) {
|
||||
totalMultiplier += Math.pow(mult, currLevel);
|
||||
++currLevel;
|
||||
}
|
||||
|
||||
return 10 * HacknetServerConstants.BaseCost * totalMultiplier * costMult;
|
||||
}
|
||||
|
||||
export function calculateRamUpgradeCost(startingRam: number, extraLevels: number=1, costMult: number=1): number {
|
||||
const sanitizedLevels = Math.round(extraLevels);
|
||||
if (isNaN(sanitizedLevels) || sanitizedLevels < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (startingRam >= HacknetServerConstants.MaxRam) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
let totalCost = 0;
|
||||
let numUpgrades = Math.round(Math.log2(startingRam));
|
||||
let currentRam = startingRam;
|
||||
for (let i = 0; i < sanitizedLevels; ++i) {
|
||||
let baseCost = currentRam * HacknetServerConstants.RamBaseCost;
|
||||
let mult = Math.pow(HacknetServerConstants.UpgradeRamMult, numUpgrades);
|
||||
|
||||
totalCost += (baseCost * mult);
|
||||
|
||||
currentRam *= 2;
|
||||
++numUpgrades;
|
||||
}
|
||||
totalCost *= costMult;
|
||||
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
export function calculateCoreUpgradeCost(startingCores: number, extraLevels: number=1, costMult: number=1): number {
|
||||
const sanitizedLevels = Math.round(extraLevels);
|
||||
if (isNaN(sanitizedLevels) || sanitizedLevels < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (startingCores >= HacknetServerConstants.MaxCores) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
const mult = HacknetServerConstants.UpgradeCoreMult;
|
||||
let totalCost = 0;
|
||||
let currentCores = startingCores;
|
||||
for (let i = 0; i < sanitizedLevels; ++i) {
|
||||
totalCost += Math.pow(mult, currentCores-1);
|
||||
++currentCores;
|
||||
}
|
||||
totalCost *= HacknetServerConstants.CoreBaseCost;
|
||||
totalCost *= costMult;
|
||||
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
export function calculateCacheUpgradeCost(startingCache: number, extraLevels: number=1): number {
|
||||
const sanitizedLevels = Math.round(extraLevels);
|
||||
if (isNaN(sanitizedLevels) || sanitizedLevels < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (startingCache >= HacknetServerConstants.MaxCache) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
const mult = HacknetServerConstants.UpgradeCacheMult;
|
||||
let totalCost = 0;
|
||||
let currentCache = startingCache;
|
||||
for (let i = 0; i < sanitizedLevels; ++i) {
|
||||
totalCost += Math.pow(mult, currentCache - 1);
|
||||
++currentCache;
|
||||
}
|
||||
totalCost *= HacknetServerConstants.CacheBaseCost;
|
||||
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
export function calculateServerCost(n: number, mult: number=1): number {
|
||||
if (n-1 >= HacknetServerConstants.MaxServers) { return Infinity; }
|
||||
|
||||
return HacknetServerConstants.BaseCost * Math.pow(HacknetServerConstants.PurchaseMult, n-1) * mult;
|
||||
}
|
||||
@@ -42,11 +42,9 @@ export class GeneralInfo extends React.Component {
|
||||
hackers all around the world to anonymously share computing power and
|
||||
perform distributed cyberattacks without the fear of being traced.
|
||||
</p>
|
||||
<br />
|
||||
<p className={"hacknet-general-info"}>
|
||||
{this.getSecondParagraph()}
|
||||
</p>
|
||||
<br />
|
||||
<p className={"hacknet-general-info"}>
|
||||
{this.getThirdParagraph()}
|
||||
</p>
|
||||
|
||||
@@ -4,11 +4,7 @@
|
||||
*/
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
HacknetNodeMaxLevel,
|
||||
HacknetNodeMaxRam,
|
||||
HacknetNodeMaxCores
|
||||
} from "../HacknetNode";
|
||||
import { HacknetNodeConstants } from "../data/Constants";
|
||||
import {
|
||||
getMaxNumberLevelUpgrades,
|
||||
getMaxNumberRamUpgrades,
|
||||
@@ -21,6 +17,8 @@ import {
|
||||
import { Player } from "../../Player";
|
||||
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { MoneyRate } from "../../ui/React/MoneyRate";
|
||||
|
||||
export class HacknetNode extends React.Component {
|
||||
render() {
|
||||
@@ -29,21 +27,21 @@ export class HacknetNode extends React.Component {
|
||||
const recalculate = this.props.recalculate;
|
||||
|
||||
// Upgrade Level Button
|
||||
let upgradeLevelText, upgradeLevelClass;
|
||||
if (node.level >= HacknetNodeMaxLevel) {
|
||||
upgradeLevelText = "MAX LEVEL";
|
||||
let upgradeLevelContent, upgradeLevelClass;
|
||||
if (node.level >= HacknetNodeConstants.MaxLevel) {
|
||||
upgradeLevelContent = <>MAX LEVEL</>;
|
||||
upgradeLevelClass = "std-button-disabled";
|
||||
} else {
|
||||
let multiplier = 0;
|
||||
if (purchaseMult === "MAX") {
|
||||
multiplier = getMaxNumberLevelUpgrades(node, HacknetNodeMaxLevel);
|
||||
multiplier = getMaxNumberLevelUpgrades(node, HacknetNodeConstants.MaxLevel);
|
||||
} else {
|
||||
const levelsToMax = HacknetNodeMaxLevel - node.level;
|
||||
const levelsToMax = HacknetNodeConstants.MaxLevel - node.level;
|
||||
multiplier = Math.min(levelsToMax, purchaseMult);
|
||||
}
|
||||
|
||||
const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, Player.hacknet_node_level_cost_mult);
|
||||
upgradeLevelText = `Upgrade x${multiplier} - ${numeralWrapper.formatMoney(upgradeLevelCost)}`;
|
||||
upgradeLevelContent = <>Upgrade x{multiplier} - {Money(upgradeLevelCost)}</>;
|
||||
if (Player.money.lt(upgradeLevelCost)) {
|
||||
upgradeLevelClass = "std-button-disabled";
|
||||
} else {
|
||||
@@ -53,28 +51,28 @@ export class HacknetNode extends React.Component {
|
||||
const upgradeLevelOnClick = () => {
|
||||
let numUpgrades = purchaseMult;
|
||||
if (purchaseMult === "MAX") {
|
||||
numUpgrades = getMaxNumberLevelUpgrades(node, HacknetNodeMaxLevel);
|
||||
numUpgrades = getMaxNumberLevelUpgrades(node, HacknetNodeConstants.MaxLevel);
|
||||
}
|
||||
purchaseLevelUpgrade(node, numUpgrades);
|
||||
recalculate();
|
||||
return false;
|
||||
}
|
||||
|
||||
let upgradeRamText, upgradeRamClass;
|
||||
if (node.ram >= HacknetNodeMaxRam) {
|
||||
upgradeRamText = "MAX RAM";
|
||||
let upgradeRamContent, upgradeRamClass;
|
||||
if (node.ram >= HacknetNodeConstants.MaxRam) {
|
||||
upgradeRamContent = <>MAX RAM</>;
|
||||
upgradeRamClass = "std-button-disabled";
|
||||
} else {
|
||||
let multiplier = 0;
|
||||
if (purchaseMult === "MAX") {
|
||||
multiplier = getMaxNumberRamUpgrades(node, HacknetNodeMaxRam);
|
||||
multiplier = getMaxNumberRamUpgrades(node, HacknetNodeConstants.MaxRam);
|
||||
} else {
|
||||
const levelsToMax = Math.round(Math.log2(HacknetNodeMaxRam / node.ram));
|
||||
const levelsToMax = Math.round(Math.log2(HacknetNodeConstants.MaxRam / node.ram));
|
||||
multiplier = Math.min(levelsToMax, purchaseMult);
|
||||
}
|
||||
|
||||
const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, Player.hacknet_node_ram_cost_mult);
|
||||
upgradeRamText = `Upgrade x${multiplier} - ${numeralWrapper.formatMoney(upgradeRamCost)}`;
|
||||
upgradeRamContent = <>Upgrade x{multiplier} - {Money(upgradeRamCost)}</>;
|
||||
if (Player.money.lt(upgradeRamCost)) {
|
||||
upgradeRamClass = "std-button-disabled";
|
||||
} else {
|
||||
@@ -84,28 +82,28 @@ export class HacknetNode extends React.Component {
|
||||
const upgradeRamOnClick = () => {
|
||||
let numUpgrades = purchaseMult;
|
||||
if (purchaseMult === "MAX") {
|
||||
numUpgrades = getMaxNumberRamUpgrades(node, HacknetNodeMaxRam);
|
||||
numUpgrades = getMaxNumberRamUpgrades(node, HacknetNodeConstants.MaxRam);
|
||||
}
|
||||
purchaseRamUpgrade(node, numUpgrades);
|
||||
recalculate();
|
||||
return false;
|
||||
}
|
||||
|
||||
let upgradeCoresText, upgradeCoresClass;
|
||||
if (node.cores >= HacknetNodeMaxCores) {
|
||||
upgradeCoresText = "MAX CORES";
|
||||
let upgradeCoresContent, upgradeCoresClass;
|
||||
if (node.cores >= HacknetNodeConstants.MaxCores) {
|
||||
upgradeCoresContent = <>MAX CORES</>;
|
||||
upgradeCoresClass = "std-button-disabled";
|
||||
} else {
|
||||
let multiplier = 0;
|
||||
if (purchaseMult === "MAX") {
|
||||
multiplier = getMaxNumberCoreUpgrades(node, HacknetNodeMaxCores);
|
||||
multiplier = getMaxNumberCoreUpgrades(node, HacknetNodeConstants.MaxCores);
|
||||
} else {
|
||||
const levelsToMax = HacknetNodeMaxCores - node.cores;
|
||||
const levelsToMax = HacknetNodeConstants.MaxCores - node.cores;
|
||||
multiplier = Math.min(levelsToMax, purchaseMult);
|
||||
}
|
||||
|
||||
const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, Player.hacknet_node_core_cost_mult);
|
||||
upgradeCoresText = `Upgrade x${multiplier} - ${numeralWrapper.formatMoney(upgradeCoreCost)}`;
|
||||
upgradeCoresContent = <>Upgrade x{multiplier} - {Money(upgradeCoreCost)}</>;
|
||||
if (Player.money.lt(upgradeCoreCost)) {
|
||||
upgradeCoresClass = "std-button-disabled";
|
||||
} else {
|
||||
@@ -115,7 +113,7 @@ export class HacknetNode extends React.Component {
|
||||
const upgradeCoresOnClick = () => {
|
||||
let numUpgrades = purchaseMult;
|
||||
if (purchaseMult === "MAX") {
|
||||
numUpgrades = getMaxNumberCoreUpgrades(node, HacknetNodeMaxCores);
|
||||
numUpgrades = getMaxNumberCoreUpgrades(node, HacknetNodeConstants.MaxCores);
|
||||
}
|
||||
purchaseCoreUpgrade(node, numUpgrades);
|
||||
recalculate();
|
||||
@@ -132,25 +130,28 @@ export class HacknetNode extends React.Component {
|
||||
<div className={"row"}>
|
||||
<p>Production:</p>
|
||||
<span className={"text money-gold"}>
|
||||
{numeralWrapper.formatMoney(node.totalMoneyGenerated)} ({numeralWrapper.formatMoney(node.moneyGainRatePerSecond)} / sec)
|
||||
{Money(node.totalMoneyGenerated)} ({MoneyRate(node.moneyGainRatePerSecond)})
|
||||
</span>
|
||||
</div>
|
||||
<div className={"row"}>
|
||||
<p>Level:</p><span className={"text upgradable-info"}>{node.level}</span>
|
||||
<p>Level:</p>
|
||||
<span className={"text upgradable-info"}>{node.level}</span>
|
||||
<button className={upgradeLevelClass} onClick={upgradeLevelOnClick}>
|
||||
{upgradeLevelText}
|
||||
{upgradeLevelContent}
|
||||
</button>
|
||||
</div>
|
||||
<div className={"row"}>
|
||||
<p>RAM:</p><span className={"text upgradable-info"}>{node.ram}GB</span>
|
||||
<p>RAM:</p>
|
||||
<span className={"text upgradable-info"}>{node.ram}GB</span>
|
||||
<button className={upgradeRamClass} onClick={upgradeRamOnClick}>
|
||||
{upgradeRamText}
|
||||
{upgradeRamContent}
|
||||
</button>
|
||||
</div>
|
||||
<div className={"row"}>
|
||||
<p>Cores:</p><span className={"text upgradable-info"}>{node.cores}</span>
|
||||
<p>Cores:</p>
|
||||
<span className={"text upgradable-info"}>{node.cores}</span>
|
||||
<button className={upgradeCoresClass} onClick={upgradeCoresOnClick}>
|
||||
{upgradeCoresText}
|
||||
{upgradeCoresContent}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,12 +4,7 @@
|
||||
*/
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
HacknetServerMaxLevel,
|
||||
HacknetServerMaxRam,
|
||||
HacknetServerMaxCores,
|
||||
HacknetServerMaxCache
|
||||
} from "../HacknetServer";
|
||||
import { HacknetServerConstants } from "../data/Constants";
|
||||
import {
|
||||
getMaxNumberLevelUpgrades,
|
||||
getMaxNumberRamUpgrades,
|
||||
@@ -25,6 +20,9 @@ import {
|
||||
import { Player } from "../../Player";
|
||||
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { Hashes } from "../../ui/React/Hashes";
|
||||
import { HashRate } from "../../ui/React/HashRate";
|
||||
|
||||
export class HacknetServer extends React.Component {
|
||||
render() {
|
||||
@@ -33,21 +31,21 @@ export class HacknetServer extends React.Component {
|
||||
const recalculate = this.props.recalculate;
|
||||
|
||||
// Upgrade Level Button
|
||||
let upgradeLevelText, upgradeLevelClass;
|
||||
if (node.level >= HacknetServerMaxLevel) {
|
||||
upgradeLevelText = "MAX LEVEL";
|
||||
let upgradeLevelContent, upgradeLevelClass;
|
||||
if (node.level >= HacknetServerConstants.MaxLevel) {
|
||||
upgradeLevelContent = <>MAX LEVEL</>;
|
||||
upgradeLevelClass = "std-button-disabled";
|
||||
} else {
|
||||
let multiplier = 0;
|
||||
if (purchaseMult === "MAX") {
|
||||
multiplier = getMaxNumberLevelUpgrades(node, HacknetServerMaxLevel);
|
||||
multiplier = getMaxNumberLevelUpgrades(node, HacknetServerConstants.MaxLevel);
|
||||
} else {
|
||||
const levelsToMax = HacknetServerMaxLevel - node.level;
|
||||
const levelsToMax = HacknetServerConstants.MaxLevel - node.level;
|
||||
multiplier = Math.min(levelsToMax, purchaseMult);
|
||||
}
|
||||
|
||||
const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, Player.hacknet_node_level_cost_mult);
|
||||
upgradeLevelText = `Upgrade x${multiplier} - ${numeralWrapper.formatMoney(upgradeLevelCost)}`;
|
||||
upgradeLevelContent = <>Upgrade x{multiplier} - {Money(upgradeLevelCost)}</>;
|
||||
if (Player.money.lt(upgradeLevelCost)) {
|
||||
upgradeLevelClass = "std-button-disabled";
|
||||
} else {
|
||||
@@ -57,7 +55,7 @@ export class HacknetServer extends React.Component {
|
||||
const upgradeLevelOnClick = () => {
|
||||
let numUpgrades = purchaseMult;
|
||||
if (purchaseMult === "MAX") {
|
||||
numUpgrades = getMaxNumberLevelUpgrades(node, HacknetServerMaxLevel);
|
||||
numUpgrades = getMaxNumberLevelUpgrades(node, HacknetServerConstants.MaxLevel);
|
||||
}
|
||||
purchaseLevelUpgrade(node, numUpgrades);
|
||||
recalculate();
|
||||
@@ -65,21 +63,21 @@ export class HacknetServer extends React.Component {
|
||||
}
|
||||
|
||||
// Upgrade RAM Button
|
||||
let upgradeRamText, upgradeRamClass;
|
||||
if (node.maxRam >= HacknetServerMaxRam) {
|
||||
upgradeRamText = "MAX RAM";
|
||||
let upgradeRamContent, upgradeRamClass;
|
||||
if (node.maxRam >= HacknetServerConstants.MaxRam) {
|
||||
upgradeRamContent = <>MAX RAM</>;
|
||||
upgradeRamClass = "std-button-disabled";
|
||||
} else {
|
||||
let multiplier = 0;
|
||||
if (purchaseMult === "MAX") {
|
||||
multiplier = getMaxNumberRamUpgrades(node, HacknetServerMaxRam);
|
||||
multiplier = getMaxNumberRamUpgrades(node, HacknetServerConstants.MaxRam);
|
||||
} else {
|
||||
const levelsToMax = Math.round(Math.log2(HacknetServerMaxRam / node.maxRam));
|
||||
const levelsToMax = Math.round(Math.log2(HacknetServerConstants.MaxRam / node.maxRam));
|
||||
multiplier = Math.min(levelsToMax, purchaseMult);
|
||||
}
|
||||
|
||||
const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, Player.hacknet_node_ram_cost_mult);
|
||||
upgradeRamText = `Upgrade x${multiplier} - ${numeralWrapper.formatMoney(upgradeRamCost)}`;
|
||||
upgradeRamContent = <>Upgrade x{multiplier} - {Money(upgradeRamCost)}</>;
|
||||
if (Player.money.lt(upgradeRamCost)) {
|
||||
upgradeRamClass = "std-button-disabled";
|
||||
} else {
|
||||
@@ -89,7 +87,7 @@ export class HacknetServer extends React.Component {
|
||||
const upgradeRamOnClick = () => {
|
||||
let numUpgrades = purchaseMult;
|
||||
if (purchaseMult === "MAX") {
|
||||
numUpgrades = getMaxNumberRamUpgrades(node, HacknetServerMaxRam);
|
||||
numUpgrades = getMaxNumberRamUpgrades(node, HacknetServerConstants.MaxRam);
|
||||
}
|
||||
purchaseRamUpgrade(node, numUpgrades);
|
||||
recalculate();
|
||||
@@ -97,21 +95,21 @@ export class HacknetServer extends React.Component {
|
||||
}
|
||||
|
||||
// Upgrade Cores Button
|
||||
let upgradeCoresText, upgradeCoresClass;
|
||||
if (node.cores >= HacknetServerMaxCores) {
|
||||
upgradeCoresText = "MAX CORES";
|
||||
let upgradeCoresContent, upgradeCoresClass;
|
||||
if (node.cores >= HacknetServerConstants.MaxCores) {
|
||||
upgradeCoresContent = <>MAX CORES</>;
|
||||
upgradeCoresClass = "std-button-disabled";
|
||||
} else {
|
||||
let multiplier = 0;
|
||||
if (purchaseMult === "MAX") {
|
||||
multiplier = getMaxNumberCoreUpgrades(node, HacknetServerMaxCores);
|
||||
multiplier = getMaxNumberCoreUpgrades(node, HacknetServerConstants.MaxCores);
|
||||
} else {
|
||||
const levelsToMax = HacknetServerMaxCores - node.cores;
|
||||
const levelsToMax = HacknetServerConstants.MaxCores - node.cores;
|
||||
multiplier = Math.min(levelsToMax, purchaseMult);
|
||||
}
|
||||
|
||||
const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, Player.hacknet_node_core_cost_mult);
|
||||
upgradeCoresText = `Upgrade x${multiplier} - ${numeralWrapper.formatMoney(upgradeCoreCost)}`;
|
||||
upgradeCoresContent = <>Upgrade x{multiplier} - {Money(upgradeCoreCost)}</>;
|
||||
if (Player.money.lt(upgradeCoreCost)) {
|
||||
upgradeCoresClass = "std-button-disabled";
|
||||
} else {
|
||||
@@ -121,7 +119,7 @@ export class HacknetServer extends React.Component {
|
||||
const upgradeCoresOnClick = () => {
|
||||
let numUpgrades = purchaseMult;
|
||||
if (purchaseMult === "MAX") {
|
||||
numUpgrades = getMaxNumberCoreUpgrades(node, HacknetServerMaxCores);
|
||||
numUpgrades = getMaxNumberCoreUpgrades(node, HacknetServerConstants.MaxCores);
|
||||
}
|
||||
purchaseCoreUpgrade(node, numUpgrades);
|
||||
recalculate();
|
||||
@@ -129,21 +127,21 @@ export class HacknetServer extends React.Component {
|
||||
}
|
||||
|
||||
// Upgrade Cache button
|
||||
let upgradeCacheText, upgradeCacheClass;
|
||||
if (node.cache >= HacknetServerMaxCache) {
|
||||
upgradeCacheText = "MAX CACHE";
|
||||
let upgradeCacheContent, upgradeCacheClass;
|
||||
if (node.cache >= HacknetServerConstants.MaxCache) {
|
||||
upgradeCacheContent = <>MAX CACHE</>;
|
||||
upgradeCacheClass = "std-button-disabled";
|
||||
} else {
|
||||
let multiplier = 0;
|
||||
if (purchaseMult === "MAX") {
|
||||
multiplier = getMaxNumberCacheUpgrades(node, HacknetServerMaxCache);
|
||||
multiplier = getMaxNumberCacheUpgrades(node, HacknetServerConstants.MaxCache);
|
||||
} else {
|
||||
const levelsToMax = HacknetServerMaxCache - node.cache;
|
||||
const levelsToMax = HacknetServerConstants.MaxCache - node.cache;
|
||||
multiplier = Math.min(levelsToMax, purchaseMult);
|
||||
}
|
||||
|
||||
const upgradeCacheCost = node.calculateCacheUpgradeCost(multiplier);
|
||||
upgradeCacheText = `Upgrade x${multiplier} - ${numeralWrapper.formatMoney(upgradeCacheCost)}`;
|
||||
upgradeCacheContent = <>Upgrade x{multiplier} - {Money(upgradeCacheCost)}</>;
|
||||
if (Player.money.lt(upgradeCacheCost)) {
|
||||
upgradeCacheClass = "std-button-disabled";
|
||||
} else {
|
||||
@@ -153,7 +151,7 @@ export class HacknetServer extends React.Component {
|
||||
const upgradeCacheOnClick = () => {
|
||||
let numUpgrades = purchaseMult;
|
||||
if (purchaseMult === "MAX") {
|
||||
numUpgrades = getMaxNumberCacheUpgrades(node, HacknetServerMaxCache);
|
||||
numUpgrades = getMaxNumberCacheUpgrades(node, HacknetServerConstants.MaxCache);
|
||||
}
|
||||
purchaseCacheUpgrade(node, numUpgrades);
|
||||
recalculate();
|
||||
@@ -171,7 +169,7 @@ export class HacknetServer extends React.Component {
|
||||
<div className={"row"}>
|
||||
<p>Production:</p>
|
||||
<span className={"text money-gold"}>
|
||||
{numeralWrapper.formatBigNumber(node.totalHashesGenerated)} ({numeralWrapper.formatBigNumber(node.hashRate)} / sec)
|
||||
{Hashes(node.totalHashesGenerated)} ({HashRate(node.hashRate)})
|
||||
</span>
|
||||
</div>
|
||||
<div className={"row"}>
|
||||
@@ -181,25 +179,25 @@ export class HacknetServer extends React.Component {
|
||||
<div className={"row"}>
|
||||
<p>Level:</p><span className={"text upgradable-info"}>{node.level}</span>
|
||||
<button className={upgradeLevelClass} onClick={upgradeLevelOnClick}>
|
||||
{upgradeLevelText}
|
||||
{upgradeLevelContent}
|
||||
</button>
|
||||
</div>
|
||||
<div className={"row"}>
|
||||
<p>RAM:</p><span className={"text upgradable-info"}>{node.maxRam}GB</span>
|
||||
<button className={upgradeRamClass} onClick={upgradeRamOnClick}>
|
||||
{upgradeRamText}
|
||||
{upgradeRamContent}
|
||||
</button>
|
||||
</div>
|
||||
<div className={"row"}>
|
||||
<p>Cores:</p><span className={"text upgradable-info"}>{node.cores}</span>
|
||||
<button className={upgradeCoresClass} onClick={upgradeCoresOnClick}>
|
||||
{upgradeCoresText}
|
||||
{upgradeCoresContent}
|
||||
</button>
|
||||
</div>
|
||||
<div className={"row"}>
|
||||
<p>Cache Level:</p><span className={"text upgradable-info"}>{node.cache}</span>
|
||||
<button className={upgradeCacheClass} onClick={upgradeCacheOnClick}>
|
||||
{upgradeCacheText}
|
||||
{upgradeCacheContent}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -19,6 +19,8 @@ import { ServerDropdown,
|
||||
ServerType } from "../../ui/React/ServerDropdown"
|
||||
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
import { CopyableText } from "../../ui/React/CopyableText";
|
||||
import { Hashes } from "../../ui/React/Hashes";
|
||||
|
||||
class HashUpgrade extends React.Component {
|
||||
constructor(props) {
|
||||
@@ -63,8 +65,8 @@ class HashUpgrade extends React.Component {
|
||||
// We'll reuse a Bladeburner css class
|
||||
return (
|
||||
<div className={"bladeburner-action"}>
|
||||
<h2>{upg.name}</h2>
|
||||
<p>Cost: {numeralWrapper.format(cost, "0.000a")}</p>
|
||||
<CopyableText value={upg.name} />
|
||||
<p>Cost: {Hashes(cost)}</p>
|
||||
<p>{upg.desc}</p>
|
||||
<button className={btnClass} onClick={this.purchase}>
|
||||
Purchase
|
||||
@@ -122,7 +124,7 @@ export class HashUpgradePopup extends React.Component {
|
||||
<div>
|
||||
<PopupCloseButton popup={this.props.popupId} text={"Close"} />
|
||||
<p>Spend your hashes on a variety of different upgrades</p>
|
||||
<p>Hashes: {numeralWrapper.formatBigNumber(this.state.totalHashes)}</p>
|
||||
<p>Hashes: {numeralWrapper.formatHashes(this.state.totalHashes)}</p>
|
||||
{upgradeElems}
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -9,43 +9,33 @@ import React from "react";
|
||||
import { hasHacknetServers } from "../HacknetHelpers";
|
||||
import { Player } from "../../Player";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { MoneyRate } from "../../ui/React/MoneyRate";
|
||||
import { HashRate } from "../../ui/React/HashRate";
|
||||
import { Hashes } from "../../ui/React/Hashes";
|
||||
|
||||
export function PlayerInfo(props) {
|
||||
const hasServers = hasHacknetServers();
|
||||
|
||||
let prod;
|
||||
if (hasServers) {
|
||||
prod = numeralWrapper.format(props.totalProduction, "0.000a") + " hashes / sec";
|
||||
prod = HashRate(props.totalProduction);
|
||||
} else {
|
||||
prod = numeralWrapper.formatMoney(props.totalProduction) + " / sec";
|
||||
}
|
||||
|
||||
let hashInfo;
|
||||
if (hasServers) {
|
||||
hashInfo = numeralWrapper.format(Player.hashManager.hashes, "0.000a") + " / " +
|
||||
numeralWrapper.format(Player.hashManager.capacity, "0.000a");
|
||||
prod = MoneyRate(props.totalProduction);
|
||||
}
|
||||
|
||||
return (
|
||||
<p id={"hacknet-nodes-money"}>
|
||||
<span>Money:</span>
|
||||
<span className={"money-gold"}>{numeralWrapper.formatMoney(Player.money.toNumber())}</span><br />
|
||||
<span>Money: </span>
|
||||
{Money(Player.money.toNumber())}<br />
|
||||
|
||||
{
|
||||
hasServers &&
|
||||
<span>Hashes:</span>
|
||||
}
|
||||
{
|
||||
hasServers &&
|
||||
<span className={"money-gold"}>{hashInfo}</span>
|
||||
}
|
||||
{
|
||||
hasServers &&
|
||||
<br />
|
||||
<><span>Hashes: {Hashes(Player.hashManager.hashes)} / {Hashes(Player.hashManager.capacity)}</span><br /></>
|
||||
}
|
||||
|
||||
<span>Total Hacknet Node Production:</span>
|
||||
<span className={"money-gold"}>{prod}</span>
|
||||
<span>Total Hacknet Node Production: </span>
|
||||
{prod}
|
||||
</p>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { hasHacknetServers,
|
||||
hasMaxNumberHacknetServers } from "../HacknetHelpers";
|
||||
import { Player } from "../../Player";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
|
||||
export function PurchaseButton(props) {
|
||||
if (props.multiplier == null || props.onClick == null) {
|
||||
@@ -20,13 +21,13 @@ export function PurchaseButton(props) {
|
||||
if (hasHacknetServers()) {
|
||||
if (hasMaxNumberHacknetServers()) {
|
||||
className = "std-button-disabled";
|
||||
text = "Hacknet Server limit reached";
|
||||
text = <>Hacknet Server limit reached</>;
|
||||
style = {color: "red"};
|
||||
} else {
|
||||
text = `Purchase Hacknet Server - ${numeralWrapper.formatMoney(cost)}`;
|
||||
text = <>Purchase Hacknet Server - {Money(cost)}</>;
|
||||
}
|
||||
} else {
|
||||
text = `Purchase Hacknet Node - ${numeralWrapper.formatMoney(cost)}`;
|
||||
text = <>Purchase Hacknet Node - {Money(cost)}</>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
26
src/Hospital/Hospital.ts
Normal file
26
src/Hospital/Hospital.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer"
|
||||
|
||||
export function getHospitalizationCost(p: IPlayer): number {
|
||||
let money;
|
||||
if (typeof p.money === 'number') {
|
||||
money = p.money;
|
||||
} else {
|
||||
money = p.money.toNumber();
|
||||
}
|
||||
|
||||
if (money < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Math.min(money*0.1, (p.max_hp - p.hp) * CONSTANTS.HospitalCostPerHp);
|
||||
}
|
||||
|
||||
export function calculateHospitalizationCost(p: IPlayer, damage: number): number {
|
||||
const oldhp = p.hp;
|
||||
p.hp -= damage
|
||||
if (p.hp < 0) p.hp = 0;
|
||||
const cost = getHospitalizationCost(p);
|
||||
p.hp = oldhp;
|
||||
return cost;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { Player } from "./Player";
|
||||
import { Settings } from "./Settings/Settings";
|
||||
|
||||
import { initializeMainMenuLinks } from "./ui/MainMenu/Links";
|
||||
import { LiteratureNames } from "./Literature/data/LiteratureNames";
|
||||
|
||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||
import { clearEventListeners } from "../utils/uiHelpers/clearEventListeners";
|
||||
@@ -499,7 +500,7 @@ function iTutorialEnd() {
|
||||
"<a class='a-link-button' href='https://bitburner.readthedocs.io/en/latest/guidesandtips/gettingstartedguideforbeginnerprogrammers.html' target='_blank'>Getting Started Guide</a>" +
|
||||
"<a class='a-link-button' href='https://bitburner.readthedocs.io/en/latest/' target='_blank'>Documentation</a><br><br>" +
|
||||
"The Beginner's Guide to Hacking was added to your home computer! It contains some tips/pointers for starting out with the game. " +
|
||||
"To read it, go to Terminal and enter<br><br>cat hackers-starting-handbook.lit"
|
||||
"To read it, go to Terminal and enter<br><br>cat " + LiteratureNames.HackersStartingHandbook
|
||||
});
|
||||
var gotitBtn = createElement("a", {
|
||||
class:"a-link-button", float:"right", padding:"6px", innerText:"Got it!",
|
||||
@@ -509,7 +510,7 @@ function iTutorialEnd() {
|
||||
});
|
||||
createPopup(popupId, [txt, gotitBtn]);
|
||||
|
||||
Player.getHomeComputer().messages.push("hackers-starting-handbook.lit");
|
||||
Player.getHomeComputer().messages.push(LiteratureNames.HackersStartingHandbook);
|
||||
}
|
||||
|
||||
function iTutorialSetText(txt) {
|
||||
|
||||
15
src/Literature/Literature.ts
Normal file
15
src/Literature/Literature.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Lore / world building literature files that can be found on servers.
|
||||
* These files can be read by the player
|
||||
*/
|
||||
export class Literature {
|
||||
title: string;
|
||||
fn: string;
|
||||
txt: string;
|
||||
|
||||
constructor(title: string, filename: string, txt: string) {
|
||||
this.title = title;
|
||||
this.fn = filename;
|
||||
this.txt = txt;
|
||||
}
|
||||
}
|
||||
9
src/Literature/LiteratureHelpers.ts
Normal file
9
src/Literature/LiteratureHelpers.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Literatures } from "./Literatures";
|
||||
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||
|
||||
export function showLiterature(fn: string): void {
|
||||
const litObj = Literatures[fn];
|
||||
if (litObj == null) { return; }
|
||||
const txt = `<i>${litObj.title}</i><br><br>${litObj.txt}`;
|
||||
dialogBoxCreate(txt);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user