diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 508adaa39..e965b1e63 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,29 +17,29 @@ heard: scripting perhaps there is something that is conflicting with the browser's Javascript interaction. So please do not be afraid to open a [new issue](https://github.com/danielyxie/bitburner/issues/new). - -## Reporting Bugs -The recommended method for reporting a bug is by opening a -[Github Issue](https://github.com/danielyxie/bitburner/issues). -Before submitting a bug report, please check to make sure the bug has not -already been reported as an [Issue](https://github.com/danielyxie/bitburner/issues). +## Reporting Bugs +The recommended method for reporting a bug is by opening a +[Github Issue](https://github.com/danielyxie/bitburner/issues). + +Before submitting a bug report, please check to make sure the bug has not +already been reported as an [Issue](https://github.com/danielyxie/bitburner/issues). #### How to Submit a Good Bug Report * **Use a clear and descriptive title** for the issue * **State your browser, your browser's version, and your computer's OS** - * **Provide instructions on how to reproduce the bug** in as much detail + * **Provide instructions on how to reproduce the bug** in as much detail as possible. If you cannot reliably reproduce the bug, then just try your best to explain what was happening when the bug occurred * **Provide any scripts** that triggered the bug if the issue is Netscript-related - * **Open your browser's Dev Console and report any error-related output** - that may be printed there. The Dev Console can be opened on most modern + * **Open your browser's Dev Console and report any error-related output** + that may be printed there. The Dev Console can be opened on most modern browsers by pressing F12 ## As a Developer -Anyone is welcome to contribute to Bitburner code. However, please read -the [license](https://github.com/danielyxie/bitburner/blob/dev/license.txt) +Anyone is welcome to contribute to Bitburner code. However, please read +the [license](https://github.com/danielyxie/bitburner/blob/dev/license.txt) and the [readme](https://github.com/danielyxie/bitburner/blob/dev/README.md) before doing so. @@ -48,22 +48,22 @@ To contribute to Bitburner code, you will need to have called `npm` is installed as well. #### What are you Allowed to Contribute? -Not all code contributions will be accepted. The safest way to ensure -that you don't waste time working on something that gets rejected is to -run your idea(s)/plan(s) past [danielyxie](https://github.com/danielyxie) first. +Not all code contributions will be accepted. The safest way to ensure +that you don't waste time working on something that gets rejected is to +run your idea(s)/plan(s) past [danielyxie](https://github.com/danielyxie) first. You can contact him through: * Github * Discord * [Reddit](https://www.reddit.com/user/chapt3r/) -Otherwise, here are some general guidelines for determining what types of changes -are okay to contribute: +Otherwise, here are some general guidelines for determining what types of +changes are okay to contribute: ##### Contributions that Will Most Likely Be Accepted * Bug Fixes * Quality-of-Life Changes - * Adding a new, commonly-requested Netscript function + * Adding a new, commonly-requested Netscript function * Fixing or improving UI elements * Adding game settings/options * Adding a new Terminal command @@ -73,8 +73,8 @@ are okay to contribute: * Changes that directly affect the game's balance * New gameplay mechanics -#### Submitting a Pull Request -When submitting a pull request with your code contributions, please abide by +#### Submitting a Pull Request +When submitting a pull request with your code contributions, please abide by the following rules: - Work in a branch forked from `dev` to isolate the new code @@ -86,14 +86,18 @@ the following rules: _danielyxie/bitburner_ and the base is _dev_. - If your changes affect the game's UI, attach some screenshots or GIFs showing the changes to the UI - - If your changes affect Netscript, provide some - scripts that can be used to test the Netscript changes. - - Do not check in any bundled files (`dist\*.bundle.js`). These will be - updated as part of official releases. + - If your changes affect Netscript, provide some + scripts that can be used to test the Netscript changes. + - Ensure you have run `npm run lint` to make sure your changes conform to the + rules enforced across the code base. The command will fail if any of the + linters find a violation. + - Do not check in any bundled files (`dist\*.bundle.js`) or the `index.html` + in the root of the repository. These will be updated as part of official + releases. ## As a Documentor -To contribute to BitBurner documentation, you will need to have Python -installed, along with [Sphinx](http://www.sphinx-doc.org). +To contribute to and view your changes to the BitBurner documentation, you will +need to have Python installed, along with [Sphinx](http://www.sphinx-doc.org). Before submitting your code for a pull request, please try to follow these rules: @@ -103,3 +107,5 @@ rules: - Rebase your branch if necessary - When submitting the pull request, make sure that the base fork is _danielyxie/bitburner_ and the base is _dev_. + - Do not check in any generated files under `doc\`. The documentation is built + automatically by ReadTheDocs. diff --git a/index.html b/index.html index 90bcab019..483f08745 100644 --- a/index.html +++ b/index.html @@ -8,13 +8,11 @@ - - + - + @@ -472,8 +471,7 @@
- Getting Started + Getting Started Servers & Networking Hacking Scripts @@ -482,8 +480,7 @@ Companies and Infiltration Factions Augmentations - Keyboard Shortcuts + Keyboard Shortcuts Back

@@ -715,7 +712,7 @@ Expand tickers Collapse tickers

- + Update Watchlist @@ -744,7 +741,7 @@ - + diff --git a/package-lock.json b/package-lock.json index 3d8a37dd1..ceff05e84 100644 --- a/package-lock.json +++ b/package-lock.json @@ -800,6 +800,12 @@ "multicast-dns-service-types": "1.1.0" } }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, "boom": { "version": "2.10.1", "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", @@ -1080,6 +1086,16 @@ "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", "dev": true }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, + "requires": { + "no-case": "2.3.2", + "upper-case": "1.1.3" + } + }, "camelcase": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", @@ -1679,6 +1695,23 @@ } } }, + "clean-css": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", + "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", + "dev": true, + "requires": { + "source-map": "0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -2181,6 +2214,30 @@ "source-list-map": "2.0.0" } }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "1.0.0", + "css-what": "2.1.0", + "domutils": "1.5.1", + "nth-check": "1.0.1" + }, + "dependencies": { + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" + } + } + } + }, "css-selector-tokenizer": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", @@ -2192,6 +2249,12 @@ "regexpu-core": "1.0.0" } }, + "css-what": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", + "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", + "dev": true + }, "cssesc": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", @@ -2524,6 +2587,23 @@ "esutils": "2.0.2" } }, + "dom-converter": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.1.4.tgz", + "integrity": "sha1-pF71cnuJDJv/5tfIduexnLDhfzs=", + "dev": true, + "requires": { + "utila": "0.3.3" + }, + "dependencies": { + "utila": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", + "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=", + "dev": true + } + } + }, "dom-serializer": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", @@ -4790,12 +4870,86 @@ "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", "dev": true }, + "html-minifier": { + "version": "3.5.20", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.20.tgz", + "integrity": "sha512-ZmgNLaTp54+HFKkONyLFEfs5dd/ZOtlquKaTnqIWFmx3Av5zG6ZPcV2d0o9XM2fXOTxxIf6eDcwzFFotke/5zA==", + "dev": true, + "requires": { + "camel-case": "3.0.0", + "clean-css": "4.2.1", + "commander": "2.17.1", + "he": "1.1.1", + "param-case": "2.1.1", + "relateurl": "0.2.7", + "uglify-js": "3.4.8" + }, + "dependencies": { + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "uglify-js": { + "version": "3.4.8", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.8.tgz", + "integrity": "sha512-WatYTD84gP/867bELqI2F/2xC9PQBETn/L+7RGq9MQOA/7yFBNvY1UwXqvtILeE6n0ITwBXxp34M0/o70dzj6A==", + "dev": true, + "requires": { + "commander": "2.17.1", + "source-map": "0.6.1" + } + } + } + }, "html-tags": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", "dev": true }, + "html-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz", + "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=", + "dev": true, + "requires": { + "html-minifier": "3.5.20", + "loader-utils": "0.2.17", + "lodash": "4.17.10", + "pretty-error": "2.1.1", + "tapable": "1.0.0", + "toposort": "1.0.7", + "util.promisify": "1.0.0" + }, + "dependencies": { + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1", + "object-assign": "4.1.1" + } + } + } + }, "htmlparser2": { "version": "3.9.2", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", @@ -6380,6 +6534,12 @@ "signal-exit": "3.0.2" } }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, "lru-cache": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", @@ -6996,6 +7156,15 @@ "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==", "dev": true }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "requires": { + "lower-case": "1.1.4" + } + }, "node-forge": { "version": "0.7.5", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", @@ -7603,6 +7772,15 @@ } } }, + "nth-check": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", + "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "dev": true, + "requires": { + "boolbase": "1.0.0" + } + }, "num2fraction": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", @@ -7726,6 +7904,16 @@ "object-keys": "1.0.11" } }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.12.0" + } + }, "object.omit": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", @@ -7926,6 +8114,15 @@ "readable-stream": "2.3.4" } }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dev": true, + "requires": { + "no-case": "2.3.2" + } + }, "parse-asn1": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", @@ -8979,6 +9176,16 @@ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, + "pretty-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", + "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", + "dev": true, + "requires": { + "renderkid": "2.0.1", + "utila": "0.4.0" + } + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -9355,6 +9562,12 @@ "jsesc": "0.5.0" } }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, "remark": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/remark/-/remark-9.0.0.tgz", @@ -9417,6 +9630,81 @@ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", "dev": true }, + "renderkid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.1.tgz", + "integrity": "sha1-iYyr/Ivt5Le5ETWj/9Mj5YwNsxk=", + "dev": true, + "requires": { + "css-select": "1.2.0", + "dom-converter": "0.1.4", + "htmlparser2": "3.3.0", + "strip-ansi": "3.0.1", + "utila": "0.3.3" + }, + "dependencies": { + "domhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.1.0.tgz", + "integrity": "sha1-0mRvXlf2w7qxHPbLBdPArPdBJZQ=", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } + }, + "domutils": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.1.6.tgz", + "integrity": "sha1-vdw94Jm5ou+sxRxiPyj0FuzFdIU=", + "dev": true, + "requires": { + "domelementtype": "1.3.0" + } + }, + "htmlparser2": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.3.0.tgz", + "integrity": "sha1-zHDQWln2VC5D8OaFyYLhTJJKnv4=", + "dev": true, + "requires": { + "domelementtype": "1.3.0", + "domhandler": "2.1.0", + "domutils": "1.1.6", + "readable-stream": "1.0.34" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "utila": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.3.3.tgz", + "integrity": "sha1-1+jn1+MJEHCSsF+NloiCTWM6QiY=", + "dev": true + } + } + }, "repeat-element": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", @@ -11688,6 +11976,12 @@ } } }, + "toposort": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", + "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", + "dev": true + }, "tough-cookie": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", @@ -12227,6 +12521,12 @@ "integrity": "sha512-d4SJySNBXDaQp+DPrziv3xGS6w3d2Xt69FijJr86zMPBy23JEloMCEOUBBzuN7xCtjLCnmB9tI/z7SBCahHBOw==", "dev": true }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -12372,6 +12672,22 @@ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "object.getownpropertydescriptors": "2.0.3" + } + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", diff --git a/package.json b/package.json index 84d48e9fe..49ee37f7f 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "eslint": "^4.19.1", "eslint-plugin-node": "^6.0.1", "file-loader": "^1.1.11", + "html-webpack-plugin": "^3.2.0", "i18n-webpack-plugin": "^1.0.0", "istanbul": "^0.4.5", "js-beautify": "^1.5.10", diff --git a/src/Constants.js b/src/Constants.js index e85f3e47e..ee1a8d382 100644 --- a/src/Constants.js +++ b/src/Constants.js @@ -493,32 +493,11 @@ let CONSTANTS = { "World Stock Exchange account and TIX API Access
", LatestUpdate: - "v0.40.2
" + - "------------------------------
" + - "* Bladeburner Changes:
" + - "*** Added getBonusTime(), getSkillUpgradeCost(), and getCity() Netscript functions to the API
" + - "*** Buffed the effects of many Bladeburner Augmentations
" + - "*** The Blade's Simulacrum Augmentation requires significantly less reputation but slightly more money
" + - "*** Slightly increased the amount of successes needed for a Contract/Operation in order to increase its max level
" + - "*** Increased the amount of money gained from Contracts by ~25%
" + - "*** Increased the base amount of rank gained from Operations by 10%
" + - "*** Significantly increased the 'randomness' in determining a Contract/Operation's initial count and rate of count increase
" + - "*** The number (count) of Operations should now increase significantly faster
" + - "*** There are now, on average, more Synthoid communities in a city
" + - "*** If automation is enabled (the feature in Bladeburner console), then switching to another action such as working for a company will now disable the automation
" + - "------------------------------
" + - "* Stock Market Changes:
" + - "***Added a watchlist filter feature to the UI that allows you to specify which stocks to show
" + - "***Added the Four Sigma (4S) Market Data feed, which provides volatility and price forecast information about stocks
" + - "***Added the 4S Market Data TIX API, which lets you access the aforementioned data through Netscript
" + - "------------------------------
" + - "* There is now a setting for enabling/disabling the popup that appears when you are hospitalized
" + - "* Bug Fix: Stock market should now be correctly initialized in BitNode-8 (by Kline-)
" + - "* Bug Fix: bladeburner.getCurrentAction() should now properly an 'Idle' object rather than null (by Kline-)
" + - "* Bug Fix: Bladeburner skill cost multiplier should now properly increase in BitNode-12 (by hydroflame)
" + - "* Bug Fix: 'document', 'hacknet', and 'window' keywords should no longer be counted multiple times in RAM calculations
" + - "* Bug Fix: Joining factions through Singularity functions should now prevent you from joining opposing factions
" + - "* Bug Fix: Four Sigma should no longer have two 'Speech Enhancement' Augmentations (by Kline-)
" + "v0.40.3
" + + "* b1t_flum3.exe program can now be created immediately at Hacking level 1 (rather than hacking level 5)
" + + "* UI improvements for the character overview panel and the left-hand menu (by mat-jaworski)
" + + "* Improved the introductory tutorial
" + } diff --git a/src/CreateProgram.js b/src/CreateProgram.js index dd8159e78..f3a808a54 100644 --- a/src/CreateProgram.js +++ b/src/CreateProgram.js @@ -83,9 +83,9 @@ const Programs = { time: CONSTANTS.MillisecondsPerQuarterHour, }), BitFlume: new Program("b1t_flum3.exe", { - level: 5, + level: 1, tooltip:"This program creates a portal to the BitNode Nexus (allows you to restart and switch BitNodes)", - req: function() {return Player.sourceFiles.length > 0 && Player.hacking_skill >= 5}, + req: function() {return Player.sourceFiles.length > 0 && Player.hacking_skill >= 1}, time: CONSTANTS.MillisecondsPerFiveMinutes / 5, }), // special because you can't create it. diff --git a/src/Hacking.js b/src/Hacking.js new file mode 100644 index 000000000..457c4fc6c --- /dev/null +++ b/src/Hacking.js @@ -0,0 +1,90 @@ +import { BitNodeMultipliers } from "./BitNodeMultipliers"; +import { Player } from "./Player"; +import { Server } from "./Server"; + +/** + * Returns the chance the player has to successfully hack a server + */ +export function calculateHackingChance(server) { + const hackFactor = 1.75; + const intFactor = 0.2; + const difficultyMult = (100 - server.hackDifficulty) / 100; + const skillMult = (hackFactor * Player.hacking_skill) + (intFactor * Player.intelligence); + const skillChance = (skillMult - server.requiredHackingSkill) / skillMult; + const chance = skillChance * difficultyMult * Player.hacking_chance_mult; + if (chance > 1) { return 1; } + if (chance < 0) { return 0; } + + return chance; +} + +/** + * Returns the amount of hacking experience the player will gain upon + * successfully hacking a server + */ +export function calculateHackingExpGain(server) { + const baseExpGain = 3; + const diffFactor = 0.3; + if (server.baseDifficulty == null) { + server.baseDifficulty = server.hackDifficulty; + } + var expGain = baseExpGain; + expGain += (server.baseDifficulty * Player.hacking_exp_mult * diffFactor); + + return expGain * BitNodeMultipliers.HackExpGain; +} + +/** + * Returns the percentage of money that will be stolen from a server if + * it is successfully hacked (returns the decimal form, not the actual percent value) + */ +export function calculatePercentMoneyHacked(server) { + // Adjust if needed for balancing. This is the divisor for the final calculation + const balanceFactor = 240; + + const difficultyMult = (100 - server.hackDifficulty) / 100; + const skillMult = (Player.hacking_skill - (server.requiredHackingSkill - 1)) / Player.hacking_skill; + const percentMoneyHacked = difficultyMult * skillMult * Player.hacking_money_mult / balanceFactor; + if (percentMoneyHacked < 0) { return 0; } + if (percentMoneyHacked > 1) { return 1; } + + return percentMoneyHacked * BitNodeMultipliers.ScriptHackMoney; +} + +/** + * Returns time it takes to complete a hack on a server, in seconds + */ +export function calculateHackingTime(server) { + const difficultyMult = server.requiredHackingSkill * server.hackDifficulty; + + const baseDiff = 500; + const baseSkill = 50; + const diffFactor = 2.5; + const intFactor = 0.1; + var skillFactor = (diffFactor * difficultyMult + baseDiff); + // tslint:disable-next-line + skillFactor /= (Player.hacking_skill + baseSkill + (intFactor * Player.intelligence)); + + const hackTimeMultiplier = 5; + const hackingTime = hackTimeMultiplier * skillFactor / Player.hacking_speed_mult; + + return hackingTime; +} + +/** + * Returns time it takes to complete a grow operation on a server, in seconds + */ +export function calculateGrowTime(server) { + const growTimeMultiplier = 3.2; // Relative to hacking time. 16/5 = 3.2 + + return growTimeMultiplier * calculateHackingTime(server); +} + +/** + * Returns time it takes to complete a weaken operation on a server, in seconds + */ +export function calculateWeakenTime(server) { + const weakenTimeMultiplier = 4; // Relative to hacking time + + return weakenTimeMultiplier * calculateHackingTime(server); +} diff --git a/src/InteractiveTutorial.js b/src/InteractiveTutorial.js index 5e3affe09..0e721d9d8 100644 --- a/src/InteractiveTutorial.js +++ b/src/InteractiveTutorial.js @@ -1,7 +1,6 @@ import {Engine} from "./engine"; import {Player} from "./Player"; import {Settings} from "./Settings"; -import {Terminal} from "./Terminal"; import {clearEventListeners} from "../utils/uiHelpers/clearEventListeners"; import {createElement} from "../utils/uiHelpers/createElement"; import {createPopup} from "../utils/uiHelpers/createPopup"; @@ -62,7 +61,6 @@ function iTutorialStart() { } Engine.loadTerminalContent(); - Terminal.resetTerminalInput(); //Don't autosave during this interactive tutorial Engine.Counters.autoSaveCounter = Infinity; diff --git a/src/NetscriptEvaluator.js b/src/NetscriptEvaluator.js index a6c6668c7..d1989f01a 100644 --- a/src/NetscriptEvaluator.js +++ b/src/NetscriptEvaluator.js @@ -911,61 +911,5 @@ function isScriptErrorMessage(msg) { return true; } -//The same as Player's calculateHackingChance() function but takes in the server as an argument -function scriptCalculateHackingChance(server) { - var difficultyMult = (100 - server.hackDifficulty) / 100; - var skillMult = (1.75 * Player.hacking_skill) + (0.2 * Player.intelligence); - var skillChance = (skillMult - server.requiredHackingSkill) / skillMult; - var chance = skillChance * difficultyMult * Player.hacking_chance_mult; - if (chance > 1) {return 1;} - if (chance < 0) {return 0;} - else {return chance;} -} - -//The same as Player's calculateHackingTime() function but takes in the server as an argument -function scriptCalculateHackingTime(server) { - var difficultyMult = server.requiredHackingSkill * server.hackDifficulty; - var skillFactor = (2.5 * difficultyMult + 500) / (Player.hacking_skill + 50 + (0.1 * Player.intelligence)); - var hackingTime = 5 * skillFactor / Player.hacking_speed_mult; //This is in seconds - return hackingTime; -} - -//The same as Player's calculateExpGain() function but takes in the server as an argument -function scriptCalculateExpGain(server) { - if (server.baseDifficulty == null) { - server.baseDifficulty = server.hackDifficulty; - } - return (server.baseDifficulty * Player.hacking_exp_mult * 0.3 + 3) * BitNodeMultipliers.HackExpGain; -} - -//The same as Player's calculatePercentMoneyHacked() function but takes in the server as an argument -function scriptCalculatePercentMoneyHacked(server) { - var difficultyMult = (100 - server.hackDifficulty) / 100; - var skillMult = (Player.hacking_skill - (server.requiredHackingSkill - 1)) / Player.hacking_skill; - var percentMoneyHacked = difficultyMult * skillMult * Player.hacking_money_mult / 240; - if (percentMoneyHacked < 0) {return 0;} - if (percentMoneyHacked > 1) {return 1;} - return percentMoneyHacked * BitNodeMultipliers.ScriptHackMoney; -} - -//Amount of time to execute grow() in milliseconds -function scriptCalculateGrowTime(server) { - var difficultyMult = server.requiredHackingSkill * server.hackDifficulty; - var skillFactor = (2.5 * difficultyMult + 500) / (Player.hacking_skill + 50 + (0.1 * Player.intelligence)); - var growTime = 16 * skillFactor / Player.hacking_speed_mult; //This is in seconds - return growTime * 1000; -} - -//Amount of time to execute weaken() in milliseconds -function scriptCalculateWeakenTime(server) { - var difficultyMult = server.requiredHackingSkill * server.hackDifficulty; - var skillFactor = (2.5 * difficultyMult + 500) / (Player.hacking_skill + 50 + (0.1 * Player.intelligence)); - var weakenTime = 20 * skillFactor / Player.hacking_speed_mult; //This is in seconds - return weakenTime * 1000; -} - -export {makeRuntimeRejectMsg, netscriptDelay, runScriptFromScript, - scriptCalculateHackingChance, scriptCalculateHackingTime, - scriptCalculateExpGain, scriptCalculatePercentMoneyHacked, - scriptCalculateGrowTime, scriptCalculateWeakenTime, evaluate, +export {makeRuntimeRejectMsg, netscriptDelay, runScriptFromScript, evaluate, isScriptErrorMessage, killNetscriptDelay, evaluateImport}; diff --git a/src/NetscriptFunctions.js b/src/NetscriptFunctions.js index 7b7a9ba5a..418f04233 100644 --- a/src/NetscriptFunctions.js +++ b/src/NetscriptFunctions.js @@ -13,6 +13,12 @@ import {Companies, Company, CompanyPosition, import {CONSTANTS} from "./Constants"; import {Programs} from "./CreateProgram"; import {DarkWebItems} from "./DarkWeb"; +import {calculateHackingChance, + calculateHackingExpGain, + calculatePercentMoneyHacked, + calculateHackingTime, + calculateGrowTime, + calculateWeakenTime} from "./Hacking"; import {AllGangs} from "./Gang"; import {Factions, Faction, joinFaction, factionExists, purchaseAugmentation} from "./Faction"; @@ -42,10 +48,8 @@ import {unknownBladeburnerActionErrorMessage, checkBladeburnerAccess} from "./NetscriptBladeburner.js"; import {WorkerScript, workerScripts, killWorkerScript, NetscriptPorts} from "./NetscriptWorker"; -import {makeRuntimeRejectMsg, netscriptDelay, runScriptFromScript, - scriptCalculateHackingChance, scriptCalculateHackingTime, - scriptCalculateExpGain, scriptCalculatePercentMoneyHacked, - scriptCalculateGrowTime, scriptCalculateWeakenTime} from "./NetscriptEvaluator"; +import {makeRuntimeRejectMsg, netscriptDelay, + runScriptFromScript} from "./NetscriptEvaluator"; import {NetscriptPort} from "./NetscriptPort"; import Decimal from "decimal.js"; @@ -292,7 +296,7 @@ function NetscriptFunctions(workerScript) { } //Calculate the hacking time - var hackingTime = scriptCalculateHackingTime(server); //This is in seconds + var hackingTime = calculateHackingTime(server); //This is in seconds //No root access or skill level too low if (server.hasAdminRights == false) { @@ -308,14 +312,14 @@ function NetscriptFunctions(workerScript) { if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.hack == null) { workerScript.scriptRef.log("Attempting to hack " + ip + " in " + hackingTime.toFixed(3) + " seconds (t=" + threads + ")"); } - return netscriptDelay(hackingTime* 1000, workerScript).then(function() { + return netscriptDelay(hackingTime * 1000, workerScript).then(function() { if (workerScript.env.stopFlag) {return Promise.reject(workerScript);} - var hackChance = scriptCalculateHackingChance(server); + var hackChance = calculateHackingChance(server); var rand = Math.random(); - var expGainedOnSuccess = scriptCalculateExpGain(server) * threads; + var expGainedOnSuccess = calculateHackingExpGain(server) * threads; var expGainedOnFailure = (expGainedOnSuccess / 4); if (rand < hackChance) { //Success! - const percentHacked = scriptCalculatePercentMoneyHacked(server); + const percentHacked = calculatePercentMoneyHacked(server); let maxThreadNeeded = Math.ceil(1/percentHacked*(server.moneyAvailable/server.moneyMax)); if (isNaN(maxThreadNeeded)) { //Server has a 'max money' of 0 (probably). @@ -390,18 +394,18 @@ function NetscriptFunctions(workerScript) { throw makeRuntimeRejectMsg(workerScript, "Cannot grow this server (" + server.hostname + ") because user does not have root access"); } - var growTime = scriptCalculateGrowTime(server); + var growTime = calculateGrowTime(server); if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.grow == null) { - workerScript.scriptRef.log("Executing grow() on server " + server.hostname + " in " + formatNumber(growTime/1000, 3) + " seconds (t=" + threads + ")"); + workerScript.scriptRef.log("Executing grow() on server " + server.hostname + " in " + formatNumber(growTime, 3) + " seconds (t=" + threads + ")"); } - return netscriptDelay(growTime, workerScript).then(function() { + return netscriptDelay(growTime * 1000, workerScript).then(function() { if (workerScript.env.stopFlag) {return Promise.reject(workerScript);} const moneyBefore = server.moneyAvailable; server.moneyAvailable += (1 * threads); //It can be grown even if it has no money var growthPercentage = processSingleServerGrowth(server, 450 * threads); const moneyAfter = server.moneyAvailable; workerScript.scriptRef.recordGrow(server.ip, threads); - var expGain = scriptCalculateExpGain(server) * threads; + var expGain = calculateHackingExpGain(server) * threads; if (growthPercentage == 1) { expGain = 0; } @@ -437,16 +441,16 @@ function NetscriptFunctions(workerScript) { throw makeRuntimeRejectMsg(workerScript, "Cannot weaken this server (" + server.hostname + ") because user does not have root access"); } - var weakenTime = scriptCalculateWeakenTime(server); + var weakenTime = calculateWeakenTime(server); if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.weaken == null) { workerScript.scriptRef.log("Executing weaken() on server " + server.hostname + " in " + - formatNumber(weakenTime/1000, 3) + " seconds (t=" + threads + ")"); + formatNumber(weakenTime, 3) + " seconds (t=" + threads + ")"); } - return netscriptDelay(weakenTime, workerScript).then(function() { + return netscriptDelay(weakenTime * 1000, workerScript).then(function() { if (workerScript.env.stopFlag) {return Promise.reject(workerScript);} server.weaken(CONSTANTS.ServerWeakenAmount * threads); workerScript.scriptRef.recordWeaken(server.ip, threads); - var expGain = scriptCalculateExpGain(server) * threads; + var expGain = calculateHackingExpGain(server) * threads; if (workerScript.disableLogs.ALL == null && workerScript.disableLogs.weaken == null) { workerScript.scriptRef.log("Server security level on " + server.hostname + " weakened to " + server.hackDifficulty + ". Gained " + formatNumber(expGain, 4) + " hacking exp (t=" + threads + ")"); @@ -2057,7 +2061,7 @@ function NetscriptFunctions(workerScript) { workerScript.scriptRef.log("getHackTime() failed. Invalid IP or hostname passed in: " + ip); throw makeRuntimeRejectMsg(workerScript, "getHackTime() failed. Invalid IP or hostname passed in: " + ip); } - return scriptCalculateHackingTime(server); //Returns seconds + return calculateHackingTime(server); //Returns seconds }, getGrowTime : function(ip) { if (workerScript.checkingRam) { @@ -2069,7 +2073,7 @@ function NetscriptFunctions(workerScript) { workerScript.scriptRef.log("getGrowTime() failed. Invalid IP or hostname passed in: " + ip); throw makeRuntimeRejectMsg(workerScript, "getGrowTime() failed. Invalid IP or hostname passed in: " + ip); } - return scriptCalculateGrowTime(server) / 1000; //Returns seconds + return calculateGrowTime(server); //Returns seconds }, getWeakenTime : function(ip) { if (workerScript.checkingRam) { @@ -2081,7 +2085,7 @@ function NetscriptFunctions(workerScript) { workerScript.scriptRef.log("getWeakenTime() failed. Invalid IP or hostname passed in: " + ip); throw makeRuntimeRejectMsg(workerScript, "getWeakenTime() failed. Invalid IP or hostname passed in: " + ip); } - return scriptCalculateWeakenTime(server) / 1000; //Returns seconds + return calculateWeakenTime(server); //Returns seconds }, getScriptIncome : function(scriptname, ip) { if (workerScript.checkingRam) { diff --git a/src/Player.js b/src/Player.js index 491e5d078..27ad67086 100644 --- a/src/Player.js +++ b/src/Player.js @@ -119,11 +119,6 @@ function PlayerObject() { this.crime_money_mult = 1; this.crime_success_mult = 1; - //Flag to let the engine know the player is starting an action - // Current actions: hack, analyze - this.startAction = false; - this.actionTime = 0; - //Flags/variables for working (Company, Faction, Creating Program, Taking Class) this.isWorking = false; this.workType = ""; @@ -265,9 +260,6 @@ PlayerObject.prototype.prestigeAugmentation = function() { this.queuedAugmentations = []; - this.startAction = false; - this.actionTime = 0; - this.isWorking = false; this.currentWorkFactionName = ""; this.currentWorkFactionDescription = ""; @@ -349,9 +341,6 @@ PlayerObject.prototype.prestigeSourceFile = function() { this.queuedAugmentations = []; this.augmentations = []; - this.startAction = false; - this.actionTime = 0; - this.isWorking = false; this.currentWorkFactionName = ""; this.currentWorkFactionDescription = ""; @@ -498,72 +487,6 @@ PlayerObject.prototype.resetMultipliers = function() { this.bladeburner_success_chance_mult = 1; } -//Calculates the chance of hacking a server -//The formula is: -// (2 * hacking_chance_multiplier * hacking_skill - requiredLevel) 100 - difficulty -// ----------------------------------------------------------- * ----------------- -// (2 * hacking_chance_multiplier * hacking_skill) 100 -PlayerObject.prototype.calculateHackingChance = function() { - var difficultyMult = (100 - this.getCurrentServer().hackDifficulty) / 100; - var skillMult = (1.75 * this.hacking_skill) + (0.2 * this.intelligence); - var skillChance = (skillMult - this.getCurrentServer().requiredHackingSkill) / skillMult; - var chance = skillChance * difficultyMult * this.hacking_chance_mult; - if (chance > 1) {return 1;} - if (chance < 0) {return 0;} - return chance; -} - -//Calculate the time it takes to hack a server in seconds. Returns the time -//The formula is: -// (2.5 * requiredLevel * difficulty + 200) -// ----------------------------------- * hacking_speed_multiplier -// hacking_skill + 100 -PlayerObject.prototype.calculateHackingTime = function() { - var difficultyMult = this.getCurrentServer().requiredHackingSkill * this.getCurrentServer().hackDifficulty; - var skillFactor = (2.5 * difficultyMult + 200) / (this.hacking_skill + 100 + (0.1 * this.intelligence)); - return 5 * skillFactor / this.hacking_speed_mult; -} - -//Calculates the PERCENTAGE of a server's money that the player will hack from the server if successful -//The formula is: -// (hacking_skill - (requiredLevel-1)) 100 - difficulty -// --------------------------------------* ----------------------- * hacking_money_multiplier -// hacking_skill 100 -PlayerObject.prototype.calculatePercentMoneyHacked = function() { - var difficultyMult = (100 - this.getCurrentServer().hackDifficulty) / 100; - var skillMult = (this.hacking_skill - (this.getCurrentServer().requiredHackingSkill - 1)) / this.hacking_skill; - var percentMoneyHacked = difficultyMult * skillMult * this.hacking_money_mult / 240; - console.log("Percent money hacked calculated to be: " + percentMoneyHacked); - if (percentMoneyHacked < 0) {return 0;} - if (percentMoneyHacked > 1) {return 1;} - return percentMoneyHacked * BitNodeMultipliers.ManualHackMoney; -} - -//Returns how much EXP the player gains on a successful hack -//The formula is: -// difficulty * requiredLevel * hacking_multiplier -PlayerObject.prototype.calculateExpGain = function() { - var s = this.getCurrentServer(); - if (s.baseDifficulty == null) { - s.baseDifficulty = s.hackDifficulty; - } - return (s.baseDifficulty * this.hacking_exp_mult * 0.3 + 3) * BitNodeMultipliers.HackExpGain; -} - -//Hack/Analyze a server. Return the amount of time the hack will take. This lets the Terminal object know how long to disable itself for -//This assumes that the server being hacked is not purchased by the player, that the player's hacking skill is greater than the -//required hacking skill and that the player has admin rights. -PlayerObject.prototype.hack = function() { - this.actionTime = this.calculateHackingTime(); - console.log("Hacking time: " + this.actionTime); - this.startAction = true; //Set the startAction flag so the engine starts the hacking process -} - -PlayerObject.prototype.analyze = function() { - this.actionTime = 1; - this.startAction = true; -} - PlayerObject.prototype.hasProgram = function(programName) { var home = Player.getHomeComputer(); if (home == null) {return false;} diff --git a/src/Terminal.js b/src/Terminal.js index 996f84aa8..ea575513b 100644 --- a/src/Terminal.js +++ b/src/Terminal.js @@ -10,14 +10,17 @@ import {executeDarkwebTerminalCommand, import {Engine} from "./engine"; import {FconfSettings, parseFconfSettings, createFconf} from "./Fconf"; +import {calculateHackingChance, + calculateHackingExpGain, + calculatePercentMoneyHacked, + calculateHackingTime, + calculateGrowTime, + calculateWeakenTime} from "./Hacking"; import {TerminalHelpText, HelpTexts} from "./HelpText"; import {iTutorialNextStep, iTutorialSteps, ITutorial} from "./InteractiveTutorial"; import {showLiterature} from "./Literature"; import {showMessage, Message} from "./Message"; -import {scriptCalculateHackingTime, - scriptCalculateGrowTime, - scriptCalculateWeakenTime} from "./NetscriptEvaluator"; import {killWorkerScript, addWorkerScript} from "./NetscriptWorker"; import numeral from "numeral/min/numeral.min"; import {Player} from "./Player"; @@ -512,8 +515,10 @@ function determineAllPossibilitiesForTabCompletion(input, index=0) { let Terminal = { //Flags to determine whether the player is currently running a hack or an analyze - hackFlag: false, - analyzeFlag: false, + hackFlag: false, + analyzeFlag: false, + actionStarted: false, + actionTime: 0, commandHistory: [], commandHistoryIndex: 0, @@ -619,6 +624,32 @@ let Terminal = { } }, + startHack: function() { + Terminal.hackFlag = true; + + //Hacking through Terminal should be faster than hacking through a script + Terminal.actionTime = calculateHackingTime(Player.getCurrentServer()) / 4; + Terminal.startAction(); + }, + + startAnalyze: function() { + Terminal.analyzeFlag = true; + Terminal.actionTime = 1; + post("Analyzing system..."); + Terminal.startAction(); + }, + + startAction: function() { + Terminal.actionStarted = true; + + hackProgressPost("Time left:"); + hackProgressBarPost("["); + + //Disable terminal + document.getElementById("terminal-input-td").innerHTML = ''; + $('input[class=terminal-input]').prop('disabled', true); + }, + finishAction: function(cancelled = false) { if (Terminal.hackFlag) { Terminal.finishHack(cancelled); @@ -633,10 +664,10 @@ let Terminal = { var server = Player.getCurrentServer(); //Calculate whether hack was successful - var hackChance = Player.calculateHackingChance(); + var hackChance = calculateHackingChance(server); var rand = Math.random(); console.log("Hack success chance: " + hackChance + ", rand: " + rand); - var expGainedOnSuccess = Player.calculateExpGain(); + var expGainedOnSuccess = calculateHackingExpGain(server); var expGainedOnFailure = (expGainedOnSuccess / 4); if (rand < hackChance) { //Success! if (SpecialServerIps[SpecialServerNames.WorldDaemon] && @@ -648,7 +679,7 @@ let Terminal = { return; } server.manuallyHacked = true; - var moneyGained = Player.calculatePercentMoneyHacked(); + var moneyGained = calculatePercentMoneyHacked(server); moneyGained = Math.floor(server.moneyAvailable * moneyGained); if (moneyGained <= 0) {moneyGained = 0;} //Safety check @@ -679,43 +710,44 @@ let Terminal = { finishAnalyze: function(cancelled = false) { if (cancelled == false) { - post(Player.getCurrentServer().hostname + ": "); - post("Organization name: " + Player.getCurrentServer().organizationName); + let currServ = Player.getCurrentServer(); + post(currServ.hostname + ": "); + post("Organization name: " + currServ.organizationName); var rootAccess = ""; - if (Player.getCurrentServer().hasAdminRights) {rootAccess = "YES";} + if (currServ.hasAdminRights) {rootAccess = "YES";} else {rootAccess = "NO";} post("Root Access: " + rootAccess); - post("Required hacking skill: " + Player.getCurrentServer().requiredHackingSkill); - post("Estimated server security level: " + formatNumber(addOffset(Player.getCurrentServer().hackDifficulty, 5), 3)); - post("Estimated chance to hack: " + formatNumber(addOffset(Player.calculateHackingChance() * 100, 5), 2) + "%"); - post("Estimated time to hack: " + formatNumber(addOffset(Player.calculateHackingTime(), 5), 3) + " seconds"); - post("Estimated total money available on server: $" + formatNumber(addOffset(Player.getCurrentServer().moneyAvailable, 5), 2)); - post("Required number of open ports for NUKE: " + Player.getCurrentServer().numOpenPortsRequired); - if (Player.getCurrentServer().sshPortOpen) { + post("Required hacking skill: " + currServ.requiredHackingSkill); + post("Server security level: " + formatNumber(currServ.hackDifficulty, 3)); + post("Chance to hack: " + formatNumber(calculateHackingChance(currServ) * 100, 2) + "%"); + post("Time to hack: " + formatNumber(calculateHackingTime(currServ), 3) + " seconds"); + post("Total money available on server: $" + formatNumber(currServ.moneyAvailable, 2)); + post("Required number of open ports for NUKE: " + currServ.numOpenPortsRequired); + if (currServ.sshPortOpen) { post("SSH port: Open") } else { post("SSH port: Closed") } - if (Player.getCurrentServer().ftpPortOpen) { + if (currServ.ftpPortOpen) { post("FTP port: Open") } else { post("FTP port: Closed") } - if (Player.getCurrentServer().smtpPortOpen) { + if (currServ.smtpPortOpen) { post("SMTP port: Open") } else { post("SMTP port: Closed") } - if (Player.getCurrentServer().httpPortOpen) { + if (currServ.httpPortOpen) { post("HTTP port: Open") } else { post("HTTP port: Closed") } - if (Player.getCurrentServer().sqlPortOpen) { + if (currServ.sqlPortOpen) { post("SQL port: Open") } else { post("SQL port: Closed") @@ -815,17 +847,7 @@ let Terminal = { if (commandArray.length != 1) { post("Incorrect usage of analyze command. Usage: analyze"); return; } - //Analyze the current server for information - Terminal.analyzeFlag = true; - post("Analyzing system..."); - hackProgressPost("Time left:"); - hackProgressBarPost("["); - Player.analyze(); - - //Disable terminal - //Terminal.resetTerminalInput(); - document.getElementById("terminal-input-td").innerHTML = ''; - $('input[class=terminal-input]').prop('disabled', true); + Terminal.startAnalyze(); iTutorialNextStep(); } else { post("Bad command. Please follow the tutorial"); @@ -841,15 +863,7 @@ let Terminal = { break; case iTutorialSteps.TerminalManualHack: if (commandArray.length == 1 && commandArray[0] == "hack") { - Terminal.hackFlag = true; - hackProgressPost("Time left:"); - hackProgressBarPost("["); - Player.hack(); - - //Disable terminal - //Terminal.resetTerminalInput(); - document.getElementById("terminal-input-td").innerHTML = ''; - $('input[class=terminal-input]').prop('disabled', true); + Terminal.startHack(); iTutorialNextStep(); } else {post("Bad command. Please follow the tutorial");} break; @@ -920,17 +934,7 @@ let Terminal = { if (commandArray.length != 1) { post("Incorrect usage of analyze command. Usage: analyze"); return; } - //Analyze the current server for information - Terminal.analyzeFlag = true; - post("Analyzing system..."); - hackProgressPost("Time left:"); - hackProgressBarPost("["); - Player.analyze(); - - //Disable terminal - //Terminal.resetTerminalInput(); - document.getElementById("terminal-input-td").innerHTML = ''; - $('input[class=terminal-input]').prop('disabled', true); + Terminal.startAnalyze(); break; case "buy": if (SpecialServerIps.hasOwnProperty("Darkweb Server")) { @@ -1083,15 +1087,7 @@ let Terminal = { } else if (Player.getCurrentServer().requiredHackingSkill > Player.hacking_skill) { post("Your hacking skill is not high enough to attempt hacking this machine. Try analyzing the machine to determine the required hacking skill"); } else { - Terminal.hackFlag = true; - hackProgressPost("Time left:"); - hackProgressBarPost("["); - Player.hack(); - - //Disable terminal - //Terminal.resetTerminalInput(); - document.getElementById("terminal-input-td").innerHTML = ''; - $('input[class=terminal-input]').prop('disabled', true); + Terminal.startHack(); } break; case "help": @@ -1891,9 +1887,9 @@ let Terminal = { post("Server base security level: " + targetServer.baseDifficulty); post("Server current security level: " + targetServer.hackDifficulty); post("Server growth rate: " + targetServer.serverGrowth); - post("Netscript hack() execution time: " + formatNumber(scriptCalculateHackingTime(targetServer), 1) + "s"); - post("Netscript grow() execution time: " + formatNumber(scriptCalculateGrowTime(targetServer)/1000, 1) + "s"); - post("Netscript weaken() execution time: " + formatNumber(scriptCalculateWeakenTime(targetServer)/1000, 1) + "s"); + post("Netscript hack() execution time: " + formatNumber(calculateHackingTime(targetServer), 1) + "s"); + post("Netscript grow() execution time: " + formatNumber(calculateGrowTime(targetServer), 1) + "s"); + post("Netscript weaken() execution time: " + formatNumber(calculateWeakenTime(targetServer), 1) + "s"); }; programHandlers[Programs.AutoLink.name] = () => { post("This executable cannot be run."); diff --git a/src/engine.js b/src/engine.js index e9745dea0..034be3ebb 100644 --- a/src/engine.js +++ b/src/engine.js @@ -923,14 +923,14 @@ let Engine = { Player.playtimeSinceLastBitnode += time; //Start Manual hack - if (Player.startAction == true) { - Engine._totalActionTime = Player.actionTime; - Engine._actionTimeLeft = Player.actionTime; + if (Terminal.actionStarted === true) { + Engine._totalActionTime = Terminal.actionTime; + Engine._actionTimeLeft = Terminal.actionTime; Engine._actionInProgress = true; Engine._actionProgressBarCount = 1; Engine._actionProgressStr = "[ ]"; Engine._actionTimeStr = "Time left: "; - Player.startAction = false; + Terminal.actionStarted = false; } //Working diff --git a/src/index.html b/src/index.html new file mode 100644 index 000000000..e3e0cf485 --- /dev/null +++ b/src/index.html @@ -0,0 +1,1026 @@ + + + + + <%= htmlWebpackPlugin.options.title %> + + + + + + + + + + + + + <% +if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %> + <% +} %> + + +
+ + +
+
+
Loading Bitburner...
+
+ + + + diff --git a/tslint.json b/tslint.json index f1ee12cc8..cd0164ccf 100644 --- a/tslint.json +++ b/tslint.json @@ -48,6 +48,7 @@ "ignore-params", "ignore-properties" ], + "no-magic-numbers": [true, -1, 0, 1, 2, 10, 100], "no-null-keyword": false, "no-unsafe-any": false, "object-literal-key-quotes": [ @@ -59,6 +60,7 @@ "allow-declarations", "allow-named-functions" ], + "triple-equals": [true, "allow-null-check", "allow-undefined-check"], "typedef": [ true, "call-signatures", @@ -73,4 +75,4 @@ ] }, "rulesDirectory": [] -} \ No newline at end of file +} diff --git a/utils/helpers/getTimestamp.ts b/utils/helpers/getTimestamp.ts index a26d220c1..6e7ee119f 100644 --- a/utils/helpers/getTimestamp.ts +++ b/utils/helpers/getTimestamp.ts @@ -1,5 +1,5 @@ /** - * Formats the current time (to the minute). + * Returns a MM/DD HH:MM timestamp for the current time */ export function getTimestamp() { const d: Date = new Date(); diff --git a/webpack.config.js b/webpack.config.js index 559733c26..666503508 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,6 +1,7 @@ var path = require('path'); var webpack = require('webpack'); var MiniCssExtractPlugin = require('mini-css-extract-plugin'); +var HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = (env, argv) => ({ plugins: [ @@ -16,6 +17,45 @@ module.exports = (env, argv) => ({ jQuery: "jquery", $: "jquery" }), + new HtmlWebpackPlugin({ + title: "Bitburner" + (argv.mode === 'development' ? ' - development' : ""), + template: "src/index.html", + favicon: "favicon.ico", + googleAnalytics: { + trackingId: 'UA-100157497-1' + }, + meta: {}, + minify: argv.mode === 'development' ? false : { + collapseBooleanAttributes: true, + collapseInlineTagWhitespace: false, + collapseWhitespace: false, + conservativeCollapse: false, + html5: true, + includeAutoGeneratedTags: false, + keepClosingSlash: true, + minifyCSS: false, + minifyJS: false, + minifyURLs: false, + preserveLineBreaks: false, + preventAttributesEscaping: false, + processConditionalComments: false, + quoteCharacter: "\"", + removeAttributeQuotes: false, + removeComments: false, + removeEmptyAttributes: false, + removeEmptyElements: false, + removeOptionalTags: false, + removeScriptTypeAttributes: false, + removeStyleLinkTypeAttributes: false, + removeTagWhitespace: false, + sortAttributes: false, + sortClassName: false, + useShortDoctype: false + }, + excludeChunks: [ + "tests/tests" + ] + }), new MiniCssExtractPlugin({ filename: "[name].css", chunkFilename: "[id].css"