mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-23 14:42:28 +01:00
commit
a7389f63b8
14
.dockerignore
Normal file
14
.dockerignore
Normal 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
35
Dockerfile
Normal 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
|
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([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
36
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@ -3,8 +3,61 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
v0.51.9 - 2021-05-17 offline progress and exports! (hydroflame & community)
|
||||
---------------------------------------------------------------
|
||||
|
||||
v0.51.8 - 2021-05-07 It was there all along (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 & community)
|
||||
--------------------------------------------------------
|
||||
|
||||
**Servers**
|
||||
@ -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 & community)
|
||||
-----------------------------------------
|
||||
|
||||
**Tutorial servers**
|
||||
|
||||
@ -118,7 +171,7 @@ v0.51.7 - 2021-04-28 n00dles
|
||||
* Faction invite text says "Decide later"/"Join!" instead of "No"/"Yes"
|
||||
|
||||
|
||||
v0.51.6 - 2021-04-28 Backdoor! (Community)
|
||||
v0.51.6 - 2021-04-28 Backdoor! (hydroflame & community)
|
||||
------------------------------------------
|
||||
|
||||
**Backdoor**
|
||||
|
@ -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
15
docker-compose.yml
Normal 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
|
10
index.html
10
index.html
@ -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
86
package-lock.json
generated
@ -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": {
|
||||
|
10
package.json
10
package.json
@ -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"
|
||||
}
|
||||
|
37
src/Alias.ts
37
src/Alias.ts
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 />
|
||||
|
@ -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();
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
@ -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
|
||||
`,
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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
22
src/ExportBonus.tsx
Normal 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();
|
||||
}
|
@ -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
|
||||
{Money(aug.baseCost * factionInfo.augmentationPriceMult)}?
|
||||
</>);
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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()}
|
||||
|
@ -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 };
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -334,6 +334,7 @@ export class Sleeve extends Person {
|
||||
this.earningsForTask.money += gain;
|
||||
this.earningsForPlayer.money += gain;
|
||||
p.gainMoney(gain);
|
||||
p.recordMoneySource(gain, 'sleeves');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
},
|
||||
|
@ -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);
|
||||
}
|
||||
@ -1771,19 +1781,22 @@ let Terminal = {
|
||||
i--;
|
||||
postContent(row, config);
|
||||
}
|
||||
if(segments.length > 0) {
|
||||
postElement(<br />);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const config = { color: "#0000FF" };
|
||||
postSegments(folders, config);
|
||||
postSegments(allMessages);
|
||||
postSegments(allTextFiles);
|
||||
postSegments(allPrograms);
|
||||
postSegments(allContracts);
|
||||
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) {
|
||||
@ -1868,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);
|
||||
}
|
||||
},
|
||||
|
@ -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};
|
||||
|
@ -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:
|
||||
|
@ -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, "");
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ export class MoneySourceTracker {
|
||||
hacknetnode = 0;
|
||||
hospitalization = 0;
|
||||
infiltration = 0;
|
||||
sleeves = 0;
|
||||
stock = 0;
|
||||
total = 0;
|
||||
work = 0;
|
||||
|
@ -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);
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user