Compare commits

...

47 Commits

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

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-12 00:32:31 +00:00
Daniel Ferri
1b57c1f7e0 Changed loops to be more concise 2021-05-11 20:16:18 +02:00
Daniel Ferri
0cb2fd1a87 Removed useless code 2021-05-11 19:46:51 +02:00
Daniel Ferri
08b0c7710d Changed import so it saves and reloads the page 2021-05-11 19:27:02 +02:00
Daniel Ferri
f8a085af7a Autofocus the input when opening a "Set Team Size" popup 2021-05-11 15:34:05 +02:00
Daniel Ferri
c95a926154 Add overflow time of bladeburner updates to the next update 2021-05-11 15:32:43 +02:00
Olivier Gagnon
5af10c8406 Offline money gain is based off hacking exp / time since last aug instead 2021-05-10 20:11:03 -04:00
Olivier Gagnon
0f2b7517b4 Added export bonus 2021-05-10 18:26:50 -04:00
Martin Fournier
ac8565d820 Add basic docker support for development
Assuming docker engine is installed, it is now possible to run the dev
server using 'docker-compose up --build' or run the production version using
'docker build -t bitburner . && docker run -it -p 8000:80 bitburner'.
2021-05-10 08:54:25 -04:00
Olivier Gagnon
2bd4892fa8 hotfix ls not listing all files lol 2021-05-08 22:38:48 -04:00
Daniel Ferri
46862d30fd Recursive and multi-command alias 2021-05-08 18:44:21 +02:00
Olivier Gagnon
f6af61d15b hotfix ls printing a bunch of newlines 2021-05-07 22:37:50 -04:00
Olivier Gagnon
04e8bc944e build 2021-05-07 22:29:18 -04:00
Olivier Gagnon
cfd78e2d36 Add installBackdoor 2021-05-07 02:14:46 -04:00
40 changed files with 644 additions and 502 deletions

14
.dockerignore Normal file
View File

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

35
Dockerfile Normal file
View File

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

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +1,2 @@
!function(n){function t(t){for(var e,i,f=t[0],c=t[1],l=t[2],p=0,s=[];p<f.length;p++)i=f[p],u[i]&&s.push(u[i][0]),u[i]=0;for(e in c)Object.prototype.hasOwnProperty.call(c,e)&&(n[e]=c[e]);for(a&&a(t);s.length;)s.shift()();return r.push.apply(r,l||[]),o()}function o(){for(var n,t=0;t<r.length;t++){for(var o=r[t],e=!0,f=1;f<o.length;f++){var c=o[f];0!==u[c]&&(e=!1)}e&&(r.splice(t--,1),n=i(i.s=o[0]))}return n}var e={},u={1:0},r=[];function i(t){if(e[t])return e[t].exports;var o=e[t]={i:t,l:!1,exports:{}};return n[t].call(o.exports,o,o.exports,i),o.l=!0,o.exports}i.m=n,i.c=e,i.d=function(n,t,o){i.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:o})},i.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},i.t=function(n,t){if(1&t&&(n=i(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)i.d(o,e,function(t){return n[t]}.bind(null,e));return o},i.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return i.d(t,"a",t),t},i.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},i.p="";var f=window.webpackJsonp=window.webpackJsonp||[],c=f.push.bind(f);f.push=t,f=f.slice();for(var l=0;l<f.length;l++)t(f[l]);var a=c;r.push([841,0]),o()}({780:function(n,t,o){},782:function(n,t,o){},784:function(n,t,o){},786:function(n,t,o){},788:function(n,t,o){},790:function(n,t,o){},792:function(n,t,o){},794:function(n,t,o){},796:function(n,t,o){},798:function(n,t,o){},800:function(n,t,o){},802:function(n,t,o){},804:function(n,t,o){},806:function(n,t,o){},808:function(n,t,o){},810:function(n,t,o){},812:function(n,t,o){},814:function(n,t,o){},816:function(n,t,o){},818:function(n,t,o){},820:function(n,t,o){},822:function(n,t,o){},824:function(n,t,o){},826:function(n,t,o){},828:function(n,t,o){},830:function(n,t,o){},832:function(n,t,o){},834:function(n,t,o){},836:function(n,t,o){},838:function(n,t,o){},841:function(n,t,o){"use strict";o.r(t);o(840),o(838),o(836),o(834),o(832),o(830),o(828),o(826),o(824),o(822),o(820),o(818),o(816),o(814),o(812),o(810),o(808),o(806),o(804),o(802),o(800),o(798),o(796),o(794),o(792),o(790),o(788),o(786),o(784),o(782),o(780)}});
!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([842,0]),o()}({781:function(n,t,o){},783:function(n,t,o){},785:function(n,t,o){},787:function(n,t,o){},789:function(n,t,o){},791:function(n,t,o){},793:function(n,t,o){},795:function(n,t,o){},797:function(n,t,o){},799:function(n,t,o){},801:function(n,t,o){},803:function(n,t,o){},805:function(n,t,o){},807:function(n,t,o){},809:function(n,t,o){},811:function(n,t,o){},813:function(n,t,o){},815:function(n,t,o){},817:function(n,t,o){},819:function(n,t,o){},821:function(n,t,o){},823:function(n,t,o){},825:function(n,t,o){},827:function(n,t,o){},829:function(n,t,o){},831:function(n,t,o){},833:function(n,t,o){},835:function(n,t,o){},837:function(n,t,o){},839:function(n,t,o){},842:function(n,t,o){"use strict";o.r(t);o(841),o(839),o(837),o(835),o(833),o(831),o(829),o(827),o(825),o(823),o(821),o(819),o(817),o(815),o(813),o(811),o(809),o(807),o(805),o(803),o(801),o(799),o(797),o(795),o(793),o(791),o(789),o(787),o(785),o(783),o(781)}});
//# sourceMappingURL=engineStyle.bundle.js.map

36
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -3,6 +3,59 @@
Changelog
=========
v0.51.9 - 2021-05-17 offline progress and exports! (hydroflame)
---------------------------------------------------------------
**Alias**
* several commands can be included in 1 alias. Recursive alias now work to
a depth of 10. (@Dawe)
**Offline**
* Offline money gain has been reworked (it is more generous)
* If you're not working anywhere and go offline the game will work for you
at all your factions evenly.
**Export**
* Exporting now gives +1 favor to all joined factions every 24h.
**Corp**
* Self-fund with an invalid name no longer takes away 150b anyway.
* Can no longer export negative amount
**Bladeburner**
* No longer waste overflowing time.
**Text Editors**
* All settings will now be saved and loaded correctly.
**Terminal**
* 'scan' now works for servers that are more than 21 character long.
**Misc.**
* ls now correctly lists all files.
* importing auto save+reloads (@Dawe)
* Fix a bug where .fconf could not be created
* Fix formatting inconsistencies for some logs of netscript functions.
* Fix a bug where Cashroot starter kit would appear as [object Object] in
confirmation dialog.
* Fix some ram not displayed as 0.00GB
* Fix error message throw undefined variable error
* City hall now has some generic text if you can't create a corp yet.
* Deleting a file without extension now returns an appropriate error message.
* Fixed an issue where bladeburner would miscalculate the cost of hospitalization.
* It is now possible to suppress bladeburner "action stopped" popup.
* Updated several dependencies (big who cares, I know)
* ls no longer prints lingering newline.
* Money earned/spent by sleeves is now tracked under Character>Money
v0.51.8 - 2021-05-07 It was there all along (hydroflame)
--------------------------------------------------------
@@ -60,8 +113,8 @@ v0.51.8 - 2021-05-07 It was there all along (hydroflame)
* script income transfers to parent on death. This helps keep track of
income for scripts that spawn short lived scripts.
v0.51.7 - 2021-04-28 n00dles
----------------------------
v0.51.7 - 2021-04-28 n00dles (hydroflame)
-----------------------------------------
**Tutorial servers**

View File

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

15
docker-compose.yml Normal file
View File

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

View File

@@ -506,6 +506,16 @@
<input class="optionCheckbox" type="checkbox" name="settingsSuppressHospitalizationPopup" id="settingsSuppressHospitalizationPopup">
</fieldset>
<!-- Suppress Bladeburner popups -->
<fieldset>
<label for="settingsSuppressBladeburnerPopup" class="tooltip">Suppress Bladeburner Popup:
<span class="tooltiptext">
If this is set, then having your Bladeburner actions interrupted by being busy with something else will not display a popup message.
</span>
</label>
<input class="optionCheckbox" type="checkbox" name="settingsSuppressBladeburnerPopup" id="settingsSuppressBladeburnerPopup">
</fieldset>
<!-- Disable Terminal and Navigation Shortcuts -->
<fieldset>
<label for="settingsDisableHotkeys" class="tooltip">Disable Hotkeys:

86
package-lock.json generated
View File

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

View File

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

View File

@@ -51,14 +51,14 @@ function addAlias(name: string, value: string): void {
if (name in GlobalAliases) {
delete GlobalAliases[name];
}
Aliases[name] = value;
Aliases[name] = value.trim();
}
function addGlobalAlias(name: string, value: string): void {
if (name in Aliases){
delete Aliases[name];
}
GlobalAliases[name] = value;
GlobalAliases[name] = value.trim();
}
function getAlias(name: string): string | null {
@@ -97,22 +97,29 @@ export function removeAlias(name: string): boolean {
export function substituteAliases(origCommand: string): string {
const commandArray = origCommand.split(" ");
if (commandArray.length > 0){
// For the unalias command, dont substite
if (commandArray[0] === "unalias") { return commandArray.join(" "); }
// For the alias and unalias commands, dont substite
if (commandArray[0] === "unalias" || commandArray[0] === "alias") { return commandArray.join(" "); }
const alias = getAlias(commandArray[0]);
if (alias != null) {
commandArray[0] = alias;
} else {
const alias = getGlobalAlias(commandArray[0]);
let somethingSubstituted = true;
let depth = 0;
while(somethingSubstituted && depth < 10){
depth++;
somethingSubstituted = false
const alias = getAlias(commandArray[0])?.split(" ");
if (alias != null) {
commandArray[0] = alias;
somethingSubstituted = true
commandArray.splice(0, 1, ...alias);
//commandArray[0] = alias;
}
}
for (let i = 0; i < commandArray.length; ++i) {
const alias = getGlobalAlias(commandArray[i]);
if (alias != null) {
commandArray[i] = alias;
for (let i = 0; i < commandArray.length; ++i) {
const alias = getGlobalAlias(commandArray[i])?.split(" ");
if (alias != null) {
somethingSubstituted = true
commandArray.splice(i, 1, ...alias);
i += alias.length - 1;
//commandArray[i] = alias;
}
}
}
}

View File

@@ -12,6 +12,7 @@ import { Player } from "../Player";
import { prestigeAugmentation } from "../Prestige";
import { saveObject } from "../SaveObject";
import { Page, routing } from "../ui/navigationTracking";
import { onExport } from "../ExportBonus";
import { dialogBoxCreate } from "../../utils/DialogBox";
import { clearObject } from "../../utils/helpers/clearObject";
@@ -2077,9 +2078,14 @@ export function displayAugmentationsContent(contentEl) {
if (!routing.isOn(Page.Augmentations)) { return; }
if (!(contentEl instanceof HTMLElement)) { return; }
function backup() {
saveObject.exportGame();
onExport(Player);
}
ReactDOM.render(
<AugmentationsRoot
exportGameFn={saveObject.exportGame.bind(saveObject)}
exportGameFn={backup}
installAugmentationsFn={installAugmentations}
/>,
contentEl,

View File

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

View File

@@ -24,6 +24,7 @@ import {
convertTimeMsToTimeElapsedString,
} from "../utils/StringHelperFunctions";
import { Settings } from "./Settings/Settings";
import { ConsoleHelpText } from "./Bladeburner/data/Help";
import { City } from "./Bladeburner/City";
import { BladeburnerConstants } from "./Bladeburner/data/Constants";
@@ -158,6 +159,7 @@ function Bladeburner(params={}) {
// These times are in seconds
this.actionTimeToComplete = 0; // 0 or -1 is an infinite running action (like training)
this.actionTimeCurrent = 0;
this.actionTimeOverflow = 0;
// ActionIdentifier Object
var idleActionType = ActionTypes["Idle"];
@@ -358,7 +360,9 @@ Bladeburner.prototype.process = function() {
msg += `<br><br>Your automation was disabled as well. You will have to re-enable it through the Bladeburner console`
this.automateEnabled = false;
}
dialogBoxCreate(msg);
if (!Settings.SuppressBladeburnerPopup) {
dialogBoxCreate(msg);
}
}
this.resetAction();
}
@@ -381,22 +385,16 @@ Bladeburner.prototype.process = function() {
this.stamina = Math.min(this.maxStamina, this.stamina);
// Count increase for contracts/operations
for (var contractName in this.contracts) {
if (this.contracts.hasOwnProperty(contractName)) {
var contract = this.contracts[contractName];
contract.count += (seconds * contract.countGrowth/BladeburnerConstants.ActionCountGrowthPeriod);
}
for (let contract of Object.values(this.contracts)) {
contract.count += (seconds * contract.countGrowth/BladeburnerConstants.ActionCountGrowthPeriod);
}
for (var operationName in this.operations) {
if (this.operations.hasOwnProperty(operationName)) {
var op = this.operations[operationName];
op.count += (seconds * op.countGrowth/BladeburnerConstants.ActionCountGrowthPeriod);
}
for (let op of Object.values(this.operations)) {
op.count += (seconds * op.countGrowth/BladeburnerConstants.ActionCountGrowthPeriod);
}
// Chaos goes down very slowly
for (var i = 0; i < BladeburnerConstants.CityNames.length; ++i) {
var city = this.cities[BladeburnerConstants.CityNames[i]];
for (let cityName of BladeburnerConstants.CityNames) {
var city = this.cities[cityName];
if (!(city instanceof City)) {throw new Error("Invalid City object when processing passive chaos reduction in Bladeburner.process");}
city.chaos -= (0.0001 * seconds);
city.chaos = Math.max(0, city.chaos);
@@ -406,7 +404,8 @@ Bladeburner.prototype.process = function() {
this.randomEventCounter -= seconds;
if (this.randomEventCounter <= 0) {
this.randomEvent();
this.randomEventCounter = getRandomInt(240, 600);
// Add instead of setting because we might have gone over the required time for the event
this.randomEventCounter += getRandomInt(240, 600);
}
this.processAction(seconds);
@@ -664,8 +663,12 @@ Bladeburner.prototype.processAction = function(seconds) {
throw new Error("Bladeburner.action is not an ActionIdentifier Object");
}
this.actionTimeCurrent += seconds;
// If the previous action went past its completion time, add to the next action
// This is not added inmediatly in case the automation changes the action
this.actionTimeCurrent += seconds + this.actionTimeOverflow;
this.actionTimeOverflow = 0;
if (this.actionTimeCurrent >= this.actionTimeToComplete) {
this.actionTimeOverflow = this.actionTimeCurrent - this.actionTimeToComplete;
return this.completeAction();
}
}
@@ -1889,17 +1892,18 @@ Bladeburner.prototype.updateActionAndSkillsContent = function() {
Bladeburner.prototype.updateGeneralActionsUIElement = function(el, action) {
removeChildrenFromElement(el);
var isActive = el.classList.contains(ActiveActionCssClass);
var computedActionTimeCurrent = Math.min(this.actionTimeCurrent+this.actionTimeOverflow,this.actionTimeToComplete);
el.appendChild(createElement("h2", { // Header
innerText:isActive ? action.name + " (IN PROGRESS - " +
formatNumber(this.actionTimeCurrent, 0) + " / " +
formatNumber(computedActionTimeCurrent, 0) + " / " +
formatNumber(this.actionTimeToComplete, 0) + ")"
: action.name,
display:"inline-block",
}));
if (isActive) { // Progress bar if its active
var progress = this.actionTimeCurrent / this.actionTimeToComplete;
var progress = computedActionTimeCurrent / this.actionTimeToComplete;
el.appendChild(createElement("p", {
display:"block",
innerText:createProgressBarText({progress:progress}),
@@ -1931,17 +1935,18 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
removeChildrenFromElement(el);
var isActive = el.classList.contains(ActiveActionCssClass);
var estimatedSuccessChance = action.getSuccessChance(this, {est:true});
var computedActionTimeCurrent = Math.min(this.actionTimeCurrent+this.actionTimeOverflow,this.actionTimeToComplete);
el.appendChild(createElement("h2", { // Header
innerText:isActive ? action.name + " (IN PROGRESS - " +
formatNumber(this.actionTimeCurrent, 0) + " / " +
formatNumber(computedActionTimeCurrent, 0) + " / " +
formatNumber(this.actionTimeToComplete, 0) + ")"
: action.name,
display:"inline-block",
}));
if (isActive) { // Progress bar if its active
var progress = this.actionTimeCurrent / this.actionTimeToComplete;
var progress = computedActionTimeCurrent / this.actionTimeToComplete;
el.appendChild(createElement("p", {
display:"block",
innerText:createProgressBarText({progress:progress}),
@@ -2030,16 +2035,18 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
removeChildrenFromElement(el);
var isActive = el.classList.contains(ActiveActionCssClass);
var estimatedSuccessChance = action.getSuccessChance(this, {est:true});
var computedActionTimeCurrent = Math.min(this.actionTimeCurrent+this.actionTimeOverflow,this.actionTimeToComplete);
el.appendChild(createElement("h2", { // Header
innerText:isActive ? action.name + " (IN PROGRESS - " +
formatNumber(this.actionTimeCurrent, 0) + " / " +
formatNumber(computedActionTimeCurrent, 0) + " / " +
formatNumber(this.actionTimeToComplete, 0) + ")"
: action.name,
display:"inline-block",
}));
if (isActive) { // Progress bar if its active
var progress = this.actionTimeCurrent / this.actionTimeToComplete;
var progress = computedActionTimeCurrent / this.actionTimeToComplete;
el.appendChild(createElement("p", {
display:"block",
innerText:createProgressBarText({progress:progress}),
@@ -2093,6 +2100,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
},
});
createPopup(popupId, [txt, input, setBtn, cancelBtn]);
input.focus();
},
}));
}
@@ -2171,6 +2179,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
var estimatedSuccessChance = action.getSuccessChance(this, {est:true});
var actionTime = action.getActionTime(this);
var hasReqdRank = this.rank >= action.reqdRank;
var computedActionTimeCurrent = Math.min(this.actionTimeCurrent+this.actionTimeOverflow,this.actionTimeToComplete);
// UI for Completed Black Op
if (isCompleted) {
@@ -2182,14 +2191,14 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
el.appendChild(createElement("h2", { // Header
innerText:isActive ? action.name + " (IN PROGRESS - " +
formatNumber(this.actionTimeCurrent, 0) + " / " +
formatNumber(computedActionTimeCurrent, 0) + " / " +
formatNumber(this.actionTimeToComplete, 0) + ")"
: action.name,
display:"inline-block",
}));
if (isActive) { // Progress bar if its active
var progress = this.actionTimeCurrent / this.actionTimeToComplete;
var progress = computedActionTimeCurrent / this.actionTimeToComplete;
el.appendChild(createElement("p", {
display:"block",
innerText:createProgressBarText({progress:progress}),
@@ -2243,6 +2252,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
},
});
createPopup(popupId, [txt, input, setBtn, cancelBtn]);
input.focus();
},
}));
}

View File

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

View File

@@ -320,7 +320,7 @@ export class CorporationEventHandler {
return false;
}
if (temp == null || isNaN(temp)) {
if (temp == null || isNaN(temp) || temp < 0) {
dialogBoxCreate("Invalid amount entered for export");
return;
}

View File

@@ -15,6 +15,8 @@ import { GetServerByHostname } from "./Server/ServerHelpers";
import { hackWorldDaemon } from "./RedPill";
import { StockMarket } from "./StockMarket/StockMarket";
import { Stock } from "./StockMarket/Stock";
import { Engine } from "./engine";
import { saveObject } from "./SaveObject";
import { dialogBoxCreate } from "../utils/DialogBox";
import { createElement } from "../utils/uiHelpers/createElement";
@@ -641,6 +643,15 @@ class DevMenuComponent extends Component {
}
}
timeskip(time) {
return () => {
Player.lastUpdate -= time;
Engine._lastUpdate -= time;
saveObject.saveGame(Engine.indexedDb);
setTimeout(() => location.reload(), 1000);
};
}
render() {
let factions = [];
for (const i in Factions) {
@@ -1212,6 +1223,19 @@ class DevMenuComponent extends Component {
</div>
</div>
<div className="row">
<div className="col">
<div className="row">
<h2>Offline time skip:</h2>
</div>
<div className="row">
<button className="std-button" onClick={this.timeskip(60*1000)}>1 minute</button>
<button className="std-button" onClick={this.timeskip(60*60*1000)}>1 hour</button>
<button className="std-button" onClick={this.timeskip(24*60*60*1000)}>1 day</button>
</div>
</div>
</div>
</div>
);
}

22
src/ExportBonus.tsx Normal file
View File

@@ -0,0 +1,22 @@
import { Factions } from "./Faction/Factions";
import { IPlayer } from "./PersonObjects/IPlayer";
export let LastExportBonus: number = 0;
const bonusTimer = 24*60*60*1000; // 24h
export function canGetBonus(): boolean {
const now = (new Date()).getTime()
console.log(now);
console.log(LastExportBonus);
console.log(now - LastExportBonus);
if(now - LastExportBonus > bonusTimer) return true;
return false;
}
export function onExport(p: IPlayer): void {
if(!canGetBonus()) return;
for (const facName of p.factions) {
Factions[facName].favor++;
}
LastExportBonus = (new Date()).getTime();
}

View File

@@ -114,9 +114,13 @@ export function purchaseAugmentationBoxCreate(aug, fac) {
yesNoBoxClose();
});
let content = (<div dangerouslySetInnerHTML={{__html: aug.info}}></div>);
if(typeof aug.info !== 'string') {
content = <div>{aug.info}</div>
}
yesNoBoxCreate(<>
<h2>{aug.name}</h2><br />
<div dangerouslySetInnerHTML={{__html: aug.info}}></div><br /><br />
{content}<br /><br />
<br />Would you like to purchase the {aug.name} Augmentation for&nbsp;
{Money(aug.baseCost * factionInfo.augmentationPriceMult)}?
</>);

View File

@@ -19,7 +19,6 @@ export function getHospitalizationCost(p: IPlayer): number {
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;

View File

@@ -140,7 +140,6 @@ export function createStartCorporationPopup(p: IPlayer): void {
dialogBoxCreate("You don't have enough money to create a corporation! You need $150b");
return false;
}
p.loseMoney(150e9);
const companyName = nameInput.value;
if (companyName == null || companyName == "") {
@@ -149,6 +148,7 @@ export function createStartCorporationPopup(p: IPlayer): void {
}
p.startCorporation(companyName);
p.loseMoney(150e9);
const worldHeader = document.getElementById("world-menu-header");
if (worldHeader instanceof HTMLElement) {

View File

@@ -108,7 +108,11 @@ export class SpecialLocation extends React.Component<IProps, IState> {
}
renderCreateCorporation(): React.ReactNode {
if (!this.props.p.canAccessCorporation()) { return null; }
if (!this.props.p.canAccessCorporation()) {
return <>
<p><i>A business man is yelling at a clerk. You should come back later.</i></p>
</>;
}
return (
<AutoupdatingStdButton
disabled={!this.props.p.canAccessCorporation() || this.props.p.hasCorporation()}

View File

@@ -166,10 +166,7 @@ import { numeralWrapper } from "./ui/numeralFormat";
import { post } from "./ui/postToTerminal";
import { setTimeoutRef } from "./utils/SetTimeoutRef";
import { is2DArray } from "./utils/helpers/is2DArray";
import {
formatNumber,
convertTimeMsToTimeElapsedString,
} from "../utils/StringHelperFunctions";
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
import { logBoxCreate } from "../utils/LogBox";
import { arrayToString } from "../utils/helpers/arrayToString";
@@ -179,77 +176,6 @@ import { createElement } from "../utils/uiHelpers/createElement";
import { createPopup } from "../utils/uiHelpers/createPopup";
import { removeElementById } from "../utils/uiHelpers/removeElementById";
const possibleLogs = {
ALL: true,
scan: true,
hack: true,
sleep: true,
disableLog: true,
enableLog: true,
grow: true,
weaken: true,
nuke: true,
brutessh: true,
ftpcrack: true,
relaysmtp: true,
httpworm: true,
sqlinject: true,
run:true,
exec:true,
spawn: true,
kill: true,
killall: true,
scp: true,
getHackingLevel: true,
getServerMoneyAvailable: true,
getServerSecurityLevel: true,
getServerBaseSecurityLevel: true,
getServerMinSecurityLevel: true,
getServerRequiredHackingLevel: true,
getServerMaxMoney: true,
getServerGrowth: true,
getServerNumPortsRequired: true,
getServerRam: true,
// TIX API
buyStock: true,
sellStock: true,
shortStock: true,
sellShort: true,
purchase4SMarketData: true,
purchase4SMarketDataTixApi: true,
// Singularity Functions
purchaseServer: true,
deleteServer: true,
universityCourse: true,
gymWorkout: true,
travelToCity: true,
purchaseTor: true,
purchaseProgram: true,
stopAction: true,
upgradeHomeRam: true,
workForCompany: true,
applyToCompany: true,
joinFaction: true,
workForFaction: true,
donateToFaction: true,
createProgram: true,
commitCrime: true,
// Bladeburner API
startAction: true,
upgradeSkill: true,
setTeamSize: true,
joinBladeburnerFaction: true,
// Gang API
recruitMember: true,
setMemberTask: true,
purchaseEquipment: true,
setTerritoryWarfare: true,
}
const defaultInterpreter = new Interpreter('', () => undefined);
// the acorn interpreter has a bug where it doesn't convert arrays correctly.
@@ -300,8 +226,8 @@ function NetscriptFunctions(workerScript) {
"Dynamic RAM usage calculated to be greater than initial RAM usage on fn: " + fnName +
". This is probably because you somehow circumvented the static RAM " +
"calculation.<br><br>Please don't do that :(<br><br>" +
"Dynamic RAM Usage: " + workerScript.dynamicRamUsage + "<br>" +
"Static RAM Usage: " + workerScript.ramUsage);
"Dynamic RAM Usage: " + numeralWrapper.formatRAM(workerScript.dynamicRamUsage) + "<br>" +
"Static RAM Usage: " + numeralWrapper.formatRAM(workerScript.ramUsage));
}
};
@@ -739,7 +665,7 @@ function NetscriptFunctions(workerScript) {
return out;
}
return {
const functions = {
hacknet : {
numNodes : function() {
return Player.hacknetNodes.length;
@@ -950,7 +876,7 @@ function NetscriptFunctions(workerScript) {
expGain = 0;
}
const logGrowPercent = (moneyAfter/moneyBefore)*100 - 100;
workerScript.log("grow", `Available money on '${server.hostname}' grown by ${formatNumber(logGrowPercent, 6)}%. Gained ${numeralWrapper.formatExp(expGain)} hacking exp (t=${numeralWrapper.formatThreads(threads)}).`);
workerScript.log("grow", `Available money on '${server.hostname}' grown by ${numeralWrapper.formatPercentage(logGrowPercent, 6)}. Gained ${numeralWrapper.formatExp(expGain)} hacking exp (t=${numeralWrapper.formatThreads(threads)}).`);
workerScript.scriptRef.onlineExpGained += expGain;
Player.gainHackingExp(expGain);
if (stock) {
@@ -1194,7 +1120,7 @@ function NetscriptFunctions(workerScript) {
throw makeRuntimeErrorMsg("run", "Usage: run(scriptname, [numThreads], [arg1], [arg2]...)");
}
if (isNaN(threads) || threads <= 0) {
throw makeRuntimeErrorMsg("run", `Invalid thread count. Must be numeric and > 0, is ${thread}`);
throw makeRuntimeErrorMsg("run", `Invalid thread count. Must be numeric and > 0, is ${threads}`);
}
var argsForNewScript = [];
for (var i = 2; i < arguments.length; ++i) {
@@ -1663,28 +1589,28 @@ function NetscriptFunctions(workerScript) {
updateDynamicRam("getServerSecurityLevel", getRamCost("getServerSecurityLevel"));
const server = safeGetServer(ip, "getServerSecurityLevel");
if (failOnHacknetServer(server, "getServerSecurityLevel")) { return 1; }
workerScript.log("getServerSecurityLevel", `returned ${formatNumber(server.hackDifficulty, 3)} for '${server.hostname}'`);
workerScript.log("getServerSecurityLevel", `returned ${numeralWrapper.formatServerSecurity(server.hackDifficulty, 3)} for '${server.hostname}'`);
return server.hackDifficulty;
},
getServerBaseSecurityLevel: function(ip) {
updateDynamicRam("getServerBaseSecurityLevel", getRamCost("getServerBaseSecurityLevel"));
const server = safeGetServer(ip, "getServerBaseSecurityLevel");
if (failOnHacknetServer(server, "getServerBaseSecurityLevel")) { return 1; }
workerScript.log("getServerBaseSecurityLevel", `returned ${formatNumber(server.baseDifficulty, 3)} for '${server.hostname}'`);
workerScript.log("getServerBaseSecurityLevel", `returned ${numeralWrapper.formatServerSecurity(server.baseDifficulty, 3)} for '${server.hostname}'`);
return server.baseDifficulty;
},
getServerMinSecurityLevel: function(ip) {
updateDynamicRam("getServerMinSecurityLevel", getRamCost("getServerMinSecurityLevel"));
const server = safeGetServer(ip, "getServerMinSecurityLevel");
if (failOnHacknetServer(server, "getServerMinSecurityLevel")) { return 1; }
workerScript.log("getServerMinSecurityLevel", `returned ${formatNumber(server.minDifficulty, 3)} for ${server.hostname}`);
workerScript.log("getServerMinSecurityLevel", `returned ${numeralWrapper.formatServerSecurity(server.minDifficulty, 3)} for ${server.hostname}`);
return server.minDifficulty;
},
getServerRequiredHackingLevel: function(ip) {
updateDynamicRam("getServerRequiredHackingLevel", getRamCost("getServerRequiredHackingLevel"));
const server = safeGetServer(ip, "getServerRequiredHackingLevel");
if (failOnHacknetServer(server, "getServerRequiredHackingLevel")) { return 1; }
workerScript.log("getServerRequiredHackingLevel", `returned ${formatNumber(server.requiredHackingSkill, 0)} for '${server.hostname}'`);
workerScript.log("getServerRequiredHackingLevel", `returned ${numeralWrapper.formatSkill(server.requiredHackingSkill, 0)} for '${server.hostname}'`);
return server.requiredHackingSkill;
},
getServerMaxMoney: function(ip) {
@@ -1698,32 +1624,32 @@ function NetscriptFunctions(workerScript) {
updateDynamicRam("getServerGrowth", getRamCost("getServerGrowth"));
const server = safeGetServer(ip, "getServerGrowth");
if (failOnHacknetServer(server, "getServerGrowth")) { return 1; }
workerScript.log("getServerGrowth", `returned ${formatNumber(server.serverGrowth, 0)} for '${server.hostname}'`);
workerScript.log("getServerGrowth", `returned ${server.serverGrowth} for '${server.hostname}'`);
return server.serverGrowth;
},
getServerNumPortsRequired: function(ip) {
updateDynamicRam("getServerNumPortsRequired", getRamCost("getServerNumPortsRequired"));
const server = safeGetServer(ip, "getServerNumPortsRequired");
if (failOnHacknetServer(server, "getServerNumPortsRequired")) { return 5; }
workerScript.log("getServerNumPortsRequired", `returned ${formatNumber(server.numOpenPortsRequired, 0)} for '${server.hostname}'`);
workerScript.log("getServerNumPortsRequired", `returned ${server.numOpenPortsRequired} for '${server.hostname}'`);
return server.numOpenPortsRequired;
},
getServerRam: function(ip) {
updateDynamicRam("getServerRam", getRamCost("getServerRam"));
const server = safeGetServer(ip, "getServerRam");
workerScript.log("getServerRam", `returned [${formatNumber(server.maxRam, 2)}GB, ${formatNumber(server.ramUsed, 2)}GB]`);
workerScript.log("getServerRam", `returned [${numeralWrapper.formatRAM(server.maxRam, 2)}, ${numeralWrapper.formatRAM(server.ramUsed, 2)}]`);
return [server.maxRam, server.ramUsed];
},
getServerMaxRam: function(ip) {
updateDynamicRam("getServerMaxRam", getRamCost("getServerMaxRam"));
const server = safeGetServer(ip, "getServerMaxRam");
workerScript.log("getServerMaxRam", `returned ${formatNumber(server.maxRam, 2)}GB`);
workerScript.log("getServerMaxRam", `returned ${numeralWrapper.formatRAM(server.maxRam, 2)}`);
return server.maxRam;
},
getServerUsedRam: function(ip) {
updateDynamicRam("getServerUsedRam", getRamCost("getServerUsedRam"));
const server = safeGetServer(ip, "getServerUsedRam");
workerScript.log("getServerUsedRam", `returned ${formatNumber(server.ramUsed, 2)}GB`);
workerScript.log("getServerUsedRam", `returned ${numeralWrapper.formatRAM(server.ramUsed, 2)}`);
return server.ramUsed;
},
serverExists: function(ip) {
@@ -4544,7 +4470,23 @@ function NetscriptFunctions(workerScript) {
}
return ret;
},
} // End return
}
function getFunctionNames(obj) {
const functionNames = [];
for(const [key, value] of Object.entries(obj)){
if(typeof(value)=="function"){
functionNames.push(key);
}else if(typeof(value)=="object"){
functionNames.push(...getFunctionNames(value));
}
}
return functionNames;
}
const possibleLogs = Object.fromEntries(["ALL", ...getFunctionNames(functions)].map(a => [a, true]))
return functions;
} // End NetscriptFunction()
export { NetscriptFunctions };

View File

@@ -564,7 +564,6 @@ export function updateOnlineScriptTimes(numCycles = 1) {
* into worker scripts so that they will start running
*/
export function loadAllRunningScripts() {
var total = 0;
let skipScriptLoad = (window.location.href.toLowerCase().indexOf("?noscripts") !== -1);
if (skipScriptLoad) { console.info("Skipping the load of any scripts during startup"); }
for (const property in AllServers) {
@@ -587,13 +586,11 @@ export function loadAllRunningScripts() {
createAndAddWorkerScript(server.runningScripts[j], server);
// Offline production
total += scriptCalculateOfflineProduction(server.runningScripts[j]);
scriptCalculateOfflineProduction(server.runningScripts[j]);
}
}
}
}
return total;
}
/**

View File

@@ -334,6 +334,7 @@ export class Sleeve extends Person {
this.earningsForTask.money += gain;
this.earningsForPlayer.money += gain;
p.gainMoney(gain);
p.recordMoneySource(gain, 'sleeves');
}
/**

View File

@@ -8,16 +8,10 @@ import { Companies, loadCompanies } from "./Company/Companies";
import { CONSTANTS } from "./Constants";
import { Engine } from "./engine";
import { Factions, loadFactions } from "./Faction/Factions";
import { processPassiveFactionRepGain } from "./Faction/FactionHelpers";
import { loadFconf } from "./Fconf/Fconf";
import { FconfSettings } from "./Fconf/FconfSettings";
import { loadAllGangs, AllGangs } from "./Gang";
import {
hasHacknetServers,
processHacknetEarnings,
} from "./Hacknet/HacknetHelpers";
import { loadMessages, initMessages, Messages } from "./Message/MessageHelpers";
import { loadAllRunningScripts } from "./NetscriptWorker";
import { Player, loadPlayer } from "./Player";
import { AllServers, loadAllServers } from "./Server/AllServers";
import { Settings } from "./Settings/Settings";
@@ -31,19 +25,15 @@ import { loadStockMarket, StockMarket } from "./StockMarket/StockMarket";
import { createStatusText } from "./ui/createStatusText";
import { setTimeoutRef } from "./utils/SetTimeoutRef";
import * as ExportBonus from "./ExportBonus";
import { dialogBoxCreate } from "../utils/DialogBox";
import { gameOptionsBoxClose } from "../utils/GameOptions";
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
import { clearEventListeners } from "../utils/uiHelpers/clearEventListeners";
import {
Reviver,
Generic_toJSON,
Generic_fromJSON,
} from "../utils/JSONReviver";
import { createElement } from "../utils/uiHelpers/createElement";
import { createPopup } from "../utils/uiHelpers/createPopup";
import { removeElementById } from "../utils/uiHelpers/removeElementById";
import Decimal from "decimal.js";
@@ -66,6 +56,7 @@ function BitburnerSaveObject() {
this.FconfSettingsSave = "";
this.VersionSave = "";
this.AllGangsSave = "";
this.LastExportBonus = "";
}
BitburnerSaveObject.prototype.getSaveString = function() {
@@ -94,6 +85,7 @@ BitburnerSaveObject.prototype.getSaveString = function() {
this.SettingsSave = JSON.stringify(Settings);
this.FconfSettingsSave = JSON.stringify(FconfSettings);
this.VersionSave = JSON.stringify(CONSTANTS.Version);
this.LastExportBonus = JSON.stringify(ExportBonus.LastExportBonus);
if (Player.inGang()) {
this.AllGangsSave = JSON.stringify(AllGangs);
}
@@ -254,6 +246,16 @@ function loadGame(saveString) {
console.error("ERROR: Failed to parse .fconf Settings.");
}
}
if (saveObj.hasOwnProperty("LastExportBonus")) {
try {
ExportBonus.LastExportBonus = JSON.parse(saveObj.LastExportBonus);
} catch(err) {
console.log(saveObj.LastExportBonus);
console.log(ExportBonus.LastExportBonus);
ExportBonus.LastExportBonus = (new Date()).getTime();
console.error("ERROR: Failed to parse .fconf Settings "+ err);
}
}
if (saveObj.hasOwnProperty("VersionSave")) {
try {
var ver = JSON.parse(saveObj.VersionSave, Reviver);
@@ -285,22 +287,11 @@ function loadGame(saveString) {
function loadImportedGame(saveObj, saveString) {
var tempSaveObj = null;
var tempPlayer = null;
var tempAllServers = null;
var tempCompanies = null;
var tempFactions = null;
var tempSpecialServerIps = null;
var tempAliases = null;
var tempGlobalAliases = null;
var tempMessages = null;
var tempStockMarket = null;
var tempAllGangs = null;
let tempCorporationResearchTrees = null;
// Check to see if the imported save file can be parsed. If any
// errors are caught it will fail
try {
var decodedSaveString = decodeURIComponent(escape(atob(saveString)));
tempSaveObj = new BitburnerSaveObject();
tempSaveObj = JSON.parse(decodedSaveString, Reviver);
tempPlayer = JSON.parse(tempSaveObj.PlayerSave, Reviver);
@@ -308,33 +299,27 @@ function loadImportedGame(saveObj, saveString) {
// Parse Decimal.js objects
tempPlayer.money = new Decimal(tempPlayer.money);
tempAllServers = JSON.parse(tempSaveObj.AllServersSave, Reviver);
tempCompanies = JSON.parse(tempSaveObj.CompaniesSave, Reviver);
tempFactions = JSON.parse(tempSaveObj.FactionsSave, Reviver);
tempSpecialServerIps = JSON.parse(tempSaveObj.SpecialServerIpsSave, Reviver);
JSON.parse(tempSaveObj.AllServersSave, Reviver);
JSON.parse(tempSaveObj.CompaniesSave, Reviver);
JSON.parse(tempSaveObj.FactionsSave, Reviver);
JSON.parse(tempSaveObj.SpecialServerIpsSave, Reviver);
if (tempSaveObj.hasOwnProperty("AliasesSave")) {
try {
tempAliases = JSON.parse(tempSaveObj.AliasesSave, Reviver);
JSON.parse(tempSaveObj.AliasesSave, Reviver);
} catch(e) {
console.error(`Parsing Aliases save failed: ${e}`);
tempAliases = {};
}
} else {
tempAliases = {};
}
if (tempSaveObj.hasOwnProperty("GlobalAliases")) {
try {
tempGlobalAliases = JSON.parse(tempSaveObj.AliasesSave, Reviver);
JSON.parse(tempSaveObj.AliasesSave, Reviver);
} catch(e) {
console.error(`Parsing Global Aliases save failed: ${e}`);
tempGlobalAliases = {};
}
} else {
tempGlobalAliases = {};
}
if (tempSaveObj.hasOwnProperty("MessagesSave")) {
try {
tempMessages = JSON.parse(tempSaveObj.MessagesSave, Reviver);
JSON.parse(tempSaveObj.MessagesSave, Reviver);
} catch(e) {
console.error(`Parsing Messages save failed: ${e}`);
initMessages();
@@ -344,13 +329,18 @@ function loadImportedGame(saveObj, saveString) {
}
if (saveObj.hasOwnProperty("StockMarketSave")) {
try {
tempStockMarket = JSON.parse(tempSaveObj.StockMarketSave, Reviver);
JSON.parse(tempSaveObj.StockMarketSave, Reviver);
} catch(e) {
console.error(`Parsing StockMarket save failed: ${e}`);
tempStockMarket = {};
}
} else {
tempStockMarket = {};
}
if (saveObj.hasOwnProperty("LastExportBonus")) {
try {
ExportBonus.LastExportBonus = JSON.parse(saveObj.LastExportBonus);
} catch(err) {
ExportBonus.LastExportBonus = (new Date()).getTime();
console.error("ERROR: Failed to parse .fconf Settings "+ err);
}
}
if (tempSaveObj.hasOwnProperty("VersionSave")) {
try {
@@ -359,7 +349,6 @@ function loadImportedGame(saveObj, saveString) {
} catch(e) {
console.error("Parsing Version save failed: " + e);
}
} else {
}
if (tempPlayer.inGang() && tempSaveObj.hasOwnProperty("AllGangsSave")) {
try {
@@ -457,75 +446,8 @@ function loadImportedGame(saveObj, saveString) {
console.error("ERROR: Failed to parse AllGangsSave: " + e);
}
}
var popupId = "import-game-restart-game-notice";
var txt = createElement("p", {
innerText:"Imported game! You need to SAVE the game and then RELOAD the page " +
"to make sure everything runs smoothly",
});
var gotitBtn = createElement("a", {
class:"a-link-button", float:"right", padding:"6px", innerText:"Got it!",
clickListener:() => {
removeElementById(popupId);
},
});
createPopup(popupId, [txt, gotitBtn]);
gameOptionsBoxClose();
// Re-start game
Engine.setDisplayElements(); // Sets variables for important DOM elements
Engine.init(); // Initialize buttons, work, etc.
// Calculate the number of cycles have elapsed while offline
Engine._lastUpdate = new Date().getTime();
var lastUpdate = Player.lastUpdate;
var numCyclesOffline = Math.floor((Engine._lastUpdate - lastUpdate) / Engine._idleSpeed);
// Process offline progress
var offlineProductionFromScripts = loadAllRunningScripts(); // This also takes care of offline production for those scripts
if (Player.isWorking) {
if (Player.workType == CONSTANTS.WorkTypeFaction) {
Player.workForFaction(numCyclesOffline);
} else if (Player.workType == CONSTANTS.WorkTypeCreateProgram) {
Player.createProgramWork(numCyclesOffline);
} else if (Player.workType == CONSTANTS.WorkTypeStudyClass) {
Player.takeClass(numCyclesOffline);
} else if (Player.workType == CONSTANTS.WorkTypeCrime) {
Player.commitCrime(numCyclesOffline);
} else if (Player.workType == CONSTANTS.WorkTypeCompanyPartTime) {
Player.workPartTime(numCyclesOffline);
} else {
Player.work(numCyclesOffline);
}
}
// Hacknet Nodes offline progress
var offlineProductionFromHacknetNodes = processHacknetEarnings(numCyclesOffline);
// Passive faction rep gain offline
processPassiveFactionRepGain(numCyclesOffline);
// Update total playtime
var time = numCyclesOffline * Engine._idleSpeed;
if (Player.totalPlaytime == null) {Player.totalPlaytime = 0;}
if (Player.playtimeSinceLastAug == null) {Player.playtimeSinceLastAug = 0;}
if (Player.playtimeSinceLastBitnode == null) {Player.playtimeSinceLastBitnode = 0;}
Player.totalPlaytime += time;
Player.playtimeSinceLastAug += time;
Player.playtimeSinceLastBitnode += time;
// Re-apply augmentations
Player.reapplyAllAugmentations();
// Clear terminal
$("#terminal tr:not(:last)").remove();
Player.lastUpdate = Engine._lastUpdate;
Engine.start(); // Run main game loop and Scripts loop
const timeOfflineString = convertTimeMsToTimeElapsedString(time);
dialogBoxCreate(<>Offline for {timeOfflineString}. While you were offline, your scripts
generated {Money(offlineProductionFromScripts)}
and your Hacknet Nodes generated hacknetProdInfo</>);
saveObject.saveGame(Engine.indexedDb);
location.reload();
return true;
}

View File

@@ -311,90 +311,51 @@ function saveAndCloseScriptEditor() {
export function scriptCalculateOfflineProduction(runningScriptObj) {
//The Player object stores the last update time from when we were online
var thisUpdate = new Date().getTime();
var lastUpdate = Player.lastUpdate;
var timePassed = (thisUpdate - lastUpdate) / 1000; //Seconds
const thisUpdate = new Date().getTime();
const lastUpdate = Player.lastUpdate;
const timePassed = (thisUpdate - lastUpdate) / 1000; //Seconds
//Calculate the "confidence" rating of the script's true production. This is based
//entirely off of time. We will arbitrarily say that if a script has been running for
//4 hours (14400 sec) then we are completely confident in its ability
var confidence = (runningScriptObj.onlineRunningTime) / 14400;
let confidence = (runningScriptObj.onlineRunningTime) / 14400;
if (confidence >= 1) {confidence = 1;}
//Data map: [MoneyStolen, NumTimesHacked, NumTimesGrown, NumTimesWeaken]
// Grow
for (var ip in runningScriptObj.dataMap) {
for (const ip in runningScriptObj.dataMap) {
if (runningScriptObj.dataMap.hasOwnProperty(ip)) {
if (runningScriptObj.dataMap[ip][2] == 0 || runningScriptObj.dataMap[ip][2] == null) {continue;}
var serv = AllServers[ip];
const serv = AllServers[ip];
if (serv == null) {continue;}
var timesGrown = Math.round(0.5 * runningScriptObj.dataMap[ip][2] / runningScriptObj.onlineRunningTime * timePassed);
runningScriptObj.log("Called grow() on " + serv.hostname + " " + timesGrown + " times while offline");
var growth = processSingleServerGrowth(serv, timesGrown, Player);
runningScriptObj.log(serv.hostname + " grown by " + numeralWrapper.format(growth * 100 - 100, '0.000000%') + " from grow() calls made while offline");
}
}
// Money from hacking
var totalOfflineProduction = 0;
for (var ip in runningScriptObj.dataMap) {
if (runningScriptObj.dataMap.hasOwnProperty(ip)) {
if (runningScriptObj.dataMap[ip][0] == 0 || runningScriptObj.dataMap[ip][0] == null) {continue;}
var serv = AllServers[ip];
if (serv == null) {continue;}
var production = 0.5 * runningScriptObj.dataMap[ip][0] / runningScriptObj.onlineRunningTime * timePassed;
production *= confidence;
if (production > serv.moneyAvailable) {
production = serv.moneyAvailable;
}
totalOfflineProduction += production;
Player.gainMoney(production);
Player.recordMoneySource(production, "hacking");
runningScriptObj.log(runningScriptObj.filename + " generated $" + production + " while offline by hacking " + serv.hostname);
serv.moneyAvailable -= production;
if (serv.moneyAvailable < 0) {serv.moneyAvailable = 0;}
if (isNaN(serv.moneyAvailable)) {serv.moneyAvailable = 0;}
const timesGrown = Math.round(0.5 * runningScriptObj.dataMap[ip][2] / runningScriptObj.onlineRunningTime * timePassed);
runningScriptObj.log(`Called on ${serv.hostname} ${timesGrown} times while offline`);
const growth = processSingleServerGrowth(serv, timesGrown, Player);
runningScriptObj.log(`'${serv.hostname}' grown by ${numeralWrapper.format(growth * 100 - 100, '0.000000%')} while offline`);
}
}
// Offline EXP gain
// A script's offline production will always be at most half of its online production.
var expGain = 0.5 * (runningScriptObj.onlineExpGained / runningScriptObj.onlineRunningTime) * timePassed;
expGain *= confidence;
const expGain = confidence * (runningScriptObj.onlineExpGained / runningScriptObj.onlineRunningTime) * timePassed;
Player.gainHackingExp(expGain);
// Update script stats
runningScriptObj.offlineMoneyMade += totalOfflineProduction;
runningScriptObj.offlineRunningTime += timePassed;
runningScriptObj.offlineExpGained += expGain;
// Fortify a server's security based on how many times it was hacked
for (var ip in runningScriptObj.dataMap) {
if (runningScriptObj.dataMap.hasOwnProperty(ip)) {
if (runningScriptObj.dataMap[ip][1] == 0 || runningScriptObj.dataMap[ip][1] == null) {continue;}
var serv = AllServers[ip];
if (serv == null) {continue;}
var timesHacked = Math.round(0.5 * runningScriptObj.dataMap[ip][1] / runningScriptObj.onlineRunningTime * timePassed);
runningScriptObj.log("Hacked " + serv.hostname + " " + timesHacked + " times while offline");
serv.fortify(CONSTANTS.ServerFortifyAmount * timesHacked);
}
}
// Weaken
for (var ip in runningScriptObj.dataMap) {
for (const ip in runningScriptObj.dataMap) {
if (runningScriptObj.dataMap.hasOwnProperty(ip)) {
if (runningScriptObj.dataMap[ip][3] == 0 || runningScriptObj.dataMap[ip][3] == null) {continue;}
var serv = AllServers[ip];
const serv = AllServers[ip];
if (serv == null) {continue;}
var timesWeakened = Math.round(0.5 * runningScriptObj.dataMap[ip][3] / runningScriptObj.onlineRunningTime * timePassed);
runningScriptObj.log("Called weaken() on " + serv.hostname + " " + timesWeakened + " times while offline");
const timesWeakened = Math.round(0.5 * runningScriptObj.dataMap[ip][3] / runningScriptObj.onlineRunningTime * timePassed);
runningScriptObj.log(`Called weaken() on ${serv.hostname} ${timesWeakened} times while offline`);
serv.weaken(CONSTANTS.ServerWeakenAmount * timesWeakened);
}
}
return totalOfflineProduction;
}
//Returns a RunningScript object matching the filename and arguments on the

View File

@@ -233,19 +233,25 @@ class AceEditorWrapper extends ScriptEditor {
// Highlight Active line
const highlightActiveChkBox = safeClearEventListeners("script-editor-option-highlightactiveline", "Active Line Checkbox");
highlightActiveChkBox.checked = Settings.EditorHighlightActiveLine;
highlightActiveChkBox.onchange = () => {
Settings.EditorHighlightActiveLine = highlightActiveChkBox.checked;
this.editor.setHighlightActiveLine(highlightActiveChkBox.checked);
};
// Show Invisibles
const showInvisiblesChkBox = safeClearEventListeners("script-editor-option-showinvisibles", "Show Invisible Checkbox");
showInvisiblesChkBox.checked = Settings.EditorShowInvisibles;
showInvisiblesChkBox.onchange = () => {
Settings.EditorShowInvisibles = showInvisiblesChkBox.checked;
this.editor.setShowInvisibles(showInvisiblesChkBox.checked);
};
// Use Soft Tab
const softTabChkBox = safeClearEventListeners("script-editor-option-usesofttab", "Soft Tab Checkbox");
softTabChkBox.checked = Settings.EditorUseSoftTab;
softTabChkBox.onchange = () => {
Settings.EditorUseSoftTab = softTabChkBox.checked;
this.editor.getSession().setUseSoftTabs(softTabChkBox.checked);
};

View File

@@ -375,14 +375,18 @@ class CodeMirrorEditorWrapper extends ScriptEditor {
// Highlight Active line
const highlightActiveChkBox = safeClearEventListeners("script-editor-option-highlightactiveline", "Active Line Checkbox");
highlightActiveChkBox.checked = Settings.EditorHighlightActiveLine;
highlightActiveChkBox.onchange = () => {
Settings.EditorHighlightActiveLine = highlightActiveChkBox.checked;
this.editor.setOption("styleActiveLine", highlightActiveChkBox.checked);
};
highlightActiveChkBox.onchange();
// Show Invisibles
const showInvisiblesChkBox = safeClearEventListeners("script-editor-option-showinvisibles", "Show Invisible Checkbox");
showInvisiblesChkBox.checked = Settings.EditorShowInvisibles;
showInvisiblesChkBox.onchange = () => {
Settings.EditorShowInvisibles = showInvisiblesChkBox.checked;
const overlayMode = {
name: 'invisibles',
token: function(stream) {
@@ -428,7 +432,9 @@ class CodeMirrorEditorWrapper extends ScriptEditor {
//Use Soft Tab
const softTabChkBox = safeClearEventListeners("script-editor-option-usesofttab", "Soft Tab Checkbox");
softTabChkBox.checked = Settings.EditorUseSoftTab;
softTabChkBox.onchange = () => {
Settings.EditorUseSoftTab = softTabChkBox.checked;
this.editor.setOption("indentWithTabs", !softTabChkBox.checked);
if (softTabChkBox.checked) {
this.editor.addKeyMap({
@@ -482,13 +488,14 @@ class CodeMirrorEditorWrapper extends ScriptEditor {
}));
const flex1Checkbox = createElement("input", {
checked: true,
checked: Settings.EditorAutoCloseBrackets,
id: flex1Id,
name: flex1Id,
type: "checkbox",
});
flex1Fieldset.appendChild(flex1Checkbox);
flex1Checkbox.onchange = () => {
Settings.EditorAutoCloseBrackets = flex1Checkbox.checked;
this.editor.setOption("autoCloseBrackets", flex1Checkbox.checked);
};
flex1Checkbox.onchange();
@@ -502,7 +509,7 @@ class CodeMirrorEditorWrapper extends ScriptEditor {
}));
const flex2Checkbox = createElement("input", {
checked: true,
checked: Settings.EditorEnableLinting,
id: flex2Id,
name: flex2Id,
type: "checkbox",
@@ -510,8 +517,10 @@ class CodeMirrorEditorWrapper extends ScriptEditor {
flex2Fieldset.appendChild(flex2Checkbox);
flex2Checkbox.onchange = () => {
if (flex2Checkbox.checked) {
Settings.EditorEnableLinting = true;
this.editor.setOption("lint", CodeMirror.lint.netscript);
} else {
Settings.EditorEnableLinting = false;
this.editor.setOption("lint", false);
}
}
@@ -526,13 +535,14 @@ class CodeMirrorEditorWrapper extends ScriptEditor {
}));
const flex3Checkbox = createElement("input", {
checked: true,
checked: Settings.EditorContinueComments,
id: flex3Id,
name: flex3Id,
type: "checkbox",
});
flex3Fieldset.appendChild(flex3Checkbox);
flex3Checkbox.onchange = () => {
Settings.EditorContinueComments = flex3Checkbox.checked;
this.editor.setOption("continueComments", flex3Checkbox.checked);
}
flex3Checkbox.onchange();

View File

@@ -181,6 +181,7 @@ export class BaseServer {
* @returns {IReturnStatus} Return status object indicating whether or not file was deleted
*/
removeFile(fn: string): IReturnStatus {
console.log(`removing ${fn}`);
if (fn.endsWith(".exe") || fn.match(/^.+\.exe-\d+(?:\.\d*)?%-INC$/) != null) {
for (let i = 0; i < this.programs.length; ++i) {
if (this.programs[i] === fn) {

View File

@@ -74,6 +74,11 @@ interface IDefaultSettings {
* Whether the user should be asked to confirm travelling between cities.
*/
SuppressTravelConfirmation: boolean;
/**
* Whether the user should be displayed a popup message when his Bladeburner actions are cancelled.
*/
SuppressBladeburnerPopup: boolean;
}
/**
@@ -106,6 +111,36 @@ interface ISettings extends IDefaultSettings {
* What order the Augmentations should be displayed in when purchasing from a Faction
*/
PurchaseAugmentationsOrder: PurchaseAugmentationsOrderSetting;
/**
* Editor settings to highlight active line.
*/
EditorHighlightActiveLine: boolean;
/**
* Editor settings to show spaces and tabs.
*/
EditorShowInvisibles: boolean;
/**
* Editor settings to use tabs or 4 spaces.
*/
EditorUseSoftTab: boolean;
/**
* Editor settings to add matching bracket.
*/
EditorAutoCloseBrackets: boolean;
/**
* Editor settings to show linting (like missing semicolons)
*/
EditorEnableLinting: boolean;
/**
* Editor settings to add extra * when entering new line inside a /* comment.
*/
EditorContinueComments: boolean;
}
const defaultSettings: IDefaultSettings = {
@@ -122,6 +157,7 @@ const defaultSettings: IDefaultSettings = {
SuppressHospitalizationPopup: false,
SuppressMessages: false,
SuppressTravelConfirmation: false,
SuppressBladeburnerPopup: false,
};
/**
@@ -147,6 +183,13 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
SuppressHospitalizationPopup: defaultSettings.SuppressHospitalizationPopup,
SuppressMessages: defaultSettings.SuppressMessages,
SuppressTravelConfirmation: defaultSettings.SuppressTravelConfirmation,
SuppressBladeburnerPopup: defaultSettings.SuppressBladeburnerPopup,
EditorHighlightActiveLine: true,
EditorShowInvisibles: false,
EditorUseSoftTab: true,
EditorAutoCloseBrackets: true,
EditorEnableLinting: true,
EditorContinueComments: true,
init() {
Object.assign(Settings, defaultSettings);
},

View File

@@ -10,6 +10,7 @@ import {
import { determineAllPossibilitiesForTabCompletion } from "./Terminal/determineAllPossibilitiesForTabCompletion";
import { TerminalHelpText, HelpTexts } from "./Terminal/HelpText";
import { tabCompletion } from "./Terminal/tabCompletion";
import { createFconf } from "./Fconf/Fconf";
import {
parseAliasDeclaration,
@@ -625,7 +626,11 @@ let Terminal = {
Terminal.commandHistoryIndex = Terminal.commandHistory.length;
// Split commands and execute sequentially
commands = commands.split(";");
commands = commands
.match(/(?:'[^']*'|"[^"]*"|[^;"])*/g)
.map(substituteAliases)
.map(c => c.match(/(?:'[^']*'|"[^"]*"|[^;"])*/g))
.flat();
for (let i = 0; i < commands.length; i++) {
if(commands[i].match(/^\s*$/)) { continue; } // Don't run commands that only have whitespace
Terminal.executeCommand(commands[i].trim());
@@ -727,9 +732,6 @@ let Terminal = {
return;
}
// Process any aliases
command = substituteAliases(command);
// Allow usage of ./
if (command.startsWith("./")) {
command = "run " + command.slice(2);
@@ -873,7 +875,7 @@ let Terminal = {
if (commandArray.length === 3) {
if (commandArray[1] === "-g") {
if (parseAliasDeclaration(commandArray[2], true)) {
post(`Set global alias ${commandArray[1]}`);
post(`Set global alias ${commandArray[2]}`);
return;
}
}
@@ -1311,9 +1313,17 @@ let Terminal = {
}
// Check programs
let delTarget = Terminal.getFilepath(commandArray[1]);
let delTarget, status;
try {
delTarget = Terminal.getFilepath(commandArray[1]);
status = s.removeFile(delTarget);
} catch(err) {
status = {
res: false,
msg: 'No such file exists'
};
}
const status = s.removeFile(delTarget);
if (!status.res) {
postError(status.msg);
}
@@ -1768,23 +1778,25 @@ let Terminal = {
row += " ".repeat((maxLength * (col+1)) - row.length);
i++
}
i--;
postContent(row, config);
}
}
const config = { color: "#0000FF" };
postSegments(folders, config);
postElement(<br />);
postSegments(allMessages);
postElement(<br />);
postSegments(allTextFiles);
postElement(<br />);
postSegments(allPrograms);
postElement(<br />);
postSegments(allContracts);
postElement(<br />);
postSegments(allScripts);
const groups = [
{segments: folders, config: config},
{segments: allMessages},
{segments: allTextFiles},
{segments: allPrograms},
{segments: allContracts},
{segments: allScripts},
].filter((g) => g.segments.length > 0)
for(let i = 0; i < groups.length; i++) {
if(i !== 0) postElement(<br />);
postSegments(groups[i].segments, groups[i].config);
}
},
executeMemCommand: function(commandArray) {
@@ -1869,30 +1881,27 @@ let Terminal = {
// Displays available network connections using TCP
const currServ = Player.getCurrentServer();
post("Hostname IP Root Access");
for (let i = 0; i < currServ.serversOnNetwork.length; i++) {
// Add hostname
let entry = getServerOnNetwork(currServ, i);
if (entry == null) { continue; }
entry = entry.hostname;
// Calculate padding and add IP
let numSpaces = 21 - entry.length;
let spaces = Array(numSpaces+1).join(" ");
entry += spaces;
entry += getServerOnNetwork(currServ, i).ip;
// Calculate padding and add root access info
let hasRoot;
if (getServerOnNetwork(currServ, i).hasAdminRights) {
hasRoot = 'Y';
} else {
hasRoot = 'N';
const servers = currServ.serversOnNetwork.map((_, i) => {
const server = getServerOnNetwork(currServ, i);
return {
hostname: server.hostname,
ip: server.ip,
hasRoot: server.hasAdminRights ? "Y" : "N"
}
numSpaces = 21 - getServerOnNetwork(currServ, i).ip.length;
spaces = Array(numSpaces+1).join(" ");
entry += spaces;
entry += hasRoot;
});
servers.unshift({
hostname: "Hostname",
ip: "IP",
hasRoot: "Root Access",
})
const maxHostname = Math.max(...servers.map(s => s.hostname.length));
const maxIP = Math.max(...servers.map(s => s.ip.length));
for(const server of servers) {
let entry = server.hostname;
entry += " ".repeat(maxHostname-server.hostname.length+1);
entry += server.ip;
entry += " ".repeat(maxIP-server.ip.length+1);
entry += server.hasRoot;
post(entry);
}
},

View File

@@ -32,6 +32,11 @@ import {
processPassiveFactionRepGain,
inviteToFaction,
} from "./Faction/FactionHelpers";
import {
getHackingWorkRepGain,
getFactionSecurityWorkRepGain,
getFactionFieldWorkRepGain,
} from "./PersonObjects/formulas/reputation";
import { FconfSettings } from "./Fconf/FconfSettings";
import {
hasHacknetServers,
@@ -91,6 +96,7 @@ import { Page, routing } from "./ui/navigationTracking";
import { setSettingsLabels } from "./ui/setSettingsLabels";
import { Money } from "./ui/React/Money";
import { Hashes } from "./ui/React/Hashes";
import { Reputation } from "./ui/React/Reputation";
import { ActiveScriptsRoot } from "./ui/ActiveScripts/Root";
import { initializeMainMenuHeaders } from "./ui/MainMenu/Headers";
@@ -230,6 +236,8 @@ const Engine = {
characterInfo: null,
},
indexedDb: undefined,
// Time variables (milliseconds unix epoch time)
_lastUpdate: new Date().getTime(),
_idleSpeed: 200, // Speed (in ms) at which the main loop is updated
@@ -809,7 +817,7 @@ const Engine = {
Engine.Counters.autoSaveCounter = Infinity;
} else {
Engine.Counters.autoSaveCounter = Settings.AutosaveInterval * 5;
saveObject.saveGame(indexedDb);
saveObject.saveGame(Engine.indexedDb);
}
}
@@ -1079,11 +1087,15 @@ const Engine = {
// Calculate the number of cycles have elapsed while offline
Engine._lastUpdate = new Date().getTime();
var lastUpdate = Player.lastUpdate;
var numCyclesOffline = Math.floor((Engine._lastUpdate - lastUpdate) / Engine._idleSpeed);
const lastUpdate = Player.lastUpdate;
const timeOffline = Engine._lastUpdate - lastUpdate;
const numCyclesOffline = Math.floor(timeOffline / Engine._idleSpeed);
let offlineReputation = 0
const offlineHackingIncome = Player.moneySourceA.hacking/(Player.playtimeSinceLastAug)*timeOffline*0.75;
Player.gainMoney(offlineHackingIncome);
// Process offline progress
var offlineProductionFromScripts = loadAllRunningScripts(); // This also takes care of offline production for those scripts
loadAllRunningScripts(); // This also takes care of offline production for those scripts
if (Player.isWorking) {
if (Player.workType == CONSTANTS.WorkTypeFaction) {
Player.workForFaction(numCyclesOffline);
@@ -1098,6 +1110,31 @@ const Engine = {
} else {
Player.work(numCyclesOffline);
}
} else {
for(let i = 0; i < Player.factions.length; i++) {
const facName = Player.factions[i];
if (!Factions.hasOwnProperty(facName)) continue;
const faction = Factions[facName];
if (!faction.isMember) continue;
// No rep for special factions.
const info = faction.getInfo();
if(!info.offersWork()) continue;
// No rep for gangs.
if(Player.getGangName() === facName) continue;
const hRep = getHackingWorkRepGain(Player, faction);
const sRep = getFactionSecurityWorkRepGain(Player, faction);
const fRep = getFactionFieldWorkRepGain(Player, faction);
// can be infinite, doesn't matter.
const reputationRate = Math.max(hRep, sRep, fRep) / Player.factions.length;
const rep = reputationRate *
(numCyclesOffline);
faction.playerReputation += rep
offlineReputation += rep;
}
}
// Hacknet Nodes offline progress
@@ -1157,7 +1194,10 @@ const Engine = {
removeLoadingScreen();
const timeOfflineString = convertTimeMsToTimeElapsedString(time);
dialogBoxCreate(<>
Offline for {timeOfflineString}. While you were offline, your scripts generated {Money(offlineProductionFromScripts)} and your Hacknet Nodes generated {hacknetProdInfo}.
Offline for {timeOfflineString}. While you were offline, your scripts
generated {Money(offlineHackingIncome)}, your Hacknet Nodes
generated {hacknetProdInfo} and you
gained {Reputation(offlineReputation)} divided amongst your factions.
</>);
// Close main menu accordions for loaded game
var visibleMenuTabs = [terminal, createScript, activeScripts, stats,
@@ -1430,13 +1470,13 @@ const Engine = {
// Save, Delete, Import/Export buttons
Engine.Clickables.saveMainMenuButton = document.getElementById("save-game-link");
Engine.Clickables.saveMainMenuButton.addEventListener("click", function() {
saveObject.saveGame(indexedDb);
saveObject.saveGame(Engine.indexedDb);
return false;
});
Engine.Clickables.deleteMainMenuButton = document.getElementById("delete-game-link");
Engine.Clickables.deleteMainMenuButton.addEventListener("click", function() {
saveObject.deleteGame(indexedDb);
saveObject.deleteGame(Engine.indexedDb);
return false;
});
@@ -1447,7 +1487,7 @@ const Engine = {
// Character Overview buttons
document.getElementById("character-overview-save-button").addEventListener("click", function() {
saveObject.saveGame(indexedDb);
saveObject.saveGame(Engine.indexedDb);
return false;
});
@@ -1559,7 +1599,7 @@ const Engine = {
},
};
var indexedDb, indexedDbRequest;
var indexedDbRequest;
window.onload = function() {
if (!window.indexedDB) {
return Engine.load(null); // Will try to load from localstorage
@@ -1579,8 +1619,8 @@ window.onload = function() {
};
indexedDbRequest.onsuccess = function(e) {
indexedDb = e.target.result;
var transaction = indexedDb.transaction(["savestring"]);
Engine.indexedDb = e.target.result;
var transaction = Engine.indexedDb.transaction(["savestring"]);
var objectStore = transaction.objectStore("savestring");
var request = objectStore.get("save");
request.onerror = function(e) {
@@ -1599,4 +1639,4 @@ window.onload = function() {
}
};
export {Engine};
export {Engine, indexedDb};

View File

@@ -519,6 +519,16 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
<input class="optionCheckbox" type="checkbox" name="settingsSuppressHospitalizationPopup" id="settingsSuppressHospitalizationPopup">
</fieldset>
<!-- Suppress Bladeburner popups -->
<fieldset>
<label for="settingsSuppressBladeburnerPopup" class="tooltip">Suppress Bladeburner Popup:
<span class="tooltiptext">
If this is set, then having your Bladeburner actions interrupted by being busy with something else will not display a popup message.
</span>
</label>
<input class="optionCheckbox" type="checkbox" name="settingsSuppressBladeburnerPopup" id="settingsSuppressBladeburnerPopup">
</fieldset>
<!-- Disable Terminal and Navigation Shortcuts -->
<fieldset>
<label for="settingsDisableHotkeys" class="tooltip">Disable Hotkeys:

View File

@@ -61,6 +61,7 @@ export function CharacterInfo(p: IPlayer): React.ReactElement {
if (src.infiltration) { parts.push([`Infiltration:`, Money(src.infiltration)]) }
if (src.stock) { parts.push([`Stock Market:`, Money(src.stock)]) }
if (src.casino) { parts.push([`Casino:`, Money(src.casino)]) }
if (src.sleeves) { parts.push([`Sleeves:`, Money(src.sleeves)]) }
return StatsTable(parts, "");
}

View File

@@ -1,6 +1,6 @@
import {Engine} from "../engine";
import {Settings} from "../Settings/Settings";
import {Player} from "../Player";
import {numeralWrapper} from "./numeralFormat";
@@ -21,6 +21,7 @@ function setSettingsLabels() {
const suppressTravelConfirmation = document.getElementById("settingsSuppressTravelConfirmation");
const suppressBuyAugmentationConfirmation = document.getElementById("settingsSuppressBuyAugmentationConfirmation");
const suppressHospitalizationPopup = document.getElementById("settingsSuppressHospitalizationPopup");
const suppressBladeburnerPopup = document.getElementById("settingsSuppressBladeburnerPopup");
const autosaveInterval = document.getElementById("settingsAutosaveIntervalValLabel");
const disableHotkeys = document.getElementById("settingsDisableHotkeys");
const disableASCIIArt = document.getElementById("settingsDisableASCIIArt");
@@ -36,6 +37,7 @@ function setSettingsLabels() {
suppressTravelConfirmation.checked = Settings.SuppressTravelConfirmation;
suppressBuyAugmentationConfirmation.checked = Settings.SuppressBuyAugmentationConfirmation;
suppressHospitalizationPopup.checked = Settings.SuppressHospitalizationPopup;
suppressBladeburnerPopup.checked = Settings.SuppressBladeburnerPopup;
setAutosaveLabel(autosaveInterval);
disableHotkeys.checked = Settings.DisableHotkeys;
disableASCIIArt.checked = Settings.CityListView;
@@ -99,6 +101,10 @@ function setSettingsLabels() {
Settings.SuppressHospitalizationPopup = this.checked;
}
suppressBladeburnerPopup.onclick = function() {
Settings.SuppressBladeburnerPopup = this.checked;
}
disableHotkeys.onclick = function() {
Settings.DisableHotkeys = this.checked;
}

View File

@@ -19,6 +19,7 @@ export class MoneySourceTracker {
hacknetnode = 0;
hospitalization = 0;
infiltration = 0;
sleeves = 0;
stock = 0;
total = 0;
work = 0;

View File

@@ -1,4 +1,5 @@
/* GameOptions.js */
import { Player } from "../src/Player";
//Close box when clicking outside
$(document).click(function(event) {
@@ -36,6 +37,11 @@ function gameOptionsBoxClose() {
function gameOptionsBoxOpen() {
var box = document.getElementById("game-options-container");
box.style.display = "flex";
// special exception for bladeburner popup because it's only visible later.
document.getElementById("settingsSuppressBladeburnerPopup").
closest('fieldset').style.display =
Player.canAccessBladeburner() ? 'block' : 'none';
setTimeout(function() {
gameOptionsOpened = true;
}, 500);

View File

@@ -5,6 +5,7 @@ var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = (env, argv) => {
const isDevServer = (env || {}).devServer === true;
const runInContainer = (env || {}).runInContainer === true;
const isDevelopment = argv.mode === 'development';
const outputDirectory = isDevServer ? "dist-dev" : "dist";
const entries = {};
@@ -22,6 +23,22 @@ module.exports = (env, argv) => {
entrypoints: true,
}
const devServerSettings = {
port: 8000,
publicPath: `/`,
stats: statsConfig,
};
// By default, the webpack-dev-server is not exposed outside of localhost.
// When running in a container we need it accessible externally.
if (runInContainer) {
devServerSettings.disableHostCheck = true;
devServerSettings.host = '0.0.0.0';
devServerSettings.watchOptions = {
poll: true,
}
}
return {
plugins: [
new webpack.DefinePlugin({
@@ -131,11 +148,7 @@ module.exports = (env, argv) => {
},
},
},
devServer: {
port: 8000,
publicPath: `/`,
stats: statsConfig,
},
devServer: devServerSettings,
resolve: {
extensions: [
".tsx",