mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-18 12:15:44 +01:00
merge dev
This commit is contained in:
commit
d2f2ab07d7
36
dist/vendor.bundle.js
vendored
36
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
18
doc/source/netscript/advancedfunctions/atExit.rst
Normal file
18
doc/source/netscript/advancedfunctions/atExit.rst
Normal file
@ -0,0 +1,18 @@
|
||||
atExit() Netscript Function
|
||||
============================
|
||||
|
||||
.. js:function:: atExit(f)
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param function f: function to call when the script dies.
|
||||
|
||||
Runs when the script dies.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
function onDeath() {
|
||||
console.log('I died!!!')
|
||||
}
|
||||
atExit(onDeath);
|
36
doc/source/netscript/advancedfunctions/autocomplete.rst
Normal file
36
doc/source/netscript/advancedfunctions/autocomplete.rst
Normal file
@ -0,0 +1,36 @@
|
||||
autocomplete() Netscript Function
|
||||
============================
|
||||
|
||||
.. warning:: This feature is not officially supported yet and the API might change.
|
||||
|
||||
.. js:function:: autocomplete(data, args)
|
||||
|
||||
:RAM cost: 0 GB
|
||||
:param Object data: general data about the game you might want to autocomplete.
|
||||
:param string[] args: current arguments.
|
||||
|
||||
data is an object with the following properties::
|
||||
|
||||
{
|
||||
servers: list of all servers in the game.
|
||||
txts: list of all text files on the current server.
|
||||
scripts: list of all scripts on the current server.
|
||||
}
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
export function autocomplete(data, args) {
|
||||
return [...data.servers]; // This script autocompletes the list of servers.
|
||||
return [...data.servers, ...data.scripts]; // Autocomplete servers and scripts
|
||||
return ["low", "medium", "high"]; // Autocomplete 3 specific strings.
|
||||
}
|
||||
|
||||
Terminal:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
$ run demo.ns mega\t
|
||||
// results in
|
||||
$ run demo.ns megacorp
|
@ -10,3 +10,4 @@ they contain spoilers for the game.
|
||||
|
||||
getBitNodeMultipliers() <advancedfunctions/getBitNodeMultipliers>
|
||||
getServer() <advancedfunctions/getServer>
|
||||
autocomplete() <advancedfunctions/autocomplete>
|
||||
|
@ -43,6 +43,7 @@ The player has access to all of these functions while in BitNode-4. Completing B
|
||||
getFactionRep() <singularityfunctions/getFactionRep>
|
||||
getFactionFavor() <singularityfunctions/getFactionFavor>
|
||||
getFactionFavorGain() <singularityfunctions/getFactionFavorGain>
|
||||
upgradeHomeCores() <singularityfunctions/upgradeHomeCores>
|
||||
|
||||
.. toctree::
|
||||
:caption: Level 3 Functions
|
||||
|
@ -0,0 +1,12 @@
|
||||
upgradeHomeRam() Netscript Function
|
||||
===================================
|
||||
|
||||
.. js:function:: upgradeHomeCores()
|
||||
|
||||
:RAM cost: 3 GB
|
||||
|
||||
If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.
|
||||
|
||||
This function will upgrade amount of CORES on the player's home computer. The cost is the same as if you were to do it manually.
|
||||
|
||||
This function will return true if the player's home computer core count is successfully upgraded, and false otherwise.
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
14355
package-lock.json
generated
14355
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
63
package.json
63
package.json
@ -14,7 +14,6 @@
|
||||
"@emotion/styled": "^11.3.0",
|
||||
"@monaco-editor/react": "^4.2.2",
|
||||
"@mui/icons-material": "^5.0.3",
|
||||
"@mui/lab": "^5.0.0-alpha.46",
|
||||
"@mui/material": "^5.0.3",
|
||||
"@mui/styles": "^5.0.1",
|
||||
"@types/escodegen": "^0.0.7",
|
||||
@ -25,47 +24,23 @@
|
||||
"@types/react-resizable": "^1.7.3",
|
||||
"acorn": "^8.4.1",
|
||||
"acorn-walk": "^8.1.1",
|
||||
"ajv": "^5.1.5",
|
||||
"ajv-keywords": "^2.0.0",
|
||||
"arg": "^5.0.0",
|
||||
"async": "^2.6.1",
|
||||
"autosize": "^4.0.2",
|
||||
"better-react-mathjax": "^1.0.3",
|
||||
"brace": "^0.11.1",
|
||||
"codemirror": "^5.58.2",
|
||||
"clsx": "^1.1.1",
|
||||
"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.5.0",
|
||||
"jshint": "^2.10.2",
|
||||
"json-loader": "^0.5.4",
|
||||
"jsplumb": "^2.6.8",
|
||||
"jszip": "^3.7.0",
|
||||
"loader-runner": "^2.3.0",
|
||||
"loader-utils": "^1.1.0",
|
||||
"material-ui-color": "^1.2.0",
|
||||
"mathjax-full": "^3.2.0",
|
||||
"memory-fs": "~0.4.1",
|
||||
"monaco-editor": "^0.27.0",
|
||||
"node-sass": "^6.0.1",
|
||||
"normalize.css": "^8.0.0",
|
||||
"notistack": "^2.0.2",
|
||||
"numeral": "2.0.6",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-draggable": "^4.4.4",
|
||||
"react-modal": "^3.12.1",
|
||||
"react-resizable": "^3.0.4",
|
||||
"sprintf-js": "^1.1.1",
|
||||
"tapable": "^1.0.0",
|
||||
"treant-js": "^1.0.1",
|
||||
"unused-webpack-plugin": "^2.4.0",
|
||||
"uuid": "^3.2.1",
|
||||
"w3c-blob": "0.0.1",
|
||||
"webpack-deadcode-plugin": "^0.1.15"
|
||||
"sprintf-js": "^1.1.1"
|
||||
},
|
||||
"description": "A cyberpunk-themed incremental game",
|
||||
"devDependencies": {
|
||||
@ -76,64 +51,33 @@
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.1",
|
||||
"@testing-library/cypress": "^8.0.1",
|
||||
"@types/file-saver": "^2.0.3",
|
||||
"@types/jest": "^27.0.1",
|
||||
"@types/lodash": "^4.14.168",
|
||||
"@types/node": "^16.9.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.22.0",
|
||||
"@typescript-eslint/parser": "^4.22.0",
|
||||
"babel-jest": "^27.0.6",
|
||||
"babel-loader": "^8.0.5",
|
||||
"beautify-lint": "^1.0.3",
|
||||
"benchmark": "^2.1.1",
|
||||
"bundle-loader": "~0.5.0",
|
||||
"css-loader": "^0.28.11",
|
||||
"cypress": "^8.3.1",
|
||||
"electron": "^14.0.1",
|
||||
"electron-packager": "^15.4.0",
|
||||
"es6-promise-polyfill": "^1.1.1",
|
||||
"eslint": "^7.24.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"file-loader": "^1.1.11",
|
||||
"fork-ts-checker-webpack-plugin": "^6.3.3",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"http-server": "^13.0.1",
|
||||
"i18n-webpack-plugin": "^1.0.0",
|
||||
"istanbul": "^0.4.5",
|
||||
"jest": "^27.1.0",
|
||||
"js-beautify": "^1.5.10",
|
||||
"jsdom": "^15.0.0",
|
||||
"jsdom-global": "^3.0.2",
|
||||
"json5": "^1.0.1",
|
||||
"less": "^3.9.0",
|
||||
"less-loader": "^4.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"mini-css-extract-plugin": "^0.4.1",
|
||||
"mkdirp": "^0.5.1",
|
||||
"null-loader": "^1.0.0",
|
||||
"prettier": "^2.3.2",
|
||||
"raw-loader": "~0.5.0",
|
||||
"react-refresh": "^0.10.0",
|
||||
"regenerator-runtime": "^0.13.9",
|
||||
"sass-loader": "^7.0.3",
|
||||
"script-loader": "~0.7.0",
|
||||
"should": "^11.1.1",
|
||||
"simple-git": "^1.96.0",
|
||||
"sinon": "^2.3.2",
|
||||
"source-map": "^0.7.3",
|
||||
"start-server-and-test": "^1.14.0",
|
||||
"style-loader": "^0.21.0",
|
||||
"stylelint": "^9.2.1",
|
||||
"stylelint-order": "^0.8.1",
|
||||
"typescript": "^4.2.4",
|
||||
"uglify-es": "^3.3.9",
|
||||
"uglifyjs-webpack-plugin": "^1.3.0",
|
||||
"url-loader": "^1.0.1",
|
||||
"watchpack": "^1.6.0",
|
||||
"webpack": "^4.46.0",
|
||||
"webpack-cli": "^3.3.12",
|
||||
"webpack-dev-middleware": "^3.7.3",
|
||||
"webpack-dev-server": "^3.11.2",
|
||||
"worker-loader": "^2.0.0"
|
||||
"webpack-dev-server": "^3.11.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8 || <=9"
|
||||
@ -157,7 +101,6 @@
|
||||
"build:dev": "webpack --mode development",
|
||||
"lint": "npm run lint:jsts & npm run lint:style",
|
||||
"lint:jsts": "eslint --fix . --ext js,jsx,ts,tsx",
|
||||
"lint:style": "stylelint --fix ./css/*",
|
||||
"preinstall": "node ./scripts/engines-check.js",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
|
@ -2,25 +2,25 @@ const numSpaces = 4;
|
||||
const maxLineLength = 160;
|
||||
|
||||
module.exports = {
|
||||
env: {
|
||||
es6: true,
|
||||
node: true,
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
extends: "eslint:recommended",
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
experimentalObjectRestSpread: true,
|
||||
"extends": "eslint:recommended",
|
||||
"parserOptions": {
|
||||
"ecmaFeatures": {
|
||||
"experimentalObjectRestSpread": true
|
||||
},
|
||||
ecmaVersion: 8,
|
||||
sourceType: "module",
|
||||
"ecmaVersion": 8,
|
||||
"sourceType": "module"
|
||||
},
|
||||
rules: {
|
||||
"rules": {
|
||||
"accessor-pairs": [
|
||||
"error",
|
||||
{
|
||||
getWithoutSet: false,
|
||||
setWithoutGet: true,
|
||||
},
|
||||
"getWithoutSet": false,
|
||||
"setWithoutGet": true
|
||||
}
|
||||
],
|
||||
"array-bracket-newline": ["error"],
|
||||
"array-bracket-spacing": ["error"],
|
||||
@ -33,35 +33,50 @@ module.exports = {
|
||||
"block-spacing": ["error"],
|
||||
"brace-style": ["error"],
|
||||
"callback-return": ["error"],
|
||||
camelcase: ["error"],
|
||||
"camelcase": ["error"],
|
||||
"capitalized-comments": ["error"],
|
||||
"class-methods-use-this": ["error"],
|
||||
"comma-dangle": ["error"],
|
||||
"comma-spacing": ["error"],
|
||||
"comma-style": ["error", "last"],
|
||||
complexity: ["error"],
|
||||
"computed-property-spacing": ["error", "never"],
|
||||
"comma-style": [
|
||||
"error",
|
||||
"last"
|
||||
],
|
||||
"complexity": ["error"],
|
||||
"computed-property-spacing": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"consistent-return": ["error"],
|
||||
"consistent-this": ["error"],
|
||||
"constructor-super": ["error"],
|
||||
curly: ["error"],
|
||||
"curly": ["error"],
|
||||
"default-case": ["error"],
|
||||
"dot-location": ["error", "property"],
|
||||
"dot-location": [
|
||||
"error",
|
||||
"property"
|
||||
],
|
||||
"dot-notation": ["error"],
|
||||
"eol-last": ["error"],
|
||||
eqeqeq: ["error"],
|
||||
"eqeqeq": ["error"],
|
||||
"for-direction": ["error"],
|
||||
"func-call-spacing": ["error"],
|
||||
"func-name-matching": ["error"],
|
||||
"func-names": ["error", "never"],
|
||||
"func-names": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"func-style": ["error"],
|
||||
"function-paren-newline": ["error"],
|
||||
"generator-star-spacing": ["error", "before"],
|
||||
"generator-star-spacing": [
|
||||
"error",
|
||||
"before"
|
||||
],
|
||||
"getter-return": [
|
||||
"error",
|
||||
{
|
||||
allowImplicit: false,
|
||||
},
|
||||
"allowImplicit": false
|
||||
}
|
||||
],
|
||||
"global-require": ["error"],
|
||||
"guard-for-in": ["error"],
|
||||
@ -69,37 +84,52 @@ module.exports = {
|
||||
"id-blacklist": ["error"],
|
||||
"id-length": ["error"],
|
||||
"id-match": ["error"],
|
||||
"implicit-arrow-linebreak": ["error", "beside"],
|
||||
indent: [
|
||||
"implicit-arrow-linebreak": [
|
||||
"error",
|
||||
"beside"
|
||||
],
|
||||
"indent": [
|
||||
"error",
|
||||
numSpaces,
|
||||
{
|
||||
SwitchCase: 1,
|
||||
},
|
||||
"SwitchCase": 1
|
||||
}
|
||||
],
|
||||
"init-declarations": ["error"],
|
||||
"jsx-quotes": ["error"],
|
||||
"key-spacing": ["error"],
|
||||
"keyword-spacing": ["error"],
|
||||
"line-comment-position": ["error"],
|
||||
"linebreak-style": ["error", "windows"],
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"windows"
|
||||
],
|
||||
"lines-around-comment": ["error"],
|
||||
"lines-between-class-members": ["error"],
|
||||
"max-depth": ["error"],
|
||||
"max-len": ["error", maxLineLength],
|
||||
"max-len": [
|
||||
"error",
|
||||
maxLineLength
|
||||
],
|
||||
"max-lines": [
|
||||
"error",
|
||||
{
|
||||
skipBlankLines: true,
|
||||
skipComments: true,
|
||||
},
|
||||
"skipBlankLines": true,
|
||||
"skipComments": true
|
||||
}
|
||||
],
|
||||
"max-nested-callbacks": ["error"],
|
||||
"max-params": ["error"],
|
||||
"max-statements": ["error"],
|
||||
"max-statements-per-line": ["error"],
|
||||
"multiline-comment-style": ["off", "starred-block"],
|
||||
"multiline-ternary": ["error", "never"],
|
||||
"multiline-comment-style": [
|
||||
"off",
|
||||
"starred-block"
|
||||
],
|
||||
"multiline-ternary": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"new-cap": ["error"],
|
||||
"new-parens": ["error"],
|
||||
// TODO: configure this...
|
||||
@ -115,15 +145,18 @@ module.exports = {
|
||||
"no-catch-shadow": ["error"],
|
||||
"no-class-assign": ["error"],
|
||||
"no-compare-neg-zero": ["error"],
|
||||
"no-cond-assign": ["error", "except-parens"],
|
||||
"no-cond-assign": [
|
||||
"error",
|
||||
"except-parens"
|
||||
],
|
||||
"no-confusing-arrow": ["error"],
|
||||
"no-console": ["error"],
|
||||
"no-const-assign": ["error"],
|
||||
"no-constant-condition": [
|
||||
"error",
|
||||
{
|
||||
checkLoops: false,
|
||||
},
|
||||
"checkLoops": false
|
||||
}
|
||||
],
|
||||
"no-continue": ["off"],
|
||||
"no-control-regex": ["error"],
|
||||
@ -137,15 +170,15 @@ module.exports = {
|
||||
"no-duplicate-imports": [
|
||||
"error",
|
||||
{
|
||||
includeExports: true,
|
||||
},
|
||||
"includeExports": true
|
||||
}
|
||||
],
|
||||
"no-else-return": ["error"],
|
||||
"no-empty": [
|
||||
"error",
|
||||
{
|
||||
allowEmptyCatch: false,
|
||||
},
|
||||
"allowEmptyCatch": false
|
||||
}
|
||||
],
|
||||
"no-empty-character-class": ["error"],
|
||||
"no-empty-function": ["error"],
|
||||
@ -161,8 +194,8 @@ module.exports = {
|
||||
"error",
|
||||
"all",
|
||||
{
|
||||
conditionalAssign: false,
|
||||
},
|
||||
"conditionalAssign": false
|
||||
}
|
||||
],
|
||||
"no-extra-semi": ["error"],
|
||||
"no-fallthrough": ["error"],
|
||||
@ -173,17 +206,20 @@ module.exports = {
|
||||
"no-implicit-globals": ["error"],
|
||||
"no-implied-eval": ["error"],
|
||||
"no-inline-comments": ["error"],
|
||||
"no-inner-declarations": ["error", "both"],
|
||||
"no-inner-declarations": [
|
||||
"error",
|
||||
"both"
|
||||
],
|
||||
"no-invalid-regexp": ["error"],
|
||||
"no-invalid-this": ["error"],
|
||||
"no-irregular-whitespace": [
|
||||
"error",
|
||||
{
|
||||
skipComments: false,
|
||||
skipRegExps: false,
|
||||
skipStrings: false,
|
||||
skipTemplates: false,
|
||||
},
|
||||
"skipComments": false,
|
||||
"skipRegExps": false,
|
||||
"skipStrings": false,
|
||||
"skipTemplates": false
|
||||
}
|
||||
],
|
||||
"no-iterator": ["error"],
|
||||
"no-label-var": ["error"],
|
||||
@ -194,9 +230,13 @@ module.exports = {
|
||||
"no-magic-numbers": [
|
||||
"error",
|
||||
{
|
||||
ignore: [-1, 0, 1],
|
||||
ignoreArrayIndexes: true,
|
||||
},
|
||||
"ignore": [
|
||||
-1,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"ignoreArrayIndexes": true
|
||||
}
|
||||
],
|
||||
"no-mixed-operators": ["error"],
|
||||
"no-mixed-requires": ["error"],
|
||||
@ -207,8 +247,8 @@ module.exports = {
|
||||
"no-multiple-empty-lines": [
|
||||
"error",
|
||||
{
|
||||
max: 1,
|
||||
},
|
||||
"max": 1
|
||||
}
|
||||
],
|
||||
"no-native-reassign": ["error"],
|
||||
"no-negated-condition": ["error"],
|
||||
@ -228,8 +268,8 @@ module.exports = {
|
||||
"no-plusplus": [
|
||||
"error",
|
||||
{
|
||||
allowForLoopAfterthoughts: true,
|
||||
},
|
||||
"allowForLoopAfterthoughts": true
|
||||
}
|
||||
],
|
||||
"no-process-env": ["error"],
|
||||
"no-process-exit": ["error"],
|
||||
@ -243,10 +283,10 @@ module.exports = {
|
||||
"no-restricted-properties": [
|
||||
"error",
|
||||
{
|
||||
message: "'log' is too general, use an appropriate level when logging.",
|
||||
object: "console",
|
||||
property: "log",
|
||||
},
|
||||
"message": "'log' is too general, use an appropriate level when logging.",
|
||||
"object": "console",
|
||||
"property": "log"
|
||||
}
|
||||
],
|
||||
"no-restricted-syntax": ["error"],
|
||||
"no-return-assign": ["error"],
|
||||
@ -255,8 +295,8 @@ module.exports = {
|
||||
"no-self-assign": [
|
||||
"error",
|
||||
{
|
||||
props: false,
|
||||
},
|
||||
"props": false
|
||||
}
|
||||
],
|
||||
"no-self-compare": ["error"],
|
||||
"no-sequences": ["error"],
|
||||
@ -293,10 +333,10 @@ module.exports = {
|
||||
"no-useless-rename": [
|
||||
"error",
|
||||
{
|
||||
ignoreDestructuring: false,
|
||||
ignoreExport: false,
|
||||
ignoreImport: false,
|
||||
},
|
||||
"ignoreDestructuring": false,
|
||||
"ignoreExport": false,
|
||||
"ignoreImport": false
|
||||
}
|
||||
],
|
||||
"no-useless-return": ["error"],
|
||||
"no-var": ["error"],
|
||||
@ -304,7 +344,10 @@ module.exports = {
|
||||
"no-warning-comments": ["error"],
|
||||
"no-whitespace-before-property": ["error"],
|
||||
"no-with": ["error"],
|
||||
"nonblock-statement-body-position": ["error", "below"],
|
||||
"nonblock-statement-body-position": [
|
||||
"error",
|
||||
"below"
|
||||
],
|
||||
"object-curly-newline": ["error"],
|
||||
"object-curly-spacing": ["error"],
|
||||
"object-property-newline": ["error"],
|
||||
@ -312,7 +355,10 @@ module.exports = {
|
||||
"one-var": ["off"],
|
||||
"one-var-declaration-per-line": ["error"],
|
||||
"operator-assignment": ["error"],
|
||||
"operator-linebreak": ["error", "none"],
|
||||
"operator-linebreak": [
|
||||
"error",
|
||||
"none"
|
||||
],
|
||||
"padded-blocks": ["off"],
|
||||
"padding-line-between-statements": ["error"],
|
||||
"prefer-arrow-callback": ["error"],
|
||||
@ -325,15 +371,24 @@ module.exports = {
|
||||
"prefer-spread": ["error"],
|
||||
"prefer-template": ["error"],
|
||||
"quote-props": ["error"],
|
||||
quotes: ["error"],
|
||||
radix: ["error", "as-needed"],
|
||||
"quotes": ["error"],
|
||||
"radix": [
|
||||
"error",
|
||||
"as-needed"
|
||||
],
|
||||
"require-await": ["error"],
|
||||
"require-jsdoc": ["off"],
|
||||
"require-yield": ["error"],
|
||||
"rest-spread-spacing": ["error", "never"],
|
||||
semi: ["error"],
|
||||
"rest-spread-spacing": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"semi": ["error"],
|
||||
"semi-spacing": ["error"],
|
||||
"semi-style": ["error", "last"],
|
||||
"semi-style": [
|
||||
"error",
|
||||
"last"
|
||||
],
|
||||
"sort-imports": ["error"],
|
||||
"sort-keys": ["error"],
|
||||
"sort-vars": ["error"],
|
||||
@ -343,25 +398,37 @@ module.exports = {
|
||||
"space-infix-ops": ["error"],
|
||||
"space-unary-ops": ["error"],
|
||||
"spaced-comment": ["error"],
|
||||
strict: ["error"],
|
||||
"strict": ["error"],
|
||||
"switch-colon-spacing": [
|
||||
"error",
|
||||
{
|
||||
after: true,
|
||||
before: false,
|
||||
},
|
||||
"after": true,
|
||||
"before": false
|
||||
}
|
||||
],
|
||||
"symbol-description": ["error"],
|
||||
"template-curly-spacing": ["error"],
|
||||
"template-tag-spacing": ["error"],
|
||||
"unicode-bom": ["error", "never"],
|
||||
"unicode-bom": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"use-isnan": ["error"],
|
||||
"valid-jsdoc": ["error"],
|
||||
"valid-typeof": ["error"],
|
||||
"vars-on-top": ["error"],
|
||||
"wrap-iife": ["error", "any"],
|
||||
"wrap-iife": [
|
||||
"error",
|
||||
"any"
|
||||
],
|
||||
"wrap-regex": ["error"],
|
||||
"yield-star-spacing": ["error", "before"],
|
||||
yoda: ["error", "never"],
|
||||
},
|
||||
"yield-star-spacing": [
|
||||
"error",
|
||||
"before"
|
||||
],
|
||||
"yoda": [
|
||||
"error",
|
||||
"never"
|
||||
]
|
||||
}
|
||||
};
|
||||
|
@ -8,8 +8,7 @@ const path = require("path");
|
||||
const exec = require("child_process").exec;
|
||||
const semver = require("./semver");
|
||||
|
||||
const getPackageJson = () =>
|
||||
new Promise((resolve, reject) => {
|
||||
const getPackageJson = () => new Promise((resolve, reject) => {
|
||||
try {
|
||||
/* eslint-disable-next-line global-require */
|
||||
resolve(require(path.resolve(process.cwd(), "package.json")));
|
||||
@ -18,8 +17,7 @@ const getPackageJson = () =>
|
||||
}
|
||||
});
|
||||
|
||||
const getEngines = (data) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const getEngines = (data) => new Promise((resolve, reject) => {
|
||||
let versions = null;
|
||||
|
||||
if (data.engines) {
|
||||
@ -33,8 +31,7 @@ const getEngines = (data) =>
|
||||
}
|
||||
});
|
||||
|
||||
const checkNpmVersion = (engines) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const checkNpmVersion = (engines) => new Promise((resolve, reject) => {
|
||||
exec("npm -v", (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
reject(`Unable to find NPM version\n${stderr}`);
|
||||
@ -46,23 +43,18 @@ const checkNpmVersion = (engines) =>
|
||||
if (semver.satisfies(npmVersion, engineVersion)) {
|
||||
resolve();
|
||||
} else {
|
||||
reject(
|
||||
`Incorrect npm version\n'package.json' specifies "${engineVersion}", you are currently running "${npmVersion}".`,
|
||||
);
|
||||
reject(`Incorrect npm version\n'package.json' specifies "${engineVersion}", you are currently running "${npmVersion}".`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const checkNodeVersion = (engines) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const checkNodeVersion = (engines) => new Promise((resolve, reject) => {
|
||||
const nodeVersion = process.version.substring(1);
|
||||
|
||||
if (semver.satisfies(nodeVersion, engines.node)) {
|
||||
resolve(engines);
|
||||
} else {
|
||||
reject(
|
||||
`Incorrect node version\n'package.json' specifies "${engines.node}", you are currently running "${process.version}".`,
|
||||
);
|
||||
reject(`Incorrect node version\n'package.json' specifies "${engines.node}", you are currently running "${process.version}".`);
|
||||
}
|
||||
});
|
||||
|
||||
@ -77,5 +69,5 @@ getPackageJson()
|
||||
/* eslint-disable no-console, no-process-exit */
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
@ -444,6 +444,7 @@ function parseComparator(comp, loose) {
|
||||
}
|
||||
|
||||
class SemVer {
|
||||
|
||||
/**
|
||||
* A semantic version.
|
||||
* @param {string} version The version.
|
||||
@ -487,7 +488,7 @@ class SemVer {
|
||||
// Numberify any prerelease numeric ids
|
||||
if (matches[4]) {
|
||||
this.prerelease = matches[4].split(".").map((id) => {
|
||||
if (/^[0-9]+$/.test(id)) {
|
||||
if ((/^[0-9]+$/).test(id)) {
|
||||
const num = Number(id);
|
||||
if (num >= 0 && num < MAX_SAFE_INTEGER) {
|
||||
return num;
|
||||
@ -531,9 +532,7 @@ class SemVer {
|
||||
}
|
||||
|
||||
return (
|
||||
compareIdentifiers(this.major, other.major) ||
|
||||
compareIdentifiers(this.minor, other.minor) ||
|
||||
compareIdentifiers(this.patch, other.patch)
|
||||
compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || compareIdentifiers(this.patch, other.patch)
|
||||
);
|
||||
}
|
||||
|
||||
@ -573,8 +572,7 @@ class SemVer {
|
||||
}
|
||||
}
|
||||
|
||||
const compare = (leftVersion, rightVersion, loose) =>
|
||||
new SemVer(leftVersion, loose).compare(new SemVer(rightVersion, loose));
|
||||
const compare = (leftVersion, rightVersion, loose) => new SemVer(leftVersion, loose).compare(new SemVer(rightVersion, loose));
|
||||
const gt = (leftVersion, rightVersion, loose) => compare(leftVersion, rightVersion, loose) > 0;
|
||||
const lt = (leftVersion, rightVersion, loose) => compare(leftVersion, rightVersion, loose) < 0;
|
||||
const eq = (leftVersion, rightVersion, loose) => compare(leftVersion, rightVersion, loose) === 0;
|
||||
|
@ -15,7 +15,7 @@ import { Skill } from "./Skill";
|
||||
import { City } from "./City";
|
||||
import { IAction } from "./IAction";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { IRouter } from "../ui/Router";
|
||||
import { IRouter, Page } from "../ui/Router";
|
||||
import { ConsoleHelpText } from "./data/Help";
|
||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||
@ -26,7 +26,6 @@ import { addOffset } from "../utils/helpers/addOffset";
|
||||
import { Faction } from "../Faction/Faction";
|
||||
import { Factions, factionExists } from "../Faction/Factions";
|
||||
import { calculateHospitalizationCost } from "../Hospital/Hospital";
|
||||
import { redPillFlag } from "../RedPill";
|
||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
import { Settings } from "../Settings/Settings";
|
||||
import { Augmentations } from "../Augmentation/Augmentations";
|
||||
@ -145,7 +144,7 @@ export class Bladeburner implements IBladeburner {
|
||||
if (action.count < 1) {
|
||||
return this.resetAction();
|
||||
}
|
||||
if (actionId.name === "Raid" && this.getCurrentCity().commsEst === 0) {
|
||||
if (actionId.name === "Raid" && this.getCurrentCity().comms === 0) {
|
||||
return this.resetAction();
|
||||
}
|
||||
this.actionTimeToComplete = action.getActionTime(this);
|
||||
@ -184,6 +183,7 @@ export class Bladeburner implements IBladeburner {
|
||||
break;
|
||||
case ActionTypes["Diplomacy"]:
|
||||
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
||||
case ActionTypes["Incite Violence"]:
|
||||
this.actionTimeToComplete = 60;
|
||||
break;
|
||||
default:
|
||||
@ -339,6 +339,10 @@ export class Bladeburner implements IBladeburner {
|
||||
action.type = ActionTypes["Hyperbolic Regeneration Chamber"];
|
||||
action.name = "Hyperbolic Regeneration Chamber";
|
||||
break;
|
||||
case "stir trouble":
|
||||
action.type = ActionTypes["Incite Violence"];
|
||||
action.name = "Incite Violence";
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
@ -1088,9 +1092,6 @@ export class Bladeburner implements IBladeburner {
|
||||
case "Investigation":
|
||||
if (success) {
|
||||
city.improvePopulationEstimateByPercentage(0.4 * this.skillMultipliers.successChanceEstimate);
|
||||
if (Math.random() < 0.02 * this.skillMultipliers.successChanceEstimate) {
|
||||
city.improveCommunityEstimate(1);
|
||||
}
|
||||
} else {
|
||||
this.triggerPotentialMigration(this.city, 0.1);
|
||||
}
|
||||
@ -1098,9 +1099,6 @@ export class Bladeburner implements IBladeburner {
|
||||
case "Undercover Operation":
|
||||
if (success) {
|
||||
city.improvePopulationEstimateByPercentage(0.8 * this.skillMultipliers.successChanceEstimate);
|
||||
if (Math.random() < 0.02 * this.skillMultipliers.successChanceEstimate) {
|
||||
city.improveCommunityEstimate(1);
|
||||
}
|
||||
} else {
|
||||
this.triggerPotentialMigration(this.city, 0.15);
|
||||
}
|
||||
@ -1121,7 +1119,6 @@ export class Bladeburner implements IBladeburner {
|
||||
nonZero: true,
|
||||
});
|
||||
--city.comms;
|
||||
--city.commsEst;
|
||||
} else {
|
||||
const change = getRandomInt(-10, -5) / 10;
|
||||
city.changePopulationByPercentage(change, {
|
||||
@ -1174,6 +1171,8 @@ export class Bladeburner implements IBladeburner {
|
||||
return GeneralActions["Diplomacy"];
|
||||
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
||||
return GeneralActions["Hyperbolic Regeneration Chamber"];
|
||||
case ActionTypes["Incite Violence"]:
|
||||
return GeneralActions["Incite Violence"];
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
@ -1500,6 +1499,23 @@ export class Bladeburner implements IBladeburner {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ActionTypes["Incite Violence"]: {
|
||||
for (const contract of Object.keys(this.contracts)) {
|
||||
const growthF = Growths[contract];
|
||||
if (!growthF) throw new Error("trying to generate count for action that doesn't exist? " + contract);
|
||||
this.contracts[contract].count += (60 * 3 * growthF()) / BladeburnerConstants.ActionCountGrowthPeriod;
|
||||
}
|
||||
for (const operation of Object.keys(this.operations)) {
|
||||
const growthF = Growths[operation];
|
||||
if (!growthF) throw new Error("trying to generate count for action that doesn't exist? " + operation);
|
||||
this.operations[operation].count += (60 * 3 * growthF()) / BladeburnerConstants.ActionCountGrowthPeriod;
|
||||
}
|
||||
if (this.logging.general) {
|
||||
this.log(`Incited violence in the synthoid communities.`);
|
||||
}
|
||||
this.startAction(player, this.action);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
console.error(`Bladeburner.completeAction() called for invalid action: ${this.action.type}`);
|
||||
break;
|
||||
@ -1854,7 +1870,7 @@ export class Bladeburner implements IBladeburner {
|
||||
|
||||
process(router: IRouter, player: IPlayer): void {
|
||||
// Edge case condition...if Operation Daedalus is complete trigger the BitNode
|
||||
if (redPillFlag === false && this.blackops.hasOwnProperty("Operation Daedalus")) {
|
||||
if (router.page() !== Page.BitVerse && this.blackops.hasOwnProperty("Operation Daedalus")) {
|
||||
return router.toBitVerse(false, false);
|
||||
}
|
||||
|
||||
@ -1967,6 +1983,7 @@ export class Bladeburner implements IBladeburner {
|
||||
"Field Analysis",
|
||||
"Diplomacy",
|
||||
"Hyperbolic Regeneration Chamber",
|
||||
"Incite Violence",
|
||||
];
|
||||
if (gen.includes(res.type)) {
|
||||
res.type = "General";
|
||||
@ -2091,6 +2108,7 @@ export class Bladeburner implements IBladeburner {
|
||||
return this.getRecruitmentTime(player);
|
||||
case ActionTypes["Diplomacy"]:
|
||||
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
||||
case ActionTypes["Incite Violence"]:
|
||||
return 60;
|
||||
default:
|
||||
workerScript.log("bladeburner.getActionTime", errorLogText);
|
||||
@ -2128,6 +2146,7 @@ export class Bladeburner implements IBladeburner {
|
||||
case ActionTypes["FieldAnalysis"]:
|
||||
case ActionTypes["Diplomacy"]:
|
||||
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
||||
case ActionTypes["Incite Violence"]:
|
||||
return [1, 1];
|
||||
case ActionTypes["Recruitment"]: {
|
||||
const recChance = this.getRecruitmentSuccessChance(player);
|
||||
@ -2170,6 +2189,7 @@ export class Bladeburner implements IBladeburner {
|
||||
case ActionTypes["FieldAnalysis"]:
|
||||
case ActionTypes["Diplomacy"]:
|
||||
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
||||
case ActionTypes["Incite Violence"]:
|
||||
return Infinity;
|
||||
default:
|
||||
workerScript.log("bladeburner.getActionCountRemaining", errorLogText);
|
||||
|
@ -34,11 +34,6 @@ export class City {
|
||||
*/
|
||||
comms = 0;
|
||||
|
||||
/**
|
||||
* Estimated number of communities in the city.
|
||||
*/
|
||||
commsEst = 0;
|
||||
|
||||
/**
|
||||
* Chaos level of the city.
|
||||
*/
|
||||
@ -53,8 +48,6 @@ export class City {
|
||||
|
||||
// Number of Synthoid communities population and estimate
|
||||
this.comms = getRandomInt(5, 150);
|
||||
this.commsEst = this.comms + getRandomInt(-5, 5);
|
||||
if (this.commsEst < 0) this.commsEst = 0;
|
||||
this.chaos = 0;
|
||||
}
|
||||
|
||||
@ -113,23 +106,6 @@ export class City {
|
||||
}
|
||||
}
|
||||
|
||||
improveCommunityEstimate(n = 1): void {
|
||||
if (isNaN(n)) {
|
||||
throw new Error("NaN passed into City.improveCommunityEstimate()");
|
||||
}
|
||||
if (this.commsEst < this.comms) {
|
||||
this.commsEst += n;
|
||||
if (this.commsEst > this.comms) {
|
||||
this.commsEst = this.comms;
|
||||
}
|
||||
} else if (this.commsEst > this.comms) {
|
||||
this.commsEst -= n;
|
||||
if (this.commsEst < this.comms) {
|
||||
this.commsEst = this.comms;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @params options:
|
||||
* estChange(int): How much the estimate should change by
|
||||
|
@ -30,4 +30,8 @@ export const GeneralActions: IMap<Action> = {};
|
||||
GeneralActions[actionName] = new Action({
|
||||
name: actionName,
|
||||
});
|
||||
actionName = "Incite Violence";
|
||||
GeneralActions[actionName] = new Action({
|
||||
name: actionName,
|
||||
});
|
||||
})();
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { IBladeburner } from "./IBladeburner";
|
||||
|
||||
export interface IStatsMultiplier {
|
||||
interface IStatsMultiplier {
|
||||
[key: string]: number;
|
||||
|
||||
hack: number;
|
||||
|
@ -12,6 +12,7 @@ export const ActionTypes: {
|
||||
"Field Analysis": number;
|
||||
Diplomacy: number;
|
||||
"Hyperbolic Regeneration Chamber": number;
|
||||
"Incite Violence": number;
|
||||
} = {
|
||||
Idle: 1,
|
||||
Contract: 2,
|
||||
@ -24,4 +25,5 @@ export const ActionTypes: {
|
||||
"Field Analysis": 7,
|
||||
Diplomacy: 8,
|
||||
"Hyperbolic Regeneration Chamber": 9,
|
||||
"Incite Violence": 10,
|
||||
};
|
||||
|
@ -62,4 +62,7 @@ export const GeneralActions: {
|
||||
</>
|
||||
),
|
||||
},
|
||||
"Incite Violence": {
|
||||
desc: <>Purposefully stir trouble in the synthoid community in order to gain a political edge.</>,
|
||||
},
|
||||
};
|
||||
|
@ -55,14 +55,18 @@ export function ActionLevel({ action, isActive, bladeburner, rerender }: IProps)
|
||||
</Tooltip>
|
||||
</Box>
|
||||
<Tooltip title={isActive ? <Typography>WARNING: changing the level will restart the Operation</Typography> : ""}>
|
||||
<span>
|
||||
<IconButton disabled={!canIncrease} onClick={increaseLevel}>
|
||||
<ArrowDropUpIcon />
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Tooltip title={isActive ? <Typography>WARNING: changing the level will restart the Operation</Typography> : ""}>
|
||||
<span>
|
||||
<IconButton disabled={!canDecrease} onClick={decreaseLevel}>
|
||||
<ArrowDropDownIcon />
|
||||
</IconButton>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
);
|
||||
|
@ -27,7 +27,11 @@ export function BlackOpElem(props: IProps): React.ReactElement {
|
||||
}
|
||||
const isCompleted = props.bladeburner.blackops[props.action.name] != null;
|
||||
if (isCompleted) {
|
||||
return <h2 style={{ display: "block" }}>{props.action.name} (COMPLETED)</h2>;
|
||||
return (
|
||||
<Paper sx={{ my: 1, p: 1 }}>
|
||||
<Typography>{props.action.name} (COMPLETED)</Typography>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
const isActive =
|
||||
@ -47,17 +51,19 @@ export function BlackOpElem(props: IProps): React.ReactElement {
|
||||
|
||||
return (
|
||||
<Paper sx={{ my: 1, p: 1 }}>
|
||||
<Typography>
|
||||
{isActive ? (
|
||||
<>
|
||||
<>
|
||||
<CopyableText value={props.action.name} /> (IN PROGRESS - {formatNumber(computedActionTimeCurrent, 0)} /{" "}
|
||||
<CopyableText value={props.action.name} />
|
||||
<Typography>
|
||||
(IN PROGRESS - {formatNumber(computedActionTimeCurrent, 0)} /{" "}
|
||||
{formatNumber(props.bladeburner.actionTimeToComplete, 0)})
|
||||
<p style={{ display: "block" }}>
|
||||
</Typography>
|
||||
<Typography>
|
||||
{createProgressBarText({
|
||||
progress: computedActionTimeCurrent / props.bladeburner.actionTimeToComplete,
|
||||
})}
|
||||
</p>
|
||||
</Typography>
|
||||
</>
|
||||
</>
|
||||
) : (
|
||||
@ -73,7 +79,7 @@ export function BlackOpElem(props: IProps): React.ReactElement {
|
||||
<TeamSizeButton action={props.action} bladeburner={props.bladeburner} />
|
||||
</>
|
||||
)}
|
||||
</Typography>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<Typography>{actionData.desc}</Typography>
|
||||
|
@ -37,6 +37,7 @@ export function GeneralActionElem(props: IProps): React.ReactElement {
|
||||
return 30;
|
||||
case "Diplomacy":
|
||||
case "Hyperbolic Regeneration Chamber":
|
||||
case "Incite Violence":
|
||||
return 60;
|
||||
case "Recruitment":
|
||||
return props.bladeburner.getRecruitmentTime(props.player);
|
||||
@ -57,8 +58,9 @@ export function GeneralActionElem(props: IProps): React.ReactElement {
|
||||
<Paper sx={{ my: 1, p: 1 }}>
|
||||
{isActive ? (
|
||||
<>
|
||||
<CopyableText value={props.action.name} />
|
||||
<Typography>
|
||||
<CopyableText value={props.action.name} /> (IN PROGRESS - {formatNumber(computedActionTimeCurrent, 0)} /{" "}
|
||||
(IN PROGRESS - {formatNumber(computedActionTimeCurrent, 0)} /{" "}
|
||||
{formatNumber(props.bladeburner.actionTimeToComplete, 0)})
|
||||
</Typography>
|
||||
<Typography>
|
||||
@ -69,9 +71,7 @@ export function GeneralActionElem(props: IProps): React.ReactElement {
|
||||
</>
|
||||
) : (
|
||||
<Box display="flex" flexDirection="row" alignItems="center">
|
||||
<Typography>
|
||||
<CopyableText value={props.action.name} />
|
||||
</Typography>
|
||||
<StartButton
|
||||
bladeburner={props.bladeburner}
|
||||
type={ActionTypes[props.action.name as string]}
|
||||
|
@ -117,9 +117,7 @@ export function Stats(props: IProps): React.ReactElement {
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<Typography>
|
||||
Est. Synthoid Communities: {formatNumber(props.bladeburner.getCurrentCity().comms, 0)}
|
||||
</Typography>
|
||||
<Typography>Synthoid Communities: {formatNumber(props.bladeburner.getCurrentCity().comms, 0)}</Typography>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
<br />
|
||||
|
@ -1,4 +1,4 @@
|
||||
export interface RNG {
|
||||
interface RNG {
|
||||
random(): number;
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ export function generateRandomContractOnHome(): void {
|
||||
serv.addContract(contract);
|
||||
}
|
||||
|
||||
export interface IGenerateContractParams {
|
||||
interface IGenerateContractParams {
|
||||
problemType?: string;
|
||||
server?: string;
|
||||
fn?: string;
|
||||
|
@ -8,7 +8,7 @@ import { CodingContractEvent } from "./ui/React/CodingContractModal";
|
||||
/* tslint:disable:no-magic-numbers completed-docs max-classes-per-file no-console */
|
||||
|
||||
/* Represents different types of problems that a Coding Contract can have */
|
||||
export class CodingContractType {
|
||||
class CodingContractType {
|
||||
/**
|
||||
* Function that generates a description of the problem
|
||||
*/
|
||||
|
@ -45,8 +45,3 @@ export function initCompanies(): void {
|
||||
export function loadCompanies(saveString: string): void {
|
||||
Companies = JSON.parse(saveString, Reviver);
|
||||
}
|
||||
|
||||
// Utility function to check if a string is valid company name
|
||||
export function companyExists(name: string): boolean {
|
||||
return Companies.hasOwnProperty(name);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ export function IndustryProductEquation(props: IProps): React.ReactElement {
|
||||
|
||||
return (
|
||||
<MathJaxContext>
|
||||
<MathJax>{"\\(" + reqs.join("+") + `\\Rightarrow` + prod.map((p) => `1\\text{ }${p}`).join("+") + "\\)"}</MathJax>
|
||||
<MathJax>{"\\(" + reqs.join("+") + `\\Rightarrow` + prod.map((p) => `1 \\text{${p}}`).join("+") + "\\)"}</MathJax>
|
||||
</MathJaxContext>
|
||||
);
|
||||
}
|
||||
|
@ -76,11 +76,6 @@ function MarketTA2(props: IMarketTA2Props): React.ReactElement {
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
|
||||
<Typography>
|
||||
Note that Market-TA.II overrides Market-TA.I. This means that if both are enabled, then Market-TA.II will take
|
||||
effect, not Market-TA.I
|
||||
</Typography>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -93,6 +88,7 @@ interface IProps {
|
||||
|
||||
// Create a popup that lets the player use the Market TA research for Materials
|
||||
export function MaterialMarketTaModal(props: IProps): React.ReactElement {
|
||||
const division = useDivision();
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
@ -106,11 +102,13 @@ export function MaterialMarketTaModal(props: IProps): React.ReactElement {
|
||||
|
||||
return (
|
||||
<Modal open={props.open} onClose={props.onClose}>
|
||||
{!division.hasResearch("Market-TA.II") && (
|
||||
<>
|
||||
<Typography variant="h4">Market-TA.I</Typography>
|
||||
<Typography>
|
||||
The maximum sale price you can mark this up to is {numeralWrapper.formatMoney(props.mat.bCost + markupLimit)}.
|
||||
This means that if you set the sale price higher than this, you will begin to experience a loss in number of
|
||||
sales
|
||||
The maximum sale price you can mark this up to is{" "}
|
||||
{numeralWrapper.formatMoney(props.mat.bCost + markupLimit)}. This means that if you set the sale price
|
||||
higher than this, you will begin to experience a loss in number of sales
|
||||
</Typography>
|
||||
|
||||
<FormControlLabel
|
||||
@ -119,8 +117,8 @@ export function MaterialMarketTaModal(props: IProps): React.ReactElement {
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
If this is enabled, then this Material will automatically be sold at the price identified by Market-TA.I
|
||||
(i.e. the price shown above)
|
||||
If this is enabled, then this Material will automatically be sold at the price identified by
|
||||
Market-TA.I (i.e. the price shown above)
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
@ -128,6 +126,8 @@ export function MaterialMarketTaModal(props: IProps): React.ReactElement {
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<MarketTA2 mat={props.mat} />
|
||||
</Modal>
|
||||
);
|
||||
|
@ -66,11 +66,6 @@ function MarketTA2(props: ITa2Props): React.ReactElement {
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
|
||||
<Typography>
|
||||
Note that Market-TA.II overrides Market-TA.I. This means that if both are enabled, then Market-TA.II will take
|
||||
effect, not Market-TA.I
|
||||
</Typography>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -83,6 +78,7 @@ interface IProps {
|
||||
|
||||
// Create a popup that lets the player use the Market TA research for Products
|
||||
export function ProductMarketTaModal(props: IProps): React.ReactElement {
|
||||
const division = useDivision();
|
||||
const markupLimit = props.product.rat / props.product.mku;
|
||||
const setRerender = useState(false)[1];
|
||||
function rerender(): void {
|
||||
@ -96,6 +92,8 @@ export function ProductMarketTaModal(props: IProps): React.ReactElement {
|
||||
|
||||
return (
|
||||
<Modal open={props.open} onClose={props.onClose}>
|
||||
{!division.hasResearch("Market-TA.II") && (
|
||||
<>
|
||||
<Typography variant="h4">Market-TA.I</Typography>
|
||||
<Typography>
|
||||
The maximum sale price you can mark this up to is{" "}
|
||||
@ -109,8 +107,8 @@ export function ProductMarketTaModal(props: IProps): React.ReactElement {
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
If this is enabled, then this Material will automatically be sold at the price identified by Market-TA.I
|
||||
(i.e. the price shown above)
|
||||
If this is enabled, then this Material will automatically be sold at the price identified by
|
||||
Market-TA.I (i.e. the price shown above)
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
@ -118,7 +116,8 @@ export function ProductMarketTaModal(props: IProps): React.ReactElement {
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
|
||||
</>
|
||||
)}
|
||||
<MarketTA2 product={props.product} />
|
||||
</Modal>
|
||||
);
|
||||
|
@ -4,7 +4,7 @@ import { IPlayerOrSleeve } from "../PersonObjects/IPlayerOrSleeve";
|
||||
import { IRouter } from "../ui/Router";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
|
||||
export interface IConstructorParams {
|
||||
interface IConstructorParams {
|
||||
hacking_success_weight?: number;
|
||||
strength_success_weight?: number;
|
||||
defense_success_weight?: number;
|
||||
|
@ -24,7 +24,7 @@ export function loadFactions(saveString: string): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function AddToFactions(faction: Faction): void {
|
||||
function AddToFactions(faction: Faction): void {
|
||||
const name: string = faction.name;
|
||||
Factions[name] = faction;
|
||||
}
|
||||
@ -42,7 +42,7 @@ export function initFactions(): void {
|
||||
//Resets a faction during (re-)initialization. Saves the favor in the new
|
||||
//Faction object and deletes the old Faction Object from "Factions". Then
|
||||
//reinserts the new Faction object
|
||||
export function resetFaction(newFactionObject: Faction): void {
|
||||
function resetFaction(newFactionObject: Faction): void {
|
||||
if (!(newFactionObject instanceof Faction)) {
|
||||
throw new Error("Invalid argument 'newFactionObject' passed into resetFaction()");
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { ITaskParams } from "../ITaskParams";
|
||||
* Defines the parameters that can be used to initialize and describe a GangMemberTask
|
||||
* (defined in Gang.js)
|
||||
*/
|
||||
export interface IGangMemberTaskMetadata {
|
||||
interface IGangMemberTaskMetadata {
|
||||
/**
|
||||
* Description of the task
|
||||
*/
|
||||
|
@ -19,7 +19,7 @@ export enum UpgradeType {
|
||||
* Defines the parameters that can be used to initialize and describe a GangMemberUpgrade
|
||||
* (defined in Gang.js)
|
||||
*/
|
||||
export interface IGangMemberUpgradeMetadata {
|
||||
interface IGangMemberUpgradeMetadata {
|
||||
cost: number;
|
||||
mults: IMults;
|
||||
name: string;
|
||||
|
@ -512,7 +512,6 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
||||
|
||||
const old = target.moneyMax;
|
||||
target.changeMaximumMoney(upg.value);
|
||||
console.log(target.moneyMax / old);
|
||||
} catch (e) {
|
||||
player.hashManager.refundUpgrade(upgName);
|
||||
return false;
|
||||
|
@ -69,6 +69,7 @@ export function TechVendorLocation(props: IProps): React.ReactElement {
|
||||
|
||||
return (
|
||||
<>
|
||||
<br />
|
||||
{purchaseServerButtons}
|
||||
<br />
|
||||
<Typography>
|
||||
|
@ -217,4 +217,4 @@ function initMessages(): void {
|
||||
);
|
||||
}
|
||||
|
||||
export { Messages, checkForMessagesToSend, sendMessage, showMessage, loadMessages, initMessages, Message };
|
||||
export { Messages, checkForMessagesToSend, showMessage, loadMessages, initMessages };
|
||||
|
@ -1,11 +0,0 @@
|
||||
import { Milestone } from "./Milestone";
|
||||
|
||||
export class Quest {
|
||||
title: string;
|
||||
milestones: Milestone[];
|
||||
|
||||
constructor(title: string, milestones: Milestone[]) {
|
||||
this.title = title;
|
||||
this.milestones = milestones;
|
||||
}
|
||||
}
|
@ -106,6 +106,11 @@ export class WorkerScript {
|
||||
*/
|
||||
hostname: string;
|
||||
|
||||
/**
|
||||
* Function called when the script ends.
|
||||
*/
|
||||
atExit: any;
|
||||
|
||||
constructor(runningScriptObj: RunningScript, pid: number, nsFuncsGenerator?: (ws: WorkerScript) => any) {
|
||||
this.name = runningScriptObj.filename;
|
||||
this.hostname = runningScriptObj.server;
|
||||
@ -132,15 +137,13 @@ export class WorkerScript {
|
||||
if (!found) {
|
||||
throw new Error(`WorkerScript constructed with invalid script filename: ${this.name}`);
|
||||
}
|
||||
|
||||
this.scriptRef = runningScriptObj;
|
||||
this.args = runningScriptObj.args.slice();
|
||||
this.env = new Environment(null);
|
||||
if (typeof nsFuncsGenerator === "function") {
|
||||
this.env.vars = nsFuncsGenerator(this);
|
||||
}
|
||||
this.env.set("args", runningScriptObj.args.slice());
|
||||
|
||||
this.scriptRef = runningScriptObj;
|
||||
this.args = runningScriptObj.args.slice();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,6 +10,7 @@ import { RunningScript } from "../Script/RunningScript";
|
||||
import { GetServer } from "../Server/AllServers";
|
||||
|
||||
import { compareArrays } from "../utils/helpers/compareArrays";
|
||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
|
||||
export function killWorkerScript(runningScriptObj: RunningScript, hostname: string, rerenderUi?: boolean): boolean;
|
||||
export function killWorkerScript(workerScript: WorkerScript): boolean;
|
||||
@ -67,6 +68,16 @@ function killWorkerScriptByPid(pid: number, rerenderUi = true): boolean {
|
||||
function stopAndCleanUpWorkerScript(workerScript: WorkerScript, rerenderUi = true): void {
|
||||
workerScript.env.stopFlag = true;
|
||||
killNetscriptDelay(workerScript);
|
||||
if (typeof workerScript.atExit === "function") {
|
||||
try {
|
||||
workerScript.atExit();
|
||||
} catch (e: any) {
|
||||
dialogBoxCreate(
|
||||
`Error trying to call atExit for script ${workerScript.name} on ${workerScript.hostname} ${workerScript.scriptRef.args} ${e}`,
|
||||
);
|
||||
}
|
||||
workerScript.atExit = undefined;
|
||||
}
|
||||
removeWorkerScript(workerScript, rerenderUi);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
224
src/NetscriptFunctions/Augmentations.ts
Normal file
224
src/NetscriptFunctions/Augmentations.ts
Normal file
@ -0,0 +1,224 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { purchaseAugmentation } from "../Faction/FactionHelpers";
|
||||
import { startWorkerScript } from "../NetscriptWorker";
|
||||
import { Augmentation } from "../Augmentation/Augmentation";
|
||||
import { Augmentations } from "../Augmentation/Augmentations";
|
||||
import { augmentationExists, installAugmentations } from "../Augmentation/AugmentationHelpers";
|
||||
import { prestigeAugmentation } from "../Prestige";
|
||||
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
||||
import { killWorkerScript } from "../Netscript/killWorkerScript";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { isString } from "../utils/helpers/isString";
|
||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||
import { RunningScript } from "../Script/RunningScript";
|
||||
|
||||
export interface INetscriptAugmentations {
|
||||
getOwnedAugmentations(purchased?: any): any;
|
||||
getOwnedSourceFiles(): any;
|
||||
getAugmentationsFromFaction(facname: any): any;
|
||||
getAugmentationCost(name: any): any;
|
||||
getAugmentationPrereq(name: any): any;
|
||||
getAugmentationPrice(name: any): any;
|
||||
getAugmentationRepReq(name: any): any;
|
||||
getAugmentationStats(name: any): any;
|
||||
purchaseAugmentation(faction: any, name: any): any;
|
||||
softReset(cbScript: any): any;
|
||||
installAugmentations(cbScript: any): any;
|
||||
}
|
||||
|
||||
export function NetscriptAugmentations(
|
||||
player: IPlayer,
|
||||
workerScript: WorkerScript,
|
||||
helper: INetscriptHelper,
|
||||
): INetscriptAugmentations {
|
||||
const getAugmentation = function (func: any, name: any): Augmentation {
|
||||
if (!augmentationExists(name)) {
|
||||
throw helper.makeRuntimeErrorMsg(func, `Invalid augmentation: '${name}'`);
|
||||
}
|
||||
|
||||
return Augmentations[name];
|
||||
};
|
||||
const runAfterReset = function (cbScript = null): void {
|
||||
//Run a script after reset
|
||||
if (cbScript && isString(cbScript)) {
|
||||
const home = player.getHomeComputer();
|
||||
for (const script of home.scripts) {
|
||||
if (script.filename === cbScript) {
|
||||
const ramUsage = script.ramUsage;
|
||||
const ramAvailable = home.maxRam - home.ramUsed;
|
||||
if (ramUsage > ramAvailable) {
|
||||
return; // Not enough RAM
|
||||
}
|
||||
const runningScriptObj = new RunningScript(script, []); // No args
|
||||
runningScriptObj.threads = 1; // Only 1 thread
|
||||
startWorkerScript(runningScriptObj, home);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
return {
|
||||
getOwnedAugmentations: function (purchased: any = false): any {
|
||||
helper.updateDynamicRam("getOwnedAugmentations", getRamCost("getOwnedAugmentations"));
|
||||
helper.checkSingularityAccess("getOwnedAugmentations", 3);
|
||||
const res = [];
|
||||
for (let i = 0; i < player.augmentations.length; ++i) {
|
||||
res.push(player.augmentations[i].name);
|
||||
}
|
||||
if (purchased) {
|
||||
for (let i = 0; i < player.queuedAugmentations.length; ++i) {
|
||||
res.push(player.queuedAugmentations[i].name);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
},
|
||||
getOwnedSourceFiles: function (): any {
|
||||
helper.updateDynamicRam("getOwnedSourceFiles", getRamCost("getOwnedSourceFiles"));
|
||||
helper.checkSingularityAccess("getOwnedSourceFiles", 3);
|
||||
const res = [];
|
||||
for (let i = 0; i < player.sourceFiles.length; ++i) {
|
||||
res.push({
|
||||
n: player.sourceFiles[i].n,
|
||||
lvl: player.sourceFiles[i].lvl,
|
||||
});
|
||||
}
|
||||
return res;
|
||||
},
|
||||
getAugmentationsFromFaction: function (facname: any): any {
|
||||
helper.updateDynamicRam("getAugmentationsFromFaction", getRamCost("getAugmentationsFromFaction"));
|
||||
helper.checkSingularityAccess("getAugmentationsFromFaction", 3);
|
||||
const faction = helper.getFaction("getAugmentationsFromFaction", facname);
|
||||
|
||||
// If player has a gang with this faction, return all augmentations.
|
||||
if (player.hasGangWith(facname)) {
|
||||
const res = [];
|
||||
for (const augName in Augmentations) {
|
||||
const aug = Augmentations[augName];
|
||||
if (!aug.isSpecial) {
|
||||
res.push(augName);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return faction.augmentations.slice();
|
||||
},
|
||||
getAugmentationCost: function (name: any): any {
|
||||
helper.updateDynamicRam("getAugmentationCost", getRamCost("getAugmentationCost"));
|
||||
helper.checkSingularityAccess("getAugmentationCost", 3);
|
||||
const aug = getAugmentation("getAugmentationCost", name);
|
||||
return [aug.baseRepRequirement, aug.baseCost];
|
||||
},
|
||||
getAugmentationPrereq: function (name: any): any {
|
||||
helper.updateDynamicRam("getAugmentationPrereq", getRamCost("getAugmentationPrereq"));
|
||||
helper.checkSingularityAccess("getAugmentationPrereq", 3);
|
||||
const aug = getAugmentation("getAugmentationPrereq", name);
|
||||
return aug.prereqs.slice();
|
||||
},
|
||||
getAugmentationPrice: function (name: any): any {
|
||||
helper.updateDynamicRam("getAugmentationPrice", getRamCost("getAugmentationPrice"));
|
||||
helper.checkSingularityAccess("getAugmentationPrice", 3);
|
||||
const aug = getAugmentation("getAugmentationPrice", name);
|
||||
return aug.baseCost;
|
||||
},
|
||||
getAugmentationRepReq: function (name: any): any {
|
||||
helper.updateDynamicRam("getAugmentationRepReq", getRamCost("getAugmentationRepReq"));
|
||||
helper.checkSingularityAccess("getAugmentationRepReq", 3);
|
||||
const aug = getAugmentation("getAugmentationRepReq", name);
|
||||
return aug.baseRepRequirement;
|
||||
},
|
||||
getAugmentationStats: function (name: any): any {
|
||||
helper.updateDynamicRam("getAugmentationStats", getRamCost("getAugmentationStats"));
|
||||
helper.checkSingularityAccess("getAugmentationStats", 3);
|
||||
const aug = getAugmentation("getAugmentationStats", name);
|
||||
return Object.assign({}, aug.mults);
|
||||
},
|
||||
purchaseAugmentation: function (faction: any, name: any): any {
|
||||
helper.updateDynamicRam("purchaseAugmentation", getRamCost("purchaseAugmentation"));
|
||||
helper.checkSingularityAccess("purchaseAugmentation", 3);
|
||||
const fac = helper.getFaction("purchaseAugmentation", faction);
|
||||
const aug = getAugmentation("purchaseAugmentation", name);
|
||||
|
||||
let augs = [];
|
||||
if (player.hasGangWith(faction)) {
|
||||
for (const augName in Augmentations) {
|
||||
const tempAug = Augmentations[augName];
|
||||
if (!tempAug.isSpecial) {
|
||||
augs.push(augName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
augs = fac.augmentations;
|
||||
}
|
||||
|
||||
if (!augs.includes(name)) {
|
||||
workerScript.log("purchaseAugmentation", `Faction '${faction}' does not have the '${name}' augmentation.`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const isNeuroflux = aug.name === AugmentationNames.NeuroFluxGovernor;
|
||||
if (!isNeuroflux) {
|
||||
for (let j = 0; j < player.queuedAugmentations.length; ++j) {
|
||||
if (player.queuedAugmentations[j].name === aug.name) {
|
||||
workerScript.log("purchaseAugmentation", `You already have the '${name}' augmentation.`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (let j = 0; j < player.augmentations.length; ++j) {
|
||||
if (player.augmentations[j].name === aug.name) {
|
||||
workerScript.log("purchaseAugmentation", `You already have the '${name}' augmentation.`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fac.playerReputation < aug.baseRepRequirement) {
|
||||
workerScript.log("purchaseAugmentation", `You do not have enough reputation with '${fac.name}'.`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const res = purchaseAugmentation(aug, fac, true);
|
||||
workerScript.log("purchaseAugmentation", res);
|
||||
if (isString(res) && res.startsWith("You purchased")) {
|
||||
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
softReset: function (cbScript: any): any {
|
||||
helper.updateDynamicRam("softReset", getRamCost("softReset"));
|
||||
helper.checkSingularityAccess("softReset", 3);
|
||||
|
||||
workerScript.log("softReset", "Soft resetting. This will cause this script to be killed");
|
||||
setTimeout(() => {
|
||||
prestigeAugmentation();
|
||||
runAfterReset(cbScript);
|
||||
}, 0);
|
||||
|
||||
// Prevent workerScript from "finishing execution naturally"
|
||||
workerScript.running = false;
|
||||
killWorkerScript(workerScript);
|
||||
},
|
||||
installAugmentations: function (cbScript: any): any {
|
||||
helper.updateDynamicRam("installAugmentations", getRamCost("installAugmentations"));
|
||||
helper.checkSingularityAccess("installAugmentations", 3);
|
||||
|
||||
if (player.queuedAugmentations.length === 0) {
|
||||
workerScript.log("installAugmentations", "You do not have any Augmentations to be installed.");
|
||||
return false;
|
||||
}
|
||||
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
|
||||
workerScript.log("installAugmentations", "Installing Augmentations. This will cause this script to be killed");
|
||||
setTimeout(() => {
|
||||
installAugmentations();
|
||||
runAfterReset(cbScript);
|
||||
}, 0);
|
||||
|
||||
workerScript.running = false; // Prevent workerScript from "finishing execution naturally"
|
||||
killWorkerScript(workerScript);
|
||||
},
|
||||
};
|
||||
}
|
403
src/NetscriptFunctions/Bladeburner.ts
Normal file
403
src/NetscriptFunctions/Bladeburner.ts
Normal file
@ -0,0 +1,403 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Bladeburner } from "../Bladeburner/Bladeburner";
|
||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
|
||||
export interface INetscriptBladeburner {
|
||||
getContractNames(): any;
|
||||
getOperationNames(): any;
|
||||
getBlackOpNames(): any;
|
||||
getBlackOpRank(name?: any): any;
|
||||
getGeneralActionNames(): any;
|
||||
getSkillNames(): any;
|
||||
startAction(type?: any, name?: any): any;
|
||||
stopBladeburnerAction(): any;
|
||||
getCurrentAction(): any;
|
||||
getActionTime(type?: any, name?: any): any;
|
||||
getActionEstimatedSuccessChance(type?: any, name?: any): any;
|
||||
getActionRepGain(type?: any, name?: any, level?: any): any;
|
||||
getActionCountRemaining(type?: any, name?: any): any;
|
||||
getActionMaxLevel(type?: any, name?: any): any;
|
||||
getActionCurrentLevel(type?: any, name?: any): any;
|
||||
getActionAutolevel(type?: any, name?: any): any;
|
||||
setActionAutolevel(type?: any, name?: any, autoLevel?: any): any;
|
||||
setActionLevel(type?: any, name?: any, level?: any): any;
|
||||
getRank(): any;
|
||||
getSkillPoints(): any;
|
||||
getSkillLevel(skillName?: any): any;
|
||||
getSkillUpgradeCost(skillName?: any): any;
|
||||
upgradeSkill(skillName: any): any;
|
||||
getTeamSize(type?: any, name?: any): any;
|
||||
setTeamSize(type?: any, name?: any, size?: any): any;
|
||||
getCityEstimatedPopulation(cityName: any): any;
|
||||
getCityEstimatedCommunities(cityName: any): any;
|
||||
getCityChaos(cityName: any): any;
|
||||
getCity(): any;
|
||||
switchCity(cityName: any): any;
|
||||
getStamina(): any;
|
||||
joinBladeburnerFaction(): any;
|
||||
joinBladeburnerDivision(): any;
|
||||
getBonusTime(): any;
|
||||
}
|
||||
|
||||
export function NetscriptBladeburner(
|
||||
player: IPlayer,
|
||||
workerScript: WorkerScript,
|
||||
helper: INetscriptHelper,
|
||||
): INetscriptBladeburner {
|
||||
const checkBladeburnerAccess = function (func: any, skipjoined: any = false): void {
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
||||
const apiAccess =
|
||||
player.bitNodeN === 7 ||
|
||||
player.sourceFiles.some((a) => {
|
||||
return a.n === 7;
|
||||
});
|
||||
if (!apiAccess) {
|
||||
const apiDenied = `You do not currently have access to the Bladeburner API. You must either be in BitNode-7 or have Source-File 7.`;
|
||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, apiDenied);
|
||||
}
|
||||
if (!skipjoined) {
|
||||
const bladeburnerAccess = bladeburner instanceof Bladeburner;
|
||||
if (!bladeburnerAccess) {
|
||||
const bladeburnerDenied = `You must be a member of the Bladeburner division to use this API.`;
|
||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, bladeburnerDenied);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const checkBladeburnerCity = function (func: any, city: any): void {
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
||||
if (!bladeburner.cities.hasOwnProperty(city)) {
|
||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, `Invalid city: ${city}`);
|
||||
}
|
||||
};
|
||||
|
||||
const getBladeburnerActionObject = function (func: any, type: any, name: any): any {
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
||||
const actionId = bladeburner.getActionIdFromTypeAndName(type, name);
|
||||
if (!actionId) {
|
||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, `Invalid action type='${type}', name='${name}'`);
|
||||
}
|
||||
const actionObj = bladeburner.getActionObject(actionId);
|
||||
if (!actionObj) {
|
||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, `Invalid action type='${type}', name='${name}'`);
|
||||
}
|
||||
|
||||
return actionObj;
|
||||
};
|
||||
|
||||
return {
|
||||
getContractNames: function (): any {
|
||||
helper.updateDynamicRam("getContractNames", getRamCost("bladeburner", "getContractNames"));
|
||||
checkBladeburnerAccess("getContractNames");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getContractNamesNetscriptFn();
|
||||
},
|
||||
getOperationNames: function (): any {
|
||||
helper.updateDynamicRam("getOperationNames", getRamCost("bladeburner", "getOperationNames"));
|
||||
checkBladeburnerAccess("getOperationNames");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getOperationNamesNetscriptFn();
|
||||
},
|
||||
getBlackOpNames: function (): any {
|
||||
helper.updateDynamicRam("getBlackOpNames", getRamCost("bladeburner", "getBlackOpNames"));
|
||||
checkBladeburnerAccess("getBlackOpNames");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getBlackOpNamesNetscriptFn();
|
||||
},
|
||||
getBlackOpRank: function (name: any = ""): any {
|
||||
helper.updateDynamicRam("getBlackOpRank", getRamCost("bladeburner", "getBlackOpRank"));
|
||||
checkBladeburnerAccess("getBlackOpRank");
|
||||
const action: any = getBladeburnerActionObject("getBlackOpRank", "blackops", name);
|
||||
return action.reqdRank;
|
||||
},
|
||||
getGeneralActionNames: function (): any {
|
||||
helper.updateDynamicRam("getGeneralActionNames", getRamCost("bladeburner", "getGeneralActionNames"));
|
||||
checkBladeburnerAccess("getGeneralActionNames");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getGeneralActionNamesNetscriptFn();
|
||||
},
|
||||
getSkillNames: function (): any {
|
||||
helper.updateDynamicRam("getSkillNames", getRamCost("bladeburner", "getSkillNames"));
|
||||
checkBladeburnerAccess("getSkillNames");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getSkillNamesNetscriptFn();
|
||||
},
|
||||
startAction: function (type: any = "", name: any = ""): any {
|
||||
helper.updateDynamicRam("startAction", getRamCost("bladeburner", "startAction"));
|
||||
checkBladeburnerAccess("startAction");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.startActionNetscriptFn(player, type, name, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.startAction", e);
|
||||
}
|
||||
},
|
||||
stopBladeburnerAction: function (): any {
|
||||
helper.updateDynamicRam("stopBladeburnerAction", getRamCost("bladeburner", "stopBladeburnerAction"));
|
||||
checkBladeburnerAccess("stopBladeburnerAction");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.resetAction();
|
||||
},
|
||||
getCurrentAction: function (): any {
|
||||
helper.updateDynamicRam("getCurrentAction", getRamCost("bladeburner", "getCurrentAction"));
|
||||
checkBladeburnerAccess("getCurrentAction");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getTypeAndNameFromActionId(bladeburner.action);
|
||||
},
|
||||
getActionTime: function (type: any = "", name: any = ""): any {
|
||||
helper.updateDynamicRam("getActionTime", getRamCost("bladeburner", "getActionTime"));
|
||||
checkBladeburnerAccess("getActionTime");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getActionTimeNetscriptFn(player, type, name, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.getActionTime", e);
|
||||
}
|
||||
},
|
||||
getActionEstimatedSuccessChance: function (type: any = "", name: any = ""): any {
|
||||
helper.updateDynamicRam(
|
||||
"getActionEstimatedSuccessChance",
|
||||
getRamCost("bladeburner", "getActionEstimatedSuccessChance"),
|
||||
);
|
||||
checkBladeburnerAccess("getActionEstimatedSuccessChance");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getActionEstimatedSuccessChanceNetscriptFn(player, type, name, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.getActionEstimatedSuccessChance", e);
|
||||
}
|
||||
},
|
||||
getActionRepGain: function (type: any = "", name: any = "", level: any): any {
|
||||
helper.updateDynamicRam("getActionRepGain", getRamCost("bladeburner", "getActionRepGain"));
|
||||
checkBladeburnerAccess("getActionRepGain");
|
||||
const action = getBladeburnerActionObject("getActionRepGain", type, name);
|
||||
let rewardMultiplier;
|
||||
if (level == null || isNaN(level)) {
|
||||
rewardMultiplier = Math.pow(action.rewardFac, action.level - 1);
|
||||
} else {
|
||||
rewardMultiplier = Math.pow(action.rewardFac, level - 1);
|
||||
}
|
||||
|
||||
return action.rankGain * rewardMultiplier * BitNodeMultipliers.BladeburnerRank;
|
||||
},
|
||||
getActionCountRemaining: function (type: any = "", name: any = ""): any {
|
||||
helper.updateDynamicRam("getActionCountRemaining", getRamCost("bladeburner", "getActionCountRemaining"));
|
||||
checkBladeburnerAccess("getActionCountRemaining");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getActionCountRemainingNetscriptFn(type, name, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.getActionCountRemaining", e);
|
||||
}
|
||||
},
|
||||
getActionMaxLevel: function (type: any = "", name: any = ""): any {
|
||||
helper.updateDynamicRam("getActionMaxLevel", getRamCost("bladeburner", "getActionMaxLevel"));
|
||||
checkBladeburnerAccess("getActionMaxLevel");
|
||||
const action = getBladeburnerActionObject("getActionMaxLevel", type, name);
|
||||
return action.maxLevel;
|
||||
},
|
||||
getActionCurrentLevel: function (type: any = "", name: any = ""): any {
|
||||
helper.updateDynamicRam("getActionCurrentLevel", getRamCost("bladeburner", "getActionCurrentLevel"));
|
||||
checkBladeburnerAccess("getActionCurrentLevel");
|
||||
const action = getBladeburnerActionObject("getActionCurrentLevel", type, name);
|
||||
return action.level;
|
||||
},
|
||||
getActionAutolevel: function (type: any = "", name: any = ""): any {
|
||||
helper.updateDynamicRam("getActionAutolevel", getRamCost("bladeburner", "getActionAutolevel"));
|
||||
checkBladeburnerAccess("getActionAutolevel");
|
||||
const action = getBladeburnerActionObject("getActionCurrentLevel", type, name);
|
||||
return action.autoLevel;
|
||||
},
|
||||
setActionAutolevel: function (type: any = "", name: any = "", autoLevel: any = true): any {
|
||||
helper.updateDynamicRam("setActionAutolevel", getRamCost("bladeburner", "setActionAutolevel"));
|
||||
checkBladeburnerAccess("setActionAutolevel");
|
||||
const action = getBladeburnerActionObject("setActionAutolevel", type, name);
|
||||
action.autoLevel = autoLevel;
|
||||
},
|
||||
setActionLevel: function (type: any = "", name: any = "", level: any = 1): any {
|
||||
helper.updateDynamicRam("setActionLevel", getRamCost("bladeburner", "setActionLevel"));
|
||||
checkBladeburnerAccess("setActionLevel");
|
||||
const action = getBladeburnerActionObject("setActionLevel", type, name);
|
||||
if (level < 1 || level > action.maxLevel) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"bladeburner.setActionLevel",
|
||||
`Level must be between 1 and ${action.maxLevel}, is ${level}`,
|
||||
);
|
||||
}
|
||||
action.level = level;
|
||||
},
|
||||
getRank: function (): any {
|
||||
helper.updateDynamicRam("getRank", getRamCost("bladeburner", "getRank"));
|
||||
checkBladeburnerAccess("getRank");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.rank;
|
||||
},
|
||||
getSkillPoints: function (): any {
|
||||
helper.updateDynamicRam("getSkillPoints", getRamCost("bladeburner", "getSkillPoints"));
|
||||
checkBladeburnerAccess("getSkillPoints");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.skillPoints;
|
||||
},
|
||||
getSkillLevel: function (skillName: any = ""): any {
|
||||
helper.updateDynamicRam("getSkillLevel", getRamCost("bladeburner", "getSkillLevel"));
|
||||
checkBladeburnerAccess("getSkillLevel");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getSkillLevelNetscriptFn(skillName, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.getSkillLevel", e);
|
||||
}
|
||||
},
|
||||
getSkillUpgradeCost: function (skillName: any = ""): any {
|
||||
helper.updateDynamicRam("getSkillUpgradeCost", getRamCost("bladeburner", "getSkillUpgradeCost"));
|
||||
checkBladeburnerAccess("getSkillUpgradeCost");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getSkillUpgradeCostNetscriptFn(skillName, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.getSkillUpgradeCost", e);
|
||||
}
|
||||
},
|
||||
upgradeSkill: function (skillName: any): any {
|
||||
helper.updateDynamicRam("upgradeSkill", getRamCost("bladeburner", "upgradeSkill"));
|
||||
checkBladeburnerAccess("upgradeSkill");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.upgradeSkillNetscriptFn(skillName, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.upgradeSkill", e);
|
||||
}
|
||||
},
|
||||
getTeamSize: function (type: any = "", name: any = ""): any {
|
||||
helper.updateDynamicRam("getTeamSize", getRamCost("bladeburner", "getTeamSize"));
|
||||
checkBladeburnerAccess("getTeamSize");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getTeamSizeNetscriptFn(type, name, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.getTeamSize", e);
|
||||
}
|
||||
},
|
||||
setTeamSize: function (type: any = "", name: any = "", size: any): any {
|
||||
helper.updateDynamicRam("setTeamSize", getRamCost("bladeburner", "setTeamSize"));
|
||||
checkBladeburnerAccess("setTeamSize");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.setTeamSizeNetscriptFn(type, name, size, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.setTeamSize", e);
|
||||
}
|
||||
},
|
||||
getCityEstimatedPopulation: function (cityName: any): any {
|
||||
helper.updateDynamicRam("getCityEstimatedPopulation", getRamCost("bladeburner", "getCityEstimatedPopulation"));
|
||||
checkBladeburnerAccess("getCityEstimatedPopulation");
|
||||
checkBladeburnerCity("getCityEstimatedPopulation", cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.cities[cityName].popEst;
|
||||
},
|
||||
getCityEstimatedCommunities: function (cityName: any): any {
|
||||
helper.updateDynamicRam("getCityEstimatedCommunities", getRamCost("bladeburner", "getCityEstimatedCommunities"));
|
||||
checkBladeburnerAccess("getCityEstimatedCommunities");
|
||||
checkBladeburnerCity("getCityEstimatedCommunities", cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.cities[cityName].commsEst;
|
||||
},
|
||||
getCityChaos: function (cityName: any): any {
|
||||
helper.updateDynamicRam("getCityChaos", getRamCost("bladeburner", "getCityChaos"));
|
||||
checkBladeburnerAccess("getCityChaos");
|
||||
checkBladeburnerCity("getCityChaos", cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.cities[cityName].chaos;
|
||||
},
|
||||
getCity: function (): any {
|
||||
helper.updateDynamicRam("getCity", getRamCost("bladeburner", "getCity"));
|
||||
checkBladeburnerAccess("getCityChaos");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.city;
|
||||
},
|
||||
switchCity: function (cityName: any): any {
|
||||
helper.updateDynamicRam("switchCity", getRamCost("bladeburner", "switchCity"));
|
||||
checkBladeburnerAccess("switchCity");
|
||||
checkBladeburnerCity("switchCity", cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return (bladeburner.city = cityName);
|
||||
},
|
||||
getStamina: function (): any {
|
||||
helper.updateDynamicRam("getStamina", getRamCost("bladeburner", "getStamina"));
|
||||
checkBladeburnerAccess("getStamina");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return [bladeburner.stamina, bladeburner.maxStamina];
|
||||
},
|
||||
joinBladeburnerFaction: function (): any {
|
||||
helper.updateDynamicRam("joinBladeburnerFaction", getRamCost("bladeburner", "joinBladeburnerFaction"));
|
||||
checkBladeburnerAccess("joinBladeburnerFaction", true);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.joinBladeburnerFactionNetscriptFn(workerScript);
|
||||
},
|
||||
joinBladeburnerDivision: function (): any {
|
||||
helper.updateDynamicRam("joinBladeburnerDivision", getRamCost("bladeburner", "joinBladeburnerDivision"));
|
||||
if (player.bitNodeN === 7 || player.sourceFileLvl(7) > 0) {
|
||||
if (player.bitNodeN === 8) {
|
||||
return false;
|
||||
}
|
||||
if (player.bladeburner instanceof Bladeburner) {
|
||||
return true; // Already member
|
||||
} else if (
|
||||
player.strength >= 100 &&
|
||||
player.defense >= 100 &&
|
||||
player.dexterity >= 100 &&
|
||||
player.agility >= 100
|
||||
) {
|
||||
player.bladeburner = new Bladeburner(player);
|
||||
workerScript.log("joinBladeburnerDivision", "You have been accepted into the Bladeburner division");
|
||||
|
||||
return true;
|
||||
} else {
|
||||
workerScript.log(
|
||||
"joinBladeburnerDivision",
|
||||
"You do not meet the requirements for joining the Bladeburner division",
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
getBonusTime: function (): any {
|
||||
helper.updateDynamicRam("getBonusTime", getRamCost("bladeburner", "getBonusTime"));
|
||||
checkBladeburnerAccess("getBonusTime");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return Math.round(bladeburner.storedCycles / 5);
|
||||
},
|
||||
};
|
||||
}
|
109
src/NetscriptFunctions/CodingContract.ts
Normal file
109
src/NetscriptFunctions/CodingContract.ts
Normal file
@ -0,0 +1,109 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||
import { is2DArray } from "../utils/helpers/is2DArray";
|
||||
import { CodingContract } from "../CodingContracts";
|
||||
|
||||
export interface INetscriptCodingContract {
|
||||
attempt(answer: any, fn: any, ip?: any, options?: { returnReward: any }): any;
|
||||
getContractType(fn: any, ip?: any): any;
|
||||
getData(fn: any, ip?: any): any;
|
||||
getDescription(fn: any, ip?: any): any;
|
||||
getNumTriesRemaining(fn: any, ip?: any): any;
|
||||
}
|
||||
|
||||
export function NetscriptCodingContract(
|
||||
player: IPlayer,
|
||||
workerScript: WorkerScript,
|
||||
helper: INetscriptHelper,
|
||||
): INetscriptCodingContract {
|
||||
const getCodingContract = function (func: any, ip: any, fn: any): CodingContract {
|
||||
const server = helper.getServer(ip, func);
|
||||
const contract = server.getContract(fn);
|
||||
if (contract == null) {
|
||||
throw helper.makeRuntimeErrorMsg(`codingcontract.${func}`, `Cannot find contract '${fn}' on server '${ip}'`);
|
||||
}
|
||||
|
||||
return contract;
|
||||
};
|
||||
|
||||
return {
|
||||
attempt: function (answer: any, fn: any, ip: any = workerScript.hostname, { returnReward }: any = {}): any {
|
||||
helper.updateDynamicRam("attempt", getRamCost("codingcontract", "attempt"));
|
||||
const contract = getCodingContract("attempt", ip, fn);
|
||||
|
||||
// Convert answer to string. If the answer is a 2D array, then we have to
|
||||
// manually add brackets for the inner arrays
|
||||
if (is2DArray(answer)) {
|
||||
const answerComponents = [];
|
||||
for (let i = 0; i < answer.length; ++i) {
|
||||
answerComponents.push(["[", answer[i].toString(), "]"].join(""));
|
||||
}
|
||||
|
||||
answer = answerComponents.join(",");
|
||||
} else {
|
||||
answer = String(answer);
|
||||
}
|
||||
|
||||
const creward = contract.reward;
|
||||
if (creward === null) throw new Error("Somehow solved a contract that didn't have a reward");
|
||||
|
||||
const serv = helper.getServer(ip, "codingcontract.attempt");
|
||||
if (contract.isSolution(answer)) {
|
||||
const reward = player.gainCodingContractReward(creward, contract.getDifficulty());
|
||||
workerScript.log("attempt", `Successfully completed Coding Contract '${fn}'. Reward: ${reward}`);
|
||||
serv.removeContract(fn);
|
||||
return returnReward ? reward : true;
|
||||
} else {
|
||||
++contract.tries;
|
||||
if (contract.tries >= contract.getMaxNumTries()) {
|
||||
workerScript.log("attempt", `Coding Contract attempt '${fn}' failed. Contract is now self-destructing`);
|
||||
serv.removeContract(fn);
|
||||
} else {
|
||||
workerScript.log(
|
||||
"attempt",
|
||||
`Coding Contract attempt '${fn}' failed. ${contract.getMaxNumTries() - contract.tries} attempts remaining.`,
|
||||
);
|
||||
}
|
||||
|
||||
return returnReward ? "" : false;
|
||||
}
|
||||
},
|
||||
getContractType: function (fn: any, ip: any = workerScript.hostname): any {
|
||||
helper.updateDynamicRam("getContractType", getRamCost("codingcontract", "getContractType"));
|
||||
const contract = getCodingContract("getContractType", ip, fn);
|
||||
return contract.getType();
|
||||
},
|
||||
getData: function (fn: any, ip: any = workerScript.hostname): any {
|
||||
helper.updateDynamicRam("getData", getRamCost("codingcontract", "getData"));
|
||||
const contract = getCodingContract("getData", ip, fn);
|
||||
const data = contract.getData();
|
||||
if (data.constructor === Array) {
|
||||
// For two dimensional arrays, we have to copy the internal arrays using
|
||||
// slice() as well. As of right now, no contract has arrays that have
|
||||
// more than two dimensions
|
||||
const copy = data.slice();
|
||||
for (let i = 0; i < copy.length; ++i) {
|
||||
if (data[i].constructor === Array) {
|
||||
copy[i] = data[i].slice();
|
||||
}
|
||||
}
|
||||
|
||||
return copy;
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
},
|
||||
getDescription: function (fn: any, ip: any = workerScript.hostname): any {
|
||||
helper.updateDynamicRam("getDescription", getRamCost("codingcontract", "getDescription"));
|
||||
const contract = getCodingContract("getDescription", ip, fn);
|
||||
return contract.getDescription();
|
||||
},
|
||||
getNumTriesRemaining: function (fn: any, ip: any = workerScript.hostname): any {
|
||||
helper.updateDynamicRam("getNumTriesRemaining", getRamCost("codingcontract", "getNumTriesRemaining"));
|
||||
const contract = getCodingContract("getNumTriesRemaining", ip, fn);
|
||||
return contract.getMaxNumTries() - contract.tries;
|
||||
},
|
||||
};
|
||||
}
|
305
src/NetscriptFunctions/Corporation.ts
Normal file
305
src/NetscriptFunctions/Corporation.ts
Normal file
@ -0,0 +1,305 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
|
||||
import { OfficeSpace } from "../Corporation/OfficeSpace";
|
||||
import { Employee } from "../Corporation/Employee";
|
||||
import { Product } from "../Corporation/Product";
|
||||
import { Material } from "../Corporation/Material";
|
||||
import { Warehouse } from "../Corporation/Warehouse";
|
||||
import { IIndustry } from "../Corporation/IIndustry";
|
||||
|
||||
import {
|
||||
NewIndustry,
|
||||
NewCity,
|
||||
UnlockUpgrade,
|
||||
LevelUpgrade,
|
||||
IssueDividends,
|
||||
SellMaterial,
|
||||
SellProduct,
|
||||
SetSmartSupply,
|
||||
BuyMaterial,
|
||||
AssignJob,
|
||||
UpgradeOfficeSize,
|
||||
ThrowParty,
|
||||
PurchaseWarehouse,
|
||||
UpgradeWarehouse,
|
||||
BuyCoffee,
|
||||
HireAdVert,
|
||||
MakeProduct,
|
||||
Research,
|
||||
ExportMaterial,
|
||||
CancelExportMaterial,
|
||||
SetMaterialMarketTA1,
|
||||
SetMaterialMarketTA2,
|
||||
SetProductMarketTA1,
|
||||
SetProductMarketTA2,
|
||||
} from "../Corporation/Actions";
|
||||
import { CorporationUnlockUpgrades } from "../Corporation/data/CorporationUnlockUpgrades";
|
||||
import { CorporationUpgrades } from "../Corporation/data/CorporationUpgrades";
|
||||
|
||||
export interface INetscriptCorporation {
|
||||
expandIndustry(industryName: any, divisionName: any): any;
|
||||
expandCity(divisionName: any, cityName: any): any;
|
||||
unlockUpgrade(upgradeName: any): any;
|
||||
levelUpgrade(upgradeName: any): any;
|
||||
issueDividends(percent: any): any;
|
||||
sellMaterial(divisionName: any, cityName: any, materialName: any, amt: any, price: any): any;
|
||||
sellProduct(divisionName: any, cityName: any, productName: any, amt: any, price: any, all: any): any;
|
||||
discontinueProduct(divisionName: any, productName: any): any;
|
||||
setSmartSupply(divisionName: any, cityName: any, enabled: any): any;
|
||||
buyMaterial(divisionName: any, cityName: any, materialName: any, amt: any): any;
|
||||
employees(divisionName: any, cityName: any): any;
|
||||
assignJob(divisionName: any, cityName: any, employeeName: any, job: any): any;
|
||||
hireEmployee(divisionName: any, cityName: any): any;
|
||||
upgradeOfficeSize(divisionName: any, cityName: any, size: any): any;
|
||||
throwParty(divisionName: any, cityName: any, costPerEmployee: any): any;
|
||||
purchaseWarehouse(divisionName: any, cityName: any): any;
|
||||
upgradeWarehouse(divisionName: any, cityName: any): any;
|
||||
buyCoffee(divisionName: any, cityName: any): any;
|
||||
hireAdVert(divisionName: any): any;
|
||||
makeProduct(divisionName: any, cityName: any, productName: any, designInvest: any, marketingInvest: any): any;
|
||||
research(divisionName: any, researchName: any): any;
|
||||
exportMaterial(
|
||||
sourceDivision: any,
|
||||
sourceCity: any,
|
||||
targetDivision: any,
|
||||
targetCity: any,
|
||||
materialName: any,
|
||||
amt: any,
|
||||
): any;
|
||||
cancelExportMaterial(
|
||||
sourceDivision: any,
|
||||
sourceCity: any,
|
||||
targetDivision: any,
|
||||
targetCity: any,
|
||||
materialName: any,
|
||||
amt: any,
|
||||
): any;
|
||||
setMaterialMarketTA1(divisionName: any, cityName: any, materialName: any, on: any): any;
|
||||
setMaterialMarketTA2(divisionName: any, cityName: any, materialName: any, on: any): any;
|
||||
setProductMarketTA1(divisionName: any, productName: any, on: any): any;
|
||||
setProductMarketTA2(divisionName: any, productName: any, on: any): any;
|
||||
getDivision(divisionName: any): any;
|
||||
getOffice(divisionName: any, cityName: any): any;
|
||||
getWarehouse(divisionName: any, cityName: any): any;
|
||||
getMaterial(divisionName: any, cityName: any, materialName: any): any;
|
||||
getProduct(divisionName: any, productName: any): any;
|
||||
getEmployee(divisionName: any, cityName: any, employeeName: any): any;
|
||||
}
|
||||
|
||||
export function NetscriptCorporation(
|
||||
player: IPlayer,
|
||||
workerScript: WorkerScript,
|
||||
helper: INetscriptHelper,
|
||||
): INetscriptCorporation {
|
||||
function getDivision(divisionName: any): IIndustry {
|
||||
const corporation = player.corporation;
|
||||
if (corporation === null) throw new Error("cannot be called without a corporation");
|
||||
const division = corporation.divisions.find((div) => div.name === divisionName);
|
||||
if (division === undefined) throw new Error(`No division named '${divisionName}'`);
|
||||
return division;
|
||||
}
|
||||
|
||||
function getOffice(divisionName: any, cityName: any): OfficeSpace {
|
||||
const division = getDivision(divisionName);
|
||||
if (!(cityName in division.offices)) throw new Error(`Invalid city name '${cityName}'`);
|
||||
const office = division.offices[cityName];
|
||||
if (office === 0) throw new Error(`${division.name} has not expanded to '${cityName}'`);
|
||||
return office;
|
||||
}
|
||||
|
||||
function getWarehouse(divisionName: any, cityName: any): Warehouse {
|
||||
const division = getDivision(divisionName);
|
||||
if (!(cityName in division.warehouses)) throw new Error(`Invalid city name '${cityName}'`);
|
||||
const warehouse = division.warehouses[cityName];
|
||||
if (warehouse === 0) throw new Error(`${division.name} has not expanded to '${cityName}'`);
|
||||
return warehouse;
|
||||
}
|
||||
|
||||
function getMaterial(divisionName: any, cityName: any, materialName: any): Material {
|
||||
const warehouse = getWarehouse(divisionName, cityName);
|
||||
const material = warehouse.materials[materialName];
|
||||
if (material === undefined) throw new Error(`Invalid material name: '${materialName}'`);
|
||||
return material;
|
||||
}
|
||||
|
||||
function getProduct(divisionName: any, productName: any): Product {
|
||||
const division = getDivision(divisionName);
|
||||
const product = division.products[productName];
|
||||
if (product === undefined) throw new Error(`Invalid product name: '${productName}'`);
|
||||
return product;
|
||||
}
|
||||
|
||||
function getEmployee(divisionName: any, cityName: any, employeeName: any): Employee {
|
||||
const office = getOffice(divisionName, cityName);
|
||||
const employee = office.employees.find((e) => e.name === employeeName);
|
||||
if (employee === undefined) throw new Error(`Invalid employee name: '${employeeName}'`);
|
||||
return employee;
|
||||
}
|
||||
// Hi, if you're reading this you're a bit nosy.
|
||||
// There's a corporation API but it's very imbalanced right now.
|
||||
// It's here so players can test with if they want.
|
||||
return {
|
||||
expandIndustry: function (industryName: any, divisionName: any): any {
|
||||
const corporation = player.corporation;
|
||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
||||
NewIndustry(corporation, industryName, divisionName);
|
||||
},
|
||||
expandCity: function (divisionName: any, cityName: any): any {
|
||||
const division = getDivision(divisionName);
|
||||
const corporation = player.corporation;
|
||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
||||
NewCity(corporation, division, cityName);
|
||||
},
|
||||
unlockUpgrade: function (upgradeName: any): any {
|
||||
const upgrade = Object.values(CorporationUnlockUpgrades).find((upgrade) => upgrade[2] === upgradeName);
|
||||
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
||||
const corporation = player.corporation;
|
||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
||||
UnlockUpgrade(corporation, upgrade);
|
||||
},
|
||||
levelUpgrade: function (upgradeName: any): any {
|
||||
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade[4] === upgradeName);
|
||||
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
||||
const corporation = player.corporation;
|
||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
||||
LevelUpgrade(corporation, upgrade);
|
||||
},
|
||||
issueDividends: function (percent: any): any {
|
||||
const corporation = player.corporation;
|
||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
||||
IssueDividends(corporation, percent);
|
||||
},
|
||||
sellMaterial: function (divisionName: any, cityName: any, materialName: any, amt: any, price: any): any {
|
||||
const material = getMaterial(divisionName, cityName, materialName);
|
||||
SellMaterial(material, amt, price);
|
||||
},
|
||||
sellProduct: function (divisionName: any, cityName: any, productName: any, amt: any, price: any, all: any): any {
|
||||
const product = getProduct(divisionName, productName);
|
||||
SellProduct(product, cityName, amt, price, all);
|
||||
},
|
||||
discontinueProduct: function (divisionName: any, productName: any): any {
|
||||
getDivision(divisionName).discontinueProduct(getProduct(divisionName, productName));
|
||||
},
|
||||
setSmartSupply: function (divisionName: any, cityName: any, enabled: any): any {
|
||||
const warehouse = getWarehouse(divisionName, cityName);
|
||||
SetSmartSupply(warehouse, enabled);
|
||||
},
|
||||
// setSmartSupplyUseLeftovers: function (): any {},
|
||||
buyMaterial: function (divisionName: any, cityName: any, materialName: any, amt: any): any {
|
||||
const material = getMaterial(divisionName, cityName, materialName);
|
||||
BuyMaterial(material, amt);
|
||||
},
|
||||
employees: function (divisionName: any, cityName: any): any {
|
||||
const office = getOffice(divisionName, cityName);
|
||||
return office.employees.map((e) => Object.assign({}, e));
|
||||
},
|
||||
assignJob: function (divisionName: any, cityName: any, employeeName: any, job: any): any {
|
||||
const employee = getEmployee(divisionName, cityName, employeeName);
|
||||
AssignJob(employee, job);
|
||||
},
|
||||
hireEmployee: function (divisionName: any, cityName: any): any {
|
||||
const office = getOffice(divisionName, cityName);
|
||||
office.hireRandomEmployee();
|
||||
},
|
||||
upgradeOfficeSize: function (divisionName: any, cityName: any, size: any): any {
|
||||
const office = getOffice(divisionName, cityName);
|
||||
const corporation = player.corporation;
|
||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
||||
UpgradeOfficeSize(corporation, office, size);
|
||||
},
|
||||
throwParty: function (divisionName: any, cityName: any, costPerEmployee: any): any {
|
||||
const office = getOffice(divisionName, cityName);
|
||||
const corporation = player.corporation;
|
||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
||||
ThrowParty(corporation, office, costPerEmployee);
|
||||
},
|
||||
purchaseWarehouse: function (divisionName: any, cityName: any): any {
|
||||
const corporation = player.corporation;
|
||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
||||
PurchaseWarehouse(corporation, getDivision(divisionName), cityName);
|
||||
},
|
||||
upgradeWarehouse: function (divisionName: any, cityName: any): any {
|
||||
const corporation = player.corporation;
|
||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
||||
UpgradeWarehouse(corporation, getDivision(divisionName), getWarehouse(divisionName, cityName));
|
||||
},
|
||||
buyCoffee: function (divisionName: any, cityName: any): any {
|
||||
const corporation = player.corporation;
|
||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
||||
BuyCoffee(corporation, getDivision(divisionName), getOffice(divisionName, cityName));
|
||||
},
|
||||
hireAdVert: function (divisionName: any): any {
|
||||
const corporation = player.corporation;
|
||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
||||
HireAdVert(corporation, getDivision(divisionName), getOffice(divisionName, "Sector-12"));
|
||||
},
|
||||
makeProduct: function (
|
||||
divisionName: any,
|
||||
cityName: any,
|
||||
productName: any,
|
||||
designInvest: any,
|
||||
marketingInvest: any,
|
||||
): any {
|
||||
const corporation = player.corporation;
|
||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
||||
MakeProduct(corporation, getDivision(divisionName), cityName, productName, designInvest, marketingInvest);
|
||||
},
|
||||
research: function (divisionName: any, researchName: any): any {
|
||||
Research(getDivision(divisionName), researchName);
|
||||
},
|
||||
exportMaterial: function (
|
||||
sourceDivision: any,
|
||||
sourceCity: any,
|
||||
targetDivision: any,
|
||||
targetCity: any,
|
||||
materialName: any,
|
||||
amt: any,
|
||||
): any {
|
||||
ExportMaterial(targetDivision, targetCity, getMaterial(sourceDivision, sourceCity, materialName), amt + "");
|
||||
},
|
||||
cancelExportMaterial: function (
|
||||
sourceDivision: any,
|
||||
sourceCity: any,
|
||||
targetDivision: any,
|
||||
targetCity: any,
|
||||
materialName: any,
|
||||
amt: any,
|
||||
): any {
|
||||
CancelExportMaterial(targetDivision, targetCity, getMaterial(sourceDivision, sourceCity, materialName), amt + "");
|
||||
},
|
||||
setMaterialMarketTA1: function (divisionName: any, cityName: any, materialName: any, on: any): any {
|
||||
SetMaterialMarketTA1(getMaterial(divisionName, cityName, materialName), on);
|
||||
},
|
||||
setMaterialMarketTA2: function (divisionName: any, cityName: any, materialName: any, on: any) {
|
||||
SetMaterialMarketTA2(getMaterial(divisionName, cityName, materialName), on);
|
||||
},
|
||||
setProductMarketTA1: function (divisionName: any, productName: any, on: any): any {
|
||||
SetProductMarketTA1(getProduct(divisionName, productName), on);
|
||||
},
|
||||
setProductMarketTA2: function (divisionName: any, productName: any, on: any) {
|
||||
SetProductMarketTA2(getProduct(divisionName, productName), on);
|
||||
},
|
||||
// If you modify these objects you will affect them for real, it's not
|
||||
// copies.
|
||||
getDivision: function (divisionName: any): any {
|
||||
return getDivision(divisionName);
|
||||
},
|
||||
getOffice: function (divisionName: any, cityName: any): any {
|
||||
return getOffice(divisionName, cityName);
|
||||
},
|
||||
getWarehouse: function (divisionName: any, cityName: any): any {
|
||||
return getWarehouse(divisionName, cityName);
|
||||
},
|
||||
getMaterial: function (divisionName: any, cityName: any, materialName: any): any {
|
||||
return getMaterial(divisionName, cityName, materialName);
|
||||
},
|
||||
getProduct: function (divisionName: any, productName: any): any {
|
||||
return getProduct(divisionName, productName);
|
||||
},
|
||||
getEmployee: function (divisionName: any, cityName: any, employeeName: any): any {
|
||||
return getEmployee(divisionName, cityName, employeeName);
|
||||
},
|
||||
};
|
||||
}
|
37
src/NetscriptFunctions/Flags.ts
Normal file
37
src/NetscriptFunctions/Flags.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { toNative } from "./toNative";
|
||||
import * as libarg from "arg";
|
||||
|
||||
export function Flags(vargs: string[]): any {
|
||||
return function (data: any): any {
|
||||
data = toNative(data);
|
||||
// We always want the help flag.
|
||||
const args: {
|
||||
[key: string]: any;
|
||||
} = {};
|
||||
|
||||
for (const d of data) {
|
||||
let t: any = String;
|
||||
if (typeof d[1] === "number") {
|
||||
t = Number;
|
||||
} else if (typeof d[1] === "boolean") {
|
||||
t = Boolean;
|
||||
} else if (Array.isArray(d[1])) {
|
||||
t = [String];
|
||||
}
|
||||
const numDashes = d[0].length > 1 ? 2 : 1;
|
||||
args["-".repeat(numDashes) + d[0]] = t;
|
||||
}
|
||||
const ret = libarg(args, { argv: vargs });
|
||||
for (const d of data) {
|
||||
if (!ret.hasOwnProperty("--" + d[0]) || !ret.hasOwnProperty("-" + d[0])) ret[d[0]] = d[1];
|
||||
}
|
||||
for (const key of Object.keys(ret)) {
|
||||
if (!key.startsWith("-")) continue;
|
||||
const value = ret[key];
|
||||
delete ret[key];
|
||||
const numDashes = key.length === 2 ? 1 : 2;
|
||||
ret[key.slice(numDashes)] = value;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
}
|
187
src/NetscriptFunctions/Formulas.ts
Normal file
187
src/NetscriptFunctions/Formulas.ts
Normal file
@ -0,0 +1,187 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { calculateServerGrowth } from "../Server/formulas/grow";
|
||||
import {
|
||||
calculateMoneyGainRate,
|
||||
calculateLevelUpgradeCost,
|
||||
calculateRamUpgradeCost,
|
||||
calculateCoreUpgradeCost,
|
||||
calculateNodeCost,
|
||||
} from "../Hacknet/formulas/HacknetNodes";
|
||||
import {
|
||||
calculateHashGainRate as HScalculateHashGainRate,
|
||||
calculateLevelUpgradeCost as HScalculateLevelUpgradeCost,
|
||||
calculateRamUpgradeCost as HScalculateRamUpgradeCost,
|
||||
calculateCoreUpgradeCost as HScalculateCoreUpgradeCost,
|
||||
calculateCacheUpgradeCost as HScalculateCacheUpgradeCost,
|
||||
calculateServerCost as HScalculateServerCost,
|
||||
} from "../Hacknet/formulas/HacknetServers";
|
||||
import { HacknetNodeConstants, HacknetServerConstants } from "../Hacknet/data/Constants";
|
||||
import { calculateSkill, calculateExp } from "../PersonObjects/formulas/skill";
|
||||
import {
|
||||
calculateHackingChance,
|
||||
calculateHackingExpGain,
|
||||
calculatePercentMoneyHacked,
|
||||
calculateHackingTime,
|
||||
calculateGrowTime,
|
||||
calculateWeakenTime,
|
||||
} from "../Hacking";
|
||||
|
||||
export interface INetscriptFormulas {
|
||||
basic: {
|
||||
calculateSkill(exp: any, mult?: any): any;
|
||||
calculateExp(skill: any, mult?: any): any;
|
||||
hackChance(server: any, player: any): any;
|
||||
hackExp(server: any, player: any): any;
|
||||
hackPercent(server: any, player: any): any;
|
||||
growPercent(server: any, threads: any, player: any, cores?: any): any;
|
||||
hackTime(server: any, player: any): any;
|
||||
growTime(server: any, player: any): any;
|
||||
weakenTime(server: any, player: any): any;
|
||||
};
|
||||
hacknetNodes: {
|
||||
moneyGainRate(level: any, ram: any, cores: any, mult?: any): any;
|
||||
levelUpgradeCost(startingLevel: any, extraLevels?: any, costMult?: any): any;
|
||||
ramUpgradeCost(startingRam: any, extraLevels?: any, costMult?: any): any;
|
||||
coreUpgradeCost(startingCore: any, extraCores?: any, costMult?: any): any;
|
||||
hacknetNodeCost(n: any, mult: any): any;
|
||||
constants(): any;
|
||||
};
|
||||
hacknetServers: {
|
||||
hashGainRate(level: any, ramUsed: any, maxRam: any, cores: any, mult?: any): any;
|
||||
levelUpgradeCost(startingLevel: any, extraLevels?: any, costMult?: any): any;
|
||||
ramUpgradeCost(startingRam: any, extraLevels?: any, costMult?: any): any;
|
||||
coreUpgradeCost(startingCore: any, extraCores?: any, costMult?: any): any;
|
||||
cacheUpgradeCost(startingCache: any, extraCache?: any): any;
|
||||
hashUpgradeCost(upgName: any, level: any): any;
|
||||
hacknetServerCost(n: any, mult: any): any;
|
||||
constants(): any;
|
||||
};
|
||||
}
|
||||
|
||||
export function NetscriptFormulas(
|
||||
player: IPlayer,
|
||||
workerScript: WorkerScript,
|
||||
helper: INetscriptHelper,
|
||||
): INetscriptFormulas {
|
||||
const checkFormulasAccess = function (func: any, n: any): void {
|
||||
if (
|
||||
(player.sourceFileLvl(5) < 1 && player.bitNodeN !== 5) ||
|
||||
(player.sourceFileLvl(n) < 1 && player.bitNodeN !== n)
|
||||
) {
|
||||
let extra = "";
|
||||
if (n !== 5) {
|
||||
extra = ` and Source-File ${n}-1`;
|
||||
}
|
||||
throw helper.makeRuntimeErrorMsg(`formulas.${func}`, `Requires Source-File 5-1${extra} to run.`);
|
||||
}
|
||||
};
|
||||
return {
|
||||
basic: {
|
||||
calculateSkill: function (exp: any, mult: any = 1): any {
|
||||
checkFormulasAccess("basic.calculateSkill", 5);
|
||||
return calculateSkill(exp, mult);
|
||||
},
|
||||
calculateExp: function (skill: any, mult: any = 1): any {
|
||||
checkFormulasAccess("basic.calculateExp", 5);
|
||||
return calculateExp(skill, mult);
|
||||
},
|
||||
hackChance: function (server: any, player: any): any {
|
||||
checkFormulasAccess("basic.hackChance", 5);
|
||||
return calculateHackingChance(server, player);
|
||||
},
|
||||
hackExp: function (server: any, player: any): any {
|
||||
checkFormulasAccess("basic.hackExp", 5);
|
||||
return calculateHackingExpGain(server, player);
|
||||
},
|
||||
hackPercent: function (server: any, player: any): any {
|
||||
checkFormulasAccess("basic.hackPercent", 5);
|
||||
return calculatePercentMoneyHacked(server, player);
|
||||
},
|
||||
growPercent: function (server: any, threads: any, player: any, cores: any = 1): any {
|
||||
checkFormulasAccess("basic.growPercent", 5);
|
||||
return calculateServerGrowth(server, threads, player, cores);
|
||||
},
|
||||
hackTime: function (server: any, player: any): any {
|
||||
checkFormulasAccess("basic.hackTime", 5);
|
||||
return calculateHackingTime(server, player);
|
||||
},
|
||||
growTime: function (server: any, player: any): any {
|
||||
checkFormulasAccess("basic.growTime", 5);
|
||||
return calculateGrowTime(server, player);
|
||||
},
|
||||
weakenTime: function (server: any, player: any): any {
|
||||
checkFormulasAccess("basic.weakenTime", 5);
|
||||
return calculateWeakenTime(server, player);
|
||||
},
|
||||
},
|
||||
hacknetNodes: {
|
||||
moneyGainRate: function (level: any, ram: any, cores: any, mult: any = 1): any {
|
||||
checkFormulasAccess("hacknetNodes.moneyGainRate", 5);
|
||||
return calculateMoneyGainRate(level, ram, cores, mult);
|
||||
},
|
||||
levelUpgradeCost: function (startingLevel: any, extraLevels: any = 1, costMult: any = 1): any {
|
||||
checkFormulasAccess("hacknetNodes.levelUpgradeCost", 5);
|
||||
return calculateLevelUpgradeCost(startingLevel, extraLevels, costMult);
|
||||
},
|
||||
ramUpgradeCost: function (startingRam: any, extraLevels: any = 1, costMult: any = 1): any {
|
||||
checkFormulasAccess("hacknetNodes.ramUpgradeCost", 5);
|
||||
return calculateRamUpgradeCost(startingRam, extraLevels, costMult);
|
||||
},
|
||||
coreUpgradeCost: function (startingCore: any, extraCores: any = 1, costMult: any = 1): any {
|
||||
checkFormulasAccess("hacknetNodes.coreUpgradeCost", 5);
|
||||
return calculateCoreUpgradeCost(startingCore, extraCores, costMult);
|
||||
},
|
||||
hacknetNodeCost: function (n: any, mult: any): any {
|
||||
checkFormulasAccess("hacknetNodes.hacknetNodeCost", 5);
|
||||
return calculateNodeCost(n, mult);
|
||||
},
|
||||
constants: function (): any {
|
||||
checkFormulasAccess("hacknetNodes.constants", 5);
|
||||
return Object.assign({}, HacknetNodeConstants);
|
||||
},
|
||||
},
|
||||
hacknetServers: {
|
||||
hashGainRate: function (level: any, ramUsed: any, maxRam: any, cores: any, mult: any = 1): any {
|
||||
checkFormulasAccess("hacknetServers.hashGainRate", 9);
|
||||
return HScalculateHashGainRate(level, ramUsed, maxRam, cores, mult);
|
||||
},
|
||||
levelUpgradeCost: function (startingLevel: any, extraLevels: any = 1, costMult: any = 1): any {
|
||||
checkFormulasAccess("hacknetServers.levelUpgradeCost", 9);
|
||||
return HScalculateLevelUpgradeCost(startingLevel, extraLevels, costMult);
|
||||
},
|
||||
ramUpgradeCost: function (startingRam: any, extraLevels: any = 1, costMult: any = 1): any {
|
||||
checkFormulasAccess("hacknetServers.ramUpgradeCost", 9);
|
||||
return HScalculateRamUpgradeCost(startingRam, extraLevels, costMult);
|
||||
},
|
||||
coreUpgradeCost: function (startingCore: any, extraCores: any = 1, costMult: any = 1): any {
|
||||
checkFormulasAccess("hacknetServers.coreUpgradeCost", 9);
|
||||
return HScalculateCoreUpgradeCost(startingCore, extraCores, costMult);
|
||||
},
|
||||
cacheUpgradeCost: function (startingCache: any, extraCache: any = 1): any {
|
||||
checkFormulasAccess("hacknetServers.cacheUpgradeCost", 9);
|
||||
return HScalculateCacheUpgradeCost(startingCache, extraCache);
|
||||
},
|
||||
hashUpgradeCost: function (upgName: any, level: any): any {
|
||||
checkFormulasAccess("hacknetServers.hashUpgradeCost", 9);
|
||||
const upg = player.hashManager.getUpgrade(upgName);
|
||||
if (!upg) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"formulas.hacknetServers.calculateHashUpgradeCost",
|
||||
`Invalid Hash Upgrade: ${upgName}`,
|
||||
);
|
||||
}
|
||||
return upg.getCost(level);
|
||||
},
|
||||
hacknetServerCost: function (n: any, mult: any): any {
|
||||
checkFormulasAccess("hacknetServers.hacknetServerCost", 9);
|
||||
return HScalculateServerCost(n, mult);
|
||||
},
|
||||
constants: function (): any {
|
||||
checkFormulasAccess("hacknetServers.constants", 9);
|
||||
return Object.assign({}, HacknetServerConstants);
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
@ -1,7 +1,13 @@
|
||||
import { BaseServer } from "../Server/BaseServer";
|
||||
import { Faction } from "../Faction/Faction";
|
||||
|
||||
export interface INetscriptHelper {
|
||||
updateDynamicRam(functionName: string, ram: number): void;
|
||||
makeRuntimeErrorMsg(functionName: string, message: string): void;
|
||||
string(funcName: string, argName: string, v: any): string;
|
||||
number(funcName: string, argName: string, v: any): number;
|
||||
boolean(v: any): boolean;
|
||||
getServer(ip: any, fn: any): BaseServer;
|
||||
checkSingularityAccess(func: string, n: number): void;
|
||||
getFaction(func: string, name: string): Faction;
|
||||
}
|
||||
|
377
src/NetscriptFunctions/StockMarket.ts
Normal file
377
src/NetscriptFunctions/StockMarket.ts
Normal file
@ -0,0 +1,377 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||
import { buyStock, sellStock, shortStock, sellShort } from "../StockMarket/BuyingAndSelling";
|
||||
import { StockMarket, SymbolToStockMap, placeOrder, cancelOrder } from "../StockMarket/StockMarket";
|
||||
import { getBuyTransactionCost, getSellTransactionGain } from "../StockMarket/StockMarketHelpers";
|
||||
import { OrderTypes } from "../StockMarket/data/OrderTypes";
|
||||
import { PositionTypes } from "../StockMarket/data/PositionTypes";
|
||||
import { StockSymbols } from "../StockMarket/data/StockSymbols";
|
||||
import { getStockMarket4SDataCost, getStockMarket4STixApiCost } from "../StockMarket/StockMarketCosts";
|
||||
import { Stock } from "../StockMarket/Stock";
|
||||
|
||||
export interface INetscriptStockMarket {
|
||||
getStockSymbols(): any;
|
||||
getStockPrice(symbol: any): any;
|
||||
getStockAskPrice(symbol: any): any;
|
||||
getStockBidPrice(symbol: any): any;
|
||||
getStockPosition(symbol: any): any;
|
||||
getStockMaxShares(symbol: any): any;
|
||||
getStockPurchaseCost(symbol: any, shares: any, posType: any): any;
|
||||
getStockSaleGain(symbol: any, shares: any, posType: any): any;
|
||||
buyStock(symbol: any, shares: any): any;
|
||||
sellStock(symbol: any, shares: any): any;
|
||||
shortStock(symbol: any, shares: any): any;
|
||||
sellShort(symbol: any, shares: any): any;
|
||||
placeOrder(symbol: any, shares: any, price: any, type: any, pos: any): any;
|
||||
cancelOrder(symbol: any, shares: any, price: any, type: any, pos: any): any;
|
||||
getOrders(): any;
|
||||
getStockVolatility(symbol: any): any;
|
||||
getStockForecast(symbol: any): any;
|
||||
purchase4SMarketData(): void;
|
||||
purchase4SMarketDataTixApi(): void;
|
||||
}
|
||||
|
||||
export function NetscriptStockMarket(
|
||||
player: IPlayer,
|
||||
workerScript: WorkerScript,
|
||||
helper: INetscriptHelper,
|
||||
): INetscriptStockMarket {
|
||||
/**
|
||||
* Checks if the player has TIX API access. Throws an error if the player does not
|
||||
*/
|
||||
const checkTixApiAccess = function (callingFn: string): void {
|
||||
if (!player.hasWseAccount) {
|
||||
throw helper.makeRuntimeErrorMsg(callingFn, `You don't have WSE Access! Cannot use ${callingFn}()`);
|
||||
}
|
||||
if (!player.hasTixApiAccess) {
|
||||
throw helper.makeRuntimeErrorMsg(callingFn, `You don't have TIX API Access! Cannot use ${callingFn}()`);
|
||||
}
|
||||
};
|
||||
|
||||
const getStockFromSymbol = function (symbol: string, callingFn: string): Stock {
|
||||
const stock = SymbolToStockMap[symbol];
|
||||
if (stock == null) {
|
||||
throw helper.makeRuntimeErrorMsg(callingFn, `Invalid stock symbol: '${symbol}'`);
|
||||
}
|
||||
|
||||
return stock;
|
||||
};
|
||||
return {
|
||||
getStockSymbols: function (): any {
|
||||
helper.updateDynamicRam("getStockSymbols", getRamCost("getStockSymbols"));
|
||||
checkTixApiAccess("getStockSymbols");
|
||||
return Object.values(StockSymbols);
|
||||
},
|
||||
getStockPrice: function (symbol: any): any {
|
||||
helper.updateDynamicRam("getStockPrice", getRamCost("getStockPrice"));
|
||||
checkTixApiAccess("getStockPrice");
|
||||
const stock = getStockFromSymbol(symbol, "getStockPrice");
|
||||
|
||||
return stock.price;
|
||||
},
|
||||
getStockAskPrice: function (symbol: any): any {
|
||||
helper.updateDynamicRam("getStockAskPrice", getRamCost("getStockAskPrice"));
|
||||
checkTixApiAccess("getStockAskPrice");
|
||||
const stock = getStockFromSymbol(symbol, "getStockAskPrice");
|
||||
|
||||
return stock.getAskPrice();
|
||||
},
|
||||
getStockBidPrice: function (symbol: any): any {
|
||||
helper.updateDynamicRam("getStockBidPrice", getRamCost("getStockBidPrice"));
|
||||
checkTixApiAccess("getStockBidPrice");
|
||||
const stock = getStockFromSymbol(symbol, "getStockBidPrice");
|
||||
|
||||
return stock.getBidPrice();
|
||||
},
|
||||
getStockPosition: function (symbol: any): any {
|
||||
helper.updateDynamicRam("getStockPosition", getRamCost("getStockPosition"));
|
||||
checkTixApiAccess("getStockPosition");
|
||||
const stock = SymbolToStockMap[symbol];
|
||||
if (stock == null) {
|
||||
throw helper.makeRuntimeErrorMsg("getStockPosition", `Invalid stock symbol: ${symbol}`);
|
||||
}
|
||||
return [stock.playerShares, stock.playerAvgPx, stock.playerShortShares, stock.playerAvgShortPx];
|
||||
},
|
||||
getStockMaxShares: function (symbol: any): any {
|
||||
helper.updateDynamicRam("getStockMaxShares", getRamCost("getStockMaxShares"));
|
||||
checkTixApiAccess("getStockMaxShares");
|
||||
const stock = getStockFromSymbol(symbol, "getStockMaxShares");
|
||||
|
||||
return stock.maxShares;
|
||||
},
|
||||
getStockPurchaseCost: function (symbol: any, shares: any, posType: any): any {
|
||||
helper.updateDynamicRam("getStockPurchaseCost", getRamCost("getStockPurchaseCost"));
|
||||
checkTixApiAccess("getStockPurchaseCost");
|
||||
const stock = getStockFromSymbol(symbol, "getStockPurchaseCost");
|
||||
shares = Math.round(shares);
|
||||
|
||||
let pos;
|
||||
const sanitizedPosType = posType.toLowerCase();
|
||||
if (sanitizedPosType.includes("l")) {
|
||||
pos = PositionTypes.Long;
|
||||
} else if (sanitizedPosType.includes("s")) {
|
||||
pos = PositionTypes.Short;
|
||||
} else {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
const res = getBuyTransactionCost(stock, shares, pos);
|
||||
if (res == null) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
return res;
|
||||
},
|
||||
getStockSaleGain: function (symbol: any, shares: any, posType: any): any {
|
||||
helper.updateDynamicRam("getStockSaleGain", getRamCost("getStockSaleGain"));
|
||||
checkTixApiAccess("getStockSaleGain");
|
||||
const stock = getStockFromSymbol(symbol, "getStockSaleGain");
|
||||
shares = Math.round(shares);
|
||||
|
||||
let pos;
|
||||
const sanitizedPosType = posType.toLowerCase();
|
||||
if (sanitizedPosType.includes("l")) {
|
||||
pos = PositionTypes.Long;
|
||||
} else if (sanitizedPosType.includes("s")) {
|
||||
pos = PositionTypes.Short;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const res = getSellTransactionGain(stock, shares, pos);
|
||||
if (res == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
},
|
||||
buyStock: function (symbol: any, shares: any): any {
|
||||
helper.updateDynamicRam("buyStock", getRamCost("buyStock"));
|
||||
checkTixApiAccess("buyStock");
|
||||
const stock = getStockFromSymbol(symbol, "buyStock");
|
||||
const res = buyStock(stock, shares, workerScript, {});
|
||||
return res ? stock.price : 0;
|
||||
},
|
||||
sellStock: function (symbol: any, shares: any): any {
|
||||
helper.updateDynamicRam("sellStock", getRamCost("sellStock"));
|
||||
checkTixApiAccess("sellStock");
|
||||
const stock = getStockFromSymbol(symbol, "sellStock");
|
||||
const res = sellStock(stock, shares, workerScript, {});
|
||||
|
||||
return res ? stock.price : 0;
|
||||
},
|
||||
shortStock: function (symbol: any, shares: any): any {
|
||||
helper.updateDynamicRam("shortStock", getRamCost("shortStock"));
|
||||
checkTixApiAccess("shortStock");
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 1) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"shortStock",
|
||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 2.",
|
||||
);
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(symbol, "shortStock");
|
||||
const res = shortStock(stock, shares, workerScript, {});
|
||||
|
||||
return res ? stock.price : 0;
|
||||
},
|
||||
sellShort: function (symbol: any, shares: any): any {
|
||||
helper.updateDynamicRam("sellShort", getRamCost("sellShort"));
|
||||
checkTixApiAccess("sellShort");
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 1) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"sellShort",
|
||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 2.",
|
||||
);
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(symbol, "sellShort");
|
||||
const res = sellShort(stock, shares, workerScript, {});
|
||||
|
||||
return res ? stock.price : 0;
|
||||
},
|
||||
placeOrder: function (symbol: any, shares: any, price: any, type: any, pos: any): any {
|
||||
helper.updateDynamicRam("placeOrder", getRamCost("placeOrder"));
|
||||
checkTixApiAccess("placeOrder");
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 2) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"placeOrder",
|
||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 3.",
|
||||
);
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(symbol, "placeOrder");
|
||||
|
||||
let orderType;
|
||||
let orderPos;
|
||||
const ltype = type.toLowerCase();
|
||||
if (ltype.includes("limit") && ltype.includes("buy")) {
|
||||
orderType = OrderTypes.LimitBuy;
|
||||
} else if (ltype.includes("limit") && ltype.includes("sell")) {
|
||||
orderType = OrderTypes.LimitSell;
|
||||
} else if (ltype.includes("stop") && ltype.includes("buy")) {
|
||||
orderType = OrderTypes.StopBuy;
|
||||
} else if (ltype.includes("stop") && ltype.includes("sell")) {
|
||||
orderType = OrderTypes.StopSell;
|
||||
} else {
|
||||
throw helper.makeRuntimeErrorMsg("placeOrder", `Invalid order type: ${type}`);
|
||||
}
|
||||
|
||||
const lpos = pos.toLowerCase();
|
||||
if (lpos.includes("l")) {
|
||||
orderPos = PositionTypes.Long;
|
||||
} else if (lpos.includes("s")) {
|
||||
orderPos = PositionTypes.Short;
|
||||
} else {
|
||||
throw helper.makeRuntimeErrorMsg("placeOrder", `Invalid position type: ${pos}`);
|
||||
}
|
||||
|
||||
return placeOrder(stock, shares, price, orderType, orderPos, workerScript);
|
||||
},
|
||||
cancelOrder: function (symbol: any, shares: any, price: any, type: any, pos: any): any {
|
||||
helper.updateDynamicRam("cancelOrder", getRamCost("cancelOrder"));
|
||||
checkTixApiAccess("cancelOrder");
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 2) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"cancelOrder",
|
||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 3.",
|
||||
);
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(symbol, "cancelOrder");
|
||||
if (isNaN(shares) || isNaN(price)) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"cancelOrder",
|
||||
`Invalid shares or price. Must be numeric. shares=${shares}, price=${price}`,
|
||||
);
|
||||
}
|
||||
let orderType;
|
||||
let orderPos;
|
||||
const ltype = type.toLowerCase();
|
||||
if (ltype.includes("limit") && ltype.includes("buy")) {
|
||||
orderType = OrderTypes.LimitBuy;
|
||||
} else if (ltype.includes("limit") && ltype.includes("sell")) {
|
||||
orderType = OrderTypes.LimitSell;
|
||||
} else if (ltype.includes("stop") && ltype.includes("buy")) {
|
||||
orderType = OrderTypes.StopBuy;
|
||||
} else if (ltype.includes("stop") && ltype.includes("sell")) {
|
||||
orderType = OrderTypes.StopSell;
|
||||
} else {
|
||||
throw helper.makeRuntimeErrorMsg("cancelOrder", `Invalid order type: ${type}`);
|
||||
}
|
||||
|
||||
const lpos = pos.toLowerCase();
|
||||
if (lpos.includes("l")) {
|
||||
orderPos = PositionTypes.Long;
|
||||
} else if (lpos.includes("s")) {
|
||||
orderPos = PositionTypes.Short;
|
||||
} else {
|
||||
throw helper.makeRuntimeErrorMsg("cancelOrder", `Invalid position type: ${pos}`);
|
||||
}
|
||||
const params = {
|
||||
stock: stock,
|
||||
shares: shares,
|
||||
price: price,
|
||||
type: orderType,
|
||||
pos: orderPos,
|
||||
};
|
||||
return cancelOrder(params, workerScript);
|
||||
},
|
||||
getOrders: function (): any {
|
||||
helper.updateDynamicRam("getOrders", getRamCost("getOrders"));
|
||||
checkTixApiAccess("getOrders");
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 2) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"getOrders",
|
||||
"You must either be in BitNode-8 or have Source-File 8 Level 3.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const orders: any = {};
|
||||
|
||||
const stockMarketOrders = StockMarket["Orders"];
|
||||
for (const symbol in stockMarketOrders) {
|
||||
const orderBook = stockMarketOrders[symbol];
|
||||
if (orderBook.constructor === Array && orderBook.length > 0) {
|
||||
orders[symbol] = [];
|
||||
for (let i = 0; i < orderBook.length; ++i) {
|
||||
orders[symbol].push({
|
||||
shares: orderBook[i].shares,
|
||||
price: orderBook[i].price,
|
||||
type: orderBook[i].type,
|
||||
position: orderBook[i].pos,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return orders;
|
||||
},
|
||||
getStockVolatility: function (symbol: any): any {
|
||||
helper.updateDynamicRam("getStockVolatility", getRamCost("getStockVolatility"));
|
||||
if (!player.has4SDataTixApi) {
|
||||
throw helper.makeRuntimeErrorMsg("getStockVolatility", "You don't have 4S Market Data TIX API Access!");
|
||||
}
|
||||
const stock = getStockFromSymbol(symbol, "getStockVolatility");
|
||||
|
||||
return stock.mv / 100; // Convert from percentage to decimal
|
||||
},
|
||||
getStockForecast: function (symbol: any): any {
|
||||
helper.updateDynamicRam("getStockForecast", getRamCost("getStockForecast"));
|
||||
if (!player.has4SDataTixApi) {
|
||||
throw helper.makeRuntimeErrorMsg("getStockForecast", "You don't have 4S Market Data TIX API Access!");
|
||||
}
|
||||
const stock = getStockFromSymbol(symbol, "getStockForecast");
|
||||
|
||||
let forecast = 50;
|
||||
stock.b ? (forecast += stock.otlkMag) : (forecast -= stock.otlkMag);
|
||||
return forecast / 100; // Convert from percentage to decimal
|
||||
},
|
||||
purchase4SMarketData: function () {
|
||||
helper.updateDynamicRam("purchase4SMarketData", getRamCost("purchase4SMarketData"));
|
||||
checkTixApiAccess("purchase4SMarketData");
|
||||
|
||||
if (player.has4SData) {
|
||||
workerScript.log("purchase4SMarketData", "Already purchased 4S Market Data.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.money.lt(getStockMarket4SDataCost())) {
|
||||
workerScript.log("purchase4SMarketData", "Not enough money to purchase 4S Market Data.");
|
||||
return false;
|
||||
}
|
||||
|
||||
player.has4SData = true;
|
||||
player.loseMoney(getStockMarket4SDataCost());
|
||||
workerScript.log("purchase4SMarketData", "Purchased 4S Market Data");
|
||||
return true;
|
||||
},
|
||||
purchase4SMarketDataTixApi: function () {
|
||||
helper.updateDynamicRam("purchase4SMarketDataTixApi", getRamCost("purchase4SMarketDataTixApi"));
|
||||
checkTixApiAccess("purchase4SMarketDataTixApi");
|
||||
|
||||
if (player.has4SDataTixApi) {
|
||||
workerScript.log("purchase4SMarketDataTixApi", "Already purchased 4S Market Data TIX API");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.money.lt(getStockMarket4STixApiCost())) {
|
||||
workerScript.log("purchase4SMarketDataTixApi", "Not enough money to purchase 4S Market Data TIX API");
|
||||
return false;
|
||||
}
|
||||
|
||||
player.has4SDataTixApi = true;
|
||||
player.loseMoney(getStockMarket4STixApiCost());
|
||||
workerScript.log("purchase4SMarketDataTixApi", "Purchased 4S Market Data TIX API");
|
||||
return true;
|
||||
},
|
||||
};
|
||||
}
|
36
src/NetscriptFunctions/toNative.ts
Normal file
36
src/NetscriptFunctions/toNative.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import { Interpreter } from "../ThirdParty/JSInterpreter";
|
||||
|
||||
const defaultInterpreter = new Interpreter("", () => undefined);
|
||||
|
||||
// the acorn interpreter has a bug where it doesn't convert arrays correctly.
|
||||
// so we have to more or less copy it here.
|
||||
export function toNative(pseudoObj: any): any {
|
||||
if (pseudoObj == null) return null;
|
||||
if (
|
||||
!pseudoObj.hasOwnProperty("properties") ||
|
||||
!pseudoObj.hasOwnProperty("getter") ||
|
||||
!pseudoObj.hasOwnProperty("setter") ||
|
||||
!pseudoObj.hasOwnProperty("proto")
|
||||
) {
|
||||
return pseudoObj; // it wasn't a pseudo object anyway.
|
||||
}
|
||||
|
||||
let nativeObj: any;
|
||||
if (pseudoObj.hasOwnProperty("class") && pseudoObj.class === "Array") {
|
||||
nativeObj = [];
|
||||
const length = defaultInterpreter.getProperty(pseudoObj, "length");
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (defaultInterpreter.hasProperty(pseudoObj, i)) {
|
||||
nativeObj[i] = toNative(defaultInterpreter.getProperty(pseudoObj, i));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Object.
|
||||
nativeObj = {};
|
||||
for (const key in pseudoObj.properties) {
|
||||
const val = pseudoObj.properties[key];
|
||||
nativeObj[key] = toNative(val);
|
||||
}
|
||||
}
|
||||
return nativeObj;
|
||||
}
|
@ -8,6 +8,22 @@ function makeScriptBlob(code: string): Blob {
|
||||
return new Blob([code], { type: "text/javascript" });
|
||||
}
|
||||
|
||||
export function compile(script: Script, scripts: Script[]): void {
|
||||
if (!shouldCompile(script, scripts)) return;
|
||||
// The URL at the top is the one we want to import. It will
|
||||
// recursively import all the other modules in the urlStack.
|
||||
//
|
||||
// Webpack likes to turn the import into a require, which sort of
|
||||
// but not really behaves like import. Particularly, it cannot
|
||||
// load fully dynamic content. So we hide the import from webpack
|
||||
// by placing it inside an eval call.
|
||||
script.markUpdated();
|
||||
const uurls = _getScriptUrls(script, scripts, []);
|
||||
script.url = uurls[uurls.length - 1].url;
|
||||
script.module = new Promise((resolve) => resolve(eval("import(uurls[uurls.length - 1].url)")));
|
||||
script.dependencies = uurls;
|
||||
}
|
||||
|
||||
// Begin executing a user JS script, and return a promise that resolves
|
||||
// or rejects when the script finishes.
|
||||
// - script is a script to execute (see Script.js). We depend only on .filename and .code.
|
||||
@ -17,23 +33,9 @@ function makeScriptBlob(code: string): Blob {
|
||||
// When the promise returned by this resolves, we'll have finished
|
||||
// running the main function of the script.
|
||||
export async function executeJSScript(scripts: Script[] = [], workerScript: WorkerScript): Promise<void> {
|
||||
let uurls: ScriptUrl[] = [];
|
||||
const script = workerScript.getScript();
|
||||
if (script === null) throw new Error("script is null");
|
||||
if (shouldCompile(script, scripts)) {
|
||||
// The URL at the top is the one we want to import. It will
|
||||
// recursively import all the other modules in the urlStack.
|
||||
//
|
||||
// Webpack likes to turn the import into a require, which sort of
|
||||
// but not really behaves like import. Particularly, it cannot
|
||||
// load fully dynamic content. So we hide the import from webpack
|
||||
// by placing it inside an eval call.
|
||||
script.markUpdated();
|
||||
uurls = _getScriptUrls(script, scripts, []);
|
||||
script.url = uurls[uurls.length - 1].url;
|
||||
script.module = new Promise((resolve) => resolve(eval("import(uurls[uurls.length - 1].url)")));
|
||||
script.dependencies = uurls;
|
||||
}
|
||||
compile(script, scripts);
|
||||
const loadedModule = await script.module;
|
||||
|
||||
const ns = workerScript.env.vars;
|
||||
|
@ -470,11 +470,7 @@ export function startWorkerScript(runningScript: RunningScript, server: BaseServ
|
||||
* @param {Server} server - Server on which the script is to be run
|
||||
* returns {boolean} indicating whether or not the workerScript was successfully added
|
||||
*/
|
||||
export function createAndAddWorkerScript(
|
||||
runningScriptObj: RunningScript,
|
||||
server: BaseServer,
|
||||
parent?: WorkerScript,
|
||||
): boolean {
|
||||
function createAndAddWorkerScript(runningScriptObj: RunningScript, server: BaseServer, parent?: WorkerScript): boolean {
|
||||
// Update server's ram usage
|
||||
let threads = 1;
|
||||
if (runningScriptObj.threads && !isNaN(runningScriptObj.threads)) {
|
||||
|
@ -276,7 +276,6 @@ export interface IPlayer {
|
||||
setBitNodeNumber(n: number): void;
|
||||
getMult(name: string): number;
|
||||
setMult(name: string, mult: number): void;
|
||||
|
||||
canAccessCotMG(): boolean;
|
||||
sourceFileLvl(n: number): number;
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
import { EventEmitter } from "../utils/EventEmitter";
|
||||
|
||||
export const PlayerEvents = new EventEmitter<[]>();
|
@ -1,100 +0,0 @@
|
||||
import * as React from "react";
|
||||
|
||||
export const SleeveFaq = (
|
||||
<>
|
||||
<strong>
|
||||
<u>How do Duplicate Sleeves work?</u>
|
||||
</strong>
|
||||
<br />
|
||||
Duplicate Sleeves are essentially clones. You can use them to perform any work type action, such as working for a
|
||||
company/faction or committing a crime. Having sleeves perform these tasks earns you money, experience, and
|
||||
reputation.
|
||||
<br />
|
||||
<br />
|
||||
Sleeves are their own individuals, which means they each have their own experience and stats.
|
||||
<br />
|
||||
<br />
|
||||
When a sleeve earns experience, it earns experience for itself, the player's original 'consciousness', as well as
|
||||
all of the player's other sleeves.
|
||||
<br />
|
||||
<br />
|
||||
<strong>
|
||||
<u>What is Synchronization (Sync)?</u>
|
||||
</strong>
|
||||
<br />
|
||||
Synchronization is a measure of how aligned your consciousness is with that of your Duplicate Sleeves. It is a
|
||||
numerical value between 1 and 100, and it affects how much experience is earned when the sleeve is performing a
|
||||
task.
|
||||
<br />
|
||||
<br />
|
||||
Let N be the sleeve's synchronization. When the sleeve earns experience by performing a task, both the sleeve and
|
||||
the player's original host consciousness earn N% of the amount of experience normally earned by the task. All of the
|
||||
player's other sleeves earn ((N/100)^2 * 100)% of the experience.
|
||||
<br />
|
||||
<br />
|
||||
Synchronization can be increased by assigning sleeves to the 'Synchronize' task.
|
||||
<br />
|
||||
<br />
|
||||
<strong>
|
||||
<u>What is Shock?</u>
|
||||
</strong>
|
||||
<br />
|
||||
Sleeve shock is a measure of how much trauma the sleeve has due to being placed in a new body. It is a numerical
|
||||
value between 0 and 99, where 99 indicates full shock and 0 indicates no shock. Shock affects the amount of
|
||||
experience earned by the sleeve.
|
||||
<br />
|
||||
<br />
|
||||
Sleeve shock slowly decreases over time. You can further increase the rate at which it decreases by assigning
|
||||
sleeves to the 'Shock Recovery' task.
|
||||
<br />
|
||||
<br />
|
||||
<strong>
|
||||
<u>Why can't I work for this company or faction?</u>
|
||||
</strong>
|
||||
<br />
|
||||
Only one of your sleeves can work for a given company/faction a time. To clarify further, if you have two sleeves
|
||||
they can work for two different companies, but they cannot both work for the same company.
|
||||
<br />
|
||||
<br />
|
||||
<strong>
|
||||
<u>Why did my Sleeve stop working?</u>
|
||||
</strong>
|
||||
<br />
|
||||
Sleeves are subject to the same time restrictions as you. This means that they automatically stop working at a
|
||||
company after 8 hours, and stop working for a faction after 20 hours.
|
||||
<br />
|
||||
<br />
|
||||
<strong>
|
||||
<u>How do I buy Augmentations for my Sleeves?</u>
|
||||
</strong>
|
||||
<br />
|
||||
Your Sleeve needs to have a Shock of 0 in order for you to buy Augmentations for it.
|
||||
<br />
|
||||
<br />
|
||||
<strong>
|
||||
<u>Why can't I buy the X Augmentation for my sleeve?</u>
|
||||
</strong>
|
||||
<br />
|
||||
Certain Augmentations, like Bladeburner-specific ones and NeuroFlux Governor, are not available for sleeves.
|
||||
<br />
|
||||
<br />
|
||||
<strong>
|
||||
<u>Do sleeves get reset when installing Augmentations or switching BitNodes?</u>
|
||||
</strong>
|
||||
<br />
|
||||
Sleeves are reset when switching BitNodes, but not when installing Augmentations.
|
||||
<br />
|
||||
<br />
|
||||
<strong>
|
||||
<u>What is Memory?</u>
|
||||
</strong>
|
||||
<br />
|
||||
Sleeve memory dictates what a sleeve's synchronization will be when its reset by switching BitNodes. For example, if
|
||||
a sleeve has a memory of 25, then when you switch BitNodes its synchronization will initially be set to 25, rather
|
||||
than 1.
|
||||
<br />
|
||||
<br />
|
||||
Memory can only be increased by purchasing upgrades from The Covenant. It is a persistent stat, meaning it never
|
||||
gets resets back to 1. The maximum possible value for a sleeve's memory is 100.
|
||||
</>
|
||||
);
|
@ -24,7 +24,7 @@ function bitFlumeRequirements() {
|
||||
};
|
||||
}
|
||||
|
||||
export interface IProgramCreationParams {
|
||||
interface IProgramCreationParams {
|
||||
key: string;
|
||||
name: string;
|
||||
create: IProgramCreate | null;
|
||||
|
@ -1,7 +1,7 @@
|
||||
export type Position = {
|
||||
interface Position {
|
||||
row: number;
|
||||
column: number;
|
||||
};
|
||||
}
|
||||
|
||||
class PositionTracker {
|
||||
positions: Map<string, Position>;
|
||||
|
@ -132,7 +132,6 @@ export class Server extends BaseServer {
|
||||
const aboveCap = this.moneyMax - softCap;
|
||||
n = 1 + (n - 1) / Math.log(aboveCap) / Math.log(8);
|
||||
}
|
||||
console.log(n);
|
||||
|
||||
this.moneyMax *= n;
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ export function initSymbolToStockMap(): void {
|
||||
}
|
||||
}
|
||||
|
||||
export function stockMarketCycle(): void {
|
||||
function stockMarketCycle(): void {
|
||||
for (const name in StockMarket) {
|
||||
const stock = StockMarket[name];
|
||||
if (!(stock instanceof Stock)) {
|
||||
|
@ -1,14 +1,6 @@
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
|
||||
export function getStockMarketAccountCost(): number {
|
||||
return CONSTANTS.WSEAccountCost;
|
||||
}
|
||||
|
||||
export function getStockMarketTixApiCost(): number {
|
||||
return CONSTANTS.TIXAPICost;
|
||||
}
|
||||
|
||||
export function getStockMarket4SDataCost(): number {
|
||||
return CONSTANTS.MarketData4SCost * BitNodeMultipliers.FourSigmaMarketDataCost;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { EventEmitter } from "../../utils/EventEmitter";
|
||||
|
||||
type txFn = (stock: Stock, shares: number) => boolean;
|
||||
export type placeOrderFn = (
|
||||
type placeOrderFn = (
|
||||
stock: Stock,
|
||||
shares: number,
|
||||
price: number,
|
||||
|
@ -39,8 +39,8 @@ enum SelectorOrderType {
|
||||
Stop = "Stop Order",
|
||||
}
|
||||
|
||||
export type txFn = (stock: Stock, shares: number) => boolean;
|
||||
export type placeOrderFn = (
|
||||
type txFn = (stock: Stock, shares: number) => boolean;
|
||||
type placeOrderFn = (
|
||||
stock: Stock,
|
||||
shares: number,
|
||||
price: number,
|
||||
|
@ -47,7 +47,7 @@ function LongPosition(props: IProps): React.ReactElement {
|
||||
</Box>
|
||||
<Typography>Shares: {numeralWrapper.formatShares(stock.playerShares)}</Typography>
|
||||
<Typography>
|
||||
Average Price: <Money money={stock.playerAvgPx} /> (Total Cost: <Money money={totalCost} />
|
||||
Average Price: <Money money={stock.playerAvgPx} /> (Total Cost: <Money money={totalCost} />)
|
||||
</Typography>
|
||||
<Typography>
|
||||
Profit: <Money money={gains} /> ({numeralWrapper.formatPercentage(percentageGains)})
|
||||
|
@ -16,8 +16,8 @@ import { PositionTypes } from "../data/PositionTypes";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { EventEmitter } from "../../utils/EventEmitter";
|
||||
|
||||
export type txFn = (stock: Stock, shares: number) => boolean;
|
||||
export type placeOrderFn = (
|
||||
type txFn = (stock: Stock, shares: number) => boolean;
|
||||
type placeOrderFn = (
|
||||
stock: Stock,
|
||||
shares: number,
|
||||
price: number,
|
||||
|
@ -35,7 +35,7 @@ export function removeTrailingSlash(s: string): string {
|
||||
* Checks whether a string is a valid filename. Only used for the filename itself,
|
||||
* not the entire filepath
|
||||
*/
|
||||
export function isValidFilename(filename: string): boolean {
|
||||
function isValidFilename(filename: string): boolean {
|
||||
// Allows alphanumerics, hyphens, underscores, and percentage signs
|
||||
// Must have a file extension
|
||||
const regex = /^[.a-zA-Z0-9_-]+[.][a-zA-Z0-9]+(?:-\d+(?:\.\d*)?%-INC)?$/;
|
||||
@ -48,7 +48,7 @@ export function isValidFilename(filename: string): boolean {
|
||||
* Checks whether a string is a valid directory name. Only used for the directory itself,
|
||||
* not an entire path
|
||||
*/
|
||||
export function isValidDirectoryName(name: string): boolean {
|
||||
function isValidDirectoryName(name: string): boolean {
|
||||
// Allows alphanumerics, hyphens, underscores, and percentage signs.
|
||||
// Name can begin with a single period, but otherwise cannot have any
|
||||
const regex = /^.?[a-zA-Z0-9_-]+$/;
|
||||
|
@ -543,7 +543,6 @@ export class Terminal implements ITerminal {
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
// TODO: remove this once we figure out the height issue.
|
||||
this.outputHistory = [new Output(`Bitburner v${CONSTANTS.Version}`, "primary")];
|
||||
TerminalEvents.emit();
|
||||
TerminalClearEvents.emit();
|
||||
|
@ -19,15 +19,6 @@ export function run(
|
||||
} else {
|
||||
const executableName = args[0] + "";
|
||||
|
||||
// Secret Music player!
|
||||
// if (executableName === "musicplayer") {
|
||||
// post(
|
||||
// '<iframe src="https://open.spotify.com/embed/user/danielyxie/playlist/1ORnnL6YNvXOracUaUV2kh" width="300" height="380" frameborder="0" allowtransparency="true"></iframe>',
|
||||
// false,
|
||||
// );
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Check if its a script or just a program/executable
|
||||
if (isScriptFilename(executableName)) {
|
||||
runScript(terminal, router, player, server, args);
|
||||
|
@ -3,9 +3,13 @@ import { getSubdirectories } from "./DirectoryServerHelpers";
|
||||
|
||||
import { Aliases, GlobalAliases } from "../Alias";
|
||||
import { DarkWebItems } from "../DarkWeb/DarkWebItems";
|
||||
import { Message } from "../Message/Message";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { GetServer, GetAllServers } from "../Server/AllServers";
|
||||
import { ParseCommand, ParseCommands } from "./Parser";
|
||||
import { isScriptFilename } from "../Script/isScriptFilename";
|
||||
import { compile } from "../NetscriptJSEvaluator";
|
||||
import { Flags } from "../NetscriptFunctions/Flags";
|
||||
import * as libarg from "arg";
|
||||
|
||||
// An array of all Terminal commands
|
||||
const commands = [
|
||||
@ -48,12 +52,12 @@ const commands = [
|
||||
"weaken",
|
||||
];
|
||||
|
||||
export function determineAllPossibilitiesForTabCompletion(
|
||||
export async function determineAllPossibilitiesForTabCompletion(
|
||||
p: IPlayer,
|
||||
input: string,
|
||||
index: number,
|
||||
currPath = "",
|
||||
): string[] {
|
||||
): Promise<string[]> {
|
||||
let allPos: string[] = [];
|
||||
allPos = allPos.concat(Object.keys(GlobalAliases));
|
||||
const currServ = p.getCurrentServer();
|
||||
@ -287,13 +291,58 @@ export function determineAllPossibilitiesForTabCompletion(
|
||||
return allPos;
|
||||
}
|
||||
|
||||
async function scriptAutocomplete(): Promise<string[] | undefined> {
|
||||
if (!isCommand("run")) return;
|
||||
const commands = ParseCommands(input);
|
||||
if (commands.length === 0) return;
|
||||
const command = ParseCommand(commands[commands.length - 1]);
|
||||
const filename = command[1] + "";
|
||||
if (!isScriptFilename(filename)) return; // Not a script.
|
||||
if (filename.endsWith(".script")) return; // Doesn't work with ns1.
|
||||
const script = currServ.scripts.find((script) => script.filename === filename);
|
||||
if (!script) return; // Doesn't exist.
|
||||
if (!script.module) {
|
||||
compile(script, currServ.scripts);
|
||||
}
|
||||
const loadedModule = await script.module;
|
||||
if (!loadedModule.autocomplete) return; // Doesn't have an autocomplete function.
|
||||
|
||||
const runArgs = { "--tail": Boolean, "-t": Number };
|
||||
const flags = libarg(runArgs, {
|
||||
permissive: true,
|
||||
argv: command.slice(2),
|
||||
});
|
||||
const flagFunc = Flags(flags._);
|
||||
let pos: string[] = [];
|
||||
let pos2: string[] = [];
|
||||
pos = pos.concat(
|
||||
loadedModule.autocomplete(
|
||||
{
|
||||
servers: GetAllServers().map((server) => server.hostname),
|
||||
scripts: currServ.scripts.map((script) => script.filename),
|
||||
txts: currServ.textFiles.map((txt) => txt.fn),
|
||||
flags: (schema: any) => {
|
||||
pos2 = schema.map((f: any) => "--" + f[0]);
|
||||
try {
|
||||
return flagFunc(schema);
|
||||
} catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
},
|
||||
flags._,
|
||||
),
|
||||
);
|
||||
return pos.concat(pos2);
|
||||
}
|
||||
const pos = await scriptAutocomplete();
|
||||
if (pos) return pos;
|
||||
|
||||
if (isCommand("run")) {
|
||||
addAllScripts();
|
||||
addAllPrograms();
|
||||
addAllCodingContracts();
|
||||
addAllDirectories();
|
||||
|
||||
return allPos;
|
||||
}
|
||||
|
||||
if (isCommand("cat")) {
|
||||
|
@ -44,7 +44,7 @@ export function tabCompletion(
|
||||
} else if (allPossibilities.length === 1) {
|
||||
if (arg === "") {
|
||||
//Autocomplete command
|
||||
val = allPossibilities[0] + " ";
|
||||
val = allPossibilities[0];
|
||||
} else {
|
||||
val = command + " " + allPossibilities[0];
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React
|
||||
return () => document.removeEventListener("keydown", keyDown);
|
||||
});
|
||||
|
||||
function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): void {
|
||||
async function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): Promise<void> {
|
||||
// Run command.
|
||||
if (event.keyCode === KEY.ENTER && value !== "") {
|
||||
event.preventDefault();
|
||||
@ -190,7 +190,7 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React
|
||||
if (index < -1) {
|
||||
index = 0;
|
||||
}
|
||||
const allPos = determineAllPossibilitiesForTabCompletion(player, copy, index, terminal.cwd());
|
||||
const allPos = await determineAllPossibilitiesForTabCompletion(player, copy, index, terminal.cwd());
|
||||
if (allPos.length == 0) {
|
||||
return;
|
||||
}
|
||||
@ -213,8 +213,9 @@ export function TerminalInput({ terminal, router, player }: IProps): React.React
|
||||
command = commandArray.join(" ");
|
||||
}
|
||||
|
||||
const newValue = tabCompletion(command, arg, allPos, value);
|
||||
let newValue = tabCompletion(command, arg, allPos, value);
|
||||
if (typeof newValue === "string" && newValue !== "") {
|
||||
if (!newValue.endsWith(" ") && allPos.length === 1) newValue += " ";
|
||||
saveValue(newValue);
|
||||
}
|
||||
if (Array.isArray(newValue)) {
|
||||
|
@ -12,7 +12,7 @@ export type SolverFunc = (data: any, answer: string) => boolean;
|
||||
Requires the 'data' of a Contract as input */
|
||||
export type DescriptionFunc = (data: any) => string;
|
||||
|
||||
export interface ICodingContractTypeMetadata {
|
||||
interface ICodingContractTypeMetadata {
|
||||
desc: DescriptionFunc;
|
||||
difficulty: number;
|
||||
gen: GeneratorFunc;
|
||||
|
@ -10,11 +10,6 @@ export interface IMap<T> {
|
||||
[key: string]: T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs some action, with no returned value.
|
||||
*/
|
||||
export type Action = () => void;
|
||||
|
||||
/**
|
||||
* Contains a method to initialize itself to a known state.
|
||||
*/
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { KEY } from "../../utils/helpers/keyCodes";
|
||||
|
||||
import { CodingContract, CodingContractType, CodingContractTypes } from "../../CodingContracts";
|
||||
import { CodingContract, CodingContractTypes } from "../../CodingContracts";
|
||||
import { CopyableText } from "./CopyableText";
|
||||
import { Modal } from "./Modal";
|
||||
import { EventEmitter } from "../../utils/EventEmitter";
|
||||
@ -49,7 +49,7 @@ export function CodingContractModal(): React.ReactElement {
|
||||
setProps(null);
|
||||
}
|
||||
|
||||
const contractType: CodingContractType = CodingContractTypes[props.c.type];
|
||||
const contractType = CodingContractTypes[props.c.type];
|
||||
const description = [];
|
||||
for (const [i, value] of contractType.desc(props.c.data).split("\n").entries())
|
||||
description.push(<span key={i} dangerouslySetInnerHTML={{ __html: value + "<br />" }}></span>);
|
||||
|
@ -12,6 +12,8 @@ import makeStyles from "@mui/styles/makeStyles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import ArrowForwardIosIcon from "@mui/icons-material/ArrowForwardIos";
|
||||
|
||||
let layerCounter = 0;
|
||||
|
||||
export const LogBoxEvents = new EventEmitter<[RunningScript]>();
|
||||
|
||||
interface Log {
|
||||
@ -86,9 +88,18 @@ function LogWindow(props: IProps): React.ReactElement {
|
||||
killWorkerScript(props.script, props.script.server, true);
|
||||
props.onClose();
|
||||
}
|
||||
//useEffect(() => TerminalEvents.subscribe(_.debounce(async () => rerender(), 25, { maxWait: 50 })), []);
|
||||
|
||||
function updateLayer(): void {
|
||||
const c = container.current;
|
||||
if (c === null) return;
|
||||
c.style.zIndex = 1500 + layerCounter + "";
|
||||
layerCounter++;
|
||||
rerender();
|
||||
}
|
||||
|
||||
return (
|
||||
<Draggable handle="#drag">
|
||||
<Draggable handle=".drag">
|
||||
<Paper
|
||||
style={{
|
||||
display: "flex",
|
||||
@ -100,12 +111,13 @@ function LogWindow(props: IProps): React.ReactElement {
|
||||
}}
|
||||
ref={container}
|
||||
>
|
||||
<div onMouseDown={updateLayer}>
|
||||
<Paper
|
||||
style={{
|
||||
cursor: "grab",
|
||||
}}
|
||||
>
|
||||
<Box id="drag" display="flex" alignItems="center">
|
||||
<Box className="drag" display="flex" alignItems="center">
|
||||
<Typography color="primary" variant="h6">
|
||||
{props.script.filename} {props.script.args.map((x: any): string => `${x}`).join(" ")}
|
||||
</Typography>
|
||||
@ -139,6 +151,7 @@ function LogWindow(props: IProps): React.ReactElement {
|
||||
</Box>
|
||||
</ResizableBox>
|
||||
</Paper>
|
||||
</div>
|
||||
</Paper>
|
||||
</Draggable>
|
||||
);
|
||||
|
@ -1,32 +0,0 @@
|
||||
/**
|
||||
* React component for a popup content container
|
||||
*
|
||||
* Takes in a prop for rendering the content inside the popup
|
||||
*/
|
||||
import React, { useEffect } from "react";
|
||||
|
||||
interface IProps<T> {
|
||||
content: (props: T) => React.ReactElement;
|
||||
id: string;
|
||||
props: T;
|
||||
removePopup: () => void;
|
||||
}
|
||||
|
||||
export function Popup<T>(props: IProps<T>): React.ReactElement {
|
||||
function keyDown(event: KeyboardEvent): void {
|
||||
if (event.key === "Escape") props.removePopup();
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener("keydown", keyDown);
|
||||
return () => {
|
||||
document.removeEventListener("keydown", keyDown);
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={"popup-box-content"} id={`${props.id}-content`}>
|
||||
{React.createElement(props.content, props.props)}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
|
||||
type cbFn = (...args: any[]) => any;
|
||||
|
||||
export interface ISubscriber {
|
||||
interface ISubscriber {
|
||||
/**
|
||||
* Callback function that will be run when an event is emitted
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Generic Reviver, toJSON, and fromJSON functions used for saving and loading objects */
|
||||
|
||||
export interface IReviverValue {
|
||||
interface IReviverValue {
|
||||
ctor: string;
|
||||
data: any;
|
||||
}
|
||||
@ -19,7 +19,7 @@ export function Reviver(key: string, value: IReviverValue | null): any {
|
||||
// Compatibility for version v0.43.1
|
||||
// TODO Remove this eventually
|
||||
if (value.ctor === "AllServersMap") {
|
||||
console.log("Converting AllServersMap for v0.43.1");
|
||||
console.warn("Converting AllServersMap for v0.43.1");
|
||||
return value.data;
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,6 @@
|
||||
import { EqualityFunc } from "../types";
|
||||
import { isString } from "./helpers/isString";
|
||||
|
||||
// Netburner String helper functions
|
||||
|
||||
// Replaces the character at an index with a new character
|
||||
function replaceAt(base: string, index: number, character: string): string {
|
||||
return base.substr(0, index) + character + base.substr(index + character.length);
|
||||
}
|
||||
|
||||
/*
|
||||
Converts a date representing time in milliseconds to a string with the format H hours M minutes and S seconds
|
||||
e.g. 10000 -> "10 seconds"
|
||||
@ -92,20 +85,6 @@ function formatNumber(num: number, numFractionDigits = 0): string {
|
||||
});
|
||||
}
|
||||
|
||||
// Checks if a string contains HTML elements
|
||||
function isHTML(str: string): boolean {
|
||||
const element: HTMLDivElement = document.createElement("div");
|
||||
element.innerHTML = str;
|
||||
const c: NodeListOf<Node & ChildNode> = element.childNodes;
|
||||
for (let i: number = c.length - 1; i >= 0; i--) {
|
||||
if (c[i].nodeType === 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generates a random alphanumeric string with N characters
|
||||
function generateRandomString(n: number): string {
|
||||
let str = "";
|
||||
@ -118,12 +97,4 @@ function generateRandomString(n: number): string {
|
||||
return str;
|
||||
}
|
||||
|
||||
export {
|
||||
convertTimeMsToTimeElapsedString,
|
||||
longestCommonStart,
|
||||
containsAllStrings,
|
||||
formatNumber,
|
||||
isHTML,
|
||||
generateRandomString,
|
||||
replaceAt,
|
||||
};
|
||||
export { convertTimeMsToTimeElapsedString, longestCommonStart, containsAllStrings, formatNumber, generateRandomString };
|
||||
|
@ -4,9 +4,7 @@ const webpack = require("webpack");
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
|
||||
const UnusedWebpackPlugin = require("unused-webpack-plugin");
|
||||
const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
|
||||
const DeadCodePlugin = require("webpack-deadcode-plugin");
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const isDevServer = (env || {}).devServer === true;
|
||||
@ -107,14 +105,6 @@ module.exports = (env, argv) => {
|
||||
},
|
||||
},
|
||||
}),
|
||||
new UnusedWebpackPlugin({
|
||||
// Source directories
|
||||
directories: [path.join(__dirname, "src"), path.join(__dirname, "utils")],
|
||||
// Exclude patterns
|
||||
exclude: ["*.test.js"],
|
||||
// Root directory (optional)
|
||||
root: __dirname,
|
||||
}),
|
||||
// In dev mode, use a faster method of create sourcemaps
|
||||
// while keeping lines/columns accurate
|
||||
isDevServer &&
|
||||
@ -132,10 +122,6 @@ module.exports = (env, argv) => {
|
||||
module: true,
|
||||
}),
|
||||
isFastRefresh && new ReactRefreshWebpackPlugin(),
|
||||
new DeadCodePlugin({
|
||||
patterns: ["src/**/*.(js|jsx|css|ts|tsx)"],
|
||||
exclude: ["**/*.(stories|spec).(js|jsx)"],
|
||||
}),
|
||||
].filter(Boolean),
|
||||
target: "web",
|
||||
entry: entry,
|
||||
|
Loading…
Reference in New Issue
Block a user