mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-19 20:55:44 +01:00
fix mc
This commit is contained in:
commit
7eb4494ac1
2
.github/PULL_REQUEST_TEMPLATE
vendored
2
.github/PULL_REQUEST_TEMPLATE
vendored
@ -1,5 +1,7 @@
|
|||||||
# DELETE THIS AFTER READING
|
# DELETE THIS AFTER READING
|
||||||
|
|
||||||
|
# READ CONTRIBUTING.md
|
||||||
|
|
||||||
# PR title
|
# PR title
|
||||||
|
|
||||||
Formatted as such:
|
Formatted as such:
|
||||||
|
4
dist/main.bundle.js
vendored
4
dist/main.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/main.bundle.js.map
vendored
2
dist/main.bundle.js.map
vendored
File diff suppressed because one or more lines are too long
42
dist/vendor.bundle.js
vendored
42
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/vendor.bundle.js.map
vendored
2
dist/vendor.bundle.js.map
vendored
File diff suppressed because one or more lines are too long
11
doc/NEW_BN_GUIDELINE.md
Normal file
11
doc/NEW_BN_GUIDELINE.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Promote:
|
||||||
|
|
||||||
|
- New mechanic
|
||||||
|
- Coding problems based on NP problems. This makes solution that are easy to implement inefficient and solutions that are hard to implement efficent. (eg. Stanek)
|
||||||
|
- inter-mechanic synergy
|
||||||
|
- Simplicity (eg. Stanek, Hashnet. bad example: Corp)
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
- Failure conditions, it's very frustrating to revert several days worth of progress.
|
||||||
|
- Making existing mechanic harder. This makes it hard to port the content to other BNs.
|
1
doc/POTENTIAL_BN_1.md
Normal file
1
doc/POTENTIAL_BN_1.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
Sleeves meet Screeps (That's all I got)
|
3
doc/POTENTIAL_BN_2.md
Normal file
3
doc/POTENTIAL_BN_2.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
A game of risk from the point of view of a politician.
|
||||||
|
|
||||||
|
You allocate resources on a world map, trying to win elections.
|
@ -1 +0,0 @@
|
|||||||
I want the wiki here https://bitburner.fandom.com/wiki/Bitburner_Wiki taken down please.
|
|
465
package-lock.json
generated
465
package-lock.json
generated
@ -56,6 +56,10 @@
|
|||||||
"@types/bcryptjs": "^2.4.2",
|
"@types/bcryptjs": "^2.4.2",
|
||||||
"@types/escodegen": "^0.0.7",
|
"@types/escodegen": "^0.0.7",
|
||||||
"@types/file-saver": "^2.0.3",
|
"@types/file-saver": "^2.0.3",
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
"@types/jest": "^27.4.1",
|
||||||
|
>>>>>>> dev
|
||||||
"@types/jquery": "^3.5.14",
|
"@types/jquery": "^3.5.14",
|
||||||
"@types/lodash": "^4.14.168",
|
"@types/lodash": "^4.14.168",
|
||||||
"@types/numeral": "^2.0.2",
|
"@types/numeral": "^2.0.2",
|
||||||
@ -2068,19 +2072,33 @@
|
|||||||
"integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA=="
|
"integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA=="
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/eslintrc": {
|
"node_modules/@eslint/eslintrc": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.2.tgz",
|
||||||
"integrity": "sha512-lTVWHs7O2hjBFZunXTZYnYqtB9GakA1lnxIf+gKq2nY5gxkkNi/lQvveW6t8gFdOHTg6nG50Xs95PrLqVpcaLg==",
|
"integrity": "sha512-lTVWHs7O2hjBFZunXTZYnYqtB9GakA1lnxIf+gKq2nY5gxkkNi/lQvveW6t8gFdOHTg6nG50Xs95PrLqVpcaLg==",
|
||||||
|
=======
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-uGo44hIwoLGNyduRpjdEpovcbMdd+Nv7amtmJxnKmI8xj6yd5LncmSwDa5NgX/41lIFJtkjD6YdVfgEzPfJ5UA==",
|
||||||
|
>>>>>>> dev
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^6.12.4",
|
"ajv": "^6.12.4",
|
||||||
"debug": "^4.3.2",
|
"debug": "^4.3.2",
|
||||||
|
<<<<<<< HEAD
|
||||||
"espree": "^9.3.1",
|
"espree": "^9.3.1",
|
||||||
|
=======
|
||||||
|
"espree": "^9.3.2",
|
||||||
|
>>>>>>> dev
|
||||||
"globals": "^13.9.0",
|
"globals": "^13.9.0",
|
||||||
"ignore": "^5.2.0",
|
"ignore": "^5.2.0",
|
||||||
"import-fresh": "^3.2.1",
|
"import-fresh": "^3.2.1",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
|
<<<<<<< HEAD
|
||||||
"minimatch": "^3.0.4",
|
"minimatch": "^3.0.4",
|
||||||
|
=======
|
||||||
|
"minimatch": "^3.1.2",
|
||||||
|
>>>>>>> dev
|
||||||
"strip-json-comments": "^3.1.1"
|
"strip-json-comments": "^3.1.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -2094,9 +2112,15 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@eslint/eslintrc/node_modules/globals": {
|
"node_modules/@eslint/eslintrc/node_modules/globals": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "13.13.0",
|
"version": "13.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz",
|
||||||
"integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==",
|
"integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==",
|
||||||
|
=======
|
||||||
|
"version": "13.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz",
|
||||||
|
"integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==",
|
||||||
|
>>>>>>> dev
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"type-fest": "^0.20.2"
|
"type-fest": "^0.20.2"
|
||||||
@ -4062,6 +4086,19 @@
|
|||||||
"@types/istanbul-lib-report": "*"
|
"@types/istanbul-lib-report": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
"node_modules/@types/jest": {
|
||||||
|
"version": "27.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.1.tgz",
|
||||||
|
"integrity": "sha512-fUy7YRpT+rHXto1YlL+J9rs0uLGyiqVt3ZOTQR+4ROc47yNl8WLdVLgUloBRhOxP1PZvguHl44T3H0wAWxahYQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"jest-matcher-utils": "^27.0.0",
|
||||||
|
"pretty-format": "^27.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
>>>>>>> dev
|
||||||
"node_modules/@types/jquery": {
|
"node_modules/@types/jquery": {
|
||||||
"version": "3.5.14",
|
"version": "3.5.14",
|
||||||
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz",
|
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz",
|
||||||
@ -4230,6 +4267,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "5.21.0",
|
"version": "5.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.21.0.tgz",
|
||||||
"integrity": "sha512-fTU85q8v5ZLpoZEyn/u1S2qrFOhi33Edo2CZ0+q1gDaWWm0JuPh3bgOyU8lM0edIEYgKLDkPFiZX2MOupgjlyg==",
|
"integrity": "sha512-fTU85q8v5ZLpoZEyn/u1S2qrFOhi33Edo2CZ0+q1gDaWWm0JuPh3bgOyU8lM0edIEYgKLDkPFiZX2MOupgjlyg==",
|
||||||
@ -4243,6 +4281,21 @@
|
|||||||
"ignore": "^5.1.8",
|
"ignore": "^5.1.8",
|
||||||
"regexpp": "^3.2.0",
|
"regexpp": "^3.2.0",
|
||||||
"semver": "^7.3.5",
|
"semver": "^7.3.5",
|
||||||
|
=======
|
||||||
|
"version": "5.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.25.0.tgz",
|
||||||
|
"integrity": "sha512-icYrFnUzvm+LhW0QeJNKkezBu6tJs9p/53dpPLFH8zoM9w1tfaKzVurkPotEpAqQ8Vf8uaFyL5jHd0Vs6Z0ZQg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@typescript-eslint/scope-manager": "5.25.0",
|
||||||
|
"@typescript-eslint/type-utils": "5.25.0",
|
||||||
|
"@typescript-eslint/utils": "5.25.0",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"functional-red-black-tree": "^1.0.1",
|
||||||
|
"ignore": "^5.2.0",
|
||||||
|
"regexpp": "^3.2.0",
|
||||||
|
"semver": "^7.3.7",
|
||||||
|
>>>>>>> dev
|
||||||
"tsutils": "^3.21.0"
|
"tsutils": "^3.21.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -4262,10 +4315,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": {
|
"node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": {
|
||||||
"version": "7.3.5",
|
"version": "7.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lru-cache": "^6.0.0"
|
"lru-cache": "^6.0.0"
|
||||||
@ -4278,6 +4348,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "5.21.0",
|
"version": "5.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.21.0.tgz",
|
||||||
"integrity": "sha512-8RUwTO77hstXUr3pZoWZbRQUxXcSXafZ8/5gpnQCfXvgmP9gpNlRGlWzvfbEQ14TLjmtU8eGnONkff8U2ui2Eg==",
|
"integrity": "sha512-8RUwTO77hstXUr3pZoWZbRQUxXcSXafZ8/5gpnQCfXvgmP9gpNlRGlWzvfbEQ14TLjmtU8eGnONkff8U2ui2Eg==",
|
||||||
@ -4287,6 +4358,17 @@
|
|||||||
"@typescript-eslint/types": "5.21.0",
|
"@typescript-eslint/types": "5.21.0",
|
||||||
"@typescript-eslint/typescript-estree": "5.21.0",
|
"@typescript-eslint/typescript-estree": "5.21.0",
|
||||||
"debug": "^4.3.2"
|
"debug": "^4.3.2"
|
||||||
|
=======
|
||||||
|
"version": "5.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.25.0.tgz",
|
||||||
|
"integrity": "sha512-r3hwrOWYbNKP1nTcIw/aZoH+8bBnh/Lh1iDHoFpyG4DnCpvEdctrSl6LOo19fZbzypjQMHdajolxs6VpYoChgA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@typescript-eslint/scope-manager": "5.25.0",
|
||||||
|
"@typescript-eslint/types": "5.25.0",
|
||||||
|
"@typescript-eslint/typescript-estree": "5.25.0",
|
||||||
|
"debug": "^4.3.4"
|
||||||
|
>>>>>>> dev
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
@ -4304,6 +4386,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "5.21.0",
|
"version": "5.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.21.0.tgz",
|
||||||
@ -4314,6 +4397,34 @@
|
|||||||
"@typescript-eslint/visitor-keys": "5.21.0"
|
"@typescript-eslint/visitor-keys": "5.21.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
=======
|
||||||
|
"node_modules/@typescript-eslint/parser/node_modules/debug": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
|
"version": "5.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.25.0.tgz",
|
||||||
|
"integrity": "sha512-p4SKTFWj+2VpreUZ5xMQsBMDdQ9XdRvODKXN4EksyBjFp2YvQdLkyHqOffakYZPuWJUDNu3jVXtHALDyTv3cww==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@typescript-eslint/types": "5.25.0",
|
||||||
|
"@typescript-eslint/visitor-keys": "5.25.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
@ -4321,6 +4432,26 @@
|
|||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
|
"version": "5.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.25.0.tgz",
|
||||||
|
"integrity": "sha512-B6nb3GK3Gv1Rsb2pqalebe/RyQoyG/WDy9yhj8EE0Ikds4Xa8RR28nHz+wlt4tMZk5bnAr0f3oC8TuDAd5CPrw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@typescript-eslint/utils": "5.25.0",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"tsutils": "^3.21.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
>>>>>>> dev
|
||||||
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
|
<<<<<<< HEAD
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@typescript-eslint/type-utils": {
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
"version": "5.21.0",
|
"version": "5.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.21.0.tgz",
|
||||||
@ -4343,14 +4474,45 @@
|
|||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"typescript": {
|
"typescript": {
|
||||||
|
=======
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"eslint": "*"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"typescript": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@typescript-eslint/type-utils/node_modules/debug": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
>>>>>>> dev
|
||||||
"optional": true
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "5.21.0",
|
"version": "5.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.21.0.tgz",
|
||||||
"integrity": "sha512-XnOOo5Wc2cBlq8Lh5WNvAgHzpjnEzxn4CJBwGkcau7b/tZ556qrWXQz4DJyChYg8JZAD06kczrdgFPpEQZfDsA==",
|
"integrity": "sha512-XnOOo5Wc2cBlq8Lh5WNvAgHzpjnEzxn4CJBwGkcau7b/tZ556qrWXQz4DJyChYg8JZAD06kczrdgFPpEQZfDsA==",
|
||||||
|
=======
|
||||||
|
"version": "5.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.25.0.tgz",
|
||||||
|
"integrity": "sha512-7fWqfxr0KNHj75PFqlGX24gWjdV/FDBABXL5dyvBOWHpACGyveok8Uj4ipPX/1fGU63fBkzSIycEje4XsOxUFA==",
|
||||||
|
>>>>>>> dev
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
@ -4361,6 +4523,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "5.21.0",
|
"version": "5.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.21.0.tgz",
|
||||||
"integrity": "sha512-Y8Y2T2FNvm08qlcoSMoNchh9y2Uj3QmjtwNMdRQkcFG7Muz//wfJBGBxh8R7HAGQFpgYpdHqUpEoPQk+q9Kjfg==",
|
"integrity": "sha512-Y8Y2T2FNvm08qlcoSMoNchh9y2Uj3QmjtwNMdRQkcFG7Muz//wfJBGBxh8R7HAGQFpgYpdHqUpEoPQk+q9Kjfg==",
|
||||||
@ -4372,6 +4535,19 @@
|
|||||||
"globby": "^11.0.4",
|
"globby": "^11.0.4",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
"semver": "^7.3.5",
|
"semver": "^7.3.5",
|
||||||
|
=======
|
||||||
|
"version": "5.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.25.0.tgz",
|
||||||
|
"integrity": "sha512-MrPODKDych/oWs/71LCnuO7NyR681HuBly2uLnX3r5i4ME7q/yBqC4hW33kmxtuauLTM0OuBOhhkFaxCCOjEEw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@typescript-eslint/types": "5.25.0",
|
||||||
|
"@typescript-eslint/visitor-keys": "5.25.0",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"globby": "^11.1.0",
|
||||||
|
"is-glob": "^4.0.3",
|
||||||
|
"semver": "^7.3.7",
|
||||||
|
>>>>>>> dev
|
||||||
"tsutils": "^3.21.0"
|
"tsutils": "^3.21.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -4387,6 +4563,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@typescript-eslint/typescript-estree/node_modules/debug": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
|
"node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
|
||||||
"version": "7.3.7",
|
"version": "7.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||||
@ -4403,6 +4596,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/utils": {
|
"node_modules/@typescript-eslint/utils": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "5.21.0",
|
"version": "5.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.21.0.tgz",
|
||||||
"integrity": "sha512-q/emogbND9wry7zxy7VYri+7ydawo2HDZhRZ5k6yggIvXa7PvBbAAZ4PFH/oZLem72ezC4Pr63rJvDK/sTlL8Q==",
|
"integrity": "sha512-q/emogbND9wry7zxy7VYri+7ydawo2HDZhRZ5k6yggIvXa7PvBbAAZ4PFH/oZLem72ezC4Pr63rJvDK/sTlL8Q==",
|
||||||
@ -4412,6 +4606,17 @@
|
|||||||
"@typescript-eslint/scope-manager": "5.21.0",
|
"@typescript-eslint/scope-manager": "5.21.0",
|
||||||
"@typescript-eslint/types": "5.21.0",
|
"@typescript-eslint/types": "5.21.0",
|
||||||
"@typescript-eslint/typescript-estree": "5.21.0",
|
"@typescript-eslint/typescript-estree": "5.21.0",
|
||||||
|
=======
|
||||||
|
"version": "5.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.25.0.tgz",
|
||||||
|
"integrity": "sha512-qNC9bhnz/n9Kba3yI6HQgQdBLuxDoMgdjzdhSInZh6NaDnFpTUlwNGxplUFWfY260Ya0TRPvkg9dd57qxrJI9g==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/json-schema": "^7.0.9",
|
||||||
|
"@typescript-eslint/scope-manager": "5.25.0",
|
||||||
|
"@typescript-eslint/types": "5.25.0",
|
||||||
|
"@typescript-eslint/typescript-estree": "5.25.0",
|
||||||
|
>>>>>>> dev
|
||||||
"eslint-scope": "^5.1.1",
|
"eslint-scope": "^5.1.1",
|
||||||
"eslint-utils": "^3.0.0"
|
"eslint-utils": "^3.0.0"
|
||||||
},
|
},
|
||||||
@ -4427,6 +4632,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "5.21.0",
|
"version": "5.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.21.0.tgz",
|
||||||
"integrity": "sha512-SX8jNN+iHqAF0riZQMkm7e8+POXa/fXw5cxL+gjpyP+FI+JVNhii53EmQgDAfDcBpFekYSlO0fGytMQwRiMQCA==",
|
"integrity": "sha512-SX8jNN+iHqAF0riZQMkm7e8+POXa/fXw5cxL+gjpyP+FI+JVNhii53EmQgDAfDcBpFekYSlO0fGytMQwRiMQCA==",
|
||||||
@ -4434,6 +4640,15 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "5.21.0",
|
"@typescript-eslint/types": "5.21.0",
|
||||||
"eslint-visitor-keys": "^3.0.0"
|
"eslint-visitor-keys": "^3.0.0"
|
||||||
|
=======
|
||||||
|
"version": "5.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.25.0.tgz",
|
||||||
|
"integrity": "sha512-yd26vFgMsC4h2dgX4+LR+GeicSKIfUvZREFLf3DDjZPtqgLx5AJZr6TetMNwFP9hcKreTTeztQYBTNbNoOycwA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@typescript-eslint/types": "5.25.0",
|
||||||
|
"eslint-visitor-keys": "^3.3.0"
|
||||||
|
>>>>>>> dev
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
@ -4650,9 +4865,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "8.7.0",
|
"version": "8.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
|
||||||
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
|
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==",
|
||||||
|
=======
|
||||||
|
"version": "8.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
|
||||||
|
"integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==",
|
||||||
|
>>>>>>> dev
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
},
|
},
|
||||||
@ -8244,12 +8465,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eslint": {
|
"node_modules/eslint": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "8.14.0",
|
"version": "8.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.14.0.tgz",
|
||||||
"integrity": "sha512-3/CE4aJX7LNEiE3i6FeodHmI/38GZtWCsAtsymScmzYapx8q1nVVb+eLcLSzATmCPXw5pT4TqVs1E0OmxAd9tw==",
|
"integrity": "sha512-3/CE4aJX7LNEiE3i6FeodHmI/38GZtWCsAtsymScmzYapx8q1nVVb+eLcLSzATmCPXw5pT4TqVs1E0OmxAd9tw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint/eslintrc": "^1.2.2",
|
"@eslint/eslintrc": "^1.2.2",
|
||||||
|
=======
|
||||||
|
"version": "8.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.15.0.tgz",
|
||||||
|
"integrity": "sha512-GG5USZ1jhCu8HJkzGgeK8/+RGnHaNYZGrGDzUtigK3BsGESW/rs2az23XqE0WVwDxy1VRvvjSSGu5nB0Bu+6SA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@eslint/eslintrc": "^1.2.3",
|
||||||
|
>>>>>>> dev
|
||||||
"@humanwhocodes/config-array": "^0.9.2",
|
"@humanwhocodes/config-array": "^0.9.2",
|
||||||
"ajv": "^6.10.0",
|
"ajv": "^6.10.0",
|
||||||
"chalk": "^4.0.0",
|
"chalk": "^4.0.0",
|
||||||
@ -8260,7 +8490,11 @@
|
|||||||
"eslint-scope": "^7.1.1",
|
"eslint-scope": "^7.1.1",
|
||||||
"eslint-utils": "^3.0.0",
|
"eslint-utils": "^3.0.0",
|
||||||
"eslint-visitor-keys": "^3.3.0",
|
"eslint-visitor-keys": "^3.3.0",
|
||||||
|
<<<<<<< HEAD
|
||||||
"espree": "^9.3.1",
|
"espree": "^9.3.1",
|
||||||
|
=======
|
||||||
|
"espree": "^9.3.2",
|
||||||
|
>>>>>>> dev
|
||||||
"esquery": "^1.4.0",
|
"esquery": "^1.4.0",
|
||||||
"esutils": "^2.0.2",
|
"esutils": "^2.0.2",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
@ -8276,7 +8510,7 @@
|
|||||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||||
"levn": "^0.4.1",
|
"levn": "^0.4.1",
|
||||||
"lodash.merge": "^4.6.2",
|
"lodash.merge": "^4.6.2",
|
||||||
"minimatch": "^3.0.4",
|
"minimatch": "^3.1.2",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
"optionator": "^0.9.1",
|
"optionator": "^0.9.1",
|
||||||
"regexpp": "^3.2.0",
|
"regexpp": "^3.2.0",
|
||||||
@ -8519,6 +8753,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/espree": {
|
"node_modules/espree": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "9.3.1",
|
"version": "9.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz",
|
||||||
"integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==",
|
"integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==",
|
||||||
@ -8526,6 +8761,15 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"acorn": "^8.7.0",
|
"acorn": "^8.7.0",
|
||||||
"acorn-jsx": "^5.3.1",
|
"acorn-jsx": "^5.3.1",
|
||||||
|
=======
|
||||||
|
"version": "9.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz",
|
||||||
|
"integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"acorn": "^8.7.1",
|
||||||
|
"acorn-jsx": "^5.3.2",
|
||||||
|
>>>>>>> dev
|
||||||
"eslint-visitor-keys": "^3.3.0"
|
"eslint-visitor-keys": "^3.3.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -15103,9 +15347,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "3.0.4",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
@ -23764,19 +24008,33 @@
|
|||||||
"integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA=="
|
"integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA=="
|
||||||
},
|
},
|
||||||
"@eslint/eslintrc": {
|
"@eslint/eslintrc": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.2.tgz",
|
||||||
"integrity": "sha512-lTVWHs7O2hjBFZunXTZYnYqtB9GakA1lnxIf+gKq2nY5gxkkNi/lQvveW6t8gFdOHTg6nG50Xs95PrLqVpcaLg==",
|
"integrity": "sha512-lTVWHs7O2hjBFZunXTZYnYqtB9GakA1lnxIf+gKq2nY5gxkkNi/lQvveW6t8gFdOHTg6nG50Xs95PrLqVpcaLg==",
|
||||||
|
=======
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-uGo44hIwoLGNyduRpjdEpovcbMdd+Nv7amtmJxnKmI8xj6yd5LncmSwDa5NgX/41lIFJtkjD6YdVfgEzPfJ5UA==",
|
||||||
|
>>>>>>> dev
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ajv": "^6.12.4",
|
"ajv": "^6.12.4",
|
||||||
"debug": "^4.3.2",
|
"debug": "^4.3.2",
|
||||||
|
<<<<<<< HEAD
|
||||||
"espree": "^9.3.1",
|
"espree": "^9.3.1",
|
||||||
|
=======
|
||||||
|
"espree": "^9.3.2",
|
||||||
|
>>>>>>> dev
|
||||||
"globals": "^13.9.0",
|
"globals": "^13.9.0",
|
||||||
"ignore": "^5.2.0",
|
"ignore": "^5.2.0",
|
||||||
"import-fresh": "^3.2.1",
|
"import-fresh": "^3.2.1",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
|
<<<<<<< HEAD
|
||||||
"minimatch": "^3.0.4",
|
"minimatch": "^3.0.4",
|
||||||
|
=======
|
||||||
|
"minimatch": "^3.1.2",
|
||||||
|
>>>>>>> dev
|
||||||
"strip-json-comments": "^3.1.1"
|
"strip-json-comments": "^3.1.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -23787,9 +24045,15 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"globals": {
|
"globals": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "13.13.0",
|
"version": "13.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz",
|
||||||
"integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==",
|
"integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==",
|
||||||
|
=======
|
||||||
|
"version": "13.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz",
|
||||||
|
"integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==",
|
||||||
|
>>>>>>> dev
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"type-fest": "^0.20.2"
|
"type-fest": "^0.20.2"
|
||||||
@ -25205,6 +25469,19 @@
|
|||||||
"@types/istanbul-lib-report": "*"
|
"@types/istanbul-lib-report": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
"@types/jest": {
|
||||||
|
"version": "27.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.1.tgz",
|
||||||
|
"integrity": "sha512-fUy7YRpT+rHXto1YlL+J9rs0uLGyiqVt3ZOTQR+4ROc47yNl8WLdVLgUloBRhOxP1PZvguHl44T3H0wAWxahYQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"jest-matcher-utils": "^27.0.0",
|
||||||
|
"pretty-format": "^27.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
>>>>>>> dev
|
||||||
"@types/jquery": {
|
"@types/jquery": {
|
||||||
"version": "3.5.14",
|
"version": "3.5.14",
|
||||||
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz",
|
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz",
|
||||||
@ -25373,6 +25650,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/eslint-plugin": {
|
"@typescript-eslint/eslint-plugin": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "5.21.0",
|
"version": "5.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.21.0.tgz",
|
||||||
"integrity": "sha512-fTU85q8v5ZLpoZEyn/u1S2qrFOhi33Edo2CZ0+q1gDaWWm0JuPh3bgOyU8lM0edIEYgKLDkPFiZX2MOupgjlyg==",
|
"integrity": "sha512-fTU85q8v5ZLpoZEyn/u1S2qrFOhi33Edo2CZ0+q1gDaWWm0JuPh3bgOyU8lM0edIEYgKLDkPFiZX2MOupgjlyg==",
|
||||||
@ -25386,13 +25664,37 @@
|
|||||||
"ignore": "^5.1.8",
|
"ignore": "^5.1.8",
|
||||||
"regexpp": "^3.2.0",
|
"regexpp": "^3.2.0",
|
||||||
"semver": "^7.3.5",
|
"semver": "^7.3.5",
|
||||||
|
=======
|
||||||
|
"version": "5.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.25.0.tgz",
|
||||||
|
"integrity": "sha512-icYrFnUzvm+LhW0QeJNKkezBu6tJs9p/53dpPLFH8zoM9w1tfaKzVurkPotEpAqQ8Vf8uaFyL5jHd0Vs6Z0ZQg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@typescript-eslint/scope-manager": "5.25.0",
|
||||||
|
"@typescript-eslint/type-utils": "5.25.0",
|
||||||
|
"@typescript-eslint/utils": "5.25.0",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"functional-red-black-tree": "^1.0.1",
|
||||||
|
"ignore": "^5.2.0",
|
||||||
|
"regexpp": "^3.2.0",
|
||||||
|
"semver": "^7.3.7",
|
||||||
|
>>>>>>> dev
|
||||||
"tsutils": "^3.21.0"
|
"tsutils": "^3.21.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "7.3.5",
|
"version": "7.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||||
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
|
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"lru-cache": "^6.0.0"
|
"lru-cache": "^6.0.0"
|
||||||
@ -25401,6 +25703,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/parser": {
|
"@typescript-eslint/parser": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "5.21.0",
|
"version": "5.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.21.0.tgz",
|
||||||
"integrity": "sha512-8RUwTO77hstXUr3pZoWZbRQUxXcSXafZ8/5gpnQCfXvgmP9gpNlRGlWzvfbEQ14TLjmtU8eGnONkff8U2ui2Eg==",
|
"integrity": "sha512-8RUwTO77hstXUr3pZoWZbRQUxXcSXafZ8/5gpnQCfXvgmP9gpNlRGlWzvfbEQ14TLjmtU8eGnONkff8U2ui2Eg==",
|
||||||
@ -25451,9 +25754,92 @@
|
|||||||
"globby": "^11.0.4",
|
"globby": "^11.0.4",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
"semver": "^7.3.5",
|
"semver": "^7.3.5",
|
||||||
|
=======
|
||||||
|
"version": "5.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.25.0.tgz",
|
||||||
|
"integrity": "sha512-r3hwrOWYbNKP1nTcIw/aZoH+8bBnh/Lh1iDHoFpyG4DnCpvEdctrSl6LOo19fZbzypjQMHdajolxs6VpYoChgA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@typescript-eslint/scope-manager": "5.25.0",
|
||||||
|
"@typescript-eslint/types": "5.25.0",
|
||||||
|
"@typescript-eslint/typescript-estree": "5.25.0",
|
||||||
|
"debug": "^4.3.4"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@typescript-eslint/scope-manager": {
|
||||||
|
"version": "5.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.25.0.tgz",
|
||||||
|
"integrity": "sha512-p4SKTFWj+2VpreUZ5xMQsBMDdQ9XdRvODKXN4EksyBjFp2YvQdLkyHqOffakYZPuWJUDNu3jVXtHALDyTv3cww==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@typescript-eslint/types": "5.25.0",
|
||||||
|
"@typescript-eslint/visitor-keys": "5.25.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@typescript-eslint/type-utils": {
|
||||||
|
"version": "5.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.25.0.tgz",
|
||||||
|
"integrity": "sha512-B6nb3GK3Gv1Rsb2pqalebe/RyQoyG/WDy9yhj8EE0Ikds4Xa8RR28nHz+wlt4tMZk5bnAr0f3oC8TuDAd5CPrw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@typescript-eslint/utils": "5.25.0",
|
||||||
|
"debug": "^4.3.4",
|
||||||
"tsutils": "^3.21.0"
|
"tsutils": "^3.21.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@typescript-eslint/types": {
|
||||||
|
"version": "5.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.25.0.tgz",
|
||||||
|
"integrity": "sha512-7fWqfxr0KNHj75PFqlGX24gWjdV/FDBABXL5dyvBOWHpACGyveok8Uj4ipPX/1fGU63fBkzSIycEje4XsOxUFA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@typescript-eslint/typescript-estree": {
|
||||||
|
"version": "5.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.25.0.tgz",
|
||||||
|
"integrity": "sha512-MrPODKDych/oWs/71LCnuO7NyR681HuBly2uLnX3r5i4ME7q/yBqC4hW33kmxtuauLTM0OuBOhhkFaxCCOjEEw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@typescript-eslint/types": "5.25.0",
|
||||||
|
"@typescript-eslint/visitor-keys": "5.25.0",
|
||||||
|
"debug": "^4.3.4",
|
||||||
|
"globby": "^11.1.0",
|
||||||
|
"is-glob": "^4.0.3",
|
||||||
|
"semver": "^7.3.7",
|
||||||
|
>>>>>>> dev
|
||||||
|
"tsutils": "^3.21.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "7.3.7",
|
"version": "7.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||||
@ -25466,6 +25852,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/utils": {
|
"@typescript-eslint/utils": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "5.21.0",
|
"version": "5.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.21.0.tgz",
|
||||||
"integrity": "sha512-q/emogbND9wry7zxy7VYri+7ydawo2HDZhRZ5k6yggIvXa7PvBbAAZ4PFH/oZLem72ezC4Pr63rJvDK/sTlL8Q==",
|
"integrity": "sha512-q/emogbND9wry7zxy7VYri+7ydawo2HDZhRZ5k6yggIvXa7PvBbAAZ4PFH/oZLem72ezC4Pr63rJvDK/sTlL8Q==",
|
||||||
@ -25475,11 +25862,23 @@
|
|||||||
"@typescript-eslint/scope-manager": "5.21.0",
|
"@typescript-eslint/scope-manager": "5.21.0",
|
||||||
"@typescript-eslint/types": "5.21.0",
|
"@typescript-eslint/types": "5.21.0",
|
||||||
"@typescript-eslint/typescript-estree": "5.21.0",
|
"@typescript-eslint/typescript-estree": "5.21.0",
|
||||||
|
=======
|
||||||
|
"version": "5.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.25.0.tgz",
|
||||||
|
"integrity": "sha512-qNC9bhnz/n9Kba3yI6HQgQdBLuxDoMgdjzdhSInZh6NaDnFpTUlwNGxplUFWfY260Ya0TRPvkg9dd57qxrJI9g==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/json-schema": "^7.0.9",
|
||||||
|
"@typescript-eslint/scope-manager": "5.25.0",
|
||||||
|
"@typescript-eslint/types": "5.25.0",
|
||||||
|
"@typescript-eslint/typescript-estree": "5.25.0",
|
||||||
|
>>>>>>> dev
|
||||||
"eslint-scope": "^5.1.1",
|
"eslint-scope": "^5.1.1",
|
||||||
"eslint-utils": "^3.0.0"
|
"eslint-utils": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/visitor-keys": {
|
"@typescript-eslint/visitor-keys": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "5.21.0",
|
"version": "5.21.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.21.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.21.0.tgz",
|
||||||
"integrity": "sha512-SX8jNN+iHqAF0riZQMkm7e8+POXa/fXw5cxL+gjpyP+FI+JVNhii53EmQgDAfDcBpFekYSlO0fGytMQwRiMQCA==",
|
"integrity": "sha512-SX8jNN+iHqAF0riZQMkm7e8+POXa/fXw5cxL+gjpyP+FI+JVNhii53EmQgDAfDcBpFekYSlO0fGytMQwRiMQCA==",
|
||||||
@ -25487,6 +25886,15 @@
|
|||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/types": "5.21.0",
|
"@typescript-eslint/types": "5.21.0",
|
||||||
"eslint-visitor-keys": "^3.0.0"
|
"eslint-visitor-keys": "^3.0.0"
|
||||||
|
=======
|
||||||
|
"version": "5.25.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.25.0.tgz",
|
||||||
|
"integrity": "sha512-yd26vFgMsC4h2dgX4+LR+GeicSKIfUvZREFLf3DDjZPtqgLx5AJZr6TetMNwFP9hcKreTTeztQYBTNbNoOycwA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@typescript-eslint/types": "5.25.0",
|
||||||
|
"eslint-visitor-keys": "^3.3.0"
|
||||||
|
>>>>>>> dev
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@webassemblyjs/ast": {
|
"@webassemblyjs/ast": {
|
||||||
@ -25693,9 +26101,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"acorn": {
|
"acorn": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "8.7.0",
|
"version": "8.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz",
|
||||||
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ=="
|
"integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ=="
|
||||||
|
=======
|
||||||
|
"version": "8.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz",
|
||||||
|
"integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A=="
|
||||||
|
>>>>>>> dev
|
||||||
},
|
},
|
||||||
"acorn-globals": {
|
"acorn-globals": {
|
||||||
"version": "4.3.4",
|
"version": "4.3.4",
|
||||||
@ -28606,12 +29020,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eslint": {
|
"eslint": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "8.14.0",
|
"version": "8.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.14.0.tgz",
|
||||||
"integrity": "sha512-3/CE4aJX7LNEiE3i6FeodHmI/38GZtWCsAtsymScmzYapx8q1nVVb+eLcLSzATmCPXw5pT4TqVs1E0OmxAd9tw==",
|
"integrity": "sha512-3/CE4aJX7LNEiE3i6FeodHmI/38GZtWCsAtsymScmzYapx8q1nVVb+eLcLSzATmCPXw5pT4TqVs1E0OmxAd9tw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@eslint/eslintrc": "^1.2.2",
|
"@eslint/eslintrc": "^1.2.2",
|
||||||
|
=======
|
||||||
|
"version": "8.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.15.0.tgz",
|
||||||
|
"integrity": "sha512-GG5USZ1jhCu8HJkzGgeK8/+RGnHaNYZGrGDzUtigK3BsGESW/rs2az23XqE0WVwDxy1VRvvjSSGu5nB0Bu+6SA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@eslint/eslintrc": "^1.2.3",
|
||||||
|
>>>>>>> dev
|
||||||
"@humanwhocodes/config-array": "^0.9.2",
|
"@humanwhocodes/config-array": "^0.9.2",
|
||||||
"ajv": "^6.10.0",
|
"ajv": "^6.10.0",
|
||||||
"chalk": "^4.0.0",
|
"chalk": "^4.0.0",
|
||||||
@ -28622,7 +29045,11 @@
|
|||||||
"eslint-scope": "^7.1.1",
|
"eslint-scope": "^7.1.1",
|
||||||
"eslint-utils": "^3.0.0",
|
"eslint-utils": "^3.0.0",
|
||||||
"eslint-visitor-keys": "^3.3.0",
|
"eslint-visitor-keys": "^3.3.0",
|
||||||
|
<<<<<<< HEAD
|
||||||
"espree": "^9.3.1",
|
"espree": "^9.3.1",
|
||||||
|
=======
|
||||||
|
"espree": "^9.3.2",
|
||||||
|
>>>>>>> dev
|
||||||
"esquery": "^1.4.0",
|
"esquery": "^1.4.0",
|
||||||
"esutils": "^2.0.2",
|
"esutils": "^2.0.2",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
@ -28638,7 +29065,7 @@
|
|||||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||||
"levn": "^0.4.1",
|
"levn": "^0.4.1",
|
||||||
"lodash.merge": "^4.6.2",
|
"lodash.merge": "^4.6.2",
|
||||||
"minimatch": "^3.0.4",
|
"minimatch": "^3.1.2",
|
||||||
"natural-compare": "^1.4.0",
|
"natural-compare": "^1.4.0",
|
||||||
"optionator": "^0.9.1",
|
"optionator": "^0.9.1",
|
||||||
"regexpp": "^3.2.0",
|
"regexpp": "^3.2.0",
|
||||||
@ -28807,6 +29234,7 @@
|
|||||||
"integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA=="
|
"integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA=="
|
||||||
},
|
},
|
||||||
"espree": {
|
"espree": {
|
||||||
|
<<<<<<< HEAD
|
||||||
"version": "9.3.1",
|
"version": "9.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz",
|
||||||
"integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==",
|
"integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==",
|
||||||
@ -28814,6 +29242,15 @@
|
|||||||
"requires": {
|
"requires": {
|
||||||
"acorn": "^8.7.0",
|
"acorn": "^8.7.0",
|
||||||
"acorn-jsx": "^5.3.1",
|
"acorn-jsx": "^5.3.1",
|
||||||
|
=======
|
||||||
|
"version": "9.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz",
|
||||||
|
"integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"acorn": "^8.7.1",
|
||||||
|
"acorn-jsx": "^5.3.2",
|
||||||
|
>>>>>>> dev
|
||||||
"eslint-visitor-keys": "^3.3.0"
|
"eslint-visitor-keys": "^3.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -33925,9 +34362,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"minimatch": {
|
"minimatch": {
|
||||||
"version": "3.0.4",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "bitburner",
|
"name": "bitburner",
|
||||||
"license": "SEE LICENSE IN license.txt",
|
"license": "SEE LICENSE IN license.txt",
|
||||||
"version": "1.6.4",
|
"version": "1.7.0",
|
||||||
"main": "electron-main.js",
|
"main": "electron-main.js",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Daniel Xie & Olivier Gagnon"
|
"name": "Daniel Xie & Olivier Gagnon"
|
||||||
@ -57,6 +57,7 @@
|
|||||||
"@types/bcryptjs": "^2.4.2",
|
"@types/bcryptjs": "^2.4.2",
|
||||||
"@types/escodegen": "^0.0.7",
|
"@types/escodegen": "^0.0.7",
|
||||||
"@types/file-saver": "^2.0.3",
|
"@types/file-saver": "^2.0.3",
|
||||||
|
"@types/jest": "^27.4.1",
|
||||||
"@types/jquery": "^3.5.14",
|
"@types/jquery": "^3.5.14",
|
||||||
"@types/lodash": "^4.14.168",
|
"@types/lodash": "^4.14.168",
|
||||||
"@types/numeral": "^2.0.2",
|
"@types/numeral": "^2.0.2",
|
||||||
|
@ -631,6 +631,7 @@ export class Augmentation {
|
|||||||
augmentationReference.baseCost *
|
augmentationReference.baseCost *
|
||||||
getGenericAugmentationPriceMultiplier() *
|
getGenericAugmentationPriceMultiplier() *
|
||||||
BitNodeMultipliers.AugmentationMoneyCost;
|
BitNodeMultipliers.AugmentationMoneyCost;
|
||||||
|
repCost = augmentationReference.baseRepRequirement * BitNodeMultipliers.AugmentationRepCost;
|
||||||
}
|
}
|
||||||
return { moneyCost, repCost };
|
return { moneyCost, repCost };
|
||||||
}
|
}
|
||||||
|
@ -45,13 +45,13 @@ function BitNodeModifiedStats(props: IBitNodeModifiedStatsProps): React.ReactEle
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
type MultiplierListItemData = [
|
interface MultiplierListItemData {
|
||||||
multiplier: string,
|
mult: string;
|
||||||
currentValue: number,
|
current: number;
|
||||||
augmentedValue: number,
|
augmented: number;
|
||||||
bitNodeMultiplier: number,
|
bnMult?: number;
|
||||||
color: string,
|
color?: string;
|
||||||
];
|
}
|
||||||
|
|
||||||
interface IMultiplierListProps {
|
interface IMultiplierListProps {
|
||||||
rows: MultiplierListItemData[];
|
rows: MultiplierListItemData[];
|
||||||
@ -60,23 +60,23 @@ interface IMultiplierListProps {
|
|||||||
function MultiplierList(props: IMultiplierListProps): React.ReactElement {
|
function MultiplierList(props: IMultiplierListProps): React.ReactElement {
|
||||||
const listItems = props.rows
|
const listItems = props.rows
|
||||||
.map((data) => {
|
.map((data) => {
|
||||||
const [multiplier, currentValue, augmentedValue, bitNodeMultiplier, color] = data;
|
const { mult, current, augmented, bnMult = 1, color = Settings.theme.primary } = data;
|
||||||
|
|
||||||
if (!isNaN(augmentedValue)) {
|
if (!isNaN(augmented)) {
|
||||||
return (
|
return (
|
||||||
<ListItem key={multiplier} disableGutters sx={{ py: 0 }}>
|
<ListItem key={mult} disableGutters sx={{ py: 0 }}>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
sx={{ my: 0.1 }}
|
sx={{ my: 0.1 }}
|
||||||
primary={
|
primary={
|
||||||
<Typography color={color}>
|
<Typography color={color}>
|
||||||
<b>{multiplier}</b>
|
<b>{mult}</b>
|
||||||
</Typography>
|
</Typography>
|
||||||
}
|
}
|
||||||
secondary={
|
secondary={
|
||||||
<span style={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
|
<span style={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
|
||||||
<BitNodeModifiedStats base={currentValue} mult={bitNodeMultiplier} color={color} />
|
<BitNodeModifiedStats base={current} mult={bnMult} color={color} />
|
||||||
<DoubleArrow fontSize="small" color="success" sx={{ mb: 0.5, mx: 1 }} />
|
<DoubleArrow fontSize="small" color="success" sx={{ mb: 0.5, mx: 1 }} />
|
||||||
<BitNodeModifiedStats base={augmentedValue} mult={bitNodeMultiplier} color={Settings.theme.success} />
|
<BitNodeModifiedStats base={augmented} mult={bnMult} color={Settings.theme.success} />
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
disableTypography
|
disableTypography
|
||||||
@ -94,177 +94,205 @@ function MultiplierList(props: IMultiplierListProps): React.ReactElement {
|
|||||||
export function PlayerMultipliers(): React.ReactElement {
|
export function PlayerMultipliers(): React.ReactElement {
|
||||||
const mults = calculateAugmentedStats();
|
const mults = calculateAugmentedStats();
|
||||||
|
|
||||||
// Column data is a bit janky, so it's set up here to allow for
|
|
||||||
// easier logic in setting up the layout
|
|
||||||
const leftColData: MultiplierListItemData[] = [
|
const leftColData: MultiplierListItemData[] = [
|
||||||
...[
|
...[
|
||||||
["Hacking Chance ", Player.hacking_chance_mult, Player.hacking_chance_mult * mults.hacking_chance_mult, 1],
|
{
|
||||||
["Hacking Speed ", Player.hacking_speed_mult, Player.hacking_speed_mult * mults.hacking_speed_mult, 1],
|
mult: "Hacking Chance",
|
||||||
["Hacking Money ", Player.hacking_money_mult, Player.hacking_money_mult * mults.hacking_money_mult, 1],
|
current: Player.hacking_chance_mult,
|
||||||
["Hacking Growth ", Player.hacking_grow_mult, Player.hacking_grow_mult * mults.hacking_grow_mult, 1],
|
augmented: Player.hacking_chance_mult * mults.hacking_chance_mult,
|
||||||
[
|
},
|
||||||
"Hacking Level ",
|
{
|
||||||
Player.hacking_mult,
|
mult: "Hacking Speed",
|
||||||
Player.hacking_mult * mults.hacking_mult,
|
current: Player.hacking_speed_mult,
|
||||||
BitNodeMultipliers.HackingLevelMultiplier,
|
augmented: Player.hacking_speed_mult * mults.hacking_speed_mult,
|
||||||
],
|
},
|
||||||
[
|
{
|
||||||
"Hacking Experience ",
|
mult: "Hacking Money",
|
||||||
Player.hacking_exp_mult,
|
current: Player.hacking_money_mult,
|
||||||
Player.hacking_exp_mult * mults.hacking_exp_mult,
|
augmented: Player.hacking_money_mult * mults.hacking_money_mult,
|
||||||
BitNodeMultipliers.HackExpGain,
|
bnMult: BitNodeMultipliers.ScriptHackMoney,
|
||||||
],
|
},
|
||||||
].map((data): MultiplierListItemData => (data as any).concat([Settings.theme.hack])),
|
{
|
||||||
|
mult: "Hacking Growth",
|
||||||
|
current: Player.hacking_grow_mult,
|
||||||
|
augmented: Player.hacking_grow_mult * mults.hacking_grow_mult,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Hacking Level",
|
||||||
|
current: Player.hacking_mult,
|
||||||
|
augmented: Player.hacking_mult * mults.hacking_mult,
|
||||||
|
bnMult: BitNodeMultipliers.HackingLevelMultiplier,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Hacking Experience",
|
||||||
|
current: Player.hacking_exp_mult,
|
||||||
|
augmented: Player.hacking_exp_mult * mults.hacking_exp_mult,
|
||||||
|
bnMult: BitNodeMultipliers.HackExpGain,
|
||||||
|
},
|
||||||
|
].map((data: MultiplierListItemData) =>
|
||||||
|
Object.defineProperty(data, "color", {
|
||||||
|
value: Settings.theme.hack,
|
||||||
|
}),
|
||||||
|
),
|
||||||
...[
|
...[
|
||||||
[
|
{
|
||||||
"Strength Level ",
|
mult: "Strength Level",
|
||||||
Player.strength_mult,
|
current: Player.strength_mult,
|
||||||
Player.strength_mult * mults.strength_mult,
|
augmented: Player.strength_mult * mults.strength_mult,
|
||||||
BitNodeMultipliers.StrengthLevelMultiplier,
|
bnMult: BitNodeMultipliers.StrengthLevelMultiplier,
|
||||||
],
|
},
|
||||||
["Strength Experience ", Player.strength_exp_mult, Player.strength_exp_mult * mults.strength_exp_mult, 1],
|
{
|
||||||
[
|
mult: "Strength Experience",
|
||||||
"Defense Level ",
|
current: Player.strength_exp_mult,
|
||||||
Player.defense_mult,
|
augmented: Player.strength_exp_mult * mults.strength_exp_mult,
|
||||||
Player.defense_mult * mults.defense_mult,
|
},
|
||||||
BitNodeMultipliers.DefenseLevelMultiplier,
|
{
|
||||||
],
|
mult: "Defense Level",
|
||||||
["Defense Experience ", Player.defense_exp_mult, Player.defense_exp_mult * mults.defense_exp_mult, 1],
|
current: Player.defense_mult,
|
||||||
[
|
augmented: Player.defense_mult * mults.defense_mult,
|
||||||
"Dexterity Level ",
|
bnMult: BitNodeMultipliers.DefenseLevelMultiplier,
|
||||||
Player.dexterity_mult,
|
},
|
||||||
Player.dexterity_mult * mults.dexterity_mult,
|
{
|
||||||
BitNodeMultipliers.DexterityLevelMultiplier,
|
mult: "Defense Experience",
|
||||||
],
|
current: Player.defense_exp_mult,
|
||||||
["Dexterity Experience ", Player.dexterity_exp_mult, Player.dexterity_exp_mult * mults.dexterity_exp_mult, 1],
|
augmented: Player.defense_exp_mult * mults.defense_exp_mult,
|
||||||
[
|
},
|
||||||
"Agility Level ",
|
{
|
||||||
Player.agility_mult,
|
mult: "Dexterity Level",
|
||||||
Player.agility_mult * mults.agility_mult,
|
current: Player.dexterity_mult,
|
||||||
BitNodeMultipliers.AgilityLevelMultiplier,
|
augmented: Player.dexterity_mult * mults.dexterity_mult,
|
||||||
],
|
bnMult: BitNodeMultipliers.DexterityLevelMultiplier,
|
||||||
["Agility Experience ", Player.agility_exp_mult, Player.agility_exp_mult * mults.agility_exp_mult, 1],
|
},
|
||||||
].map((data): MultiplierListItemData => (data as any).concat([Settings.theme.combat])),
|
{
|
||||||
[
|
mult: "Dexterity Experience",
|
||||||
"Charisma Level ",
|
current: Player.dexterity_exp_mult,
|
||||||
Player.charisma_mult,
|
augmented: Player.dexterity_exp_mult * mults.dexterity_exp_mult,
|
||||||
Player.charisma_mult * mults.charisma_mult,
|
},
|
||||||
BitNodeMultipliers.CharismaLevelMultiplier,
|
{
|
||||||
Settings.theme.cha,
|
mult: "Agility Level",
|
||||||
],
|
current: Player.agility_mult,
|
||||||
[
|
augmented: Player.agility_mult * mults.agility_mult,
|
||||||
"Charisma Experience ",
|
bnMult: BitNodeMultipliers.AgilityLevelMultiplier,
|
||||||
Player.charisma_exp_mult,
|
},
|
||||||
Player.charisma_exp_mult * mults.charisma_exp_mult,
|
{
|
||||||
1,
|
mult: "Agility Experience",
|
||||||
Settings.theme.cha,
|
current: Player.agility_exp_mult,
|
||||||
],
|
augmented: Player.agility_exp_mult * mults.agility_exp_mult,
|
||||||
|
},
|
||||||
|
].map((data: MultiplierListItemData) =>
|
||||||
|
Object.defineProperty(data, "color", {
|
||||||
|
value: Settings.theme.combat,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
{
|
||||||
|
mult: "Charisma Level",
|
||||||
|
current: Player.charisma_mult,
|
||||||
|
augmented: Player.charisma_mult * mults.charisma_mult,
|
||||||
|
bnMult: BitNodeMultipliers.CharismaLevelMultiplier,
|
||||||
|
color: Settings.theme.cha,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Charisma Experience",
|
||||||
|
current: Player.charisma_exp_mult,
|
||||||
|
augmented: Player.charisma_exp_mult * mults.charisma_exp_mult,
|
||||||
|
color: Settings.theme.cha,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
const rightColData: MultiplierListItemData[] = [
|
const rightColData: MultiplierListItemData[] = [
|
||||||
...[
|
{
|
||||||
[
|
mult: "Hacknet Node Production",
|
||||||
"Hacknet Node production ",
|
current: Player.hacknet_node_money_mult,
|
||||||
Player.hacknet_node_money_mult,
|
augmented: Player.hacknet_node_money_mult * mults.hacknet_node_money_mult,
|
||||||
Player.hacknet_node_money_mult * mults.hacknet_node_money_mult,
|
bnMult: BitNodeMultipliers.HacknetNodeMoney,
|
||||||
BitNodeMultipliers.HacknetNodeMoney,
|
},
|
||||||
],
|
{
|
||||||
[
|
mult: "Hacknet Node Purchase Cost",
|
||||||
"Hacknet Node purchase cost ",
|
current: Player.hacknet_node_purchase_cost_mult,
|
||||||
Player.hacknet_node_purchase_cost_mult,
|
augmented: Player.hacknet_node_purchase_cost_mult * mults.hacknet_node_purchase_cost_mult,
|
||||||
Player.hacknet_node_purchase_cost_mult * mults.hacknet_node_purchase_cost_mult,
|
},
|
||||||
1,
|
{
|
||||||
],
|
mult: "Hacknet Node RAM Upgrade Cost",
|
||||||
[
|
current: Player.hacknet_node_ram_cost_mult,
|
||||||
"Hacknet Node RAM upgrade cost ",
|
augmented: Player.hacknet_node_ram_cost_mult * mults.hacknet_node_ram_cost_mult,
|
||||||
Player.hacknet_node_ram_cost_mult,
|
},
|
||||||
Player.hacknet_node_ram_cost_mult * mults.hacknet_node_ram_cost_mult,
|
{
|
||||||
1,
|
mult: "Hacknet Node Core Purchase Cost",
|
||||||
],
|
current: Player.hacknet_node_core_cost_mult,
|
||||||
[
|
augmented: Player.hacknet_node_core_cost_mult * mults.hacknet_node_core_cost_mult,
|
||||||
"Hacknet Node Core purchase cost ",
|
},
|
||||||
Player.hacknet_node_core_cost_mult,
|
{
|
||||||
Player.hacknet_node_core_cost_mult * mults.hacknet_node_core_cost_mult,
|
mult: "Hacknet Node Level Upgrade Cost",
|
||||||
1,
|
current: Player.hacknet_node_level_cost_mult,
|
||||||
],
|
augmented: Player.hacknet_node_level_cost_mult * mults.hacknet_node_level_cost_mult,
|
||||||
[
|
},
|
||||||
"Hacknet Node level upgrade cost ",
|
{
|
||||||
Player.hacknet_node_level_cost_mult,
|
mult: "Company Reputation Gain",
|
||||||
Player.hacknet_node_level_cost_mult * mults.hacknet_node_level_cost_mult,
|
current: Player.company_rep_mult,
|
||||||
1,
|
augmented: Player.company_rep_mult * mults.company_rep_mult,
|
||||||
],
|
},
|
||||||
["Company reputation gain ", Player.company_rep_mult, Player.company_rep_mult * mults.company_rep_mult, 1],
|
{
|
||||||
[
|
mult: "Faction Reputation Gain",
|
||||||
"Faction reputation gain ",
|
current: Player.faction_rep_mult,
|
||||||
Player.faction_rep_mult,
|
augmented: Player.faction_rep_mult * mults.faction_rep_mult,
|
||||||
Player.faction_rep_mult * mults.faction_rep_mult,
|
bnMult: BitNodeMultipliers.FactionWorkRepGain,
|
||||||
BitNodeMultipliers.FactionWorkRepGain,
|
},
|
||||||
],
|
{
|
||||||
].map((data): MultiplierListItemData => (data as any).concat([Settings.theme.primary])),
|
mult: "Salary",
|
||||||
[
|
current: Player.work_money_mult,
|
||||||
"Salary ",
|
augmented: Player.work_money_mult * mults.work_money_mult,
|
||||||
Player.work_money_mult,
|
bnMult: BitNodeMultipliers.CompanyWorkMoney,
|
||||||
Player.work_money_mult * mults.work_money_mult,
|
color: Settings.theme.money,
|
||||||
BitNodeMultipliers.CompanyWorkMoney,
|
},
|
||||||
Settings.theme.money,
|
{
|
||||||
],
|
mult: "Crime Success Chance",
|
||||||
[
|
current: Player.crime_success_mult,
|
||||||
"Crime success ",
|
augmented: Player.crime_success_mult * mults.crime_success_mult,
|
||||||
Player.crime_success_mult,
|
color: Settings.theme.combat,
|
||||||
Player.crime_success_mult * mults.crime_success_mult,
|
},
|
||||||
1,
|
{
|
||||||
Settings.theme.combat,
|
mult: "Crime Money",
|
||||||
],
|
current: Player.crime_money_mult,
|
||||||
[
|
augmented: Player.crime_money_mult * mults.crime_money_mult,
|
||||||
"Crime money ",
|
bnMult: BitNodeMultipliers.CrimeMoney,
|
||||||
Player.crime_money_mult,
|
color: Settings.theme.money,
|
||||||
Player.crime_money_mult * mults.crime_money_mult,
|
},
|
||||||
BitNodeMultipliers.CrimeMoney,
|
|
||||||
Settings.theme.money,
|
|
||||||
],
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if (Player.canAccessBladeburner()) {
|
if (Player.canAccessBladeburner()) {
|
||||||
rightColData.push(
|
rightColData.push(
|
||||||
...[
|
{
|
||||||
[
|
mult: "Bladeburner Success Chance",
|
||||||
"Bladeburner Success Chance",
|
current: Player.bladeburner_success_chance_mult,
|
||||||
Player.bladeburner_success_chance_mult,
|
augmented: Player.bladeburner_success_chance_mult * mults.bladeburner_success_chance_mult,
|
||||||
Player.bladeburner_success_chance_mult * mults.bladeburner_success_chance_mult,
|
},
|
||||||
1,
|
{
|
||||||
],
|
mult: "Bladeburner Max Stamina",
|
||||||
[
|
current: Player.bladeburner_max_stamina_mult,
|
||||||
"Bladeburner Max Stamina",
|
augmented: Player.bladeburner_max_stamina_mult * mults.bladeburner_max_stamina_mult,
|
||||||
Player.bladeburner_max_stamina_mult,
|
},
|
||||||
Player.bladeburner_max_stamina_mult * mults.bladeburner_max_stamina_mult,
|
{
|
||||||
1,
|
mult: "Bladeburner Stamina Gain",
|
||||||
],
|
current: Player.bladeburner_stamina_gain_mult,
|
||||||
[
|
augmented: Player.bladeburner_stamina_gain_mult * mults.bladeburner_stamina_gain_mult,
|
||||||
"Bladeburner Stamina Gain",
|
},
|
||||||
Player.bladeburner_stamina_gain_mult,
|
{
|
||||||
Player.bladeburner_stamina_gain_mult * mults.bladeburner_stamina_gain_mult,
|
mult: "Bladeburner Field Analysis",
|
||||||
1,
|
current: Player.bladeburner_analysis_mult,
|
||||||
],
|
augmented: Player.bladeburner_analysis_mult * mults.bladeburner_analysis_mult,
|
||||||
[
|
},
|
||||||
"Bladeburner Field Analysis",
|
|
||||||
Player.bladeburner_analysis_mult,
|
|
||||||
Player.bladeburner_analysis_mult * mults.bladeburner_analysis_mult,
|
|
||||||
1,
|
|
||||||
],
|
|
||||||
].map((data): MultiplierListItemData => (data as any).concat([Settings.theme.primary])),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasLeftImprovements = +!!(leftColData.filter((item) => item[2] !== 0).length > 0),
|
|
||||||
hasRightImprovements = +!!(rightColData.filter((item) => item[2] !== 0).length > 0);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper
|
<Paper
|
||||||
sx={{
|
sx={{
|
||||||
p: 1,
|
p: 1,
|
||||||
maxHeight: 400,
|
maxHeight: 400,
|
||||||
overflowY: "scroll",
|
overflowY: "scroll",
|
||||||
display: "grid",
|
display: "flex",
|
||||||
gridTemplateColumns: `repeat(${hasLeftImprovements + hasRightImprovements}, 1fr)`,
|
flexDirection: "column",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
gap: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MultiplierList rows={leftColData} />
|
<MultiplierList rows={leftColData} />
|
||||||
|
@ -83,7 +83,7 @@ const Exclusive = (props: IExclusiveProps): React.ReactElement => {
|
|||||||
<li>
|
<li>
|
||||||
<b>{props.aug.factions[0]}</b> faction
|
<b>{props.aug.factions[0]}</b> faction
|
||||||
</li>
|
</li>
|
||||||
{props.player.canAccessGang() && !props.aug.isSpecial && (
|
{props.player.isAwareOfGang() && !props.aug.isSpecial && (
|
||||||
<li>
|
<li>
|
||||||
Certain <b>gangs</b>
|
Certain <b>gangs</b>
|
||||||
</li>
|
</li>
|
||||||
|
@ -488,7 +488,7 @@ export const defaultMultipliers: IBitNodeMultipliers = {
|
|||||||
FourSigmaMarketDataApiCost: 1,
|
FourSigmaMarketDataApiCost: 1,
|
||||||
|
|
||||||
CorporationValuation: 1,
|
CorporationValuation: 1,
|
||||||
CorporationSoftCap: 1,
|
CorporationSoftcap: 1,
|
||||||
|
|
||||||
BladeburnerRank: 1,
|
BladeburnerRank: 1,
|
||||||
BladeburnerSkillCost: 1,
|
BladeburnerSkillCost: 1,
|
||||||
@ -504,6 +504,8 @@ export const defaultMultipliers: IBitNodeMultipliers = {
|
|||||||
WorldDaemonDifficulty: 1,
|
WorldDaemonDifficulty: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Object.freeze(defaultMultipliers);
|
||||||
|
|
||||||
export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultipliers {
|
export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultipliers {
|
||||||
const mults = Object.assign({}, defaultMultipliers);
|
const mults = Object.assign({}, defaultMultipliers);
|
||||||
switch (n) {
|
switch (n) {
|
||||||
@ -523,7 +525,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
|||||||
StaneksGiftPowerMultiplier: 2,
|
StaneksGiftPowerMultiplier: 2,
|
||||||
StaneksGiftExtraSize: -6,
|
StaneksGiftExtraSize: -6,
|
||||||
PurchasedServerSoftcap: 1.3,
|
PurchasedServerSoftcap: 1.3,
|
||||||
CorporationSoftCap: 0.9,
|
CorporationSoftcap: 0.9,
|
||||||
WorldDaemonDifficulty: 5,
|
WorldDaemonDifficulty: 5,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -609,7 +611,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
|||||||
StaneksGiftPowerMultiplier: 0.5,
|
StaneksGiftPowerMultiplier: 0.5,
|
||||||
StaneksGiftExtraSize: 2,
|
StaneksGiftExtraSize: 2,
|
||||||
GangSoftcap: 0.7,
|
GangSoftcap: 0.7,
|
||||||
CorporationSoftCap: 0.9,
|
CorporationSoftcap: 0.9,
|
||||||
WorldDaemonDifficulty: 2,
|
WorldDaemonDifficulty: 2,
|
||||||
GangUniqueAugs: 0.2,
|
GangUniqueAugs: 0.2,
|
||||||
});
|
});
|
||||||
@ -637,7 +639,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
|||||||
StaneksGiftPowerMultiplier: 0.9,
|
StaneksGiftPowerMultiplier: 0.9,
|
||||||
StaneksGiftExtraSize: -1,
|
StaneksGiftExtraSize: -1,
|
||||||
GangSoftcap: 0.7,
|
GangSoftcap: 0.7,
|
||||||
CorporationSoftCap: 0.9,
|
CorporationSoftcap: 0.9,
|
||||||
WorldDaemonDifficulty: 2,
|
WorldDaemonDifficulty: 2,
|
||||||
GangUniqueAugs: 0.2,
|
GangUniqueAugs: 0.2,
|
||||||
});
|
});
|
||||||
@ -657,7 +659,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
|||||||
StaneksGiftExtraSize: -99,
|
StaneksGiftExtraSize: -99,
|
||||||
PurchasedServerSoftcap: 4,
|
PurchasedServerSoftcap: 4,
|
||||||
GangSoftcap: 0,
|
GangSoftcap: 0,
|
||||||
CorporationSoftCap: 0,
|
CorporationSoftcap: 0,
|
||||||
GangUniqueAugs: 0,
|
GangUniqueAugs: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -685,7 +687,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
|||||||
StaneksGiftPowerMultiplier: 0.5,
|
StaneksGiftPowerMultiplier: 0.5,
|
||||||
StaneksGiftExtraSize: 2,
|
StaneksGiftExtraSize: 2,
|
||||||
GangSoftcap: 0.8,
|
GangSoftcap: 0.8,
|
||||||
CorporationSoftCap: 0.7,
|
CorporationSoftcap: 0.7,
|
||||||
WorldDaemonDifficulty: 2,
|
WorldDaemonDifficulty: 2,
|
||||||
GangUniqueAugs: 0.25,
|
GangUniqueAugs: 0.25,
|
||||||
});
|
});
|
||||||
@ -717,7 +719,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
|||||||
StaneksGiftExtraSize: -3,
|
StaneksGiftExtraSize: -3,
|
||||||
PurchasedServerSoftcap: 1.1,
|
PurchasedServerSoftcap: 1.1,
|
||||||
GangSoftcap: 0.9,
|
GangSoftcap: 0.9,
|
||||||
CorporationSoftCap: 0.9,
|
CorporationSoftcap: 0.9,
|
||||||
WorldDaemonDifficulty: 2,
|
WorldDaemonDifficulty: 2,
|
||||||
GangUniqueAugs: 0.25,
|
GangUniqueAugs: 0.25,
|
||||||
});
|
});
|
||||||
@ -741,7 +743,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
|||||||
FourSigmaMarketDataCost: 4,
|
FourSigmaMarketDataCost: 4,
|
||||||
FourSigmaMarketDataApiCost: 4,
|
FourSigmaMarketDataApiCost: 4,
|
||||||
PurchasedServerSoftcap: 2,
|
PurchasedServerSoftcap: 2,
|
||||||
CorporationSoftCap: 0.9,
|
CorporationSoftcap: 0.9,
|
||||||
WorldDaemonDifficulty: 1.5,
|
WorldDaemonDifficulty: 1.5,
|
||||||
GangUniqueAugs: 0.75,
|
GangUniqueAugs: 0.75,
|
||||||
});
|
});
|
||||||
@ -809,7 +811,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
|||||||
StaneksGiftPowerMultiplier: inc,
|
StaneksGiftPowerMultiplier: inc,
|
||||||
StaneksGiftExtraSize: inc,
|
StaneksGiftExtraSize: inc,
|
||||||
GangSoftcap: 0.8,
|
GangSoftcap: 0.8,
|
||||||
CorporationSoftCap: 0.8,
|
CorporationSoftcap: 0.8,
|
||||||
WorldDaemonDifficulty: inc,
|
WorldDaemonDifficulty: inc,
|
||||||
|
|
||||||
GangUniqueAugs: dec,
|
GangUniqueAugs: dec,
|
||||||
@ -854,7 +856,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
|||||||
StaneksGiftPowerMultiplier: 2,
|
StaneksGiftPowerMultiplier: 2,
|
||||||
StaneksGiftExtraSize: 1,
|
StaneksGiftExtraSize: 1,
|
||||||
GangSoftcap: 0.3,
|
GangSoftcap: 0.3,
|
||||||
CorporationSoftCap: 0.3,
|
CorporationSoftcap: 0.3,
|
||||||
WorldDaemonDifficulty: 3,
|
WorldDaemonDifficulty: 3,
|
||||||
GangUniqueAugs: 0.1,
|
GangUniqueAugs: 0.1,
|
||||||
});
|
});
|
||||||
|
@ -242,7 +242,7 @@ export interface IBitNodeMultipliers {
|
|||||||
/**
|
/**
|
||||||
* Influences corporation dividends.
|
* Influences corporation dividends.
|
||||||
*/
|
*/
|
||||||
CorporationSoftCap: number;
|
CorporationSoftcap: number;
|
||||||
|
|
||||||
// Index signature
|
// Index signature
|
||||||
[key: string]: number;
|
[key: string]: number;
|
||||||
@ -252,4 +252,4 @@ export interface IBitNodeMultipliers {
|
|||||||
* The multipliers that are influenced by current Bitnode progression.
|
* The multipliers that are influenced by current Bitnode progression.
|
||||||
*/
|
*/
|
||||||
// tslint:disable-next-line:variable-name
|
// tslint:disable-next-line:variable-name
|
||||||
export const BitNodeMultipliers = defaultMultipliers;
|
export const BitNodeMultipliers = Object.assign({}, defaultMultipliers);
|
||||||
|
@ -1,554 +1,335 @@
|
|||||||
import ExpandMore from "@mui/icons-material/ExpandMore";
|
|
||||||
import ExpandLess from "@mui/icons-material/ExpandLess";
|
import ExpandLess from "@mui/icons-material/ExpandLess";
|
||||||
import { Box, Collapse, ListItemButton, ListItemText, Paper, Typography } from "@mui/material";
|
import ExpandMore from "@mui/icons-material/ExpandMore";
|
||||||
|
import { Box, Collapse, ListItemButton, ListItemText, Paper, Table, TableBody, Typography } from "@mui/material";
|
||||||
|
import { uniqueId } from "lodash";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { SpecialServers } from "../../Server/data/SpecialServers";
|
||||||
|
import { Settings } from "../../Settings/Settings";
|
||||||
import { use } from "../../ui/Context";
|
import { use } from "../../ui/Context";
|
||||||
|
import { StatsRow } from "../../ui/React/StatsRow";
|
||||||
import { defaultMultipliers, getBitNodeMultipliers } from "../BitNode";
|
import { defaultMultipliers, getBitNodeMultipliers } from "../BitNode";
|
||||||
import { IBitNodeMultipliers } from "../BitNodeMultipliers";
|
import { IBitNodeMultipliers } from "../BitNodeMultipliers";
|
||||||
import { SpecialServers } from "../../Server/data/SpecialServers";
|
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
n: number;
|
n: number;
|
||||||
|
level?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BitnodeMultiplierDescription({ n }: IProps): React.ReactElement {
|
export function BitnodeMultiplierDescription({ n, level }: IProps): React.ReactElement {
|
||||||
const player = use.Player();
|
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
const mults = getBitNodeMultipliers(n, player.sourceFileLvl(n));
|
|
||||||
if (n === 1) return <></>;
|
if (n === 1) return <></>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Box component={Paper} sx={{ mt: 1, p: 1 }}>
|
||||||
<br />
|
<ListItemButton disableGutters onClick={() => setOpen((old) => !old)}>
|
||||||
<Box component={Paper}>
|
<ListItemText primary={<Typography variant="h6">Bitnode Multipliers</Typography>} />
|
||||||
<ListItemButton onClick={() => setOpen((old) => !old)}>
|
{open ? <ExpandLess color="primary" /> : <ExpandMore color="primary" />}
|
||||||
<ListItemText primary={<Typography>Bitnode multipliers:</Typography>} />
|
</ListItemButton>
|
||||||
{open ? <ExpandLess color="primary" /> : <ExpandMore color="primary" />}
|
<Collapse in={open}>
|
||||||
</ListItemButton>
|
<BitNodeMultipliersDisplay n={n} level={level} />
|
||||||
<Box mx={2}>
|
</Collapse>
|
||||||
<Collapse in={open}>
|
</Box>
|
||||||
<GeneralMults n={n} mults={mults} />
|
|
||||||
<FactionMults n={n} mults={mults} />
|
|
||||||
<AugmentationMults n={n} mults={mults} />
|
|
||||||
<StockMults n={n} mults={mults} />
|
|
||||||
<SkillMults n={n} mults={mults} />
|
|
||||||
<HackingMults n={n} mults={mults} />
|
|
||||||
<PurchasedServersMults n={n} mults={mults} />
|
|
||||||
<CrimeMults n={n} mults={mults} />
|
|
||||||
<InfiltrationMults n={n} mults={mults} />
|
|
||||||
<CompanyMults n={n} mults={mults} />
|
|
||||||
<GangMults n={n} mults={mults} />
|
|
||||||
<CorporationMults n={n} mults={mults} />
|
|
||||||
<BladeburnerMults n={n} mults={mults} />
|
|
||||||
<StanekMults n={n} mults={mults} />
|
|
||||||
<br />
|
|
||||||
</Collapse>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const BitNodeMultipliersDisplay = ({ n, level }: IProps): React.ReactElement => {
|
||||||
|
const player = use.Player();
|
||||||
|
// If a level argument has been provided, use that as the multiplier level
|
||||||
|
// If not, then we have to assume that we want the next level up from the
|
||||||
|
// current node's source file, so we get the min of that, the SF's max level,
|
||||||
|
// or if it's BN12, ∞
|
||||||
|
const maxSfLevel = n === 12 ? Infinity : 3;
|
||||||
|
const mults = getBitNodeMultipliers(n, level ?? Math.min(player.sourceFileLvl(n) + 1, maxSfLevel));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{ columnCount: 2, columnGap: 1, mb: -2 }}>
|
||||||
|
<GeneralMults n={n} mults={mults} />
|
||||||
|
<SkillMults n={n} mults={mults} />
|
||||||
|
<FactionMults n={n} mults={mults} />
|
||||||
|
<AugmentationMults n={n} mults={mults} />
|
||||||
|
<HackingMults n={n} mults={mults} />
|
||||||
|
<PurchasedServersMults n={n} mults={mults} />
|
||||||
|
<StockMults n={n} mults={mults} />
|
||||||
|
<CrimeMults n={n} mults={mults} />
|
||||||
|
<InfiltrationMults n={n} mults={mults} />
|
||||||
|
<CompanyMults n={n} mults={mults} />
|
||||||
|
<GangMults n={n} mults={mults} />
|
||||||
|
<CorporationMults n={n} mults={mults} />
|
||||||
|
<BladeburnerMults n={n} mults={mults} />
|
||||||
|
<StanekMults n={n} mults={mults} />
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
interface IBNMultRows {
|
||||||
|
[mult: string]: {
|
||||||
|
name: string;
|
||||||
|
content?: string;
|
||||||
|
color?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IBNMultTableProps {
|
||||||
|
sectionName: string;
|
||||||
|
rowData: IBNMultRows;
|
||||||
|
mults: IBitNodeMultipliers;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BNMultTable = (props: IBNMultTableProps): React.ReactElement => {
|
||||||
|
const rowsArray = Object.entries(props.rowData)
|
||||||
|
.filter(([key, _value]) => props.mults[key] !== defaultMultipliers[key])
|
||||||
|
.map(([key, value]) => (
|
||||||
|
<StatsRow
|
||||||
|
key={uniqueId()}
|
||||||
|
name={value.name}
|
||||||
|
data={{ content: value.content ?? `${(props.mults[key] * 100).toFixed(3)}%` }}
|
||||||
|
color={value.color ?? Settings.theme.primary}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
||||||
|
return rowsArray.length > 0 ? (
|
||||||
|
<span style={{ display: "inline-block", width: "100%", marginBottom: "16px" }}>
|
||||||
|
<Typography variant="h6">{props.sectionName}</Typography>
|
||||||
|
<Table>
|
||||||
|
<TableBody>{rowsArray}</TableBody>
|
||||||
|
</Table>
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
interface IMultsProps {
|
interface IMultsProps {
|
||||||
n: number;
|
n: number;
|
||||||
mults: IBitNodeMultipliers;
|
mults: IBitNodeMultipliers;
|
||||||
}
|
}
|
||||||
|
|
||||||
function GeneralMults({ mults }: IMultsProps): React.ReactElement {
|
function GeneralMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
// is it empty check
|
const rows: IBNMultRows = {
|
||||||
if (
|
WorldDaemonDifficulty: { name: `${SpecialServers.WorldDaemon} Difficulty` },
|
||||||
mults.ClassGymExpGain === defaultMultipliers.ClassGymExpGain &&
|
DaedalusAugsRequirement: {
|
||||||
mults.CodingContractMoney === defaultMultipliers.CodingContractMoney &&
|
name: "Daedalus Augs Requirement",
|
||||||
mults.DaedalusAugsRequirement === defaultMultipliers.DaedalusAugsRequirement &&
|
content: String(mults.DaedalusAugsRequirement),
|
||||||
mults.WorldDaemonDifficulty === defaultMultipliers.WorldDaemonDifficulty &&
|
},
|
||||||
mults.HacknetNodeMoney === defaultMultipliers.HacknetNodeMoney
|
HacknetNodeMoney: { name: "Hacknet Production" },
|
||||||
)
|
CodingContractMoney: { name: "Coding Contract Reward" },
|
||||||
return <></>;
|
ClassGymExpGain: { name: "Class/Gym Exp" },
|
||||||
return (
|
};
|
||||||
<>
|
|
||||||
<br />
|
return <BNMultTable sectionName="General" rowData={rows} mults={mults} />;
|
||||||
<Typography variant={"h5"}>General:</Typography>
|
|
||||||
<Box mx={1}>
|
|
||||||
{mults.WorldDaemonDifficulty !== defaultMultipliers.WorldDaemonDifficulty ? (
|
|
||||||
<Typography>
|
|
||||||
{SpecialServers.WorldDaemon} difficulty: x{mults.WorldDaemonDifficulty.toFixed(3)}
|
|
||||||
</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.DaedalusAugsRequirement !== defaultMultipliers.DaedalusAugsRequirement ? (
|
|
||||||
<Typography>Daedalus aug req.: {mults.DaedalusAugsRequirement}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.HacknetNodeMoney !== defaultMultipliers.HacknetNodeMoney ? (
|
|
||||||
<Typography>Hacknet production: x{mults.HacknetNodeMoney.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.CodingContractMoney !== defaultMultipliers.CodingContractMoney ? (
|
|
||||||
<Typography>Coding contract reward: x{mults.CodingContractMoney.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.ClassGymExpGain !== defaultMultipliers.ClassGymExpGain ? (
|
|
||||||
<Typography>Class/Gym exp: x{mults.ClassGymExpGain.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function AugmentationMults({ mults }: IMultsProps): React.ReactElement {
|
function AugmentationMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
// is it empty check
|
const rows: IBNMultRows = {
|
||||||
if (
|
AugmentationMoneyCost: { name: "Money Cost" },
|
||||||
mults.AugmentationMoneyCost === defaultMultipliers.AugmentationMoneyCost &&
|
AugmentationRepCost: {
|
||||||
mults.AugmentationRepCost === defaultMultipliers.AugmentationRepCost
|
name: "Reputation Cost",
|
||||||
)
|
color: Settings.theme.rep,
|
||||||
return <></>;
|
},
|
||||||
return (
|
};
|
||||||
<>
|
|
||||||
<br />
|
return <BNMultTable sectionName="Augmentations" rowData={rows} mults={mults} />;
|
||||||
<Typography variant={"h5"}>Augmentations:</Typography>
|
|
||||||
<Box mx={1}>
|
|
||||||
{mults.AugmentationMoneyCost !== defaultMultipliers.AugmentationMoneyCost ? (
|
|
||||||
<Typography>Cost: x{mults.AugmentationMoneyCost.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.AugmentationRepCost !== defaultMultipliers.AugmentationRepCost ? (
|
|
||||||
<Typography>Reputation: x{mults.AugmentationRepCost.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function CompanyMults({ mults }: IMultsProps): React.ReactElement {
|
function CompanyMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
// is it empty check
|
const rows: IBNMultRows = {
|
||||||
if (
|
CompanyWorkMoney: {
|
||||||
mults.CompanyWorkExpGain === defaultMultipliers.CompanyWorkExpGain &&
|
name: "Work Money",
|
||||||
mults.CompanyWorkMoney === defaultMultipliers.CompanyWorkMoney
|
color: Settings.theme.money,
|
||||||
)
|
},
|
||||||
return <></>;
|
CompanyWorkExpGain: { name: "Work Exp" },
|
||||||
return (
|
};
|
||||||
<>
|
|
||||||
<br />
|
return <BNMultTable sectionName="Company" rowData={rows} mults={mults} />;
|
||||||
<Typography variant={"h5"}>Company:</Typography>
|
|
||||||
<Box mx={1}>
|
|
||||||
{mults.CompanyWorkMoney !== defaultMultipliers.CompanyWorkMoney ? (
|
|
||||||
<Typography>Money: x{mults.CompanyWorkMoney.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.CompanyWorkExpGain !== defaultMultipliers.CompanyWorkExpGain ? (
|
|
||||||
<Typography>Exp: x{mults.CompanyWorkExpGain.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function StockMults({ mults }: IMultsProps): React.ReactElement {
|
function StockMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
// is it empty check
|
const rows: IBNMultRows = {
|
||||||
if (
|
FourSigmaMarketDataCost: { name: "Market Data Cost" },
|
||||||
mults.FourSigmaMarketDataApiCost === defaultMultipliers.FourSigmaMarketDataApiCost &&
|
FourSigmaMarketDataApiCost: { name: "Market Data API Cost" },
|
||||||
mults.FourSigmaMarketDataCost === defaultMultipliers.FourSigmaMarketDataCost
|
};
|
||||||
)
|
|
||||||
return <></>;
|
return <BNMultTable sectionName="Stock Market" rowData={rows} mults={mults} />;
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<br />
|
|
||||||
<Typography variant={"h5"}>Stock market:</Typography>
|
|
||||||
<Box mx={1}>
|
|
||||||
{mults.FourSigmaMarketDataCost !== defaultMultipliers.FourSigmaMarketDataCost ? (
|
|
||||||
<Typography>Market data cost: x{mults.FourSigmaMarketDataCost.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.FourSigmaMarketDataApiCost !== defaultMultipliers.FourSigmaMarketDataApiCost ? (
|
|
||||||
<Typography>Market data API cost: x{mults.FourSigmaMarketDataApiCost.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function FactionMults({ mults }: IMultsProps): React.ReactElement {
|
function FactionMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
// is it empty check
|
const rows: IBNMultRows = {
|
||||||
if (
|
RepToDonateToFaction: { name: "Favor to Donate" },
|
||||||
mults.FactionPassiveRepGain === defaultMultipliers.FactionPassiveRepGain &&
|
FactionWorkRepGain: {
|
||||||
mults.FactionWorkExpGain === defaultMultipliers.FactionWorkExpGain &&
|
name: "Work Reputation",
|
||||||
mults.FactionWorkRepGain === defaultMultipliers.FactionWorkRepGain &&
|
color: Settings.theme.rep,
|
||||||
mults.RepToDonateToFaction === defaultMultipliers.RepToDonateToFaction
|
},
|
||||||
)
|
FactionWorkExpGain: { name: "Work Exp" },
|
||||||
return <></>;
|
FactionPassiveRepGain: {
|
||||||
return (
|
name: "Passive Rep",
|
||||||
<>
|
color: Settings.theme.rep,
|
||||||
<br />
|
},
|
||||||
<Typography variant={"h5"}>Faction:</Typography>
|
};
|
||||||
<Box mx={1}>
|
|
||||||
{mults.RepToDonateToFaction !== defaultMultipliers.RepToDonateToFaction ? (
|
return <BNMultTable sectionName="Faction" rowData={rows} mults={mults} />;
|
||||||
<Typography>Favor to donate: x{mults.RepToDonateToFaction.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.FactionWorkRepGain !== defaultMultipliers.FactionWorkRepGain ? (
|
|
||||||
<Typography>Work rep: x{mults.FactionWorkRepGain.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.FactionWorkExpGain !== defaultMultipliers.FactionWorkExpGain ? (
|
|
||||||
<Typography>Work exp: x{mults.FactionWorkExpGain.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.FactionPassiveRepGain !== defaultMultipliers.FactionPassiveRepGain ? (
|
|
||||||
<Typography>Passive rep: x{mults.FactionPassiveRepGain.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function CrimeMults({ mults }: IMultsProps): React.ReactElement {
|
function CrimeMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
// is it empty check
|
const rows: IBNMultRows = {
|
||||||
if (mults.CrimeExpGain === defaultMultipliers.CrimeExpGain && mults.CrimeMoney === defaultMultipliers.CrimeMoney)
|
CrimeExpGain: {
|
||||||
return <></>;
|
name: "Crime Exp",
|
||||||
return (
|
color: Settings.theme.combat,
|
||||||
<>
|
},
|
||||||
<br />
|
CrimeMoney: {
|
||||||
<Typography variant={"h5"}>Crime:</Typography>
|
name: "Crime Money",
|
||||||
<Box mx={1}>
|
color: Settings.theme.combat,
|
||||||
{mults.CrimeExpGain !== defaultMultipliers.CrimeExpGain ? (
|
},
|
||||||
<Typography>Exp: x{mults.CrimeExpGain.toFixed(3)}</Typography>
|
};
|
||||||
) : (
|
|
||||||
<></>
|
return <BNMultTable sectionName="Crime" rowData={rows} mults={mults} />;
|
||||||
)}
|
|
||||||
{mults.CrimeMoney !== defaultMultipliers.CrimeMoney ? (
|
|
||||||
<Typography>Money: x{mults.CrimeMoney.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function SkillMults({ mults }: IMultsProps): React.ReactElement {
|
function SkillMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
// is it empty check
|
const rows: IBNMultRows = {
|
||||||
if (
|
HackingLevelMultiplier: {
|
||||||
mults.HackingLevelMultiplier === defaultMultipliers.HackingLevelMultiplier &&
|
name: "Hacking Level",
|
||||||
mults.AgilityLevelMultiplier === defaultMultipliers.AgilityLevelMultiplier &&
|
color: Settings.theme.hack,
|
||||||
mults.DefenseLevelMultiplier === defaultMultipliers.DefenseLevelMultiplier &&
|
},
|
||||||
mults.DexterityLevelMultiplier === defaultMultipliers.DexterityLevelMultiplier &&
|
StrengthLevelMultiplier: {
|
||||||
mults.StrengthLevelMultiplier === defaultMultipliers.StrengthLevelMultiplier &&
|
name: "Strength Level",
|
||||||
mults.CharismaLevelMultiplier === defaultMultipliers.CharismaLevelMultiplier
|
color: Settings.theme.combat,
|
||||||
)
|
},
|
||||||
return <></>;
|
DefenseLevelMultiplier: {
|
||||||
return (
|
name: "Defense Level",
|
||||||
<>
|
color: Settings.theme.combat,
|
||||||
<br />
|
},
|
||||||
<Typography variant={"h5"}>Skills:</Typography>
|
DexterityLevelMultiplier: {
|
||||||
<Box mx={1}>
|
name: "Dexterity Level",
|
||||||
{mults.HackingLevelMultiplier !== defaultMultipliers.HackingLevelMultiplier ? (
|
color: Settings.theme.combat,
|
||||||
<Typography>Hacking: x{mults.HackingLevelMultiplier.toFixed(3)}</Typography>
|
},
|
||||||
) : (
|
AgilityLevelMultiplier: {
|
||||||
<></>
|
name: "Agility Level",
|
||||||
)}
|
color: Settings.theme.combat,
|
||||||
{mults.AgilityLevelMultiplier !== defaultMultipliers.AgilityLevelMultiplier ? (
|
},
|
||||||
<Typography>Agility: x{mults.AgilityLevelMultiplier.toFixed(3)}</Typography>
|
CharismaLevelMultiplier: {
|
||||||
) : (
|
name: "Charisma Level",
|
||||||
<></>
|
color: Settings.theme.cha,
|
||||||
)}
|
},
|
||||||
{mults.DefenseLevelMultiplier !== defaultMultipliers.DefenseLevelMultiplier ? (
|
};
|
||||||
<Typography>Defense: x{mults.DefenseLevelMultiplier.toFixed(3)}</Typography>
|
|
||||||
) : (
|
return <BNMultTable sectionName="Skills" rowData={rows} mults={mults} />;
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.DexterityLevelMultiplier !== defaultMultipliers.DexterityLevelMultiplier ? (
|
|
||||||
<Typography>Dexterity: x{mults.DexterityLevelMultiplier.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.StrengthLevelMultiplier !== defaultMultipliers.StrengthLevelMultiplier ? (
|
|
||||||
<Typography>Strength: x{mults.StrengthLevelMultiplier.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.CharismaLevelMultiplier !== defaultMultipliers.CharismaLevelMultiplier ? (
|
|
||||||
<Typography>Charisma: x{mults.CharismaLevelMultiplier.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function HackingMults({ mults }: IMultsProps): React.ReactElement {
|
function HackingMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
// is it empty check
|
const rows: IBNMultRows = {
|
||||||
if (
|
HackExpGain: {
|
||||||
mults.ServerGrowthRate === defaultMultipliers.ServerGrowthRate &&
|
name: "Hacking Exp",
|
||||||
mults.ServerMaxMoney === defaultMultipliers.ServerMaxMoney &&
|
color: Settings.theme.hack,
|
||||||
mults.ServerStartingMoney === defaultMultipliers.ServerStartingMoney &&
|
},
|
||||||
mults.ServerStartingSecurity === defaultMultipliers.ServerStartingSecurity &&
|
ServerGrowthRate: { name: "Server Growth Rate" },
|
||||||
mults.ServerWeakenRate === defaultMultipliers.ServerWeakenRate &&
|
ServerMaxMoney: { name: "Server Max Money" },
|
||||||
mults.ManualHackMoney === defaultMultipliers.ManualHackMoney &&
|
ServerStartingMoney: { name: "Server Starting Money" },
|
||||||
mults.ScriptHackMoney === defaultMultipliers.ScriptHackMoney &&
|
ServerStartingSecurity: { name: "Server Starting Security" },
|
||||||
mults.ScriptHackMoneyGain === defaultMultipliers.ScriptHackMoneyGain &&
|
ServerWeakenRate: { name: "Server Weaken Rate" },
|
||||||
mults.HackExpGain === defaultMultipliers.HackExpGain
|
ManualHackMoney: {
|
||||||
)
|
name: "Manual Hack Money",
|
||||||
return <></>;
|
color: Settings.theme.money,
|
||||||
|
},
|
||||||
|
ScriptHackMoney: {
|
||||||
|
name: "Script Hack Money",
|
||||||
|
color: Settings.theme.money,
|
||||||
|
},
|
||||||
|
ScriptHackMoneyGain: {
|
||||||
|
name: "Money Gained From Hack",
|
||||||
|
color: Settings.theme.money,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return <BNMultTable sectionName="Hacking" rowData={rows} mults={mults} />;
|
||||||
<>
|
|
||||||
<br />
|
|
||||||
<Typography variant={"h5"}>Hacking:</Typography>
|
|
||||||
<Box mx={1}>
|
|
||||||
{mults.HackExpGain !== defaultMultipliers.HackExpGain ? (
|
|
||||||
<Typography>Exp: x{mults.HackExpGain.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.ServerGrowthRate !== defaultMultipliers.ServerGrowthRate ? (
|
|
||||||
<Typography>Growth rate: x{mults.ServerGrowthRate.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.ServerMaxMoney !== defaultMultipliers.ServerMaxMoney ? (
|
|
||||||
<Typography>Max money: x{mults.ServerMaxMoney.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.ServerStartingMoney !== defaultMultipliers.ServerStartingMoney ? (
|
|
||||||
<Typography>Starting money: x{mults.ServerStartingMoney.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.ServerStartingSecurity !== defaultMultipliers.ServerStartingSecurity ? (
|
|
||||||
<Typography>Starting security: x{mults.ServerStartingSecurity.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.ServerWeakenRate !== defaultMultipliers.ServerWeakenRate ? (
|
|
||||||
<Typography>Weaken rate: x{mults.ServerWeakenRate.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.ManualHackMoney !== defaultMultipliers.ManualHackMoney ? (
|
|
||||||
<Typography>Manual hack money: x{mults.ManualHackMoney.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.ScriptHackMoney !== defaultMultipliers.ScriptHackMoney ? (
|
|
||||||
<Typography>Hack money stolen: x{mults.ScriptHackMoney.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.ScriptHackMoneyGain !== defaultMultipliers.ScriptHackMoneyGain ? (
|
|
||||||
<Typography>Money gained from hack: x{mults.ScriptHackMoneyGain.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function PurchasedServersMults({ mults }: IMultsProps): React.ReactElement {
|
function PurchasedServersMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
// is it empty check
|
const rows: IBNMultRows = {
|
||||||
if (
|
PurchasedServerCost: {
|
||||||
mults.PurchasedServerCost === defaultMultipliers.PurchasedServerCost &&
|
name: "Base Cost",
|
||||||
mults.PurchasedServerSoftcap === defaultMultipliers.PurchasedServerSoftcap &&
|
content: mults.PurchasedServerCost.toFixed(3),
|
||||||
mults.PurchasedServerLimit === defaultMultipliers.PurchasedServerLimit &&
|
},
|
||||||
mults.PurchasedServerMaxRam === defaultMultipliers.PurchasedServerMaxRam &&
|
PurchasedServerSoftcap: {
|
||||||
mults.HomeComputerRamCost === defaultMultipliers.HomeComputerRamCost
|
name: "Softcap Cost",
|
||||||
)
|
content: mults.PurchasedServerSoftcap.toFixed(3),
|
||||||
return <></>;
|
},
|
||||||
return (
|
PurchasedServerLimit: { name: "Server Limit" },
|
||||||
<>
|
PurchasedServerMaxRam: { name: "Max RAM" },
|
||||||
<br />
|
HomeComputerRamCost: { name: "Home RAM Cost" },
|
||||||
<Typography variant={"h5"}>Purchased servers:</Typography>
|
};
|
||||||
<Box mx={1}>
|
|
||||||
{mults.PurchasedServerCost !== defaultMultipliers.PurchasedServerCost ? (
|
return <BNMultTable sectionName="Purchased Servers" rowData={rows} mults={mults} />;
|
||||||
<Typography>Base cost: {mults.PurchasedServerCost.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.PurchasedServerSoftcap !== defaultMultipliers.PurchasedServerSoftcap ? (
|
|
||||||
<Typography>Softcap cost: {mults.PurchasedServerSoftcap.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.PurchasedServerLimit !== defaultMultipliers.PurchasedServerLimit ? (
|
|
||||||
<Typography>Limit: x{mults.PurchasedServerLimit.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.PurchasedServerMaxRam !== defaultMultipliers.PurchasedServerMaxRam ? (
|
|
||||||
<Typography>Max ram: x{mults.PurchasedServerMaxRam.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.HomeComputerRamCost !== defaultMultipliers.HomeComputerRamCost ? (
|
|
||||||
<Typography>Home ram cost: x{mults.HomeComputerRamCost.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function InfiltrationMults({ mults }: IMultsProps): React.ReactElement {
|
function InfiltrationMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
// is it empty check
|
const rows: IBNMultRows = {
|
||||||
if (
|
InfiltrationMoney: {
|
||||||
mults.InfiltrationMoney === defaultMultipliers.InfiltrationMoney &&
|
name: "Infiltration Money",
|
||||||
mults.InfiltrationRep === defaultMultipliers.InfiltrationRep
|
color: Settings.theme.money,
|
||||||
)
|
},
|
||||||
return <></>;
|
InfiltrationRep: {
|
||||||
return (
|
name: "Infiltration Reputation",
|
||||||
<>
|
color: Settings.theme.rep,
|
||||||
<br />
|
},
|
||||||
<Typography variant={"h5"}>Infiltration:</Typography>
|
};
|
||||||
<Box mx={1}>
|
|
||||||
{mults.InfiltrationMoney !== defaultMultipliers.InfiltrationMoney ? (
|
return <BNMultTable sectionName="Infiltration" rowData={rows} mults={mults} />;
|
||||||
<Typography>Money: {mults.InfiltrationMoney.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.InfiltrationRep !== defaultMultipliers.InfiltrationRep ? (
|
|
||||||
<Typography>Reputation: x{mults.InfiltrationRep.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function BladeburnerMults({ n, mults }: IMultsProps): React.ReactElement {
|
function BladeburnerMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
const player = use.Player();
|
const player = use.Player();
|
||||||
// access check
|
if (!player.canAccessBladeburner()) return <></>;
|
||||||
if (n !== 6 && n !== 7 && player.sourceFileLvl(6) === 0) return <></>;
|
|
||||||
//default mults check
|
const rows: IBNMultRows = {
|
||||||
if (mults.BladeburnerRank === 1 && mults.BladeburnerSkillCost === 1) return <></>;
|
BladeburnerRank: { name: "Rank Gain" },
|
||||||
return (
|
BladeburnerSkillCost: { name: "Skill Cost" },
|
||||||
<>
|
};
|
||||||
<br />
|
|
||||||
<Typography variant={"h5"}>Bladeburner:</Typography>
|
return <BNMultTable sectionName="Bladeburner" rowData={rows} mults={mults} />;
|
||||||
<Box mx={1}>
|
|
||||||
{mults.BladeburnerRank !== 1 ? <Typography>Rank gain: x{mults.BladeburnerRank.toFixed(3)}</Typography> : <></>}
|
|
||||||
{mults.BladeburnerSkillCost !== 1 ? (
|
|
||||||
<Typography>Skill cost: x{mults.BladeburnerSkillCost.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function StanekMults({ n, mults }: IMultsProps): React.ReactElement {
|
function StanekMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
const player = use.Player();
|
const player = use.Player();
|
||||||
// access check
|
if (!player.canAccessCotMG()) return <></>;
|
||||||
if (n !== 13 && player.sourceFileLvl(13) === 0) return <></>;
|
|
||||||
//default mults check
|
|
||||||
if (
|
|
||||||
mults.StaneksGiftExtraSize === defaultMultipliers.StaneksGiftExtraSize &&
|
|
||||||
mults.StaneksGiftPowerMultiplier === defaultMultipliers.StaneksGiftPowerMultiplier
|
|
||||||
)
|
|
||||||
return <></>;
|
|
||||||
|
|
||||||
const s = mults.StaneksGiftExtraSize;
|
const extraSize = mults.StaneksGiftExtraSize.toFixed(3);
|
||||||
return (
|
const rows: IBNMultRows = {
|
||||||
<>
|
StnakesGiftPowerMultiplier: { name: "Gift Power" },
|
||||||
<br />
|
StaneksGiftExtraSize: {
|
||||||
<Typography variant={"h5"}>Stanek's Gift:</Typography>
|
name: "Base Size Modifier",
|
||||||
<Box mx={1}>
|
content: `${mults.StaneksGiftExtraSize > defaultMultipliers.StaneksGiftExtraSize ? `+${extraSize}` : extraSize}`,
|
||||||
{mults.StaneksGiftPowerMultiplier !== defaultMultipliers.StaneksGiftPowerMultiplier ? (
|
},
|
||||||
<Typography>Gift power: x{mults.StaneksGiftPowerMultiplier.toFixed(3)}</Typography>
|
};
|
||||||
) : (
|
|
||||||
<></>
|
return <BNMultTable sectionName="Stanek's Gift" rowData={rows} mults={mults} />;
|
||||||
)}
|
|
||||||
{s !== defaultMultipliers.StaneksGiftExtraSize ? (
|
|
||||||
<Typography>Base size modifier: {s > defaultMultipliers.StaneksGiftExtraSize ? `+${s}` : s}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function GangMults({ n, mults }: IMultsProps): React.ReactElement {
|
function GangMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
const player = use.Player();
|
const player = use.Player();
|
||||||
// access check
|
if (player.bitNodeN !== 2 && player.sourceFileLvl(2) <= 0) return <></>;
|
||||||
if (n !== 2 && player.sourceFileLvl(2) === 0) return <></>;
|
|
||||||
// is it empty check
|
const rows: IBNMultRows = {
|
||||||
if (
|
GangSoftcap: {
|
||||||
mults.GangSoftcap === defaultMultipliers.GangSoftcap &&
|
name: "Gang Softcap",
|
||||||
mults.GangUniqueAugs === defaultMultipliers.GangUniqueAugs
|
content: mults.GangSoftcap.toFixed(3),
|
||||||
)
|
},
|
||||||
return <></>;
|
GangUniqueAugs: { name: "Unique Augmentations" },
|
||||||
return (
|
};
|
||||||
<>
|
|
||||||
<br />
|
return <BNMultTable sectionName="Gang" rowData={rows} mults={mults} />;
|
||||||
<Typography variant={"h5"}>Gang:</Typography>
|
|
||||||
<Box mx={1}>
|
|
||||||
{mults.GangSoftcap !== defaultMultipliers.GangSoftcap ? (
|
|
||||||
<Typography>Softcap: {mults.GangSoftcap.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{mults.GangUniqueAugs !== defaultMultipliers.GangUniqueAugs ? (
|
|
||||||
<Typography>Unique augs: x{mults.GangUniqueAugs.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function CorporationMults({ n, mults }: IMultsProps): React.ReactElement {
|
function CorporationMults({ mults }: IMultsProps): React.ReactElement {
|
||||||
const player = use.Player();
|
const player = use.Player();
|
||||||
// access check
|
if (!player.canAccessCorporation()) return <></>;
|
||||||
if (n !== 3 && player.sourceFileLvl(3) === 0) return <></>;
|
|
||||||
// is it empty check
|
|
||||||
if (
|
|
||||||
mults.CorporationSoftCap === defaultMultipliers.CorporationSoftCap &&
|
|
||||||
mults.CorporationValuation === defaultMultipliers.CorporationValuation
|
|
||||||
)
|
|
||||||
return <></>;
|
|
||||||
|
|
||||||
return (
|
const rows: IBNMultRows = {
|
||||||
<>
|
CorporationSoftcap: {
|
||||||
<br />
|
name: "Corporation Softcap",
|
||||||
<Typography variant={"h5"}>Corporation:</Typography>
|
content: mults.CorporationSoftcap.toFixed(3),
|
||||||
<Box mx={1}>
|
},
|
||||||
{mults.CorporationSoftCap !== defaultMultipliers.CorporationSoftCap ? (
|
CorporationValuation: { name: "Valuation" },
|
||||||
<Typography>Softcap: {mults.CorporationSoftCap.toFixed(3)}</Typography>
|
};
|
||||||
) : (
|
|
||||||
<></>
|
return <BNMultTable sectionName="Corporation" rowData={rows} mults={mults} />;
|
||||||
)}
|
|
||||||
{mults.CorporationValuation !== defaultMultipliers.CorporationValuation ? (
|
|
||||||
<Typography>Valuation: x{mults.CorporationValuation.toFixed(3)}</Typography>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ export function PortalModal(props: IProps): React.ReactElement {
|
|||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<Typography>{bitNode.info}</Typography>
|
<Typography>{bitNode.info}</Typography>
|
||||||
<BitnodeMultiplierDescription n={props.n} />
|
<BitnodeMultiplierDescription n={props.n} level={newLevel} />
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<Button
|
<Button
|
||||||
|
@ -700,7 +700,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
|
|
||||||
// Set variables
|
// Set variables
|
||||||
if (args.length === 4) {
|
if (args.length === 4) {
|
||||||
const variable = args[1];
|
const variable = args[1].toLowerCase(); // allows Action Type to be with or without capitalisation.
|
||||||
const val = args[2];
|
const val = args[2];
|
||||||
|
|
||||||
let highLow = false; // True for high, false for low
|
let highLow = false; // True for high, false for low
|
||||||
@ -1993,7 +1993,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the Player starts doing some other actions, set action to idle and alert
|
// If the Player starts doing some other actions, set action to idle and alert
|
||||||
if (player.hasAugmentation(AugmentationNames.BladesSimulacrum) === false && player.isWorking) {
|
if (!player.hasAugmentation(AugmentationNames.BladesSimulacrum, true) && player.isWorking) {
|
||||||
if (this.action.type !== ActionTypes["Idle"]) {
|
if (this.action.type !== ActionTypes["Idle"]) {
|
||||||
let msg = "Your Bladeburner action was cancelled because you started doing something else.";
|
let msg = "Your Bladeburner action was cancelled because you started doing something else.";
|
||||||
if (this.automateEnabled) {
|
if (this.automateEnabled) {
|
||||||
|
176
src/Constants.ts
176
src/Constants.ts
@ -84,11 +84,12 @@ export const CONSTANTS: {
|
|||||||
SoARepMult: number;
|
SoARepMult: number;
|
||||||
EntropyEffect: number;
|
EntropyEffect: number;
|
||||||
TotalNumBitNodes: number;
|
TotalNumBitNodes: number;
|
||||||
|
InfiniteLoopLimit: number;
|
||||||
Donations: number; // number of blood/plasma/palette donation the dev have verified., boosts NFG
|
Donations: number; // number of blood/plasma/palette donation the dev have verified., boosts NFG
|
||||||
LatestUpdate: string;
|
LatestUpdate: string;
|
||||||
} = {
|
} = {
|
||||||
VersionString: "1.6.4",
|
VersionString: "1.7.0",
|
||||||
VersionNumber: 17,
|
VersionNumber: 18,
|
||||||
|
|
||||||
// Speed (in ms) at which the main loop is updated
|
// Speed (in ms) at which the main loop is updated
|
||||||
_idleSpeed: 200,
|
_idleSpeed: 200,
|
||||||
@ -226,22 +227,173 @@ export const CONSTANTS: {
|
|||||||
// BitNode/Source-File related stuff
|
// BitNode/Source-File related stuff
|
||||||
TotalNumBitNodes: 24,
|
TotalNumBitNodes: 24,
|
||||||
|
|
||||||
|
InfiniteLoopLimit: 1000,
|
||||||
|
|
||||||
Donations: 7,
|
Donations: 7,
|
||||||
|
|
||||||
LatestUpdate: `
|
LatestUpdate: `
|
||||||
v1.6.3 - 2022-04-01 Few stanek fixes
|
## [draft] v1.7.0 - 2022-04-13 to 2022-05-20
|
||||||
----------------------------
|
|
||||||
|
|
||||||
Stanek Gift
|
#### Information
|
||||||
|
|
||||||
* Has a minimum size of 2x3
|
Modifications included between **2022-04-13** and **2022-05-20** 'b5e4d70' to '0fbe4a1').
|
||||||
* Active Fragment property 'avgCharge' renamed to 'highestCharge'
|
|
||||||
* Formula for fragment effect updated to make 561% more sense.
|
|
||||||
Now you can charge to your heart content.
|
|
||||||
* Logs for the 'chargeFragment' function updated.
|
|
||||||
|
|
||||||
Misc.
|
_[See Pull Requests on GitHub](https://github.com/search?q=user%3Adanielyxie%20repo%3Abitburner%20is%3Apr%20is%3Amerged%20merged%3A%222022-04-13T16%3A32%3A26.000Z..2022-05-20T06%3A08%3A51.000Z%22)_
|
||||||
|
|
||||||
|
#### Merged Pull Requests
|
||||||
|
|
||||||
|
- [Feature] Monaco Theme Editor (by @nickofolas) #[3438](https://github.com/danielyxie/bitburner/pull/3438)
|
||||||
|
- [Fix] Dummy Stanek grid width (by @nickofolas) #[3442](https://github.com/danielyxie/bitburner/pull/3442)
|
||||||
|
- [Fix] Theme browser assets not loading (by @nickofolas) #[3446](https://github.com/danielyxie/bitburner/pull/3446)
|
||||||
|
- Accept valid JSON arrays in coding contracts (by @Savlik) #[3247](https://github.com/danielyxie/bitburner/pull/3247)
|
||||||
|
- another dark theme? (by @hydroflame) #[3450](https://github.com/danielyxie/bitburner/pull/3450)
|
||||||
|
- API: Add repFromDonation() to the Formula API (by @Hoekstraa) #[3461](https://github.com/danielyxie/bitburner/pull/3461)
|
||||||
|
- API: Add safeguard to ns.killall(), preventing killing itself by default (by @Hoekstraa) #[3607](https://github.com/danielyxie/bitburner/pull/3607)
|
||||||
|
- API: FIX #2993 sleeve.travel with invalid city names (by @TheMas3212) #[3458](https://github.com/danielyxie/bitburner/pull/3458)
|
||||||
|
- API: Fix inconsistent return value in 'ns.grafting.getAugmentationGraftTime' (by @nickofolas) #[3539](https://github.com/danielyxie/bitburner/pull/3539)
|
||||||
|
- API: Fix leak of real Employee object in hireEmployee (by @TheMas3212) #[3483](https://github.com/danielyxie/bitburner/pull/3483)
|
||||||
|
- API: replace a number of references to workerscript.log with \_ctx.log (by @TheMas3212) #[3470](https://github.com/danielyxie/bitburner/pull/3470)
|
||||||
|
- API: Terminal screen can now be cleared from within scripts with ns.ui.clearTerminal() (by @Hoekstraa) #[3618](https://github.com/danielyxie/bitburner/pull/3618)
|
||||||
|
- AUGMENTATIONS: Fix 'isSpecial' filter in helper (Removes NeuroFlux, Stanek's Gift, etc from gangs) (by @nickofolas) #[3565](https://github.com/danielyxie/bitburner/pull/3565)
|
||||||
|
- AUGMENTATIONS: Fix Augmentation rep req not being properly influenced by BitNode multipliers (by @nickofolas) #[3652](https://github.com/danielyxie/bitburner/pull/3652)
|
||||||
|
- AUGMENTATIONS: Fix NeuroFlux being applied improperly and migrate broken saves (by @nickofolas) #[3613](https://github.com/danielyxie/bitburner/pull/3613)
|
||||||
|
- AUGMENTATIONS: Fix reputation check for faction augs (by @nickofolas) #[3609](https://github.com/danielyxie/bitburner/pull/3609)
|
||||||
|
- AUGMENTATIONS: Tweak a couple small UI elements (by @nickofolas) #[3614](https://github.com/danielyxie/bitburner/pull/3614)
|
||||||
|
- basic doc no longer hacker themed (by @hydroflame) #[3449](https://github.com/danielyxie/bitburner/pull/3449)
|
||||||
|
- BITNODE: FIX #3546 BitVerse now shows proper BN level when accessed via flume (by @nickofolas) #[3550](https://github.com/danielyxie/bitburner/pull/3550)
|
||||||
|
- BLADEBURNER: fixes #3648 : Automate console command capitalisation inconsistent (by @Vic1970) #[3647](https://github.com/danielyxie/bitburner/pull/3647)
|
||||||
|
- BLADEBURNER: Fix #3594 Blade's Simulacrum worked without being installed (by @Undeemiss) #[3639](https://github.com/danielyxie/bitburner/pull/3639)
|
||||||
|
- blood (by @hydroflame) #[3495](https://github.com/danielyxie/bitburner/pull/3495)
|
||||||
|
- BUGFIX: getAugmentationCost response backwards (by @phyzical) #[3617](https://github.com/danielyxie/bitburner/pull/3617)
|
||||||
|
- BUGFIX: Handle edge case in LZ compression code and fix docs (by @stalefishies) #[3581](https://github.com/danielyxie/bitburner/pull/3581)
|
||||||
|
- BUGFIX: make bonustime for gang in miliseconds (by @phyzical) #[3578](https://github.com/danielyxie/bitburner/pull/3578)
|
||||||
|
- BUGFIX: sleeve stale object refence during augmentation (by @phyzical) #[3601](https://github.com/danielyxie/bitburner/pull/3601)
|
||||||
|
- Bugfix/corp updates (by @phyzical) #[3321](https://github.com/danielyxie/bitburner/pull/3321)
|
||||||
|
- Bump async from 2.6.3 to 2.6.4 (by @dependabot[bot]) #[3463](https://github.com/danielyxie/bitburner/pull/3463)
|
||||||
|
- CODINGCONTRACT: Fix #3391 Double contract reward exploit (by @Undeemiss) #[3646](https://github.com/danielyxie/bitburner/pull/3646)
|
||||||
|
- CODINGCONTRACT: FIX #3484 BREAKING Fixed capitalization in contract name (by @Undeemiss) #[3537](https://github.com/danielyxie/bitburner/pull/3537)
|
||||||
|
- CODINGCONTRACT: New "Proper 2-Coloring of a Graph" contract (by @Undeemiss) #[3530](https://github.com/danielyxie/bitburner/pull/3530)
|
||||||
|
- CODINGCONTRACT: Three new compression contracts (by @stalefishies) #[3541](https://github.com/danielyxie/bitburner/pull/3541)
|
||||||
|
- CODINGCONTRACT: Typo & clarity fixes to description of Encoded Binary to Integer contract (by @ActuallyCurtis) #[3469](https://github.com/danielyxie/bitburner/pull/3469)
|
||||||
|
- CODINGCONTRACT: Updated description of 2-coloring contract (by @Undeemiss) #[3531](https://github.com/danielyxie/bitburner/pull/3531)
|
||||||
|
- COMPANY: Fix #3551 Applying for a new job will not change active employer if player is performing company work (by @Snarling) #[3552](https://github.com/danielyxie/bitburner/pull/3552)
|
||||||
|
- CORPORATIONS: Expose makeProducts on NSDivision interface (by @DavidGrinberg) #[3570](https://github.com/danielyxie/bitburner/pull/3570)
|
||||||
|
- CORPORATIONS: Expose sales cost on NSMaterial interface (by @DavidGrinberg) #[3574](https://github.com/danielyxie/bitburner/pull/3574)
|
||||||
|
- Corrected example grids found in Stanek help (by @Undeemiss) #[3441](https://github.com/danielyxie/bitburner/pull/3441)
|
||||||
|
- Create program action no longer creates duplicates (by @Undeemiss) #[3436](https://github.com/danielyxie/bitburner/pull/3436)
|
||||||
|
- DOCUMENTATION: Add descriptions for compression contracts (by @stalefishies) #[3559](https://github.com/danielyxie/bitburner/pull/3559)
|
||||||
|
- DOCUMENTATION: Add new coding contract descriptions (by @stalefishies) #[3542](https://github.com/danielyxie/bitburner/pull/3542)
|
||||||
|
- DOCUMENTATION: Clarify definition for installAugmentations() (by @PSEUDOSTAGE) #[3560](https://github.com/danielyxie/bitburner/pull/3560)
|
||||||
|
- DOCUMENTATION: FIX #3516 "cannot" misspelled as "cannnot" (by @Undeemiss) #[3533](https://github.com/danielyxie/bitburner/pull/3533)
|
||||||
|
- EDITOR: FIX #3502 Editor theme migration crash (by @nickofolas) #[3503](https://github.com/danielyxie/bitburner/pull/3503)
|
||||||
|
- FEATURE: added logic to allow quitJob to be called from singularity (by @phyzical) #[3577](https://github.com/danielyxie/bitburner/pull/3577)
|
||||||
|
- fix #3395 donating to special factions possible via singularity (by @TheMas3212) #[3456](https://github.com/danielyxie/bitburner/pull/3456)
|
||||||
|
- fix b1tflum3 and destroyW0r1dD43m0n singularity functions to check for sf4 (by @TheMas3212) #[3443](https://github.com/danielyxie/bitburner/pull/3443)
|
||||||
|
- Fix inconsistancy with trying to work for gang factions while running a gang (by @TheMas3212) #[3454](https://github.com/danielyxie/bitburner/pull/3454)
|
||||||
|
- Fix infiltration rep BN mult calculation (by @trambelus) #[3632](https://github.com/danielyxie/bitburner/pull/3632)
|
||||||
|
- Fix script editor settings. (by @hydroflame) #[3504](https://github.com/danielyxie/bitburner/pull/3504)
|
||||||
|
- Fix test/jest/Netscript/DynamicRamCalculation.test.js (by @TheMas3212) #[3455](https://github.com/danielyxie/bitburner/pull/3455)
|
||||||
|
- GRAFTING: Fix Grafting not being handled in singularity stop work (by @nickofolas) #[3568](https://github.com/danielyxie/bitburner/pull/3568)
|
||||||
|
- GRAFTING: Implement sorting options (by @nickofolas) #[3654](https://github.com/danielyxie/bitburner/pull/3654)
|
||||||
|
- INFILTRATION: Added new faction called infiltrators that provide infiltration specific augs. (by @phyzical) #[3241](https://github.com/danielyxie/bitburner/pull/3241)
|
||||||
|
- INFILTRATION: Fix minigame cycle (by @nickofolas) #[3549](https://github.com/danielyxie/bitburner/pull/3549)
|
||||||
|
- INFILTRATION: Fix phyzical WKS aug effects being applied before aug is installed (by @nickofolas) #[3555](https://github.com/danielyxie/bitburner/pull/3555)
|
||||||
|
- INFILTRATION: Fix rep reward being substantially higher than intended (by @nickofolas) #[3562](https://github.com/danielyxie/bitburner/pull/3562)
|
||||||
|
- INFILTRATION: New faction, Shadows of Anarchy, provides various augs to help infiltrations. (by @hydroflame) #[3543](https://github.com/danielyxie/bitburner/pull/3543)
|
||||||
|
- INFILTRATION: Update gameplay UI (by @nickofolas) #[3587](https://github.com/danielyxie/bitburner/pull/3587)
|
||||||
|
- keeping up to date (by @hydroflame) #[3432](https://github.com/danielyxie/bitburner/pull/3432)
|
||||||
|
- Keeping up to date. (by @hydroflame) #[3561](https://github.com/danielyxie/bitburner/pull/3561)
|
||||||
|
- Make .lit and .msg files clickable (by @Chris380) #[3453](https://github.com/danielyxie/bitburner/pull/3453)
|
||||||
|
- MESSAGES: Added the name of NiteSec's server to their .msg (by @Undeemiss) #[3466](https://github.com/danielyxie/bitburner/pull/3466)
|
||||||
|
- MISC: add better typing to Electron.tsx (by @taralx) #[3540](https://github.com/danielyxie/bitburner/pull/3540)
|
||||||
|
- MISC: Added NS function closeTail to close tail windows (by @Undeemiss) #[3666](https://github.com/danielyxie/bitburner/pull/3666)
|
||||||
|
- MISC: Adjust deps to current usage (by @taralx) #[3519](https://github.com/danielyxie/bitburner/pull/3519)
|
||||||
|
- MISC: Close some GitHub issues that do not need action (by @Undeemiss) #[3640](https://github.com/danielyxie/bitburner/pull/3640)
|
||||||
|
- MISC: Closing more GitHub issues I missed last time (by @Undeemiss) #[3665](https://github.com/danielyxie/bitburner/pull/3665)
|
||||||
|
- MISC: Correct BB Skill point achievement name (by @Undeemiss) #[3571](https://github.com/danielyxie/bitburner/pull/3571)
|
||||||
|
- MISC: Correct typos in getScriptRam docs. (by @nzdjb) #[3590](https://github.com/danielyxie/bitburner/pull/3590)
|
||||||
|
- MISC: Fix #3125 BREAKING Renamed BN mult CorporationSoftCap to CorporationSoftcap (by @Undeemiss) #[3638](https://github.com/danielyxie/bitburner/pull/3638)
|
||||||
|
- MISC: FIX #3593 Float errors can no longer prevent full usage of a server's available ram. (by @Snarling) #[3619](https://github.com/danielyxie/bitburner/pull/3619)
|
||||||
|
- MISC: fix typing conflict between jest and cypress (by @taralx) #[3518](https://github.com/danielyxie/bitburner/pull/3518)
|
||||||
|
- MISC: fix typing conflict between jest and cypress (by @taralx) #[3644](https://github.com/danielyxie/bitburner/pull/3644)
|
||||||
|
- MISC: Fixed typo in exceptionAlert.ts (by @Undeemiss) #[3572](https://github.com/danielyxie/bitburner/pull/3572)
|
||||||
|
- MISC: Fixed typos in game options (by @notacompsciguy) #[3584](https://github.com/danielyxie/bitburner/pull/3584)
|
||||||
|
- MISC: HammingCodingContracts need rework (by @Hedrauta) #[3479](https://github.com/danielyxie/bitburner/pull/3479)
|
||||||
|
- MISC: Implemented infinite loop safety net. (by @hydroflame) #[3624](https://github.com/danielyxie/bitburner/pull/3624)
|
||||||
|
- MISC: make jQuery use explicit (by @taralx) #[3517](https://github.com/danielyxie/bitburner/pull/3517)
|
||||||
|
- MISC: Make tutorial explain ns1 vs ns2 better (by @hydroflame) #[3586](https://github.com/danielyxie/bitburner/pull/3586)
|
||||||
|
- MISC: Remove comments that describe nonexistent augs (by @Undeemiss) #[3569](https://github.com/danielyxie/bitburner/pull/3569)
|
||||||
|
- MISC: update @types/numeral and fix type errors (by @taralx) #[3521](https://github.com/danielyxie/bitburner/pull/3521)
|
||||||
|
- MISC: Update logic for stats page BitNode level (by @nickofolas) #[3512](https://github.com/danielyxie/bitburner/pull/3512)
|
||||||
|
- MISC: upgrade to eslint v8 (by @taralx) #[3523](https://github.com/danielyxie/bitburner/pull/3523)
|
||||||
|
- MISC: Wrap most of the API in the new api wrapper (by @hydroflame) #[3627](https://github.com/danielyxie/bitburner/pull/3627)
|
||||||
|
- OPTIONS: Fix sliders not sliding correctly (by @nickofolas) #[3642](https://github.com/danielyxie/bitburner/pull/3642)
|
||||||
|
- REFACTOR: augmentation cost, rep cost and level to be calculated in place (by @phyzical) #[3544](https://github.com/danielyxie/bitburner/pull/3544)
|
||||||
|
- REFACTOR: augmentation isSpecial adjustments (by @phyzical) #[3564](https://github.com/danielyxie/bitburner/pull/3564)
|
||||||
|
- Reran npm format and lint to fix formatting (by @Undeemiss) #[3434](https://github.com/danielyxie/bitburner/pull/3434)
|
||||||
|
- Revert "MISC: fix typing conflict between jest and cypress" (by @hydroflame) #[3608](https://github.com/danielyxie/bitburner/pull/3608)
|
||||||
|
- Revert "MISC: HammingCodingContracts need rework" (by @hydroflame) #[3500](https://github.com/danielyxie/bitburner/pull/3500)
|
||||||
|
- revert theme (by @hydroflame) #[3451](https://github.com/danielyxie/bitburner/pull/3451)
|
||||||
|
- Singularity: Fix #3489 Disable checkTixApiAccess for purchase4SMarketData (by @DavidGrinberg) #[3490](https://github.com/danielyxie/bitburner/pull/3490)
|
||||||
|
- SLEEVES: Fix issues with Sleeve UI crashing when Sleeve task faction becomes gang faction (by @nickofolas) #[3557](https://github.com/danielyxie/bitburner/pull/3557)
|
||||||
|
- STANEK: Fix #3196 Charging booster fragments throws an error (by @Undeemiss) #[3637](https://github.com/danielyxie/bitburner/pull/3637)
|
||||||
|
- STANEK: FIX #3277 Can no longer overlap rotated fragments (by @Undeemiss) #[3460](https://github.com/danielyxie/bitburner/pull/3460)
|
||||||
|
- STANEK: FIX #3282 Added NS function stanek.acceptGift (by @Undeemiss) #[3513](https://github.com/danielyxie/bitburner/pull/3513)
|
||||||
|
- STANEK: Properly reapply entropy in Stanek's Gift (by @nickofolas) #[3673](https://github.com/danielyxie/bitburner/pull/3673)
|
||||||
|
- STANEK: Stanek NS functions correctly throw errors when stanek not installed (by @Undeemiss) #[3660](https://github.com/danielyxie/bitburner/pull/3660)
|
||||||
|
- Started collecting lore so that additions to it are simpler (by @Undeemiss) #[3465](https://github.com/danielyxie/bitburner/pull/3465)
|
||||||
|
- TERMINAL: FIX #3492 Allow cd .. even when destination directory is empty (by @Snarling) #[3525](https://github.com/danielyxie/bitburner/pull/3525)
|
||||||
|
- TERMINAL: FIX #3651 Make directory name regex more flexible (by @Dane-Horn) #[3653](https://github.com/danielyxie/bitburner/pull/3653)
|
||||||
|
- TOOLING: Add GitHub action to validate PR titles (by @MartinFournier) #[3471](https://github.com/danielyxie/bitburner/pull/3471)
|
||||||
|
- UI FIX #3485 - Allow bulk purchasing when smart supply is enabled (by @phyzical) #[3486](https://github.com/danielyxie/bitburner/pull/3486)
|
||||||
|
- UI: Change text color of Augmentations page backup button (by @nickofolas) #[3511](https://github.com/danielyxie/bitburner/pull/3511)
|
||||||
|
- UI: FIX #1754 Stanek effect summary & slight tweak. (by @borisflagell) #[3622](https://github.com/danielyxie/bitburner/pull/3622)
|
||||||
|
- UI: FIX #2228,#2958 Fix tab highlights and highlight files not on home. (by @phyzical) #[2989](https://github.com/danielyxie/bitburner/pull/2989)
|
||||||
|
- UI: FIX #2256 Hacknet server's upgrade tooltip were not handling RAM… (by @borisflagell) #[3532](https://github.com/danielyxie/bitburner/pull/3532)
|
||||||
|
- UI: FIX #2741 Allow using modifier keys inside the typing infiltration (by @Dane-Horn) #[3634](https://github.com/danielyxie/bitburner/pull/3634)
|
||||||
|
- UI: FIX #2829 Remove defeated NPC gangs from territory page (by @Dane-Horn) #[3633](https://github.com/danielyxie/bitburner/pull/3633)
|
||||||
|
- UI: FIX #3313 Streamline the GraftingRoot page by making it rerender. (by @borisflagell) #[3558](https://github.com/danielyxie/bitburner/pull/3558)
|
||||||
|
- UI: FIX #3341 Enable touch-clicks in react-draggable (by @Snarling) #[3488](https://github.com/danielyxie/bitburner/pull/3488)
|
||||||
|
- UI: FIX #3415 Tweak Manage Gang button visibility (by @borisflagell) #[3528](https://github.com/danielyxie/bitburner/pull/3528)
|
||||||
|
- UI: FIX #3457 autocomplete suggestions no longer require hovering terminal input (by @Snarling) #[3493](https://github.com/danielyxie/bitburner/pull/3493)
|
||||||
|
- UI: FIX #3473 'mv' now says destination script is running instead of returning an error (by @Hoekstraa) #[3474](https://github.com/danielyxie/bitburner/pull/3474)
|
||||||
|
- UI: FIX #3522 realigned autocomplete popup (by @Snarling) #[3524](https://github.com/danielyxie/bitburner/pull/3524)
|
||||||
|
- UI: FIX #3592 Sidebar and bash shortcuts now work on MacOS with US-like layouts (by @Hoekstraa) #[3605](https://github.com/danielyxie/bitburner/pull/3605)
|
||||||
|
- UI: Fix Agility BitNode multiplier not appearing in UI (by @nickofolas) #[3662](https://github.com/danielyxie/bitburner/pull/3662)
|
||||||
|
- UI: Fix exclusive augs not always showing as purchasable through gangs when they should (by @nickofolas) #[3676](https://github.com/danielyxie/bitburner/pull/3676)
|
||||||
|
- UI: Fix the achievement covenant icon was not shown (by @Risenafis) #[3510](https://github.com/danielyxie/bitburner/pull/3510)
|
||||||
|
- UI: Fix z-index of modals overriding everything (by @nickofolas) #[3620](https://github.com/danielyxie/bitburner/pull/3620)
|
||||||
|
- UI: lightweight description update on "increase maximum money" hash spending option. (by @borisflagell) #[3547](https://github.com/danielyxie/bitburner/pull/3547)
|
||||||
|
- UI: Minor improvements to log boxes (by @nickofolas) #[3641](https://github.com/danielyxie/bitburner/pull/3641)
|
||||||
|
- UI: Overhaul GameOptions UI (by @nickofolas) #[3505](https://github.com/danielyxie/bitburner/pull/3505)
|
||||||
|
- UI: Positioning improved for tail titlebar buttons, and tail window has minimum size constraints. (by @Snarling) #[3548](https://github.com/danielyxie/bitburner/pull/3548)
|
||||||
|
- UI: Redesign purchasable Augmentations (by @nickofolas) #[3545](https://github.com/danielyxie/bitburner/pull/3545)
|
||||||
|
- UI: Refactor and redesign WorkInProgress interface (by @nickofolas) #[3611](https://github.com/danielyxie/bitburner/pull/3611)
|
||||||
|
- UI: Refactors, redesigns, and new section to stats page (by @nickofolas) #[3626](https://github.com/danielyxie/bitburner/pull/3626)
|
||||||
|
- UI: Sort and color Graft Augmentation list (by @jaype87) #[3616](https://github.com/danielyxie/bitburner/pull/3616)
|
||||||
|
- UI: Update Factions list interface (by @nickofolas) #[3675](https://github.com/danielyxie/bitburner/pull/3675)
|
||||||
|
- WORK: FIX #3435 Quitting the active job now sets first remaining job as active (by @Snarling) #[3507](https://github.com/danielyxie/bitburner/pull/3507)
|
||||||
|
- WORK: Refactor work types to use 'enum's instead of constants (by @nickofolas) #[3612](https://github.com/danielyxie/bitburner/pull/3612)
|
||||||
|
|
||||||
|
#### Other Changes
|
||||||
|
|
||||||
|
- increase donation counter (by @hydroflame) - [8456410](https://github.com/danielyxie/bitburner/commit/84564100e90c46ae4b816853c2cdea0bc309af4d)
|
||||||
|
- allbuild commit 7f9e3775 (by @hydroflame) - [791c19c](https://github.com/danielyxie/bitburner/commit/791c19c4fe447c9231bfb423b9fc48114e783b43)
|
||||||
|
- allbuild commit bcbda22a (by @hydroflame) - [032c440](https://github.com/danielyxie/bitburner/commit/032c440eaeb069eecd720ec2f8e069f705a0c1b4)
|
||||||
|
- fix documentation for getDarkwebPrograms (by @hydroflame) - [4056956](https://github.com/danielyxie/bitburner/commit/4056956c2ada37946333bdad44cb0b6eb3909bf8)
|
||||||
|
- support ASNI (by @hydroflame) - [36c7ef1](https://github.com/danielyxie/bitburner/commit/36c7ef1ad7ea8bb69fca23bce5883a3c2e23f1e0)
|
||||||
|
- allbuild commit 22b6d0d5 (by @hydroflame) - [b46718d](https://github.com/danielyxie/bitburner/commit/b46718d188880ecf716ae045861d81d61e00af4b)
|
||||||
|
- allbuild commit 36c7ef1a (by @hydroflame) - [d0ebf5e](https://github.com/danielyxie/bitburner/commit/d0ebf5e14e0498cb063fde35d63c9f59f2c01e35)
|
||||||
|
- Update documentation for employee (by @hydroflame) - [100e81c](https://github.com/danielyxie/bitburner/commit/100e81c8ab4a408f74cc9bd9ffe2b8bad3d03462)
|
||||||
|
- allbuild commit c799b291 (by @hydroflame) - [f5f5879](https://github.com/danielyxie/bitburner/commit/f5f5879fc380678d978e2b0a29ba7b6f0b4c9ec0)
|
||||||
|
- ideas (by @hydroflame) - [0121fee](https://github.com/danielyxie/bitburner/commit/0121fee6e4c690d01650d1e68a80ea363bb48bce)
|
||||||
|
- allbuild commit 0121fee6 (by @hydroflame) - [5c417e9](https://github.com/danielyxie/bitburner/commit/5c417e9b4df236df8bf3e2f8262b7bce87c934df)
|
||||||
|
- Update codebase for stanek (by @hydroflame) - [c2b4a5b](https://github.com/danielyxie/bitburner/commit/c2b4a5b52a2162d2e49c7317b0a60a349984eb47)
|
||||||
|
- fix lint (by @hydroflame) - [4cc518f](https://github.com/danielyxie/bitburner/commit/4cc518f37723aafb3168b64cd689408afdb74877)
|
||||||
|
- Fix (by @hydroflame) - [9af553f](https://github.com/danielyxie/bitburner/commit/9af553f63cb1380795550648b0134b608564fab8)
|
||||||
|
- Fix stanek leaking classes (by @hydroflame) - [fda3f02](https://github.com/danielyxie/bitburner/commit/fda3f02d73dba27034128c9be5e810a51e475e38)
|
||||||
|
- fix conflicts (by @hydroflame) - [ca1a2aa](https://github.com/danielyxie/bitburner/commit/ca1a2aad333fa838b6d0e57f89e1cedba086a4a0)
|
||||||
|
- Nerf noodle bar.
|
||||||
|
|
||||||
* Nerf noodle bar.
|
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
@ -159,7 +159,7 @@ export class Corporation {
|
|||||||
if (this.unlockUpgrades[6] === 1) {
|
if (this.unlockUpgrades[6] === 1) {
|
||||||
upgrades += 0.1;
|
upgrades += 0.1;
|
||||||
}
|
}
|
||||||
return Math.pow(dividends, BitNodeMultipliers.CorporationSoftCap + upgrades);
|
return Math.pow(dividends, BitNodeMultipliers.CorporationSoftcap + upgrades);
|
||||||
}
|
}
|
||||||
|
|
||||||
determineValuation(): number {
|
determineValuation(): number {
|
||||||
|
@ -68,13 +68,7 @@ export class ActiveFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
copy(): ActiveFragment {
|
copy(): ActiveFragment {
|
||||||
// We have to do a round trip because the constructor.
|
return Object.assign({}, this);
|
||||||
const fragment = FragmentById(this.id);
|
|
||||||
if (fragment === null) throw new Error("ActiveFragment id refers to unknown Fragment.");
|
|
||||||
const c = new ActiveFragment({ x: this.x, y: this.y, rotation: this.rotation, fragment: fragment });
|
|
||||||
c.highestCharge = this.highestCharge;
|
|
||||||
c.numCharge = this.numCharge;
|
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,13 +76,7 @@ export class Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
copy(): Fragment {
|
copy(): Fragment {
|
||||||
return new Fragment(
|
return Object.assign({}, this);
|
||||||
this.id,
|
|
||||||
this.shape.map((a) => a.slice()),
|
|
||||||
this.type,
|
|
||||||
this.power,
|
|
||||||
this.limit,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,8 +136,9 @@ export class StaneksGift implements IStaneksGift {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateMults(p: IPlayer): void {
|
updateMults(p: IPlayer): void {
|
||||||
p.reapplyAllAugmentations(true);
|
// applyEntropy also reapplies all augmentations and source files
|
||||||
p.reapplyAllSourceFiles();
|
// This wraps up the reset nicely
|
||||||
|
p.applyEntropy(p.entropy);
|
||||||
|
|
||||||
for (const aFrag of this.fragments) {
|
for (const aFrag of this.fragments) {
|
||||||
const fragment = aFrag.fragment();
|
const fragment = aFrag.fragment();
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
import { StanekConstants } from "../data/Constants";
|
|
||||||
|
|
||||||
export function CalculateCharge(ram: number): number {
|
|
||||||
return ram * Math.pow(1 + Math.log2(ram) * StanekConstants.RAMBonus, 0.7);
|
|
||||||
}
|
|
@ -1,9 +1,9 @@
|
|||||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||||
|
|
||||||
export function CalculateEffect(avgCharge: number, numCharge: number, power: number, boost: number): number {
|
export function CalculateEffect(highestCharge: number, numCharge: number, power: number, boost: number): number {
|
||||||
return (
|
return (
|
||||||
1 +
|
1 +
|
||||||
(Math.log(avgCharge + 1) / (Math.log(1.8) * 100)) *
|
(Math.log(highestCharge + 1) / 60) *
|
||||||
Math.pow((numCharge + 1) / 5, 0.07) *
|
Math.pow((numCharge + 1) / 5, 0.07) *
|
||||||
power *
|
power *
|
||||||
boost *
|
boost *
|
||||||
|
88
src/CotMG/ui/ActiveFragmentSummary.tsx
Normal file
88
src/CotMG/ui/ActiveFragmentSummary.tsx
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { ActiveFragment } from "../ActiveFragment";
|
||||||
|
import { IStaneksGift } from "../IStaneksGift";
|
||||||
|
import { FragmentType, Effect } from "../FragmentType";
|
||||||
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
|
||||||
|
import Paper from "@mui/material/Paper";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import Table from "@mui/material/Table";
|
||||||
|
import { TableBody, TableCell, TableRow } from "@mui/material";
|
||||||
|
|
||||||
|
type IProps = {
|
||||||
|
gift: IStaneksGift;
|
||||||
|
};
|
||||||
|
|
||||||
|
function formatEffect(effect: number, type: FragmentType): string {
|
||||||
|
if (Effect(type).includes("+x%")) {
|
||||||
|
return Effect(type).replace(/-*x%/, numeralWrapper.formatPercentage(effect - 1));
|
||||||
|
} else if (Effect(type).includes("-x%")) {
|
||||||
|
const perc = numeralWrapper.formatPercentage(1 - 1 / effect);
|
||||||
|
return Effect(type).replace(/-x%/, perc);
|
||||||
|
} else {
|
||||||
|
return Effect(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ActiveFragmentSummary(props: IProps): React.ReactElement {
|
||||||
|
const summary: { coordinate: { x: number; y: number }[]; effect: number; type: FragmentType }[] = [];
|
||||||
|
// Iterate through Active Fragment
|
||||||
|
props.gift.fragments.forEach((fragment: ActiveFragment) => {
|
||||||
|
const f = fragment.fragment();
|
||||||
|
// Discard ToolBrush and Booster.
|
||||||
|
if (![FragmentType.Booster, FragmentType.None, FragmentType.Delete].includes(f.type)) {
|
||||||
|
// Check for an existing entry in summary for this fragment's type
|
||||||
|
const entry = summary.find((e) => {
|
||||||
|
return e.type === f.type;
|
||||||
|
});
|
||||||
|
if (entry) {
|
||||||
|
// If there's one, update the existing entry
|
||||||
|
entry.effect *= props.gift.effect(fragment);
|
||||||
|
entry.coordinate.push({ x: fragment.x, y: fragment.y });
|
||||||
|
} else {
|
||||||
|
// If there's none, create a new entry
|
||||||
|
summary.push({
|
||||||
|
coordinate: [{ x: fragment.x, y: fragment.y }],
|
||||||
|
effect: props.gift.effect(fragment),
|
||||||
|
type: f.type,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper sx={{ mb: 1 }}>
|
||||||
|
<Typography variant="h5">Summary of active fragments:</Typography>
|
||||||
|
<Table sx={{ display: "table", width: "100%" }}>
|
||||||
|
<TableBody>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell sx={{ borderBottom: "none", p: 0, m: 0 }}>
|
||||||
|
<Typography>Coordinate</Typography>
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
<TableCell sx={{ borderBottom: "none", p: 0, m: 0 }}>
|
||||||
|
<Typography>Effect</Typography>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
{summary.map((entry) => {
|
||||||
|
return (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell sx={{ borderBottom: "none", p: 0, m: 0 }}>
|
||||||
|
<Typography>
|
||||||
|
{entry.coordinate.map((coord) => {
|
||||||
|
return "[" + coord.x + "," + coord.y + "]";
|
||||||
|
})}
|
||||||
|
</Typography>
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
<TableCell sx={{ borderBottom: "none", p: 0, m: 0 }}>
|
||||||
|
<Typography>{formatEffect(entry.effect, entry.type)}</Typography>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
}
|
@ -25,23 +25,21 @@ export function FragmentInspector(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
if (props.fragment === undefined) {
|
if (props.fragment === undefined) {
|
||||||
return (
|
return (
|
||||||
<Paper>
|
<Paper sx={{ flexGrow: 1 }}>
|
||||||
<Typography>
|
<Typography>
|
||||||
|
[X, Y] {props.x}, {props.y}
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
ID: N/A
|
ID: N/A
|
||||||
<br />
|
<br />
|
||||||
Effect: N/A
|
Effect: N/A
|
||||||
<br />
|
<br />
|
||||||
Magnitude: N/A
|
Base Power: N/A
|
||||||
<br />
|
<br />
|
||||||
Charge: N/A
|
Charge: N/A
|
||||||
<br />
|
<br />
|
||||||
Heat: N/A
|
root [X, Y] N/A
|
||||||
<br />
|
<br />
|
||||||
Effect: N/A
|
|
||||||
<br />
|
|
||||||
[X, Y] N/A
|
|
||||||
<br />
|
|
||||||
[X, Y] {props.x}, {props.y}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
</Paper>
|
</Paper>
|
||||||
);
|
);
|
||||||
@ -63,8 +61,11 @@ export function FragmentInspector(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper>
|
<Paper sx={{ flexGrow: 1 }}>
|
||||||
<Typography>
|
<Typography>
|
||||||
|
[X, Y] {props.x}, {props.y}
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
ID: {props.fragment.id}
|
ID: {props.fragment.id}
|
||||||
<br />
|
<br />
|
||||||
Effect: {effect}
|
Effect: {effect}
|
||||||
@ -73,10 +74,8 @@ export function FragmentInspector(props: IProps): React.ReactElement {
|
|||||||
<br />
|
<br />
|
||||||
Charge: {charge}
|
Charge: {charge}
|
||||||
<br />
|
<br />
|
||||||
<br />
|
|
||||||
root [X, Y] {props.fragment.x}, {props.fragment.y}
|
root [X, Y] {props.fragment.x}, {props.fragment.y}
|
||||||
<br />
|
<br />
|
||||||
[X, Y] {props.x}, {props.y}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
</Paper>
|
</Paper>
|
||||||
);
|
);
|
||||||
|
@ -9,6 +9,9 @@ import Button from "@mui/material/Button";
|
|||||||
import { Table } from "../../ui/React/Table";
|
import { Table } from "../../ui/React/Table";
|
||||||
import { Grid } from "./Grid";
|
import { Grid } from "./Grid";
|
||||||
import { zeros, calculateGrid } from "../Helper";
|
import { zeros, calculateGrid } from "../Helper";
|
||||||
|
import { ActiveFragmentSummary } from "./ActiveFragmentSummary";
|
||||||
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
gift: IStaneksGift;
|
gift: IStaneksGift;
|
||||||
@ -84,9 +87,8 @@ export function MainBoard(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button onClick={clear}>Clear</Button>
|
<Box display="flex" sx={{ mb: 1 }}>
|
||||||
<Box display="flex">
|
<Table sx={{ mr: 1 }}>
|
||||||
<Table>
|
|
||||||
<Grid
|
<Grid
|
||||||
width={props.gift.width()}
|
width={props.gift.width()}
|
||||||
height={props.gift.height()}
|
height={props.gift.height()}
|
||||||
@ -99,7 +101,22 @@ export function MainBoard(props: IProps): React.ReactElement {
|
|||||||
</Table>
|
</Table>
|
||||||
<FragmentInspector gift={props.gift} x={pos[0]} y={pos[1]} fragment={props.gift.fragmentAt(pos[0], pos[1])} />
|
<FragmentInspector gift={props.gift} x={pos[0]} y={pos[1]} fragment={props.gift.fragmentAt(pos[0], pos[1])} />
|
||||||
</Box>
|
</Box>
|
||||||
<FragmentSelector gift={props.gift} selectFragment={updateSelectedFragment} />
|
<Box display="flex" sx={{ mb: 1 }}>
|
||||||
|
<FragmentSelector gift={props.gift} selectFragment={updateSelectedFragment} />
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<ActiveFragmentSummary gift={props.gift} />
|
||||||
|
|
||||||
|
<Tooltip
|
||||||
|
title={
|
||||||
|
<Typography>
|
||||||
|
WARNING : This will remove all active fragment from the grid. <br />
|
||||||
|
All cumulated charges will be lost.
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Button onClick={clear}>Clear grid</Button>
|
||||||
|
</Tooltip>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import Typography from "@mui/material/Typography";
|
|||||||
import { ActiveFragment } from "../ActiveFragment";
|
import { ActiveFragment } from "../ActiveFragment";
|
||||||
import { Fragments } from "../Fragment";
|
import { Fragments } from "../Fragment";
|
||||||
import { DummyGrid } from "./DummyGrid";
|
import { DummyGrid } from "./DummyGrid";
|
||||||
|
import Container from "@mui/material/Container";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
staneksGift: IStaneksGift;
|
staneksGift: IStaneksGift;
|
||||||
@ -22,7 +23,7 @@ export function StaneksGiftRoot({ staneksGift }: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
useEffect(() => StaneksGiftEvents.subscribe(rerender), []);
|
useEffect(() => StaneksGiftEvents.subscribe(rerender), []);
|
||||||
return (
|
return (
|
||||||
<>
|
<Container maxWidth="lg" disableGutters sx={{ mx: 0 }}>
|
||||||
<Typography variant="h4">
|
<Typography variant="h4">
|
||||||
Stanek's Gift
|
Stanek's Gift
|
||||||
<Info
|
<Info
|
||||||
@ -184,18 +185,18 @@ export function StaneksGiftRoot({ staneksGift }: IProps): React.ReactElement {
|
|||||||
/>
|
/>
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Typography>
|
<Typography sx={{ mb: 1 }}>
|
||||||
The gift is a grid on which you can place upgrades called fragments. The main type of fragment increases a stat,
|
The gift is a grid on which you can place upgrades called fragments. The main type of fragment increases a stat,
|
||||||
like your hacking skill or agility exp. Once a stat fragment is placed it then needs to be charged via scripts
|
like your hacking skill or agility exp. Once a stat fragment is placed it then needs to be charged via scripts
|
||||||
in order to become useful. The other kind of fragments are called booster fragments. They increase the
|
in order to become useful. The other kind of fragments are called booster fragments. They increase the
|
||||||
efficiency of the neighboring fragments (not diagonally). Use Q/E to rotate fragments.
|
efficiency of the neighboring fragments (not diagonally). Use Q/E to rotate fragments.
|
||||||
</Typography>
|
</Typography>
|
||||||
{staneksGift.storedCycles > 5 && (
|
{staneksGift.storedCycles > 5 && (
|
||||||
<Typography>
|
<Typography sx={{ mb: 1 }}>
|
||||||
Bonus time: {convertTimeMsToTimeElapsedString(CONSTANTS._idleSpeed * staneksGift.storedCycles)}
|
Bonus time: {convertTimeMsToTimeElapsedString(CONSTANTS._idleSpeed * staneksGift.storedCycles)}
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
<MainBoard gift={staneksGift} />
|
<MainBoard gift={staneksGift} />
|
||||||
</>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,194 @@
|
|||||||
|
import { Explore, Info, LastPage, LocalPolice, NewReleases, Report, SportsMma } from "@mui/icons-material";
|
||||||
|
import { Box, Button, Container, Paper, Tooltip, Typography, useTheme } from "@mui/material";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
||||||
import { Box, Button, Container, Paper, TableBody, TableRow, Typography } from "@mui/material";
|
|
||||||
|
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { Table, TableCell } from "../../ui/React/Table";
|
import { Settings } from "../../Settings/Settings";
|
||||||
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
import { IRouter } from "../../ui/Router";
|
import { IRouter } from "../../ui/Router";
|
||||||
|
|
||||||
import { Faction } from "../Faction";
|
|
||||||
import { joinFaction, getFactionAugmentationsFiltered } from "../FactionHelpers";
|
|
||||||
import { Factions } from "../Factions";
|
|
||||||
import { FactionNames } from "../data/FactionNames";
|
import { FactionNames } from "../data/FactionNames";
|
||||||
|
import { Faction } from "../Faction";
|
||||||
|
import { getFactionAugmentationsFiltered, joinFaction } from "../FactionHelpers";
|
||||||
|
import { Factions } from "../Factions";
|
||||||
|
|
||||||
export const InvitationsSeen: string[] = [];
|
export const InvitationsSeen: string[] = [];
|
||||||
|
|
||||||
|
const getAugsLeft = (faction: Faction, player: IPlayer): number => {
|
||||||
|
const augs = getFactionAugmentationsFiltered(player, faction);
|
||||||
|
|
||||||
|
return augs.filter((augmentation: string) => !player.hasAugmentation(augmentation)).length;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface IWorkTypeProps {
|
||||||
|
faction: Faction;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fontSize = "small";
|
||||||
|
const marginRight = 0.5;
|
||||||
|
|
||||||
|
const WorkTypesOffered = (props: IWorkTypeProps): React.ReactElement => {
|
||||||
|
const info = props.faction.getInfo();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{info.offerFieldWork && (
|
||||||
|
<Tooltip title="This Faction offers field work">
|
||||||
|
<Explore sx={{ color: Settings.theme.info, mr: marginRight }} fontSize={fontSize} />
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
{info.offerHackingWork && (
|
||||||
|
<Tooltip title="This Faction offers hacking work">
|
||||||
|
<LastPage sx={{ color: Settings.theme.hack, mr: marginRight }} fontSize={fontSize} />
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
{info.offerSecurityWork && (
|
||||||
|
<Tooltip title="This Faction offers security work">
|
||||||
|
<LocalPolice sx={{ color: Settings.theme.combat, mr: marginRight }} fontSize={fontSize} />
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
interface IFactionProps {
|
||||||
|
player: IPlayer;
|
||||||
|
router: IRouter;
|
||||||
|
faction: Faction;
|
||||||
|
|
||||||
|
joined: boolean;
|
||||||
|
|
||||||
|
rerender: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FactionElement = (props: IFactionProps): React.ReactElement => {
|
||||||
|
const facInfo = props.faction.getInfo();
|
||||||
|
|
||||||
|
function openFaction(faction: Faction): void {
|
||||||
|
props.router.toFaction(faction);
|
||||||
|
}
|
||||||
|
|
||||||
|
function openFactionAugPage(faction: Faction): void {
|
||||||
|
props.router.toFaction(faction, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function acceptInvitation(event: React.MouseEvent<HTMLButtonElement, MouseEvent>, faction: string): void {
|
||||||
|
if (!event.isTrusted) return;
|
||||||
|
joinFaction(Factions[faction]);
|
||||||
|
props.rerender();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper
|
||||||
|
sx={{
|
||||||
|
display: "grid",
|
||||||
|
p: 1,
|
||||||
|
alignItems: "center",
|
||||||
|
gridTemplateColumns: "minmax(0, 4fr)" + (props.joined ? " 1fr" : ""),
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box display="flex" sx={{ alignItems: "center" }}>
|
||||||
|
{props.joined ? (
|
||||||
|
<Box
|
||||||
|
display="grid"
|
||||||
|
sx={{
|
||||||
|
mr: 1,
|
||||||
|
gridTemplateColumns: "1fr 1fr",
|
||||||
|
minWidth: "fit-content",
|
||||||
|
gap: 0.5,
|
||||||
|
"& .MuiButton-root": { height: "48px" },
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button onClick={() => openFaction(props.faction)}>Details</Button>
|
||||||
|
<Button onClick={() => openFactionAugPage(props.faction)}>Augments</Button>
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<Button sx={{ height: "48px", mr: 1 }} onClick={(e) => acceptInvitation(e, props.faction.name)}>
|
||||||
|
Join!
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<span style={{ maxWidth: props.joined ? "70%" : "95%" }}>
|
||||||
|
<Typography
|
||||||
|
variant="h6"
|
||||||
|
sx={{
|
||||||
|
mr: 1,
|
||||||
|
display: "grid",
|
||||||
|
gridTemplateColumns: "fit-content(100vw) max-content",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
style={{ overflow: "hidden", whiteSpace: "nowrap", textOverflow: "ellipsis" }}
|
||||||
|
title={props.faction.name}
|
||||||
|
>
|
||||||
|
{props.faction.name}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span style={{ display: "flex", alignItems: "center" }}>
|
||||||
|
{props.player.hasGangWith(props.faction.name) && (
|
||||||
|
<Tooltip title="You have a gang with this Faction">
|
||||||
|
<SportsMma sx={{ color: Settings.theme.hp, ml: 1 }} />
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{facInfo.special && (
|
||||||
|
<Tooltip title="This is a special Faction">
|
||||||
|
<NewReleases sx={{ ml: 1, color: Settings.theme.money, transform: "rotate(180deg)" }} />
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!props.joined && facInfo.enemies.length > 0 && (
|
||||||
|
<Tooltip
|
||||||
|
title={
|
||||||
|
<Typography>
|
||||||
|
This Faction is enemies with:
|
||||||
|
<ul>
|
||||||
|
{facInfo.enemies.map((enemy) => (
|
||||||
|
<li key={enemy}>{enemy}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
Joining this Faction will prevent you from joining its enemies
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Report sx={{ ml: 1, color: Settings.theme.error }} />
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<span style={{ display: "flex", alignItems: "center" }}>
|
||||||
|
{!props.player.hasGangWith(props.faction.name) && <WorkTypesOffered faction={props.faction} />}
|
||||||
|
|
||||||
|
{props.joined && (
|
||||||
|
<Typography variant="body2" sx={{ display: "flex" }}>
|
||||||
|
{getAugsLeft(props.faction, props.player)} Augmentations left
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{props.joined && (
|
||||||
|
<Box display="grid" sx={{ alignItems: "center", justifyItems: "left", gridAutoFlow: "row" }}>
|
||||||
|
<Typography sx={{ color: Settings.theme.rep }}>
|
||||||
|
{numeralWrapper.formatFavor(props.faction.favor)} favor
|
||||||
|
</Typography>
|
||||||
|
<Typography sx={{ color: Settings.theme.rep }}>
|
||||||
|
{numeralWrapper.formatReputation(props.faction.playerReputation)} rep
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
player: IPlayer;
|
player: IPlayer;
|
||||||
router: IRouter;
|
router: IRouter;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FactionsRoot(props: IProps): React.ReactElement {
|
export function FactionsRoot(props: IProps): React.ReactElement {
|
||||||
|
const theme = useTheme();
|
||||||
const setRerender = useState(false)[1];
|
const setRerender = useState(false)[1];
|
||||||
function rerender(): void {
|
function rerender(): void {
|
||||||
setRerender((old) => !old);
|
setRerender((old) => !old);
|
||||||
@ -35,99 +205,90 @@ export function FactionsRoot(props: IProps): React.ReactElement {
|
|||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
function openFaction(faction: Faction): void {
|
|
||||||
props.router.toFaction(faction);
|
|
||||||
}
|
|
||||||
|
|
||||||
function openFactionAugPage(faction: Faction): void {
|
|
||||||
props.router.toFaction(faction, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function acceptInvitation(event: React.MouseEvent<HTMLButtonElement, MouseEvent>, faction: string): void {
|
|
||||||
if (!event.isTrusted) return;
|
|
||||||
joinFaction(Factions[faction]);
|
|
||||||
setRerender((x) => !x);
|
|
||||||
}
|
|
||||||
|
|
||||||
const getAugsLeft = (faction: Faction, player: IPlayer): number => {
|
|
||||||
const augs = getFactionAugmentationsFiltered(player, faction);
|
|
||||||
|
|
||||||
return augs.filter((augmentation: string) => !player.hasAugmentation(augmentation)).length;
|
|
||||||
};
|
|
||||||
|
|
||||||
const allFactions = Object.values(FactionNames).map((faction) => faction as string);
|
const allFactions = Object.values(FactionNames).map((faction) => faction as string);
|
||||||
const allJoinedFactions = props.player.factions.slice(0);
|
const allJoinedFactions = [...props.player.factions];
|
||||||
allJoinedFactions.sort((a, b) => allFactions.indexOf(a) - allFactions.indexOf(b));
|
allJoinedFactions.sort((a, b) => allFactions.indexOf(a) - allFactions.indexOf(b));
|
||||||
|
const invitations = props.player.factionInvitations;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container disableGutters maxWidth="md" sx={{ mx: 0, mb: 10 }}>
|
<Container disableGutters maxWidth="lg" sx={{ mx: 0, mb: 10 }}>
|
||||||
<Typography variant="h4">Factions</Typography>
|
<Typography variant="h4">
|
||||||
<Typography mb={4}>
|
Factions
|
||||||
Throughout the game you may receive invitations from factions. There are many different factions, and each
|
<Tooltip
|
||||||
faction has different criteria for determining its potential members. Joining a faction and furthering its cause
|
title={
|
||||||
is crucial to progressing in the game and unlocking endgame content.
|
<Typography>
|
||||||
|
Throughout the game you may receive invitations from factions. There are many different factions, and each
|
||||||
|
faction has different criteria for determining its potential members. Joining a faction and furthering its
|
||||||
|
cause is crucial to progressing in the game and unlocking endgame content.
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Info sx={{ ml: 1, mb: 0 }} color="info" />
|
||||||
|
</Tooltip>
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Typography variant="h5" color="primary" mt={2} mb={1}>
|
<Box
|
||||||
Factions you have joined:
|
display="grid"
|
||||||
</Typography>
|
sx={{
|
||||||
{(allJoinedFactions.length > 0 && (
|
gap: 1,
|
||||||
<Paper sx={{ my: 1, p: 1, pb: 0, display: "inline-block" }}>
|
gridTemplateColumns: (invitations.length > 0 ? "1fr " : "") + "2fr",
|
||||||
<Table padding="none" style={{ width: "fit-content" }}>
|
[theme.breakpoints.down("lg")]: { gridTemplateColumns: "1fr", "& > span:nth-child(1)": { order: 1 } },
|
||||||
<TableBody>
|
gridTemplateRows: "minmax(0, 1fr)",
|
||||||
{allJoinedFactions.map((faction: string) => (
|
"& > span > .MuiBox-root": {
|
||||||
<TableRow key={faction}>
|
display: "grid",
|
||||||
<TableCell>
|
gridAutoRows: "70px",
|
||||||
<Typography noWrap mb={1}>
|
gap: 1,
|
||||||
{faction}
|
},
|
||||||
</Typography>
|
}}
|
||||||
</TableCell>
|
>
|
||||||
<TableCell align="right">
|
{invitations.length > 0 && (
|
||||||
<Box ml={1} mb={1}>
|
<span>
|
||||||
<Button onClick={() => openFaction(Factions[faction])}>Details</Button>
|
<Typography variant="h5" color="primary">
|
||||||
</Box>
|
Faction Invitations
|
||||||
</TableCell>
|
</Typography>
|
||||||
<TableCell align="right">
|
<Box>
|
||||||
<Box ml={1} mb={1}>
|
{invitations.map((facName) => {
|
||||||
<Button sx={{ width: "100%" }} onClick={() => openFactionAugPage(Factions[faction])}>
|
if (!Factions.hasOwnProperty(facName)) return null;
|
||||||
Augmentations Left: {getAugsLeft(Factions[faction], props.player)}
|
return (
|
||||||
</Button>
|
<FactionElement
|
||||||
</Box>
|
key={facName}
|
||||||
</TableCell>
|
faction={Factions[facName]}
|
||||||
</TableRow>
|
player={props.player}
|
||||||
))}
|
router={props.router}
|
||||||
</TableBody>
|
joined={false}
|
||||||
</Table>
|
rerender={rerender}
|
||||||
</Paper>
|
/>
|
||||||
)) || <Typography>You haven't joined any factions.</Typography>}
|
);
|
||||||
<Typography variant="h5" color="primary" mt={4} mb={1}>
|
})}
|
||||||
Outstanding Faction Invitations
|
</Box>
|
||||||
</Typography>
|
</span>
|
||||||
<Typography mb={1}>
|
)}
|
||||||
Factions you have been invited to. You can accept these faction invitations at any time:
|
|
||||||
</Typography>
|
<span>
|
||||||
{(props.player.factionInvitations.length > 0 && (
|
<Typography variant="h5" color="primary">
|
||||||
<Paper sx={{ my: 1, mb: 4, p: 1, pb: 0, display: "inline-block" }}>
|
Your Factions
|
||||||
<Table padding="none">
|
</Typography>
|
||||||
<TableBody>
|
<Box>
|
||||||
{props.player.factionInvitations.map((faction: string) => (
|
{allJoinedFactions.length > 0 ? (
|
||||||
<TableRow key={faction}>
|
allJoinedFactions.map((facName) => {
|
||||||
<TableCell>
|
if (!Factions.hasOwnProperty(facName)) return null;
|
||||||
<Typography noWrap mb={1}>
|
return (
|
||||||
{faction}
|
<FactionElement
|
||||||
</Typography>
|
key={facName}
|
||||||
</TableCell>
|
faction={Factions[facName]}
|
||||||
<TableCell align="right">
|
player={props.player}
|
||||||
<Box ml={1} mb={1}>
|
router={props.router}
|
||||||
<Button onClick={(e) => acceptInvitation(e, faction)}>Join!</Button>
|
joined={true}
|
||||||
</Box>
|
rerender={rerender}
|
||||||
</TableCell>
|
/>
|
||||||
</TableRow>
|
);
|
||||||
))}
|
})
|
||||||
</TableBody>
|
) : (
|
||||||
</Table>
|
<Typography>You have not yet joined any Factions.</Typography>
|
||||||
</Paper>
|
)}
|
||||||
)) || <Typography>You have no outstanding faction invites.</Typography>}
|
</Box>
|
||||||
|
</span>
|
||||||
|
</Box>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ export const CurrentOptionsPage = (props: IProps): React.ReactElement => {
|
|||||||
<>
|
<>
|
||||||
<OptionsSlider
|
<OptionsSlider
|
||||||
label=".script exec time (ms)"
|
label=".script exec time (ms)"
|
||||||
value={execTime}
|
initialValue={execTime}
|
||||||
callback={handleExecTimeChange}
|
callback={handleExecTimeChange}
|
||||||
step={1}
|
step={1}
|
||||||
min={5}
|
min={5}
|
||||||
@ -84,7 +84,7 @@ export const CurrentOptionsPage = (props: IProps): React.ReactElement => {
|
|||||||
/>
|
/>
|
||||||
<OptionsSlider
|
<OptionsSlider
|
||||||
label="Recently killed scripts size"
|
label="Recently killed scripts size"
|
||||||
value={recentScriptsSize}
|
initialValue={recentScriptsSize}
|
||||||
callback={handleRecentScriptsSizeChange}
|
callback={handleRecentScriptsSizeChange}
|
||||||
step={25}
|
step={25}
|
||||||
min={0}
|
min={0}
|
||||||
@ -98,7 +98,7 @@ export const CurrentOptionsPage = (props: IProps): React.ReactElement => {
|
|||||||
/>
|
/>
|
||||||
<OptionsSlider
|
<OptionsSlider
|
||||||
label="Netscript log size"
|
label="Netscript log size"
|
||||||
value={logSize}
|
initialValue={logSize}
|
||||||
callback={handleLogSizeChange}
|
callback={handleLogSizeChange}
|
||||||
step={20}
|
step={20}
|
||||||
min={20}
|
min={20}
|
||||||
@ -112,7 +112,7 @@ export const CurrentOptionsPage = (props: IProps): React.ReactElement => {
|
|||||||
/>
|
/>
|
||||||
<OptionsSlider
|
<OptionsSlider
|
||||||
label="Netscript port size"
|
label="Netscript port size"
|
||||||
value={portSize}
|
initialValue={portSize}
|
||||||
callback={handlePortSizeChange}
|
callback={handlePortSizeChange}
|
||||||
step={1}
|
step={1}
|
||||||
min={20}
|
min={20}
|
||||||
@ -126,7 +126,7 @@ export const CurrentOptionsPage = (props: IProps): React.ReactElement => {
|
|||||||
/>
|
/>
|
||||||
<OptionsSlider
|
<OptionsSlider
|
||||||
label="Terminal capacity"
|
label="Terminal capacity"
|
||||||
value={terminalSize}
|
initialValue={terminalSize}
|
||||||
callback={handleTerminalSizeChange}
|
callback={handleTerminalSizeChange}
|
||||||
step={50}
|
step={50}
|
||||||
min={50}
|
min={50}
|
||||||
@ -141,7 +141,7 @@ export const CurrentOptionsPage = (props: IProps): React.ReactElement => {
|
|||||||
/>
|
/>
|
||||||
<OptionsSlider
|
<OptionsSlider
|
||||||
label="Autosave interval (s)"
|
label="Autosave interval (s)"
|
||||||
value={autosaveInterval}
|
initialValue={autosaveInterval}
|
||||||
callback={handleAutosaveIntervalChange}
|
callback={handleAutosaveIntervalChange}
|
||||||
step={30}
|
step={30}
|
||||||
min={0}
|
min={0}
|
||||||
@ -179,6 +179,12 @@ export const CurrentOptionsPage = (props: IProps): React.ReactElement => {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<OptionSwitch
|
||||||
|
checked={Settings.InfinityLoopSafety}
|
||||||
|
onChange={(newValue) => (Settings.InfinityLoopSafety = newValue)}
|
||||||
|
text="Script infinite loop safety net"
|
||||||
|
tooltip={<>If this is set the game will attempt to automatically kill scripts stuck in infinite loops.</>}
|
||||||
|
/>
|
||||||
</GameOptionsPage>
|
</GameOptionsPage>
|
||||||
),
|
),
|
||||||
[GameOptionsTab.INTERFACE]: (
|
[GameOptionsTab.INTERFACE]: (
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { Slider, Tooltip, Typography, Box } from "@mui/material";
|
import { Slider, Tooltip, Typography, Box } from "@mui/material";
|
||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
value: any;
|
initialValue: any;
|
||||||
callback: (event: any, newValue: number | number[]) => void;
|
callback: (event: any, newValue: number | number[]) => void;
|
||||||
step: number;
|
step: number;
|
||||||
min: number;
|
min: number;
|
||||||
@ -13,14 +13,21 @@ interface IProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const OptionsSlider = (props: IProps): React.ReactElement => {
|
export const OptionsSlider = (props: IProps): React.ReactElement => {
|
||||||
|
const [value, setValue] = useState(props.initialValue);
|
||||||
|
|
||||||
|
const onChange = (_evt: Event, newValue: number | Array<number>): void => {
|
||||||
|
setValue(newValue);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Tooltip title={<Typography>{props.tooltip}</Typography>}>
|
<Tooltip title={<Typography>{props.tooltip}</Typography>}>
|
||||||
<Typography>{props.label}</Typography>
|
<Typography>{props.label}</Typography>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Slider
|
<Slider
|
||||||
value={props.value}
|
value={value}
|
||||||
onChange={props.callback}
|
onChange={onChange}
|
||||||
|
onChangeCommitted={props.callback}
|
||||||
step={props.step}
|
step={props.step}
|
||||||
min={props.min}
|
min={props.min}
|
||||||
max={props.max}
|
max={props.max}
|
||||||
|
@ -85,9 +85,15 @@ export function TerritorySubpage(): React.ReactElement {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)" }}>
|
<Box sx={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)" }}>
|
||||||
{gangNames.map((name) => (
|
{gangNames
|
||||||
<OtherGangTerritory key={name} name={name} />
|
.sort((a, b) => {
|
||||||
))}
|
if (AllGangs[a].territory <= 0 && AllGangs[b].territory > 0) return 1;
|
||||||
|
if (AllGangs[a].territory > 0 && AllGangs[b].territory <= 0) return -1;
|
||||||
|
return 0;
|
||||||
|
})
|
||||||
|
.map((name) => (
|
||||||
|
<OtherGangTerritory key={name} name={name} />
|
||||||
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
<TerritoryInfoModal open={infoOpen} onClose={() => setInfoOpen(false)} />
|
<TerritoryInfoModal open={infoOpen} onClose={() => setInfoOpen(false)} />
|
||||||
</Container>
|
</Container>
|
||||||
@ -114,14 +120,16 @@ function OtherGangTerritory(props: ITerritoryProps): React.ReactElement {
|
|||||||
const playerPower = AllGangs[gang.facName].power;
|
const playerPower = AllGangs[gang.facName].power;
|
||||||
const power = AllGangs[props.name].power;
|
const power = AllGangs[props.name].power;
|
||||||
const clashVictoryChance = playerPower / (power + playerPower);
|
const clashVictoryChance = playerPower / (power + playerPower);
|
||||||
|
const territory = AllGangs[props.name].territory;
|
||||||
|
const opacity = territory ? 1 : 0.75;
|
||||||
return (
|
return (
|
||||||
<Box component={Paper} sx={{ p: 1 }}>
|
<Box component={Paper} sx={{ p: 1, opacity }}>
|
||||||
<Typography variant="h6" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
|
<Typography variant="h6" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
|
||||||
{props.name}
|
{props.name}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>
|
<Typography>
|
||||||
<b>Power:</b> {formatNumber(power, 3)} <br />
|
<b>Power:</b> {formatNumber(power, 3)} <br />
|
||||||
<b>Territory:</b> {formatTerritory(AllGangs[props.name].territory)}% <br />
|
<b>Territory:</b> {formatTerritory(territory)}% <br />
|
||||||
<b>Clash Win Chance:</b> {numeralWrapper.formatPercentage(clashVictoryChance, 3)}
|
<b>Clash Win Chance:</b> {numeralWrapper.formatPercentage(clashVictoryChance, 3)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -36,7 +36,7 @@ export function calculateTradeInformationRepReward(
|
|||||||
30 *
|
30 *
|
||||||
levelBonus *
|
levelBonus *
|
||||||
(player.hasAugmentation(AugmentationNames.WKSharmonizer, true) ? 1.5 : 1) *
|
(player.hasAugmentation(AugmentationNames.WKSharmonizer, true) ? 1.5 : 1) *
|
||||||
BitNodeMultipliers.InfiltrationMoney
|
BitNodeMultipliers.InfiltrationRep
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,9 +37,13 @@ export function BackwardGame(props: IMinigameProps): React.ReactElement {
|
|||||||
const [guess, setGuess] = useState("");
|
const [guess, setGuess] = useState("");
|
||||||
const hasAugment = Player.hasAugmentation(AugmentationNames.ChaosOfDionysus, true);
|
const hasAugment = Player.hasAugmentation(AugmentationNames.ChaosOfDionysus, true);
|
||||||
|
|
||||||
|
function ignorableKeyboardEvent(event: KeyboardEvent): boolean {
|
||||||
|
return event.key === KEY.BACKSPACE || (event.shiftKey && event.key === "Shift") || event.ctrlKey || event.altKey;
|
||||||
|
}
|
||||||
|
|
||||||
function press(this: Document, event: KeyboardEvent): void {
|
function press(this: Document, event: KeyboardEvent): void {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (event.key === KEY.BACKSPACE) return;
|
if (ignorableKeyboardEvent(event)) return;
|
||||||
const nextGuess = guess + event.key.toUpperCase();
|
const nextGuess = guess + event.key.toUpperCase();
|
||||||
if (!answer.startsWith(nextGuess)) props.onFailure();
|
if (!answer.startsWith(nextGuess)) props.onFailure();
|
||||||
else if (answer === nextGuess) props.onSuccess();
|
else if (answer === nextGuess) props.onSuccess();
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
* Location and traveling-related helper functions.
|
* Location and traveling-related helper functions.
|
||||||
* Mostly used for UI
|
* Mostly used for UI
|
||||||
*/
|
*/
|
||||||
|
import { SpecialServers } from "../Server/data/SpecialServers";
|
||||||
import { CONSTANTS } from "../Constants";
|
import { CONSTANTS } from "../Constants";
|
||||||
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { AddToAllServers, createUniqueRandomIp } from "../Server/AllServers";
|
import { GetServer } from "../Server/AllServers";
|
||||||
import { safetlyCreateUniqueServer } from "../Server/ServerHelpers";
|
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||||
|
|
||||||
@ -25,19 +25,14 @@ export function purchaseTorRouter(p: IPlayer): void {
|
|||||||
}
|
}
|
||||||
p.loseMoney(CONSTANTS.TorRouterCost, "other");
|
p.loseMoney(CONSTANTS.TorRouterCost, "other");
|
||||||
|
|
||||||
const darkweb = safetlyCreateUniqueServer({
|
const darkweb = GetServer(SpecialServers.DarkWeb);
|
||||||
ip: createUniqueRandomIp(),
|
if (!darkweb) {
|
||||||
hostname: "darkweb",
|
throw new Error("Dark web is not a server.");
|
||||||
organizationName: "",
|
}
|
||||||
isConnectedTo: false,
|
|
||||||
adminRights: false,
|
|
||||||
purchasedByPlayer: false,
|
|
||||||
maxRam: 1,
|
|
||||||
});
|
|
||||||
AddToAllServers(darkweb);
|
|
||||||
|
|
||||||
p.getHomeComputer().serversOnNetwork.push(darkweb.hostname);
|
p.getHomeComputer().serversOnNetwork.push(darkweb.hostname);
|
||||||
darkweb.serversOnNetwork.push(p.getHomeComputer().hostname);
|
darkweb.serversOnNetwork.push(p.getHomeComputer().hostname);
|
||||||
|
console.log(darkweb);
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
"You have purchased a TOR router!<br>" +
|
"You have purchased a TOR router!<br>" +
|
||||||
"You now have access to the dark web from your home computer.<br>" +
|
"You now have access to the dark web from your home computer.<br>" +
|
||||||
|
@ -32,7 +32,7 @@ export function RamButton(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bnMult = BitNodeMultipliers.HomeComputerRamCost === 1 ? "" : `\\cdot ${BitNodeMultipliers.HomeComputerRamCost}`;
|
const bnMult = BitNodeMultipliers.HomeComputerRamCost === 1 ? "" : `\\cdot ${BitNodeMultipliers.HomeComputerRamCost}`;
|
||||||
console.log(BitNodeMultipliers.HomeComputerRamCost);
|
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={
|
title={
|
||||||
|
@ -317,7 +317,7 @@ export function SpecialLocation(props: IProps): React.ReactElement {
|
|||||||
return renderGrafting();
|
return renderGrafting();
|
||||||
}
|
}
|
||||||
case LocationName.Sector12CityHall: {
|
case LocationName.Sector12CityHall: {
|
||||||
return (BitNodeMultipliers.CorporationSoftCap < 0.15 && <></>) || <CreateCorporation />;
|
return (BitNodeMultipliers.CorporationSoftcap < 0.15 && <></>) || <CreateCorporation />;
|
||||||
}
|
}
|
||||||
case LocationName.Sector12NSA: {
|
case LocationName.Sector12NSA: {
|
||||||
return renderBladeburner();
|
return renderBladeburner();
|
||||||
|
@ -5,6 +5,8 @@ import type { WorkerScript } from "./WorkerScript";
|
|||||||
import { makeRuntimeRejectMsg } from "../NetscriptEvaluator";
|
import { makeRuntimeRejectMsg } from "../NetscriptEvaluator";
|
||||||
import { Player } from "../Player";
|
import { Player } from "../Player";
|
||||||
import { CityName } from "src/Locations/data/CityNames";
|
import { CityName } from "src/Locations/data/CityNames";
|
||||||
|
import { Settings } from "../Settings/Settings";
|
||||||
|
import { CONSTANTS } from "../Constants";
|
||||||
|
|
||||||
type ExternalFunction = (...args: any[]) => any;
|
type ExternalFunction = (...args: any[]) => any;
|
||||||
type ExternalAPI = {
|
type ExternalAPI = {
|
||||||
@ -91,8 +93,14 @@ function wrapFunction(
|
|||||||
getValidPort: (port: any) => helpers.getValidPort(functionPath, port),
|
getValidPort: (port: any) => helpers.getValidPort(functionPath, port),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
const safetyEnabled = Settings.InfinityLoopSafety;
|
||||||
function wrappedFunction(...args: unknown[]): unknown {
|
function wrappedFunction(...args: unknown[]): unknown {
|
||||||
helpers.updateDynamicRam(ctx.function, getRamCost(Player, ...tree, ctx.function));
|
helpers.updateDynamicRam(ctx.function, getRamCost(Player, ...tree, ctx.function));
|
||||||
|
if (safetyEnabled) workerScript.infiniteLoopSafetyCounter++;
|
||||||
|
if (workerScript.infiniteLoopSafetyCounter > CONSTANTS.InfiniteLoopLimit)
|
||||||
|
throw new Error(
|
||||||
|
`Infinite loop without sleep detected. ${CONSTANTS.InfiniteLoopLimit} ns functions were called without sleep. This will cause your UI to hang.`,
|
||||||
|
);
|
||||||
return func(ctx)(...args);
|
return func(ctx)(...args);
|
||||||
}
|
}
|
||||||
const parent = getNestedProperty(wrappedAPI, ...tree);
|
const parent = getNestedProperty(wrappedAPI, ...tree);
|
||||||
|
@ -51,6 +51,7 @@ export const RamCostConstants: IMap<number> = {
|
|||||||
ScriptCodingContractBaseRamCost: 10,
|
ScriptCodingContractBaseRamCost: 10,
|
||||||
ScriptSleeveBaseRamCost: 4,
|
ScriptSleeveBaseRamCost: 4,
|
||||||
ScriptGetOwnedSourceFiles: 5,
|
ScriptGetOwnedSourceFiles: 5,
|
||||||
|
ScriptClearTerminalCost: 0.2,
|
||||||
|
|
||||||
ScriptSingularityFn1RamCost: 2,
|
ScriptSingularityFn1RamCost: 2,
|
||||||
ScriptSingularityFn2RamCost: 3,
|
ScriptSingularityFn2RamCost: 3,
|
||||||
@ -359,6 +360,7 @@ export const RamCosts: IMap<any> = {
|
|||||||
enableLog: 0,
|
enableLog: 0,
|
||||||
isLogEnabled: 0,
|
isLogEnabled: 0,
|
||||||
getScriptLogs: 0,
|
getScriptLogs: 0,
|
||||||
|
clearTerminal: RamCostConstants.ScriptClearTerminalCost,
|
||||||
nuke: RamCostConstants.ScriptPortProgramRamCost,
|
nuke: RamCostConstants.ScriptPortProgramRamCost,
|
||||||
brutessh: RamCostConstants.ScriptPortProgramRamCost,
|
brutessh: RamCostConstants.ScriptPortProgramRamCost,
|
||||||
ftpcrack: RamCostConstants.ScriptPortProgramRamCost,
|
ftpcrack: RamCostConstants.ScriptPortProgramRamCost,
|
||||||
|
@ -111,6 +111,11 @@ export class WorkerScript {
|
|||||||
*/
|
*/
|
||||||
atExit: any;
|
atExit: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Once this counter reaches it's limit the script crashes. It is reset when a promise completes.
|
||||||
|
*/
|
||||||
|
infiniteLoopSafetyCounter = 0;
|
||||||
|
|
||||||
constructor(runningScriptObj: RunningScript, pid: number, nsFuncsGenerator?: (ws: WorkerScript) => any) {
|
constructor(runningScriptObj: RunningScript, pid: number, nsFuncsGenerator?: (ws: WorkerScript) => any) {
|
||||||
this.name = runningScriptObj.filename;
|
this.name = runningScriptObj.filename;
|
||||||
this.hostname = runningScriptObj.server;
|
this.hostname = runningScriptObj.server;
|
||||||
|
@ -14,6 +14,7 @@ export function netscriptDelay(time: number, workerScript: WorkerScript): Promis
|
|||||||
workerScript.delay = null;
|
workerScript.delay = null;
|
||||||
workerScript.delayReject = undefined;
|
workerScript.delayReject = undefined;
|
||||||
|
|
||||||
|
workerScript.infiniteLoopSafetyCounter = 0;
|
||||||
if (workerScript.env.stopFlag) reject(new ScriptDeath(workerScript));
|
if (workerScript.env.stopFlag) reject(new ScriptDeath(workerScript));
|
||||||
else resolve();
|
else resolve();
|
||||||
}, time);
|
}, time);
|
||||||
|
@ -55,7 +55,7 @@ import { makeRuntimeRejectMsg, netscriptDelay, resolveNetscriptRequestedThreads
|
|||||||
import { numeralWrapper } from "./ui/numeralFormat";
|
import { numeralWrapper } from "./ui/numeralFormat";
|
||||||
import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions";
|
import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions";
|
||||||
|
|
||||||
import { LogBoxEvents } from "./ui/React/LogBoxManager";
|
import { LogBoxEvents, LogBoxCloserEvents } from "./ui/React/LogBoxManager";
|
||||||
import { arrayToString } from "./utils/helpers/arrayToString";
|
import { arrayToString } from "./utils/helpers/arrayToString";
|
||||||
import { isString } from "./utils/helpers/isString";
|
import { isString } from "./utils/helpers/isString";
|
||||||
|
|
||||||
@ -82,6 +82,7 @@ import {
|
|||||||
Gang as IGang,
|
Gang as IGang,
|
||||||
Bladeburner as IBladeburner,
|
Bladeburner as IBladeburner,
|
||||||
Stanek as IStanek,
|
Stanek as IStanek,
|
||||||
|
Sleeve as ISleeve,
|
||||||
Infiltration as IInfiltration,
|
Infiltration as IInfiltration,
|
||||||
RunningScript as IRunningScript,
|
RunningScript as IRunningScript,
|
||||||
RecentScript as IRecentScript,
|
RecentScript as IRecentScript,
|
||||||
@ -93,6 +94,12 @@ import {
|
|||||||
BitNodeMultipliers as IBNMults,
|
BitNodeMultipliers as IBNMults,
|
||||||
Server as IServerDef,
|
Server as IServerDef,
|
||||||
RunningScript as IRunningScriptDef,
|
RunningScript as IRunningScriptDef,
|
||||||
|
Grafting as IGrafting,
|
||||||
|
UserInterface as IUserInterface,
|
||||||
|
TIX as ITIX,
|
||||||
|
Corporation as ICorporation,
|
||||||
|
CodingContract as ICodingContract,
|
||||||
|
Hacknet as IHacknet,
|
||||||
// ToastVariant,
|
// ToastVariant,
|
||||||
} from "./ScriptEditor/NetscriptDefinitions";
|
} from "./ScriptEditor/NetscriptDefinitions";
|
||||||
import { NetscriptSingularity } from "./NetscriptFunctions/Singularity";
|
import { NetscriptSingularity } from "./NetscriptFunctions/Singularity";
|
||||||
@ -360,7 +367,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const hack = function (
|
const hack = async function (
|
||||||
hostname: string,
|
hostname: string,
|
||||||
manual: boolean,
|
manual: boolean,
|
||||||
{ threads: requestedThreads, stock }: any = {},
|
{ threads: requestedThreads, stock }: any = {},
|
||||||
@ -524,23 +531,35 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const gang = NetscriptGang(Player, workerScript, helper);
|
|
||||||
const sleeve = NetscriptSleeve(Player, workerScript, helper);
|
|
||||||
const extra = NetscriptExtra(Player, workerScript, helper);
|
const extra = NetscriptExtra(Player, workerScript, helper);
|
||||||
const hacknet = NetscriptHacknet(Player, workerScript, helper);
|
const formulas = NetscriptFormulas(Player, workerScript, helper);
|
||||||
|
|
||||||
|
const gang = wrapAPI(helper, {}, workerScript, NetscriptGang(Player, workerScript), "gang").gang as unknown as IGang;
|
||||||
|
const sleeve = wrapAPI(helper, {}, workerScript, NetscriptSleeve(Player), "sleeve").sleeve as unknown as ISleeve;
|
||||||
|
const hacknet = wrapAPI(helper, {}, workerScript, NetscriptHacknet(Player, workerScript), "hacknet")
|
||||||
|
.hacknet as unknown as IHacknet;
|
||||||
|
const bladeburner = wrapAPI(helper, {}, workerScript, NetscriptBladeburner(Player, workerScript), "bladeburner")
|
||||||
|
.bladeburner as unknown as IBladeburner;
|
||||||
|
const codingcontract = wrapAPI(
|
||||||
|
helper,
|
||||||
|
{},
|
||||||
|
workerScript,
|
||||||
|
NetscriptCodingContract(Player, workerScript),
|
||||||
|
"codingcontract",
|
||||||
|
).codingcontract as unknown as ICodingContract;
|
||||||
const infiltration = wrapAPI(helper, {}, workerScript, NetscriptInfiltration(Player), "infiltration")
|
const infiltration = wrapAPI(helper, {}, workerScript, NetscriptInfiltration(Player), "infiltration")
|
||||||
.infiltration as unknown as IInfiltration;
|
.infiltration as unknown as IInfiltration;
|
||||||
const stanek = wrapAPI(helper, {}, workerScript, NetscriptStanek(Player, workerScript, helper), "stanek")
|
const stanek = wrapAPI(helper, {}, workerScript, NetscriptStanek(Player, workerScript, helper), "stanek")
|
||||||
.stanek as unknown as IStanek;
|
.stanek as unknown as IStanek;
|
||||||
const bladeburner = NetscriptBladeburner(Player, workerScript, helper);
|
const corporation = wrapAPI(helper, {}, workerScript, NetscriptCorporation(Player, workerScript), "corporation")
|
||||||
const codingcontract = NetscriptCodingContract(Player, workerScript, helper);
|
.corporation as unknown as ICorporation;
|
||||||
const corporation = NetscriptCorporation(Player, workerScript, helper);
|
|
||||||
const formulas = NetscriptFormulas(Player, workerScript, helper);
|
|
||||||
const singularity = wrapAPI(helper, {}, workerScript, NetscriptSingularity(Player, workerScript), "singularity")
|
const singularity = wrapAPI(helper, {}, workerScript, NetscriptSingularity(Player, workerScript), "singularity")
|
||||||
.singularity as unknown as ISingularity;
|
.singularity as unknown as ISingularity;
|
||||||
const stockmarket = NetscriptStockMarket(Player, workerScript, helper);
|
const stockmarket = wrapAPI(helper, {}, workerScript, NetscriptStockMarket(Player, workerScript), "stock")
|
||||||
const ui = NetscriptUserInterface(Player, workerScript, helper);
|
.stock as unknown as ITIX;
|
||||||
const grafting = NetscriptGrafting(Player, workerScript, helper);
|
const ui = wrapAPI(helper, {}, workerScript, NetscriptUserInterface(), "ui").ui as unknown as IUserInterface;
|
||||||
|
const grafting = wrapAPI(helper, {}, workerScript, NetscriptGrafting(Player), "grafting")
|
||||||
|
.grafting as unknown as IGrafting;
|
||||||
|
|
||||||
const base: INS = {
|
const base: INS = {
|
||||||
...singularity,
|
...singularity,
|
||||||
@ -988,6 +1007,12 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
|||||||
|
|
||||||
LogBoxEvents.emit(runningScriptObj);
|
LogBoxEvents.emit(runningScriptObj);
|
||||||
},
|
},
|
||||||
|
closeTail: function (_pid: unknown = workerScript.scriptRef.pid): void {
|
||||||
|
updateDynamicRam("closeTail", getRamCost(Player, "closeTail"));
|
||||||
|
const pid = helper.number("closeTail", "pid", _pid);
|
||||||
|
//Emit an event to tell the game to close the tail window if it exists
|
||||||
|
LogBoxCloserEvents.emit(pid);
|
||||||
|
},
|
||||||
nuke: function (_hostname: unknown): boolean {
|
nuke: function (_hostname: unknown): boolean {
|
||||||
updateDynamicRam("nuke", getRamCost(Player, "nuke"));
|
updateDynamicRam("nuke", getRamCost(Player, "nuke"));
|
||||||
const hostname = helper.string("tail", "hostname", _hostname);
|
const hostname = helper.string("tail", "hostname", _hostname);
|
||||||
|
@ -1,18 +1,13 @@
|
|||||||
import { INetscriptHelper } from "./INetscriptHelper";
|
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { Bladeburner } from "../Bladeburner/Bladeburner";
|
import { Bladeburner } from "../Bladeburner/Bladeburner";
|
||||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
|
||||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
import { Bladeburner as INetscriptBladeburner, BladeburnerCurAction } from "../ScriptEditor/NetscriptDefinitions";
|
import { Bladeburner as INetscriptBladeburner, BladeburnerCurAction } from "../ScriptEditor/NetscriptDefinitions";
|
||||||
import { IAction } from "src/Bladeburner/IAction";
|
import { IAction } from "src/Bladeburner/IAction";
|
||||||
|
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
||||||
|
|
||||||
export function NetscriptBladeburner(
|
export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript): InternalAPI<INetscriptBladeburner> {
|
||||||
player: IPlayer,
|
const checkBladeburnerAccess = function (ctx: NetscriptContext, skipjoined = false): void {
|
||||||
workerScript: WorkerScript,
|
|
||||||
helper: INetscriptHelper,
|
|
||||||
): INetscriptBladeburner {
|
|
||||||
const checkBladeburnerAccess = function (func: string, skipjoined = false): void {
|
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
||||||
const apiAccess =
|
const apiAccess =
|
||||||
@ -22,367 +17,368 @@ export function NetscriptBladeburner(
|
|||||||
});
|
});
|
||||||
if (!apiAccess) {
|
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.`;
|
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);
|
throw ctx.makeRuntimeErrorMsg(apiDenied);
|
||||||
}
|
}
|
||||||
if (!skipjoined) {
|
if (!skipjoined) {
|
||||||
const bladeburnerAccess = bladeburner instanceof Bladeburner;
|
const bladeburnerAccess = bladeburner instanceof Bladeburner;
|
||||||
if (!bladeburnerAccess) {
|
if (!bladeburnerAccess) {
|
||||||
const bladeburnerDenied = `You must be a member of the Bladeburner division to use this API.`;
|
const bladeburnerDenied = `You must be a member of the Bladeburner division to use this API.`;
|
||||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, bladeburnerDenied);
|
throw ctx.makeRuntimeErrorMsg(bladeburnerDenied);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkBladeburnerCity = function (func: string, city: string): void {
|
const checkBladeburnerCity = function (ctx: NetscriptContext, city: string): void {
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
||||||
if (!bladeburner.cities.hasOwnProperty(city)) {
|
if (!bladeburner.cities.hasOwnProperty(city)) {
|
||||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, `Invalid city: ${city}`);
|
throw ctx.makeRuntimeErrorMsg(`Invalid city: ${city}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getBladeburnerActionObject = function (func: string, type: string, name: string): IAction {
|
const getBladeburnerActionObject = function (ctx: NetscriptContext, type: string, name: string): IAction {
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
||||||
const actionId = bladeburner.getActionIdFromTypeAndName(type, name);
|
const actionId = bladeburner.getActionIdFromTypeAndName(type, name);
|
||||||
if (!actionId) {
|
if (!actionId) {
|
||||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, `Invalid action type='${type}', name='${name}'`);
|
throw ctx.makeRuntimeErrorMsg(`Invalid action type='${type}', name='${name}'`);
|
||||||
}
|
}
|
||||||
const actionObj = bladeburner.getActionObject(actionId);
|
const actionObj = bladeburner.getActionObject(actionId);
|
||||||
if (!actionObj) {
|
if (!actionObj) {
|
||||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, `Invalid action type='${type}', name='${name}'`);
|
throw ctx.makeRuntimeErrorMsg(`Invalid action type='${type}', name='${name}'`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return actionObj;
|
return actionObj;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateRam = (funcName: string): void =>
|
|
||||||
helper.updateDynamicRam(funcName, getRamCost(player, "bladeburner", funcName));
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getContractNames: function (): string[] {
|
getContractNames: (ctx: NetscriptContext) => (): string[] => {
|
||||||
updateRam("getContractNames");
|
checkBladeburnerAccess(ctx);
|
||||||
checkBladeburnerAccess("getContractNames");
|
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return bladeburner.getContractNamesNetscriptFn();
|
return bladeburner.getContractNamesNetscriptFn();
|
||||||
},
|
},
|
||||||
getOperationNames: function (): string[] {
|
getOperationNames: (ctx: NetscriptContext) => (): string[] => {
|
||||||
updateRam("getOperationNames");
|
checkBladeburnerAccess(ctx);
|
||||||
checkBladeburnerAccess("getOperationNames");
|
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return bladeburner.getOperationNamesNetscriptFn();
|
return bladeburner.getOperationNamesNetscriptFn();
|
||||||
},
|
},
|
||||||
getBlackOpNames: function (): string[] {
|
getBlackOpNames: (ctx: NetscriptContext) => (): string[] => {
|
||||||
updateRam("getBlackOpNames");
|
checkBladeburnerAccess(ctx);
|
||||||
checkBladeburnerAccess("getBlackOpNames");
|
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return bladeburner.getBlackOpNamesNetscriptFn();
|
return bladeburner.getBlackOpNamesNetscriptFn();
|
||||||
},
|
},
|
||||||
getBlackOpRank: function (_blackOpName: unknown): number {
|
getBlackOpRank:
|
||||||
updateRam("getBlackOpRank");
|
(ctx: NetscriptContext) =>
|
||||||
const blackOpName = helper.string("getBlackOpRank", "blackOpName", _blackOpName);
|
(_blackOpName: unknown): number => {
|
||||||
checkBladeburnerAccess("getBlackOpRank");
|
const blackOpName = ctx.helper.string("blackOpName", _blackOpName);
|
||||||
const action: any = getBladeburnerActionObject("getBlackOpRank", "blackops", blackOpName);
|
checkBladeburnerAccess(ctx);
|
||||||
return action.reqdRank;
|
const action: any = getBladeburnerActionObject(ctx, "blackops", blackOpName);
|
||||||
},
|
return action.reqdRank;
|
||||||
getGeneralActionNames: function (): string[] {
|
},
|
||||||
updateRam("getGeneralActionNames");
|
getGeneralActionNames: (ctx: NetscriptContext) => (): string[] => {
|
||||||
checkBladeburnerAccess("getGeneralActionNames");
|
checkBladeburnerAccess(ctx);
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return bladeburner.getGeneralActionNamesNetscriptFn();
|
return bladeburner.getGeneralActionNamesNetscriptFn();
|
||||||
},
|
},
|
||||||
getSkillNames: function (): string[] {
|
getSkillNames: (ctx: NetscriptContext) => (): string[] => {
|
||||||
updateRam("getSkillNames");
|
checkBladeburnerAccess(ctx);
|
||||||
checkBladeburnerAccess("getSkillNames");
|
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return bladeburner.getSkillNamesNetscriptFn();
|
return bladeburner.getSkillNamesNetscriptFn();
|
||||||
},
|
},
|
||||||
startAction: function (_type: unknown, _name: unknown): boolean {
|
startAction:
|
||||||
updateRam("startAction");
|
(ctx: NetscriptContext) =>
|
||||||
const type = helper.string("startAction", "type", _type);
|
(_type: unknown, _name: unknown): boolean => {
|
||||||
const name = helper.string("startAction", "name", _name);
|
const type = ctx.helper.string("type", _type);
|
||||||
checkBladeburnerAccess("startAction");
|
const name = ctx.helper.string("name", _name);
|
||||||
const bladeburner = player.bladeburner;
|
checkBladeburnerAccess(ctx);
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
const bladeburner = player.bladeburner;
|
||||||
try {
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return bladeburner.startActionNetscriptFn(player, type, name, workerScript);
|
try {
|
||||||
} catch (e: any) {
|
return bladeburner.startActionNetscriptFn(player, type, name, workerScript);
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.startAction", e);
|
} catch (e: any) {
|
||||||
}
|
throw ctx.makeRuntimeErrorMsg(e);
|
||||||
},
|
}
|
||||||
stopBladeburnerAction: function (): void {
|
},
|
||||||
updateRam("stopBladeburnerAction");
|
stopBladeburnerAction: (ctx: NetscriptContext) => (): void => {
|
||||||
checkBladeburnerAccess("stopBladeburnerAction");
|
checkBladeburnerAccess(ctx);
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return bladeburner.resetAction();
|
return bladeburner.resetAction();
|
||||||
},
|
},
|
||||||
getCurrentAction: function (): BladeburnerCurAction {
|
getCurrentAction: (ctx: NetscriptContext) => (): BladeburnerCurAction => {
|
||||||
updateRam("getCurrentAction");
|
checkBladeburnerAccess(ctx);
|
||||||
checkBladeburnerAccess("getCurrentAction");
|
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return bladeburner.getTypeAndNameFromActionId(bladeburner.action);
|
return bladeburner.getTypeAndNameFromActionId(bladeburner.action);
|
||||||
},
|
},
|
||||||
getActionTime: function (_type: unknown, _name: unknown): number {
|
getActionTime:
|
||||||
updateRam("getActionTime");
|
(ctx: NetscriptContext) =>
|
||||||
const type = helper.string("getActionTime", "type", _type);
|
(_type: unknown, _name: unknown): number => {
|
||||||
const name = helper.string("getActionTime", "name", _name);
|
const type = ctx.helper.string("type", _type);
|
||||||
checkBladeburnerAccess("getActionTime");
|
const name = ctx.helper.string("name", _name);
|
||||||
const bladeburner = player.bladeburner;
|
checkBladeburnerAccess(ctx);
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
const bladeburner = player.bladeburner;
|
||||||
try {
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
const time = bladeburner.getActionTimeNetscriptFn(player, type, name);
|
try {
|
||||||
if (typeof time === "string") {
|
const time = bladeburner.getActionTimeNetscriptFn(player, type, name);
|
||||||
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
if (typeof time === "string") {
|
||||||
workerScript.log("bladeburner.getActionTime", () => errorLogText);
|
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
||||||
return -1;
|
ctx.log(() => errorLogText);
|
||||||
} else {
|
return -1;
|
||||||
return time;
|
} else {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
} catch (e: any) {
|
||||||
|
throw ctx.makeRuntimeErrorMsg(e);
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
},
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.getActionTime", e);
|
getActionEstimatedSuccessChance:
|
||||||
}
|
(ctx: NetscriptContext) =>
|
||||||
},
|
(_type: unknown, _name: unknown): [number, number] => {
|
||||||
getActionEstimatedSuccessChance: function (_type: unknown, _name: unknown): [number, number] {
|
const type = ctx.helper.string("type", _type);
|
||||||
updateRam("getActionEstimatedSuccessChance");
|
const name = ctx.helper.string("name", _name);
|
||||||
const type = helper.string("getActionEstimatedSuccessChance", "type", _type);
|
checkBladeburnerAccess(ctx);
|
||||||
const name = helper.string("getActionEstimatedSuccessChance", "name", _name);
|
const bladeburner = player.bladeburner;
|
||||||
checkBladeburnerAccess("getActionEstimatedSuccessChance");
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
const bladeburner = player.bladeburner;
|
try {
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
const chance = bladeburner.getActionEstimatedSuccessChanceNetscriptFn(player, type, name);
|
||||||
try {
|
if (typeof chance === "string") {
|
||||||
const chance = bladeburner.getActionEstimatedSuccessChanceNetscriptFn(player, type, name);
|
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
||||||
if (typeof chance === "string") {
|
ctx.log(() => errorLogText);
|
||||||
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
return [-1, -1];
|
||||||
workerScript.log("bladeburner.getActionTime", () => errorLogText);
|
} else {
|
||||||
return [-1, -1];
|
return chance;
|
||||||
} else {
|
}
|
||||||
return chance;
|
} catch (e: any) {
|
||||||
|
throw ctx.makeRuntimeErrorMsg(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getActionRepGain:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_type: unknown, _name: unknown, _level: unknown): number => {
|
||||||
|
const type = ctx.helper.string("type", _type);
|
||||||
|
const name = ctx.helper.string("name", _name);
|
||||||
|
const level = ctx.helper.number("level", _level);
|
||||||
|
checkBladeburnerAccess(ctx);
|
||||||
|
const action = getBladeburnerActionObject(ctx, 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);
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.getActionEstimatedSuccessChance", e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getActionRepGain: function (_type: unknown, _name: unknown, _level: unknown): number {
|
|
||||||
updateRam("getActionRepGain");
|
|
||||||
const type = helper.string("getActionRepGain", "type", _type);
|
|
||||||
const name = helper.string("getActionRepGain", "name", _name);
|
|
||||||
const level = helper.number("getActionRepGain", "level", _level);
|
|
||||||
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;
|
return action.rankGain * rewardMultiplier * BitNodeMultipliers.BladeburnerRank;
|
||||||
},
|
},
|
||||||
getActionCountRemaining: function (_type: unknown, _name: unknown): number {
|
getActionCountRemaining:
|
||||||
updateRam("getActionCountRemaining");
|
(ctx: NetscriptContext) =>
|
||||||
const type = helper.string("getActionCountRemaining", "type", _type);
|
(_type: unknown, _name: unknown): number => {
|
||||||
const name = helper.string("getActionCountRemaining", "name", _name);
|
const type = ctx.helper.string("type", _type);
|
||||||
checkBladeburnerAccess("getActionCountRemaining");
|
const name = ctx.helper.string("name", _name);
|
||||||
const bladeburner = player.bladeburner;
|
checkBladeburnerAccess(ctx);
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
const bladeburner = player.bladeburner;
|
||||||
try {
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return bladeburner.getActionCountRemainingNetscriptFn(type, name, workerScript);
|
try {
|
||||||
} catch (e: any) {
|
return bladeburner.getActionCountRemainingNetscriptFn(type, name, workerScript);
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.getActionCountRemaining", e);
|
} catch (e: any) {
|
||||||
}
|
throw ctx.makeRuntimeErrorMsg(e);
|
||||||
},
|
}
|
||||||
getActionMaxLevel: function (_type: unknown, _name: unknown): number {
|
},
|
||||||
updateRam("getActionMaxLevel");
|
getActionMaxLevel:
|
||||||
const type = helper.string("getActionMaxLevel", "type", _type);
|
(ctx: NetscriptContext) =>
|
||||||
const name = helper.string("getActionMaxLevel", "name", _name);
|
(_type: unknown, _name: unknown): number => {
|
||||||
checkBladeburnerAccess("getActionMaxLevel");
|
const type = ctx.helper.string("type", _type);
|
||||||
const action = getBladeburnerActionObject("getActionMaxLevel", type, name);
|
const name = ctx.helper.string("name", _name);
|
||||||
return action.maxLevel;
|
checkBladeburnerAccess(ctx);
|
||||||
},
|
const action = getBladeburnerActionObject(ctx, type, name);
|
||||||
getActionCurrentLevel: function (_type: unknown, _name: unknown): number {
|
return action.maxLevel;
|
||||||
updateRam("getActionCurrentLevel");
|
},
|
||||||
const type = helper.string("getActionCurrentLevel", "type", _type);
|
getActionCurrentLevel:
|
||||||
const name = helper.string("getActionCurrentLevel", "name", _name);
|
(ctx: NetscriptContext) =>
|
||||||
checkBladeburnerAccess("getActionCurrentLevel");
|
(_type: unknown, _name: unknown): number => {
|
||||||
const action = getBladeburnerActionObject("getActionCurrentLevel", type, name);
|
const type = ctx.helper.string("type", _type);
|
||||||
return action.level;
|
const name = ctx.helper.string("name", _name);
|
||||||
},
|
checkBladeburnerAccess(ctx);
|
||||||
getActionAutolevel: function (_type: unknown, _name: unknown): boolean {
|
const action = getBladeburnerActionObject(ctx, type, name);
|
||||||
updateRam("getActionAutolevel");
|
return action.level;
|
||||||
const type = helper.string("getActionAutolevel", "type", _type);
|
},
|
||||||
const name = helper.string("getActionAutolevel", "name", _name);
|
getActionAutolevel:
|
||||||
checkBladeburnerAccess("getActionAutolevel");
|
(ctx: NetscriptContext) =>
|
||||||
const action = getBladeburnerActionObject("getActionCurrentLevel", type, name);
|
(_type: unknown, _name: unknown): boolean => {
|
||||||
return action.autoLevel;
|
const type = ctx.helper.string("type", _type);
|
||||||
},
|
const name = ctx.helper.string("name", _name);
|
||||||
setActionAutolevel: function (_type: unknown, _name: unknown, _autoLevel: unknown = true): void {
|
checkBladeburnerAccess(ctx);
|
||||||
updateRam("setActionAutolevel");
|
const action = getBladeburnerActionObject(ctx, type, name);
|
||||||
const type = helper.string("setActionAutolevel", "type", _type);
|
return action.autoLevel;
|
||||||
const name = helper.string("setActionAutolevel", "name", _name);
|
},
|
||||||
const autoLevel = helper.boolean(_autoLevel);
|
setActionAutolevel:
|
||||||
checkBladeburnerAccess("setActionAutolevel");
|
(ctx: NetscriptContext) =>
|
||||||
const action = getBladeburnerActionObject("setActionAutolevel", type, name);
|
(_type: unknown, _name: unknown, _autoLevel: unknown = true): void => {
|
||||||
action.autoLevel = autoLevel;
|
const type = ctx.helper.string("type", _type);
|
||||||
},
|
const name = ctx.helper.string("name", _name);
|
||||||
setActionLevel: function (_type: unknown, _name: unknown, _level: unknown = 1): void {
|
const autoLevel = ctx.helper.boolean(_autoLevel);
|
||||||
updateRam("setActionLevel");
|
checkBladeburnerAccess(ctx);
|
||||||
const type = helper.string("setActionLevel", "type", _type);
|
const action = getBladeburnerActionObject(ctx, type, name);
|
||||||
const name = helper.string("setActionLevel", "name", _name);
|
action.autoLevel = autoLevel;
|
||||||
const level = helper.number("setActionLevel", "level", _level);
|
},
|
||||||
checkBladeburnerAccess("setActionLevel");
|
setActionLevel:
|
||||||
const action = getBladeburnerActionObject("setActionLevel", type, name);
|
(ctx: NetscriptContext) =>
|
||||||
if (level < 1 || level > action.maxLevel) {
|
(_type: unknown, _name: unknown, _level: unknown = 1): void => {
|
||||||
throw helper.makeRuntimeErrorMsg(
|
const type = ctx.helper.string("type", _type);
|
||||||
"bladeburner.setActionLevel",
|
const name = ctx.helper.string("name", _name);
|
||||||
`Level must be between 1 and ${action.maxLevel}, is ${level}`,
|
const level = ctx.helper.number("level", _level);
|
||||||
);
|
checkBladeburnerAccess(ctx);
|
||||||
}
|
const action = getBladeburnerActionObject(ctx, type, name);
|
||||||
action.level = level;
|
if (level < 1 || level > action.maxLevel) {
|
||||||
},
|
ctx.helper.makeRuntimeErrorMsg(`Level must be between 1 and ${action.maxLevel}, is ${level}`);
|
||||||
getRank: function (): number {
|
}
|
||||||
updateRam("getRank");
|
action.level = level;
|
||||||
checkBladeburnerAccess("getRank");
|
},
|
||||||
|
getRank: (ctx: NetscriptContext) => (): number => {
|
||||||
|
checkBladeburnerAccess(ctx);
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return bladeburner.rank;
|
return bladeburner.rank;
|
||||||
},
|
},
|
||||||
getSkillPoints: function (): number {
|
getSkillPoints: (ctx: NetscriptContext) => (): number => {
|
||||||
updateRam("getSkillPoints");
|
checkBladeburnerAccess(ctx);
|
||||||
checkBladeburnerAccess("getSkillPoints");
|
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return bladeburner.skillPoints;
|
return bladeburner.skillPoints;
|
||||||
},
|
},
|
||||||
getSkillLevel: function (_skillName: unknown): number {
|
getSkillLevel:
|
||||||
updateRam("getSkillLevel");
|
(ctx: NetscriptContext) =>
|
||||||
const skillName = helper.string("getSkillLevel", "skillName", _skillName);
|
(_skillName: unknown): number => {
|
||||||
checkBladeburnerAccess("getSkillLevel");
|
const skillName = ctx.helper.string("skillName", _skillName);
|
||||||
const bladeburner = player.bladeburner;
|
checkBladeburnerAccess(ctx);
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
const bladeburner = player.bladeburner;
|
||||||
try {
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return bladeburner.getSkillLevelNetscriptFn(skillName, workerScript);
|
try {
|
||||||
} catch (e: any) {
|
return bladeburner.getSkillLevelNetscriptFn(skillName, workerScript);
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.getSkillLevel", e);
|
} catch (e: any) {
|
||||||
}
|
throw ctx.makeRuntimeErrorMsg(e);
|
||||||
},
|
}
|
||||||
getSkillUpgradeCost: function (_skillName: unknown): number {
|
},
|
||||||
updateRam("getSkillUpgradeCost");
|
getSkillUpgradeCost:
|
||||||
const skillName = helper.string("getSkillUpgradeCost", "skillName", _skillName);
|
(ctx: NetscriptContext) =>
|
||||||
checkBladeburnerAccess("getSkillUpgradeCost");
|
(_skillName: unknown): number => {
|
||||||
const bladeburner = player.bladeburner;
|
const skillName = ctx.helper.string("skillName", _skillName);
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
checkBladeburnerAccess(ctx);
|
||||||
try {
|
const bladeburner = player.bladeburner;
|
||||||
return bladeburner.getSkillUpgradeCostNetscriptFn(skillName, workerScript);
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
} catch (e: any) {
|
try {
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.getSkillUpgradeCost", e);
|
return bladeburner.getSkillUpgradeCostNetscriptFn(skillName, workerScript);
|
||||||
}
|
} catch (e: any) {
|
||||||
},
|
throw ctx.makeRuntimeErrorMsg(e);
|
||||||
upgradeSkill: function (_skillName: unknown): boolean {
|
}
|
||||||
updateRam("upgradeSkill");
|
},
|
||||||
const skillName = helper.string("upgradeSkill", "skillName", _skillName);
|
upgradeSkill:
|
||||||
checkBladeburnerAccess("upgradeSkill");
|
(ctx: NetscriptContext) =>
|
||||||
const bladeburner = player.bladeburner;
|
(_skillName: unknown): boolean => {
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
const skillName = ctx.helper.string("skillName", _skillName);
|
||||||
try {
|
checkBladeburnerAccess(ctx);
|
||||||
return bladeburner.upgradeSkillNetscriptFn(skillName, workerScript);
|
const bladeburner = player.bladeburner;
|
||||||
} catch (e: any) {
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.upgradeSkill", e);
|
try {
|
||||||
}
|
return bladeburner.upgradeSkillNetscriptFn(skillName, workerScript);
|
||||||
},
|
} catch (e: any) {
|
||||||
getTeamSize: function (_type: unknown, _name: unknown): number {
|
throw ctx.makeRuntimeErrorMsg(e);
|
||||||
updateRam("getTeamSize");
|
}
|
||||||
const type = helper.string("getTeamSize", "type", _type);
|
},
|
||||||
const name = helper.string("getTeamSize", "name", _name);
|
getTeamSize:
|
||||||
checkBladeburnerAccess("getTeamSize");
|
(ctx: NetscriptContext) =>
|
||||||
const bladeburner = player.bladeburner;
|
(_type: unknown, _name: unknown): number => {
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
const type = ctx.helper.string("type", _type);
|
||||||
try {
|
const name = ctx.helper.string("name", _name);
|
||||||
return bladeburner.getTeamSizeNetscriptFn(type, name, workerScript);
|
checkBladeburnerAccess(ctx);
|
||||||
} catch (e: any) {
|
const bladeburner = player.bladeburner;
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.getTeamSize", e);
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
}
|
try {
|
||||||
},
|
return bladeburner.getTeamSizeNetscriptFn(type, name, workerScript);
|
||||||
setTeamSize: function (_type: unknown, _name: unknown, _size: unknown): number {
|
} catch (e: any) {
|
||||||
updateRam("setTeamSize");
|
throw ctx.makeRuntimeErrorMsg(e);
|
||||||
const type = helper.string("setTeamSize", "type", _type);
|
}
|
||||||
const name = helper.string("setTeamSize", "name", _name);
|
},
|
||||||
const size = helper.number("setTeamSize", "size", _size);
|
setTeamSize:
|
||||||
checkBladeburnerAccess("setTeamSize");
|
(ctx: NetscriptContext) =>
|
||||||
const bladeburner = player.bladeburner;
|
(_type: unknown, _name: unknown, _size: unknown): number => {
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
const type = ctx.helper.string("type", _type);
|
||||||
try {
|
const name = ctx.helper.string("name", _name);
|
||||||
return bladeburner.setTeamSizeNetscriptFn(type, name, size, workerScript);
|
const size = ctx.helper.number("size", _size);
|
||||||
} catch (e: any) {
|
checkBladeburnerAccess(ctx);
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.setTeamSize", e);
|
const bladeburner = player.bladeburner;
|
||||||
}
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
},
|
try {
|
||||||
getCityEstimatedPopulation: function (_cityName: unknown): number {
|
return bladeburner.setTeamSizeNetscriptFn(type, name, size, workerScript);
|
||||||
updateRam("getCityEstimatedPopulation");
|
} catch (e: any) {
|
||||||
const cityName = helper.string("getCityEstimatedPopulation", "cityName", _cityName);
|
throw ctx.makeRuntimeErrorMsg(e);
|
||||||
checkBladeburnerAccess("getCityEstimatedPopulation");
|
}
|
||||||
checkBladeburnerCity("getCityEstimatedPopulation", cityName);
|
},
|
||||||
const bladeburner = player.bladeburner;
|
getCityEstimatedPopulation:
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
(ctx: NetscriptContext) =>
|
||||||
return bladeburner.cities[cityName].popEst;
|
(_cityName: unknown): number => {
|
||||||
},
|
const cityName = ctx.helper.string("cityName", _cityName);
|
||||||
getCityCommunities: function (_cityName: unknown): number {
|
checkBladeburnerAccess(ctx);
|
||||||
updateRam("getCityCommunities");
|
checkBladeburnerCity(ctx, cityName);
|
||||||
const cityName = helper.string("getCityCommunities", "cityName", _cityName);
|
const bladeburner = player.bladeburner;
|
||||||
checkBladeburnerAccess("getCityCommunities");
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
checkBladeburnerCity("getCityCommunities", cityName);
|
return bladeburner.cities[cityName].popEst;
|
||||||
const bladeburner = player.bladeburner;
|
},
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
getCityCommunities:
|
||||||
return bladeburner.cities[cityName].comms;
|
(ctx: NetscriptContext) =>
|
||||||
},
|
(_cityName: unknown): number => {
|
||||||
getCityChaos: function (_cityName: unknown): number {
|
const cityName = ctx.helper.string("cityName", _cityName);
|
||||||
updateRam("getCityChaos");
|
checkBladeburnerAccess(ctx);
|
||||||
const cityName = helper.string("getCityChaos", "cityName", _cityName);
|
checkBladeburnerCity(ctx, cityName);
|
||||||
checkBladeburnerAccess("getCityChaos");
|
const bladeburner = player.bladeburner;
|
||||||
checkBladeburnerCity("getCityChaos", cityName);
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
const bladeburner = player.bladeburner;
|
return bladeburner.cities[cityName].comms;
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
},
|
||||||
return bladeburner.cities[cityName].chaos;
|
getCityChaos:
|
||||||
},
|
(ctx: NetscriptContext) =>
|
||||||
getCity: function (): string {
|
(_cityName: unknown): number => {
|
||||||
updateRam("getCity");
|
const cityName = ctx.helper.string("cityName", _cityName);
|
||||||
checkBladeburnerAccess("getCityChaos");
|
checkBladeburnerAccess(ctx);
|
||||||
|
checkBladeburnerCity(ctx, cityName);
|
||||||
|
const bladeburner = player.bladeburner;
|
||||||
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
|
return bladeburner.cities[cityName].chaos;
|
||||||
|
},
|
||||||
|
getCity: (ctx: NetscriptContext) => (): string => {
|
||||||
|
checkBladeburnerAccess(ctx);
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return bladeburner.city;
|
return bladeburner.city;
|
||||||
},
|
},
|
||||||
switchCity: function (_cityName: unknown): boolean {
|
switchCity:
|
||||||
updateRam("switchCity");
|
(ctx: NetscriptContext) =>
|
||||||
const cityName = helper.string("switchCity", "cityName", _cityName);
|
(_cityName: unknown): boolean => {
|
||||||
checkBladeburnerAccess("switchCity");
|
const cityName = ctx.helper.string("cityName", _cityName);
|
||||||
checkBladeburnerCity("switchCity", cityName);
|
checkBladeburnerAccess(ctx);
|
||||||
const bladeburner = player.bladeburner;
|
checkBladeburnerCity(ctx, cityName);
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
const bladeburner = player.bladeburner;
|
||||||
bladeburner.city = cityName;
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return true;
|
bladeburner.city = cityName;
|
||||||
},
|
return true;
|
||||||
getStamina: function (): [number, number] {
|
},
|
||||||
updateRam("getStamina");
|
getStamina: (ctx: NetscriptContext) => (): [number, number] => {
|
||||||
checkBladeburnerAccess("getStamina");
|
checkBladeburnerAccess(ctx);
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return [bladeburner.stamina, bladeburner.maxStamina];
|
return [bladeburner.stamina, bladeburner.maxStamina];
|
||||||
},
|
},
|
||||||
joinBladeburnerFaction: function (): boolean {
|
joinBladeburnerFaction: (ctx: NetscriptContext) => (): boolean => {
|
||||||
updateRam("joinBladeburnerFaction");
|
checkBladeburnerAccess(ctx, true);
|
||||||
checkBladeburnerAccess("joinBladeburnerFaction", true);
|
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return bladeburner.joinBladeburnerFactionNetscriptFn(workerScript);
|
return bladeburner.joinBladeburnerFactionNetscriptFn(workerScript);
|
||||||
},
|
},
|
||||||
joinBladeburnerDivision: function (): boolean {
|
joinBladeburnerDivision: (ctx: NetscriptContext) => (): boolean => {
|
||||||
updateRam("joinBladeburnerDivision");
|
|
||||||
if (player.bitNodeN === 7 || player.sourceFileLvl(7) > 0) {
|
if (player.bitNodeN === 7 || player.sourceFileLvl(7) > 0) {
|
||||||
if (player.bitNodeN === 8) {
|
if (player.bitNodeN === 8) {
|
||||||
return false;
|
return false;
|
||||||
@ -396,22 +392,18 @@ export function NetscriptBladeburner(
|
|||||||
player.agility >= 100
|
player.agility >= 100
|
||||||
) {
|
) {
|
||||||
player.bladeburner = new Bladeburner(player);
|
player.bladeburner = new Bladeburner(player);
|
||||||
workerScript.log("joinBladeburnerDivision", () => "You have been accepted into the Bladeburner division");
|
ctx.log(() => "You have been accepted into the Bladeburner division");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
workerScript.log(
|
ctx.log(() => "You do not meet the requirements for joining the Bladeburner division");
|
||||||
"joinBladeburnerDivision",
|
|
||||||
() => "You do not meet the requirements for joining the Bladeburner division",
|
|
||||||
);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
getBonusTime: function (): number {
|
getBonusTime: (ctx: NetscriptContext) => (): number => {
|
||||||
updateRam("getBonusTime");
|
checkBladeburnerAccess(ctx);
|
||||||
checkBladeburnerAccess("getBonusTime");
|
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||||
return Math.round(bladeburner.storedCycles / 5) * 1000;
|
return Math.round(bladeburner.storedCycles / 5) * 1000;
|
||||||
|
@ -1,132 +1,124 @@
|
|||||||
import { INetscriptHelper } from "./INetscriptHelper";
|
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
|
||||||
import { is2DArray } from "../utils/helpers/is2DArray";
|
import { is2DArray } from "../utils/helpers/is2DArray";
|
||||||
import { CodingContract } from "../CodingContracts";
|
import { CodingContract } from "../CodingContracts";
|
||||||
import { CodingAttemptOptions, CodingContract as ICodingContract } from "../ScriptEditor/NetscriptDefinitions";
|
import { CodingAttemptOptions, CodingContract as ICodingContract } from "../ScriptEditor/NetscriptDefinitions";
|
||||||
|
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
||||||
|
|
||||||
export function NetscriptCodingContract(
|
export function NetscriptCodingContract(player: IPlayer, workerScript: WorkerScript): InternalAPI<ICodingContract> {
|
||||||
player: IPlayer,
|
const getCodingContract = function (
|
||||||
workerScript: WorkerScript,
|
ctx: NetscriptContext,
|
||||||
helper: INetscriptHelper,
|
func: string,
|
||||||
): ICodingContract {
|
hostname: string,
|
||||||
const getCodingContract = function (func: string, hostname: string, filename: string): CodingContract {
|
filename: string,
|
||||||
const server = helper.getServer(hostname, func);
|
): CodingContract {
|
||||||
|
const server = ctx.helper.getServer(hostname);
|
||||||
const contract = server.getContract(filename);
|
const contract = server.getContract(filename);
|
||||||
if (contract == null) {
|
if (contract == null) {
|
||||||
throw helper.makeRuntimeErrorMsg(
|
throw ctx.makeRuntimeErrorMsg(`Cannot find contract '${filename}' on server '${hostname}'`);
|
||||||
`codingcontract.${func}`,
|
|
||||||
`Cannot find contract '${filename}' on server '${hostname}'`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return contract;
|
return contract;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateRam = (funcName: string): void =>
|
|
||||||
helper.updateDynamicRam(funcName, getRamCost(player, "codingcontract", funcName));
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
attempt: function (
|
attempt:
|
||||||
answer: any,
|
(ctx: NetscriptContext) =>
|
||||||
_filename: unknown,
|
(
|
||||||
_hostname: unknown = workerScript.hostname,
|
answer: any,
|
||||||
{ returnReward }: CodingAttemptOptions = { returnReward: false },
|
_filename: unknown,
|
||||||
): boolean | string {
|
_hostname: unknown = workerScript.hostname,
|
||||||
updateRam("attempt");
|
{ returnReward }: CodingAttemptOptions = { returnReward: false },
|
||||||
const filename = helper.string("attempt", "filename", _filename);
|
): boolean | string => {
|
||||||
const hostname = helper.string("attempt", "hostname", _hostname);
|
const filename = ctx.helper.string("filename", _filename);
|
||||||
const contract = getCodingContract("attempt", hostname, filename);
|
const hostname = ctx.helper.string("hostname", _hostname);
|
||||||
|
const contract = getCodingContract(ctx, "attempt", hostname, filename);
|
||||||
|
|
||||||
// Convert answer to string. If the answer is a 2D array, then we have to
|
// Convert answer to string. If the answer is a 2D array, then we have to
|
||||||
// manually add brackets for the inner arrays
|
// manually add brackets for the inner arrays
|
||||||
if (is2DArray(answer)) {
|
if (is2DArray(answer)) {
|
||||||
const answerComponents = [];
|
const answerComponents = [];
|
||||||
for (let i = 0; i < answer.length; ++i) {
|
for (let i = 0; i < answer.length; ++i) {
|
||||||
answerComponents.push(["[", answer[i].toString(), "]"].join(""));
|
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(hostname, "codingcontract.attempt");
|
|
||||||
if (contract.isSolution(answer)) {
|
|
||||||
const reward = player.gainCodingContractReward(creward, contract.getDifficulty());
|
|
||||||
workerScript.log(
|
|
||||||
"codingcontract.attempt",
|
|
||||||
() => `Successfully completed Coding Contract '${filename}'. Reward: ${reward}`,
|
|
||||||
);
|
|
||||||
serv.removeContract(filename);
|
|
||||||
return returnReward ? reward : true;
|
|
||||||
} else {
|
|
||||||
++contract.tries;
|
|
||||||
if (contract.tries >= contract.getMaxNumTries()) {
|
|
||||||
workerScript.log(
|
|
||||||
"codingcontract.attempt",
|
|
||||||
() => `Coding Contract attempt '${filename}' failed. Contract is now self-destructing`,
|
|
||||||
);
|
|
||||||
serv.removeContract(filename);
|
|
||||||
} else {
|
|
||||||
workerScript.log(
|
|
||||||
"codingcontract.attempt",
|
|
||||||
() =>
|
|
||||||
`Coding Contract attempt '${filename}' failed. ${
|
|
||||||
contract.getMaxNumTries() - contract.tries
|
|
||||||
} attempts remaining.`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnReward ? "" : false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getContractType: function (_filename: unknown, _hostname: unknown = workerScript.hostname): string {
|
|
||||||
updateRam("getContractType");
|
|
||||||
const filename = helper.string("getContractType", "filename", _filename);
|
|
||||||
const hostname = helper.string("getContractType", "hostname", _hostname);
|
|
||||||
const contract = getCodingContract("getContractType", hostname, filename);
|
|
||||||
return contract.getType();
|
|
||||||
},
|
|
||||||
getData: function (_filename: unknown, _hostname: unknown = workerScript.hostname): any {
|
|
||||||
updateRam("getData");
|
|
||||||
const filename = helper.string("getContractType", "filename", _filename);
|
|
||||||
const hostname = helper.string("getContractType", "hostname", _hostname);
|
|
||||||
const contract = getCodingContract("getData", hostname, filename);
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
answer = answerComponents.join(",");
|
||||||
|
} else {
|
||||||
|
answer = String(answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return copy;
|
const creward = contract.reward;
|
||||||
} else {
|
if (creward === null) throw new Error("Somehow solved a contract that didn't have a reward");
|
||||||
return data;
|
|
||||||
}
|
const serv = ctx.helper.getServer(hostname);
|
||||||
},
|
if (contract.isSolution(answer)) {
|
||||||
getDescription: function (_filename: unknown, _hostname: unknown = workerScript.hostname): string {
|
const reward = player.gainCodingContractReward(creward, contract.getDifficulty());
|
||||||
updateRam("getDescription");
|
ctx.log(() => `Successfully completed Coding Contract '${filename}'. Reward: ${reward}`);
|
||||||
const filename = helper.string("getDescription", "filename", _filename);
|
serv.removeContract(filename);
|
||||||
const hostname = helper.string("getDescription", "hostname", _hostname);
|
return returnReward ? reward : true;
|
||||||
const contract = getCodingContract("getDescription", hostname, filename);
|
} else {
|
||||||
return contract.getDescription();
|
++contract.tries;
|
||||||
},
|
if (contract.tries >= contract.getMaxNumTries()) {
|
||||||
getNumTriesRemaining: function (_filename: unknown, _hostname: unknown = workerScript.hostname): number {
|
ctx.log(() => `Coding Contract attempt '${filename}' failed. Contract is now self-destructing`);
|
||||||
updateRam("getNumTriesRemaining");
|
serv.removeContract(filename);
|
||||||
const filename = helper.string("getNumTriesRemaining", "filename", _filename);
|
} else {
|
||||||
const hostname = helper.string("getNumTriesRemaining", "hostname", _hostname);
|
ctx.log(
|
||||||
const contract = getCodingContract("getNumTriesRemaining", hostname, filename);
|
() =>
|
||||||
return contract.getMaxNumTries() - contract.tries;
|
`Coding Contract attempt '${filename}' failed. ${
|
||||||
},
|
contract.getMaxNumTries() - contract.tries
|
||||||
|
} attempts remaining.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnReward ? "" : false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getContractType:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_filename: unknown, _hostname: unknown = workerScript.hostname): string => {
|
||||||
|
const filename = ctx.helper.string("filename", _filename);
|
||||||
|
const hostname = ctx.helper.string("hostname", _hostname);
|
||||||
|
const contract = getCodingContract(ctx, "getContractType", hostname, filename);
|
||||||
|
return contract.getType();
|
||||||
|
},
|
||||||
|
getData:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_filename: unknown, _hostname: unknown = workerScript.hostname): any => {
|
||||||
|
const filename = ctx.helper.string("filename", _filename);
|
||||||
|
const hostname = ctx.helper.string("hostname", _hostname);
|
||||||
|
const contract = getCodingContract(ctx, "getData", hostname, filename);
|
||||||
|
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:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_filename: unknown, _hostname: unknown = workerScript.hostname): string => {
|
||||||
|
const filename = ctx.helper.string("filename", _filename);
|
||||||
|
const hostname = ctx.helper.string("hostname", _hostname);
|
||||||
|
const contract = getCodingContract(ctx, "getDescription", hostname, filename);
|
||||||
|
return contract.getDescription();
|
||||||
|
},
|
||||||
|
getNumTriesRemaining:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_filename: unknown, _hostname: unknown = workerScript.hostname): number => {
|
||||||
|
const filename = ctx.helper.string("filename", _filename);
|
||||||
|
const hostname = ctx.helper.string("hostname", _hostname);
|
||||||
|
const contract = getCodingContract(ctx, "getNumTriesRemaining", hostname, filename);
|
||||||
|
return contract.getMaxNumTries() - contract.tries;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,6 @@
|
|||||||
import { FactionNames } from "../Faction/data/FactionNames";
|
import { FactionNames } from "../Faction/data/FactionNames";
|
||||||
import { GangConstants } from "../Gang/data/Constants";
|
import { GangConstants } from "../Gang/data/Constants";
|
||||||
import { INetscriptHelper } from "./INetscriptHelper";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
|
||||||
import { Gang } from "../Gang/Gang";
|
import { Gang } from "../Gang/Gang";
|
||||||
import { AllGangs } from "../Gang/AllGangs";
|
import { AllGangs } from "../Gang/AllGangs";
|
||||||
import { GangMemberTasks } from "../Gang/GangMemberTasks";
|
import { GangMemberTasks } from "../Gang/GangMemberTasks";
|
||||||
@ -20,63 +18,60 @@ import {
|
|||||||
EquipmentStats,
|
EquipmentStats,
|
||||||
GangTaskStats,
|
GangTaskStats,
|
||||||
} from "../ScriptEditor/NetscriptDefinitions";
|
} from "../ScriptEditor/NetscriptDefinitions";
|
||||||
|
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||||
|
|
||||||
export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): IGang {
|
export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): InternalAPI<IGang> {
|
||||||
const checkGangApiAccess = function (func: string): void {
|
const checkGangApiAccess = function (ctx: NetscriptContext): void {
|
||||||
const gang = player.gang;
|
const gang = player.gang;
|
||||||
if (gang === null) throw new Error("Must have joined gang");
|
if (gang === null) throw new Error("Must have joined gang");
|
||||||
const hasAccess = gang instanceof Gang;
|
const hasAccess = gang instanceof Gang;
|
||||||
if (!hasAccess) {
|
if (!hasAccess) {
|
||||||
throw helper.makeRuntimeErrorMsg(`gang.${func}`, `You do not currently have a Gang`);
|
throw ctx.makeRuntimeErrorMsg(`You do not currently have a Gang`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getGangMember = function (func: string, name: string): GangMember {
|
const getGangMember = function (ctx: NetscriptContext, name: string): GangMember {
|
||||||
const gang = player.gang;
|
const gang = player.gang;
|
||||||
if (gang === null) throw new Error("Must have joined gang");
|
if (gang === null) throw new Error("Must have joined gang");
|
||||||
for (const member of gang.members) if (member.name === name) return member;
|
for (const member of gang.members) if (member.name === name) return member;
|
||||||
throw helper.makeRuntimeErrorMsg(`gang.${func}`, `Invalid gang member: '${name}'`);
|
throw ctx.makeRuntimeErrorMsg(`Invalid gang member: '${name}'`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getGangTask = function (func: string, name: string): GangMemberTask {
|
const getGangTask = function (ctx: NetscriptContext, name: string): GangMemberTask {
|
||||||
const task = GangMemberTasks[name];
|
const task = GangMemberTasks[name];
|
||||||
if (!task) {
|
if (!task) {
|
||||||
throw helper.makeRuntimeErrorMsg(`gang.${func}`, `Invalid task: '${name}'`);
|
throw ctx.makeRuntimeErrorMsg(`Invalid task: '${name}'`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return task;
|
return task;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateRam = (funcName: string): void => helper.updateDynamicRam(funcName, getRamCost(player, "gang", funcName));
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
createGang: function (_faction: unknown): boolean {
|
createGang:
|
||||||
updateRam("createGang");
|
(ctx: NetscriptContext) =>
|
||||||
const faction = helper.string("createGang", "faction", _faction);
|
(_faction: unknown): boolean => {
|
||||||
// this list is copied from Faction/ui/Root.tsx
|
const faction = ctx.helper.string("faction", _faction);
|
||||||
|
// this list is copied from Faction/ui/Root.tsx
|
||||||
|
|
||||||
if (!player.canAccessGang() || !GangConstants.Names.includes(faction)) return false;
|
if (!player.canAccessGang() || !GangConstants.Names.includes(faction)) return false;
|
||||||
if (player.inGang()) return false;
|
if (player.inGang()) return false;
|
||||||
if (!player.factions.includes(faction)) return false;
|
if (!player.factions.includes(faction)) return false;
|
||||||
|
|
||||||
const isHacking = faction === FactionNames.NiteSec || faction === FactionNames.TheBlackHand;
|
const isHacking = faction === FactionNames.NiteSec || faction === FactionNames.TheBlackHand;
|
||||||
player.startGang(faction, isHacking);
|
player.startGang(faction, isHacking);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
inGang: function (): boolean {
|
inGang: () => (): boolean => {
|
||||||
updateRam("inGang");
|
|
||||||
return player.inGang();
|
return player.inGang();
|
||||||
},
|
},
|
||||||
getMemberNames: function (): string[] {
|
getMemberNames: (ctx: NetscriptContext) => (): string[] => {
|
||||||
updateRam("getMemberNames");
|
checkGangApiAccess(ctx);
|
||||||
checkGangApiAccess("getMemberNames");
|
|
||||||
const gang = player.gang;
|
const gang = player.gang;
|
||||||
if (gang === null) throw new Error("Should not be called without Gang");
|
if (gang === null) throw new Error("Should not be called without Gang");
|
||||||
return gang.members.map((member) => member.name);
|
return gang.members.map((member) => member.name);
|
||||||
},
|
},
|
||||||
getGangInformation: function (): GangGenInfo {
|
getGangInformation: (ctx: NetscriptContext) => (): GangGenInfo => {
|
||||||
updateRam("getGangInformation");
|
checkGangApiAccess(ctx);
|
||||||
checkGangApiAccess("getGangInformation");
|
|
||||||
const gang = player.gang;
|
const gang = player.gang;
|
||||||
if (gang === null) throw new Error("Should not be called without Gang");
|
if (gang === null) throw new Error("Should not be called without Gang");
|
||||||
return {
|
return {
|
||||||
@ -94,9 +89,8 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
|||||||
wantedPenalty: gang.getWantedPenalty(),
|
wantedPenalty: gang.getWantedPenalty(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getOtherGangInformation: function (): GangOtherInfo {
|
getOtherGangInformation: (ctx: NetscriptContext) => (): GangOtherInfo => {
|
||||||
updateRam("getOtherGangInformation");
|
checkGangApiAccess(ctx);
|
||||||
checkGangApiAccess("getOtherGangInformation");
|
|
||||||
const cpy: any = {};
|
const cpy: any = {};
|
||||||
for (const gang of Object.keys(AllGangs)) {
|
for (const gang of Object.keys(AllGangs)) {
|
||||||
cpy[gang] = Object.assign({}, AllGangs[gang]);
|
cpy[gang] = Object.assign({}, AllGangs[gang]);
|
||||||
@ -104,242 +98,251 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
|||||||
|
|
||||||
return cpy;
|
return cpy;
|
||||||
},
|
},
|
||||||
getMemberInformation: function (_memberName: unknown): GangMemberInfo {
|
getMemberInformation:
|
||||||
updateRam("getMemberInformation");
|
(ctx: NetscriptContext) =>
|
||||||
const memberName = helper.string("getMemberInformation", "memberName", _memberName);
|
(_memberName: unknown): GangMemberInfo => {
|
||||||
checkGangApiAccess("getMemberInformation");
|
const memberName = ctx.helper.string("memberName", _memberName);
|
||||||
const gang = player.gang;
|
checkGangApiAccess(ctx);
|
||||||
if (gang === null) throw new Error("Should not be called without Gang");
|
const gang = player.gang;
|
||||||
const member = getGangMember("getMemberInformation", memberName);
|
if (gang === null) throw new Error("Should not be called without Gang");
|
||||||
return {
|
const member = getGangMember(ctx, memberName);
|
||||||
name: member.name,
|
return {
|
||||||
task: member.task,
|
name: member.name,
|
||||||
earnedRespect: member.earnedRespect,
|
task: member.task,
|
||||||
hack: member.hack,
|
earnedRespect: member.earnedRespect,
|
||||||
str: member.str,
|
hack: member.hack,
|
||||||
def: member.def,
|
str: member.str,
|
||||||
dex: member.dex,
|
def: member.def,
|
||||||
agi: member.agi,
|
dex: member.dex,
|
||||||
cha: member.cha,
|
agi: member.agi,
|
||||||
|
cha: member.cha,
|
||||||
|
|
||||||
hack_exp: member.hack_exp,
|
hack_exp: member.hack_exp,
|
||||||
str_exp: member.str_exp,
|
str_exp: member.str_exp,
|
||||||
def_exp: member.def_exp,
|
def_exp: member.def_exp,
|
||||||
dex_exp: member.dex_exp,
|
dex_exp: member.dex_exp,
|
||||||
agi_exp: member.agi_exp,
|
agi_exp: member.agi_exp,
|
||||||
cha_exp: member.cha_exp,
|
cha_exp: member.cha_exp,
|
||||||
|
|
||||||
hack_mult: member.hack_mult,
|
hack_mult: member.hack_mult,
|
||||||
str_mult: member.str_mult,
|
str_mult: member.str_mult,
|
||||||
def_mult: member.def_mult,
|
def_mult: member.def_mult,
|
||||||
dex_mult: member.dex_mult,
|
dex_mult: member.dex_mult,
|
||||||
agi_mult: member.agi_mult,
|
agi_mult: member.agi_mult,
|
||||||
cha_mult: member.cha_mult,
|
cha_mult: member.cha_mult,
|
||||||
|
|
||||||
hack_asc_mult: member.calculateAscensionMult(member.hack_asc_points),
|
hack_asc_mult: member.calculateAscensionMult(member.hack_asc_points),
|
||||||
str_asc_mult: member.calculateAscensionMult(member.str_asc_points),
|
str_asc_mult: member.calculateAscensionMult(member.str_asc_points),
|
||||||
def_asc_mult: member.calculateAscensionMult(member.def_asc_points),
|
def_asc_mult: member.calculateAscensionMult(member.def_asc_points),
|
||||||
dex_asc_mult: member.calculateAscensionMult(member.dex_asc_points),
|
dex_asc_mult: member.calculateAscensionMult(member.dex_asc_points),
|
||||||
agi_asc_mult: member.calculateAscensionMult(member.agi_asc_points),
|
agi_asc_mult: member.calculateAscensionMult(member.agi_asc_points),
|
||||||
cha_asc_mult: member.calculateAscensionMult(member.cha_asc_points),
|
cha_asc_mult: member.calculateAscensionMult(member.cha_asc_points),
|
||||||
|
|
||||||
hack_asc_points: member.hack_asc_points,
|
hack_asc_points: member.hack_asc_points,
|
||||||
str_asc_points: member.str_asc_points,
|
str_asc_points: member.str_asc_points,
|
||||||
def_asc_points: member.def_asc_points,
|
def_asc_points: member.def_asc_points,
|
||||||
dex_asc_points: member.dex_asc_points,
|
dex_asc_points: member.dex_asc_points,
|
||||||
agi_asc_points: member.agi_asc_points,
|
agi_asc_points: member.agi_asc_points,
|
||||||
cha_asc_points: member.cha_asc_points,
|
cha_asc_points: member.cha_asc_points,
|
||||||
|
|
||||||
upgrades: member.upgrades.slice(),
|
upgrades: member.upgrades.slice(),
|
||||||
augmentations: member.augmentations.slice(),
|
augmentations: member.augmentations.slice(),
|
||||||
|
|
||||||
respectGain: member.calculateRespectGain(gang),
|
respectGain: member.calculateRespectGain(gang),
|
||||||
wantedLevelGain: member.calculateWantedLevelGain(gang),
|
wantedLevelGain: member.calculateWantedLevelGain(gang),
|
||||||
moneyGain: member.calculateMoneyGain(gang),
|
moneyGain: member.calculateMoneyGain(gang),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
canRecruitMember: function (): boolean {
|
canRecruitMember: (ctx: NetscriptContext) => (): boolean => {
|
||||||
updateRam("canRecruitMember");
|
checkGangApiAccess(ctx);
|
||||||
checkGangApiAccess("canRecruitMember");
|
|
||||||
const gang = player.gang;
|
const gang = player.gang;
|
||||||
if (gang === null) throw new Error("Should not be called without Gang");
|
if (gang === null) throw new Error("Should not be called without Gang");
|
||||||
return gang.canRecruitMember();
|
return gang.canRecruitMember();
|
||||||
},
|
},
|
||||||
recruitMember: function (_memberName: unknown): boolean {
|
recruitMember:
|
||||||
updateRam("recruitMember");
|
(ctx: NetscriptContext) =>
|
||||||
const memberName = helper.string("recruitMember", "memberName", _memberName);
|
(_memberName: unknown): boolean => {
|
||||||
checkGangApiAccess("recruitMember");
|
const memberName = ctx.helper.string("memberName", _memberName);
|
||||||
const gang = player.gang;
|
checkGangApiAccess(ctx);
|
||||||
if (gang === null) throw new Error("Should not be called without Gang");
|
const gang = player.gang;
|
||||||
const recruited = gang.recruitMember(memberName);
|
if (gang === null) throw new Error("Should not be called without Gang");
|
||||||
if (recruited) {
|
const recruited = gang.recruitMember(memberName);
|
||||||
workerScript.log("gang.recruitMember", () => `Successfully recruited Gang Member '${memberName}'`);
|
if (recruited) {
|
||||||
} else {
|
workerScript.log("gang.recruitMember", () => `Successfully recruited Gang Member '${memberName}'`);
|
||||||
workerScript.log("gang.recruitMember", () => `Failed to recruit Gang Member '${memberName}'`);
|
} else {
|
||||||
}
|
workerScript.log("gang.recruitMember", () => `Failed to recruit Gang Member '${memberName}'`);
|
||||||
|
}
|
||||||
|
|
||||||
return recruited;
|
return recruited;
|
||||||
},
|
},
|
||||||
getTaskNames: function (): string[] {
|
getTaskNames: (ctx: NetscriptContext) => (): string[] => {
|
||||||
updateRam("getTaskNames");
|
checkGangApiAccess(ctx);
|
||||||
checkGangApiAccess("getTaskNames");
|
|
||||||
const gang = player.gang;
|
const gang = player.gang;
|
||||||
if (gang === null) throw new Error("Should not be called without Gang");
|
if (gang === null) throw new Error("Should not be called without Gang");
|
||||||
const tasks = gang.getAllTaskNames();
|
const tasks = gang.getAllTaskNames();
|
||||||
tasks.unshift("Unassigned");
|
tasks.unshift("Unassigned");
|
||||||
return tasks;
|
return tasks;
|
||||||
},
|
},
|
||||||
setMemberTask: function (_memberName: unknown, _taskName: unknown): boolean {
|
setMemberTask:
|
||||||
updateRam("setMemberTask");
|
(ctx: NetscriptContext) =>
|
||||||
const memberName = helper.string("setMemberTask", "memberName", _memberName);
|
(_memberName: unknown, _taskName: unknown): boolean => {
|
||||||
const taskName = helper.string("setMemberTask", "taskName", _taskName);
|
const memberName = ctx.helper.string("memberName", _memberName);
|
||||||
checkGangApiAccess("setMemberTask");
|
const taskName = ctx.helper.string("taskName", _taskName);
|
||||||
const member = getGangMember("setMemberTask", memberName);
|
checkGangApiAccess(ctx);
|
||||||
const gang = player.gang;
|
const member = getGangMember(ctx, memberName);
|
||||||
if (gang === null) throw new Error("Should not be called without Gang");
|
const gang = player.gang;
|
||||||
if (!gang.getAllTaskNames().includes(taskName)) {
|
if (gang === null) throw new Error("Should not be called without Gang");
|
||||||
workerScript.log(
|
if (!gang.getAllTaskNames().includes(taskName)) {
|
||||||
"gang.setMemberTask",
|
workerScript.log(
|
||||||
() =>
|
"gang.setMemberTask",
|
||||||
`Failed to assign Gang Member '${memberName}' to Invalid task '${taskName}'. '${memberName}' is now Unassigned`,
|
() =>
|
||||||
);
|
`Failed to assign Gang Member '${memberName}' to Invalid task '${taskName}'. '${memberName}' is now Unassigned`,
|
||||||
return member.assignToTask("Unassigned");
|
);
|
||||||
}
|
return member.assignToTask("Unassigned");
|
||||||
const success = member.assignToTask(taskName);
|
}
|
||||||
if (success) {
|
const success = member.assignToTask(taskName);
|
||||||
workerScript.log(
|
if (success) {
|
||||||
"gang.setMemberTask",
|
workerScript.log(
|
||||||
() => `Successfully assigned Gang Member '${memberName}' to '${taskName}' task`,
|
"gang.setMemberTask",
|
||||||
);
|
() => `Successfully assigned Gang Member '${memberName}' to '${taskName}' task`,
|
||||||
} else {
|
);
|
||||||
workerScript.log(
|
} else {
|
||||||
"gang.setMemberTask",
|
workerScript.log(
|
||||||
() => `Failed to assign Gang Member '${memberName}' to '${taskName}' task. '${memberName}' is now Unassigned`,
|
"gang.setMemberTask",
|
||||||
);
|
() =>
|
||||||
}
|
`Failed to assign Gang Member '${memberName}' to '${taskName}' task. '${memberName}' is now Unassigned`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
},
|
},
|
||||||
getTaskStats: function (_taskName: unknown): GangTaskStats {
|
getTaskStats:
|
||||||
updateRam("getTaskStats");
|
(ctx: NetscriptContext) =>
|
||||||
const taskName = helper.string("getTaskStats", "taskName", _taskName);
|
(_taskName: unknown): GangTaskStats => {
|
||||||
checkGangApiAccess("getTaskStats");
|
const taskName = ctx.helper.string("taskName", _taskName);
|
||||||
const task = getGangTask("getTaskStats", taskName);
|
checkGangApiAccess(ctx);
|
||||||
const copy = Object.assign({}, task);
|
const task = getGangTask(ctx, taskName);
|
||||||
copy.territory = Object.assign({}, task.territory);
|
const copy = Object.assign({}, task);
|
||||||
return copy;
|
copy.territory = Object.assign({}, task.territory);
|
||||||
},
|
return copy;
|
||||||
getEquipmentNames: function (): string[] {
|
},
|
||||||
updateRam("getEquipmentNames");
|
getEquipmentNames: (ctx: NetscriptContext) => (): string[] => {
|
||||||
checkGangApiAccess("getEquipmentNames");
|
checkGangApiAccess(ctx);
|
||||||
return Object.keys(GangMemberUpgrades);
|
return Object.keys(GangMemberUpgrades);
|
||||||
},
|
},
|
||||||
getEquipmentCost: function (_equipName: any): number {
|
getEquipmentCost:
|
||||||
updateRam("getEquipmentCost");
|
(ctx: NetscriptContext) =>
|
||||||
const equipName = helper.string("getEquipmentCost", "equipName", _equipName);
|
(_equipName: any): number => {
|
||||||
checkGangApiAccess("getEquipmentCost");
|
const equipName = ctx.helper.string("equipName", _equipName);
|
||||||
const gang = player.gang;
|
checkGangApiAccess(ctx);
|
||||||
if (gang === null) throw new Error("Should not be called without Gang");
|
const gang = player.gang;
|
||||||
const upg = GangMemberUpgrades[equipName];
|
if (gang === null) throw new Error("Should not be called without Gang");
|
||||||
if (upg === null) return Infinity;
|
const upg = GangMemberUpgrades[equipName];
|
||||||
return gang.getUpgradeCost(upg);
|
if (upg === null) return Infinity;
|
||||||
},
|
return gang.getUpgradeCost(upg);
|
||||||
getEquipmentType: function (_equipName: unknown): string {
|
},
|
||||||
updateRam("getEquipmentType");
|
getEquipmentType:
|
||||||
const equipName = helper.string("getEquipmentType", "equipName", _equipName);
|
(ctx: NetscriptContext) =>
|
||||||
checkGangApiAccess("getEquipmentType");
|
(_equipName: unknown): string => {
|
||||||
const upg = GangMemberUpgrades[equipName];
|
const equipName = ctx.helper.string("equipName", _equipName);
|
||||||
if (upg == null) return "";
|
checkGangApiAccess(ctx);
|
||||||
return upg.getType();
|
const upg = GangMemberUpgrades[equipName];
|
||||||
},
|
if (upg == null) return "";
|
||||||
getEquipmentStats: function (_equipName: unknown): EquipmentStats {
|
return upg.getType();
|
||||||
updateRam("getEquipmentStats");
|
},
|
||||||
const equipName = helper.string("getEquipmentStats", "equipName", _equipName);
|
getEquipmentStats:
|
||||||
checkGangApiAccess("getEquipmentStats");
|
(ctx: NetscriptContext) =>
|
||||||
const equipment = GangMemberUpgrades[equipName];
|
(_equipName: unknown): EquipmentStats => {
|
||||||
if (!equipment) {
|
const equipName = ctx.helper.string("equipName", _equipName);
|
||||||
throw helper.makeRuntimeErrorMsg("getEquipmentStats", `Invalid equipment: ${equipName}`);
|
checkGangApiAccess(ctx);
|
||||||
}
|
const equipment = GangMemberUpgrades[equipName];
|
||||||
const typecheck: EquipmentStats = equipment.mults;
|
if (!equipment) {
|
||||||
return Object.assign({}, typecheck) as any;
|
throw ctx.makeRuntimeErrorMsg(`Invalid equipment: ${equipName}`);
|
||||||
},
|
}
|
||||||
purchaseEquipment: function (_memberName: unknown, _equipName: unknown): boolean {
|
const typecheck: EquipmentStats = equipment.mults;
|
||||||
updateRam("purchaseEquipment");
|
return Object.assign({}, typecheck) as any;
|
||||||
const memberName = helper.string("purchaseEquipment", "memberName", _memberName);
|
},
|
||||||
const equipName = helper.string("purchaseEquipment", "equipName", _equipName);
|
purchaseEquipment:
|
||||||
checkGangApiAccess("purchaseEquipment");
|
(ctx: NetscriptContext) =>
|
||||||
const gang = player.gang;
|
(_memberName: unknown, _equipName: unknown): boolean => {
|
||||||
if (gang === null) throw new Error("Should not be called without Gang");
|
const memberName = ctx.helper.string("memberName", _memberName);
|
||||||
const member = getGangMember("purchaseEquipment", memberName);
|
const equipName = ctx.helper.string("equipName", _equipName);
|
||||||
const equipment = GangMemberUpgrades[equipName];
|
checkGangApiAccess(ctx);
|
||||||
if (!equipment) return false;
|
const gang = player.gang;
|
||||||
const res = member.buyUpgrade(equipment, player, gang);
|
if (gang === null) throw new Error("Should not be called without Gang");
|
||||||
if (res) {
|
const member = getGangMember(ctx, memberName);
|
||||||
workerScript.log("gang.purchaseEquipment", () => `Purchased '${equipName}' for Gang member '${memberName}'`);
|
const equipment = GangMemberUpgrades[equipName];
|
||||||
} else {
|
if (!equipment) return false;
|
||||||
workerScript.log(
|
const res = member.buyUpgrade(equipment, player, gang);
|
||||||
"gang.purchaseEquipment",
|
if (res) {
|
||||||
() => `Failed to purchase '${equipName}' for Gang member '${memberName}'`,
|
workerScript.log("gang.purchaseEquipment", () => `Purchased '${equipName}' for Gang member '${memberName}'`);
|
||||||
);
|
} else {
|
||||||
}
|
workerScript.log(
|
||||||
|
"gang.purchaseEquipment",
|
||||||
|
() => `Failed to purchase '${equipName}' for Gang member '${memberName}'`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
ascendMember: function (_memberName: unknown): GangMemberAscension | undefined {
|
ascendMember:
|
||||||
updateRam("ascendMember");
|
(ctx: NetscriptContext) =>
|
||||||
const memberName = helper.string("ascendMember", "memberName", _memberName);
|
(_memberName: unknown): GangMemberAscension | undefined => {
|
||||||
checkGangApiAccess("ascendMember");
|
const memberName = ctx.helper.string("memberName", _memberName);
|
||||||
const gang = player.gang;
|
checkGangApiAccess(ctx);
|
||||||
if (gang === null) throw new Error("Should not be called without Gang");
|
const gang = player.gang;
|
||||||
const member = getGangMember("ascendMember", memberName);
|
if (gang === null) throw new Error("Should not be called without Gang");
|
||||||
if (!member.canAscend()) return;
|
const member = getGangMember(ctx, memberName);
|
||||||
return gang.ascendMember(member, workerScript);
|
if (!member.canAscend()) return;
|
||||||
},
|
return gang.ascendMember(member, workerScript);
|
||||||
getAscensionResult: function (_memberName: unknown): GangMemberAscension | undefined {
|
},
|
||||||
updateRam("getAscensionResult");
|
getAscensionResult:
|
||||||
const memberName = helper.string("getAscensionResult", "memberName", _memberName);
|
(ctx: NetscriptContext) =>
|
||||||
checkGangApiAccess("getAscensionResult");
|
(_memberName: unknown): GangMemberAscension | undefined => {
|
||||||
const gang = player.gang;
|
const memberName = ctx.helper.string("memberName", _memberName);
|
||||||
if (gang === null) throw new Error("Should not be called without Gang");
|
checkGangApiAccess(ctx);
|
||||||
const member = getGangMember("getAscensionResult", memberName);
|
const gang = player.gang;
|
||||||
if (!member.canAscend()) return;
|
if (gang === null) throw new Error("Should not be called without Gang");
|
||||||
return {
|
const member = getGangMember(ctx, memberName);
|
||||||
respect: member.earnedRespect,
|
if (!member.canAscend()) return;
|
||||||
...member.getAscensionResults(),
|
return {
|
||||||
};
|
respect: member.earnedRespect,
|
||||||
},
|
...member.getAscensionResults(),
|
||||||
setTerritoryWarfare: function (_engage: unknown): void {
|
};
|
||||||
updateRam("setTerritoryWarfare");
|
},
|
||||||
const engage = helper.boolean(_engage);
|
setTerritoryWarfare:
|
||||||
checkGangApiAccess("setTerritoryWarfare");
|
(ctx: NetscriptContext) =>
|
||||||
const gang = player.gang;
|
(_engage: unknown): void => {
|
||||||
if (gang === null) throw new Error("Should not be called without Gang");
|
const engage = ctx.helper.boolean(_engage);
|
||||||
if (engage) {
|
checkGangApiAccess(ctx);
|
||||||
gang.territoryWarfareEngaged = true;
|
const gang = player.gang;
|
||||||
workerScript.log("gang.setTerritoryWarfare", () => "Engaging in Gang Territory Warfare");
|
if (gang === null) throw new Error("Should not be called without Gang");
|
||||||
} else {
|
if (engage) {
|
||||||
gang.territoryWarfareEngaged = false;
|
gang.territoryWarfareEngaged = true;
|
||||||
workerScript.log("gang.setTerritoryWarfare", () => "Disengaging in Gang Territory Warfare");
|
workerScript.log("gang.setTerritoryWarfare", () => "Engaging in Gang Territory Warfare");
|
||||||
}
|
} else {
|
||||||
},
|
gang.territoryWarfareEngaged = false;
|
||||||
getChanceToWinClash: function (_otherGang: unknown): number {
|
workerScript.log("gang.setTerritoryWarfare", () => "Disengaging in Gang Territory Warfare");
|
||||||
updateRam("getChanceToWinClash");
|
}
|
||||||
const otherGang = helper.string("getChanceToWinClash", "otherGang", _otherGang);
|
},
|
||||||
checkGangApiAccess("getChanceToWinClash");
|
getChanceToWinClash:
|
||||||
const gang = player.gang;
|
(ctx: NetscriptContext) =>
|
||||||
if (gang === null) throw new Error("Should not be called without Gang");
|
(_otherGang: unknown): number => {
|
||||||
if (AllGangs[otherGang] == null) {
|
const otherGang = ctx.helper.string("otherGang", _otherGang);
|
||||||
throw helper.makeRuntimeErrorMsg(`gang.getChanceToWinClash`, `Invalid gang: ${otherGang}`);
|
checkGangApiAccess(ctx);
|
||||||
}
|
const gang = player.gang;
|
||||||
|
if (gang === null) throw new Error("Should not be called without Gang");
|
||||||
|
if (AllGangs[otherGang] == null) {
|
||||||
|
throw ctx.makeRuntimeErrorMsg(`Invalid gang: ${otherGang}`);
|
||||||
|
}
|
||||||
|
|
||||||
const playerPower = AllGangs[gang.facName].power;
|
const playerPower = AllGangs[gang.facName].power;
|
||||||
const otherPower = AllGangs[otherGang].power;
|
const otherPower = AllGangs[otherGang].power;
|
||||||
|
|
||||||
return playerPower / (otherPower + playerPower);
|
return playerPower / (otherPower + playerPower);
|
||||||
},
|
},
|
||||||
getBonusTime: function (): number {
|
getBonusTime: (ctx: NetscriptContext) => (): number => {
|
||||||
updateRam("getBonusTime");
|
checkGangApiAccess(ctx);
|
||||||
checkGangApiAccess("getBonusTime");
|
|
||||||
const gang = player.gang;
|
const gang = player.gang;
|
||||||
if (gang === null) throw new Error("Should not be called without Gang");
|
if (gang === null) throw new Error("Should not be called without Gang");
|
||||||
return Math.round(gang.storedCycles / 5) * 1000;
|
return Math.round(gang.storedCycles / 5) * 1000;
|
||||||
|
@ -1,104 +1,97 @@
|
|||||||
|
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||||
import { StaticAugmentations } from "../Augmentation/StaticAugmentations";
|
import { StaticAugmentations } from "../Augmentation/StaticAugmentations";
|
||||||
import { hasAugmentationPrereqs } from "../Faction/FactionHelpers";
|
import { hasAugmentationPrereqs } from "../Faction/FactionHelpers";
|
||||||
import { CityName } from "../Locations/data/CityNames";
|
import { CityName } from "../Locations/data/CityNames";
|
||||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
|
||||||
import { GraftableAugmentation } from "../PersonObjects/Grafting/GraftableAugmentation";
|
import { GraftableAugmentation } from "../PersonObjects/Grafting/GraftableAugmentation";
|
||||||
import { getGraftingAvailableAugs, calculateGraftingTimeWithBonus } from "../PersonObjects/Grafting/GraftingHelpers";
|
import { getGraftingAvailableAugs, calculateGraftingTimeWithBonus } from "../PersonObjects/Grafting/GraftingHelpers";
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { Grafting as IGrafting } from "../ScriptEditor/NetscriptDefinitions";
|
import { Grafting as IGrafting } from "../ScriptEditor/NetscriptDefinitions";
|
||||||
import { Router } from "../ui/GameRoot";
|
import { Router } from "../ui/GameRoot";
|
||||||
import { INetscriptHelper } from "./INetscriptHelper";
|
|
||||||
|
|
||||||
export function NetscriptGrafting(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): IGrafting {
|
export function NetscriptGrafting(player: IPlayer): InternalAPI<IGrafting> {
|
||||||
const checkGraftingAPIAccess = (func: string): void => {
|
const checkGraftingAPIAccess = (ctx: NetscriptContext): void => {
|
||||||
if (!player.canAccessGrafting()) {
|
if (!player.canAccessGrafting()) {
|
||||||
throw helper.makeRuntimeErrorMsg(
|
throw ctx.makeRuntimeErrorMsg(
|
||||||
`grafting.${func}`,
|
|
||||||
"You do not currently have access to the Grafting API. This is either because you are not in BitNode 10 or because you do not have Source-File 10",
|
"You do not currently have access to the Grafting API. This is either because you are not in BitNode 10 or because you do not have Source-File 10",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateRam = (funcName: string): void =>
|
|
||||||
helper.updateDynamicRam(funcName, getRamCost(player, "grafting", funcName));
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getAugmentationGraftPrice: (_augName: unknown): number => {
|
getAugmentationGraftPrice:
|
||||||
updateRam("getAugmentationGraftPrice");
|
(ctx: NetscriptContext) =>
|
||||||
const augName = helper.string("getAugmentationGraftPrice", "augName", _augName);
|
(_augName: unknown): number => {
|
||||||
checkGraftingAPIAccess("getAugmentationGraftPrice");
|
const augName = ctx.helper.string("augName", _augName);
|
||||||
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
checkGraftingAPIAccess(ctx);
|
||||||
throw helper.makeRuntimeErrorMsg("grafting.getAugmentationGraftPrice", `Invalid aug: ${augName}`);
|
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||||
}
|
throw ctx.makeRuntimeErrorMsg(`Invalid aug: ${augName}`);
|
||||||
const graftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
}
|
||||||
return graftableAug.cost;
|
const graftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
||||||
},
|
return graftableAug.cost;
|
||||||
|
},
|
||||||
|
|
||||||
getAugmentationGraftTime: (_augName: string): number => {
|
getAugmentationGraftTime:
|
||||||
updateRam("getAugmentationGraftTime");
|
(ctx: NetscriptContext) =>
|
||||||
const augName = helper.string("getAugmentationGraftTime", "augName", _augName);
|
(_augName: string): number => {
|
||||||
checkGraftingAPIAccess("getAugmentationGraftTime");
|
const augName = ctx.helper.string("augName", _augName);
|
||||||
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
checkGraftingAPIAccess(ctx);
|
||||||
throw helper.makeRuntimeErrorMsg("grafting.getAugmentationGraftTime", `Invalid aug: ${augName}`);
|
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||||
}
|
throw ctx.makeRuntimeErrorMsg(`Invalid aug: ${augName}`);
|
||||||
const graftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
}
|
||||||
return calculateGraftingTimeWithBonus(player, graftableAug);
|
const graftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
||||||
},
|
return calculateGraftingTimeWithBonus(player, graftableAug);
|
||||||
|
},
|
||||||
|
|
||||||
getGraftableAugmentations: (): string[] => {
|
getGraftableAugmentations: (ctx: NetscriptContext) => (): string[] => {
|
||||||
updateRam("getGraftableAugmentations");
|
checkGraftingAPIAccess(ctx);
|
||||||
checkGraftingAPIAccess("getGraftableAugmentations");
|
|
||||||
const graftableAugs = getGraftingAvailableAugs(player);
|
const graftableAugs = getGraftingAvailableAugs(player);
|
||||||
return graftableAugs;
|
return graftableAugs;
|
||||||
},
|
},
|
||||||
|
|
||||||
graftAugmentation: (_augName: string, _focus: unknown = true): boolean => {
|
graftAugmentation:
|
||||||
updateRam("graftAugmentation");
|
(ctx: NetscriptContext) =>
|
||||||
const augName = helper.string("graftAugmentation", "augName", _augName);
|
(_augName: string, _focus: unknown = true): boolean => {
|
||||||
const focus = helper.boolean(_focus);
|
const augName = ctx.helper.string("augName", _augName);
|
||||||
checkGraftingAPIAccess("graftAugmentation");
|
const focus = ctx.helper.boolean(_focus);
|
||||||
if (player.city !== CityName.NewTokyo) {
|
checkGraftingAPIAccess(ctx);
|
||||||
throw helper.makeRuntimeErrorMsg(
|
if (player.city !== CityName.NewTokyo) {
|
||||||
"grafting.graftAugmentation",
|
throw ctx.makeRuntimeErrorMsg("You must be in New Tokyo to begin grafting an Augmentation.");
|
||||||
"You must be in New Tokyo to begin grafting an Augmentation.",
|
}
|
||||||
);
|
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||||
}
|
ctx.log(() => `Invalid aug: ${augName}`);
|
||||||
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
return false;
|
||||||
workerScript.log("grafting.graftAugmentation", () => `Invalid aug: ${augName}`);
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const wasFocusing = player.focus;
|
const wasFocusing = player.focus;
|
||||||
if (player.isWorking) {
|
if (player.isWorking) {
|
||||||
const txt = player.singularityStopWork();
|
const txt = player.singularityStopWork();
|
||||||
workerScript.log("graftAugmentation", () => txt);
|
ctx.log(() => txt);
|
||||||
}
|
}
|
||||||
|
|
||||||
const craftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
const craftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
||||||
if (player.money < craftableAug.cost) {
|
if (player.money < craftableAug.cost) {
|
||||||
workerScript.log("grafting.graftAugmentation", () => `You don't have enough money to craft ${augName}`);
|
ctx.log(() => `You don't have enough money to craft ${augName}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasAugmentationPrereqs(craftableAug.augmentation)) {
|
if (!hasAugmentationPrereqs(craftableAug.augmentation)) {
|
||||||
workerScript.log("grafting.graftAugmentation", () => `You don't have the pre-requisites for ${augName}`);
|
ctx.log(() => `You don't have the pre-requisites for ${augName}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.loseMoney(craftableAug.cost, "augmentations");
|
player.loseMoney(craftableAug.cost, "augmentations");
|
||||||
player.startGraftAugmentationWork(augName, craftableAug.time);
|
player.startGraftAugmentationWork(augName, craftableAug.time);
|
||||||
|
|
||||||
if (focus) {
|
if (focus) {
|
||||||
player.startFocusing();
|
player.startFocusing();
|
||||||
Router.toWork();
|
Router.toWork();
|
||||||
} else if (wasFocusing) {
|
} else if (wasFocusing) {
|
||||||
player.stopFocusing();
|
player.stopFocusing();
|
||||||
Router.toTerminal();
|
Router.toTerminal();
|
||||||
}
|
}
|
||||||
|
|
||||||
workerScript.log("grafting.graftAugmentation", () => `Began grafting Augmentation ${augName}.`);
|
ctx.log(() => `Began grafting Augmentation ${augName}.`);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { INetscriptHelper } from "./INetscriptHelper";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
import { HacknetServerConstants } from "../Hacknet/data/Constants";
|
import { HacknetServerConstants } from "../Hacknet/data/Constants";
|
||||||
@ -21,12 +20,13 @@ import { HashUpgrade } from "../Hacknet/HashUpgrade";
|
|||||||
import { GetServer } from "../Server/AllServers";
|
import { GetServer } from "../Server/AllServers";
|
||||||
|
|
||||||
import { Hacknet as IHacknet, NodeStats } from "../ScriptEditor/NetscriptDefinitions";
|
import { Hacknet as IHacknet, NodeStats } from "../ScriptEditor/NetscriptDefinitions";
|
||||||
|
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||||
|
|
||||||
export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): IHacknet {
|
export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript): InternalAPI<IHacknet> {
|
||||||
// Utility function to get Hacknet Node object
|
// Utility function to get Hacknet Node object
|
||||||
const getHacknetNode = function (i: number, callingFn = ""): HacknetNode | HacknetServer {
|
const getHacknetNode = function (ctx: NetscriptContext, i: number): HacknetNode | HacknetServer {
|
||||||
if (i < 0 || i >= player.hacknetNodes.length) {
|
if (i < 0 || i >= player.hacknetNodes.length) {
|
||||||
throw helper.makeRuntimeErrorMsg(callingFn, "Index specified for Hacknet Node is out-of-bounds: " + i);
|
throw ctx.makeRuntimeErrorMsg("Index specified for Hacknet Node is out-of-bounds: " + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasHacknetServers(player)) {
|
if (hasHacknetServers(player)) {
|
||||||
@ -35,8 +35,7 @@ export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript, he
|
|||||||
const hserver = GetServer(hi);
|
const hserver = GetServer(hi);
|
||||||
if (!(hserver instanceof HacknetServer)) throw new Error("hacknet server was not actually hacknet server");
|
if (!(hserver instanceof HacknetServer)) throw new Error("hacknet server was not actually hacknet server");
|
||||||
if (hserver == null) {
|
if (hserver == null) {
|
||||||
throw helper.makeRuntimeErrorMsg(
|
throw ctx.makeRuntimeErrorMsg(
|
||||||
callingFn,
|
|
||||||
`Could not get Hacknet Server for index ${i}. This is probably a bug, please report to game dev`,
|
`Could not get Hacknet Server for index ${i}. This is probably a bug, please report to game dev`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -50,162 +49,186 @@ export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript, he
|
|||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
numNodes: function (): number {
|
numNodes: () => (): number => {
|
||||||
return player.hacknetNodes.length;
|
return player.hacknetNodes.length;
|
||||||
},
|
},
|
||||||
maxNumNodes: function (): number {
|
maxNumNodes: () => (): number => {
|
||||||
if (hasHacknetServers(player)) {
|
if (hasHacknetServers(player)) {
|
||||||
return HacknetServerConstants.MaxServers;
|
return HacknetServerConstants.MaxServers;
|
||||||
}
|
}
|
||||||
return Infinity;
|
return Infinity;
|
||||||
},
|
},
|
||||||
purchaseNode: function (): number {
|
purchaseNode: () => (): number => {
|
||||||
return purchaseHacknet(player);
|
return purchaseHacknet(player);
|
||||||
},
|
},
|
||||||
getPurchaseNodeCost: function (): number {
|
getPurchaseNodeCost: () => (): number => {
|
||||||
if (hasHacknetServers(player)) {
|
if (hasHacknetServers(player)) {
|
||||||
return getCostOfNextHacknetServer(player);
|
return getCostOfNextHacknetServer(player);
|
||||||
} else {
|
} else {
|
||||||
return getCostOfNextHacknetNode(player);
|
return getCostOfNextHacknetNode(player);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getNodeStats: function (_i: unknown): NodeStats {
|
getNodeStats:
|
||||||
const i = helper.number("getNodeStats", "i", _i);
|
(ctx: NetscriptContext) =>
|
||||||
const node = getHacknetNode(i, "getNodeStats");
|
(_i: unknown): NodeStats => {
|
||||||
const hasUpgraded = hasHacknetServers(player);
|
const i = ctx.helper.number("i", _i);
|
||||||
const res: any = {
|
const node = getHacknetNode(ctx, i);
|
||||||
name: node instanceof HacknetServer ? node.hostname : node.name,
|
const hasUpgraded = hasHacknetServers(player);
|
||||||
level: node.level,
|
const res: any = {
|
||||||
ram: node instanceof HacknetServer ? node.maxRam : node.ram,
|
name: node instanceof HacknetServer ? node.hostname : node.name,
|
||||||
ramUsed: node instanceof HacknetServer ? node.ramUsed : undefined,
|
level: node.level,
|
||||||
cores: node.cores,
|
ram: node instanceof HacknetServer ? node.maxRam : node.ram,
|
||||||
production: node instanceof HacknetServer ? node.hashRate : node.moneyGainRatePerSecond,
|
ramUsed: node instanceof HacknetServer ? node.ramUsed : undefined,
|
||||||
timeOnline: node.onlineTimeSeconds,
|
cores: node.cores,
|
||||||
totalProduction: node instanceof HacknetServer ? node.totalHashesGenerated : node.totalMoneyGenerated,
|
production: node instanceof HacknetServer ? node.hashRate : node.moneyGainRatePerSecond,
|
||||||
};
|
timeOnline: node.onlineTimeSeconds,
|
||||||
|
totalProduction: node instanceof HacknetServer ? node.totalHashesGenerated : node.totalMoneyGenerated,
|
||||||
|
};
|
||||||
|
|
||||||
if (hasUpgraded && node instanceof HacknetServer) {
|
if (hasUpgraded && node instanceof HacknetServer) {
|
||||||
res.cache = node.cache;
|
res.cache = node.cache;
|
||||||
res.hashCapacity = node.hashCapacity;
|
res.hashCapacity = node.hashCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
upgradeLevel: function (_i: unknown, _n: unknown = 1): boolean {
|
upgradeLevel:
|
||||||
const i = helper.number("upgradeLevel", "i", _i);
|
(ctx: NetscriptContext) =>
|
||||||
const n = helper.number("upgradeLevel", "n", _n);
|
(_i: unknown, _n: unknown = 1): boolean => {
|
||||||
const node = getHacknetNode(i, "upgradeLevel");
|
const i = ctx.helper.number("i", _i);
|
||||||
return purchaseLevelUpgrade(player, node, n);
|
const n = ctx.helper.number("n", _n);
|
||||||
},
|
const node = getHacknetNode(ctx, i);
|
||||||
upgradeRam: function (_i: unknown, _n: unknown = 1): boolean {
|
return purchaseLevelUpgrade(player, node, n);
|
||||||
const i = helper.number("upgradeRam", "i", _i);
|
},
|
||||||
const n = helper.number("upgradeRam", "n", _n);
|
upgradeRam:
|
||||||
const node = getHacknetNode(i, "upgradeRam");
|
(ctx: NetscriptContext) =>
|
||||||
return purchaseRamUpgrade(player, node, n);
|
(_i: unknown, _n: unknown = 1): boolean => {
|
||||||
},
|
const i = ctx.helper.number("i", _i);
|
||||||
upgradeCore: function (_i: unknown, _n: unknown = 1): boolean {
|
const n = ctx.helper.number("n", _n);
|
||||||
const i = helper.number("upgradeCore", "i", _i);
|
const node = getHacknetNode(ctx, i);
|
||||||
const n = helper.number("upgradeCore", "n", _n);
|
return purchaseRamUpgrade(player, node, n);
|
||||||
const node = getHacknetNode(i, "upgradeCore");
|
},
|
||||||
return purchaseCoreUpgrade(player, node, n);
|
upgradeCore:
|
||||||
},
|
(ctx: NetscriptContext) =>
|
||||||
upgradeCache: function (_i: unknown, _n: unknown = 1): boolean {
|
(_i: unknown, _n: unknown = 1): boolean => {
|
||||||
const i = helper.number("upgradeCache", "i", _i);
|
const i = ctx.helper.number("i", _i);
|
||||||
const n = helper.number("upgradeCache", "n", _n);
|
const n = ctx.helper.number("n", _n);
|
||||||
if (!hasHacknetServers(player)) {
|
const node = getHacknetNode(ctx, i);
|
||||||
return false;
|
return purchaseCoreUpgrade(player, node, n);
|
||||||
}
|
},
|
||||||
const node = getHacknetNode(i, "upgradeCache");
|
upgradeCache:
|
||||||
if (!(node instanceof HacknetServer)) {
|
(ctx: NetscriptContext) =>
|
||||||
workerScript.log("hacknet.upgradeCache", () => "Can only be called on hacknet servers");
|
(_i: unknown, _n: unknown = 1): boolean => {
|
||||||
return false;
|
const i = ctx.helper.number("i", _i);
|
||||||
}
|
const n = ctx.helper.number("n", _n);
|
||||||
const res = purchaseCacheUpgrade(player, node, n);
|
if (!hasHacknetServers(player)) {
|
||||||
if (res) {
|
return false;
|
||||||
updateHashManagerCapacity(player);
|
}
|
||||||
}
|
const node = getHacknetNode(ctx, i);
|
||||||
return res;
|
if (!(node instanceof HacknetServer)) {
|
||||||
},
|
workerScript.log("hacknet.upgradeCache", () => "Can only be called on hacknet servers");
|
||||||
getLevelUpgradeCost: function (_i: unknown, _n: unknown = 1): number {
|
return false;
|
||||||
const i = helper.number("getLevelUpgradeCost", "i", _i);
|
}
|
||||||
const n = helper.number("getLevelUpgradeCost", "n", _n);
|
const res = purchaseCacheUpgrade(player, node, n);
|
||||||
const node = getHacknetNode(i, "upgradeLevel");
|
if (res) {
|
||||||
return node.calculateLevelUpgradeCost(n, player.hacknet_node_level_cost_mult);
|
updateHashManagerCapacity(player);
|
||||||
},
|
}
|
||||||
getRamUpgradeCost: function (_i: unknown, _n: unknown = 1): number {
|
return res;
|
||||||
const i = helper.number("getRamUpgradeCost", "i", _i);
|
},
|
||||||
const n = helper.number("getRamUpgradeCost", "n", _n);
|
getLevelUpgradeCost:
|
||||||
const node = getHacknetNode(i, "upgradeRam");
|
(ctx: NetscriptContext) =>
|
||||||
return node.calculateRamUpgradeCost(n, player.hacknet_node_ram_cost_mult);
|
(_i: unknown, _n: unknown = 1): number => {
|
||||||
},
|
const i = ctx.helper.number("i", _i);
|
||||||
getCoreUpgradeCost: function (_i: unknown, _n: unknown = 1): number {
|
const n = ctx.helper.number("n", _n);
|
||||||
const i = helper.number("getCoreUpgradeCost", "i", _i);
|
const node = getHacknetNode(ctx, i);
|
||||||
const n = helper.number("getCoreUpgradeCost", "n", _n);
|
return node.calculateLevelUpgradeCost(n, player.hacknet_node_level_cost_mult);
|
||||||
const node = getHacknetNode(i, "upgradeCore");
|
},
|
||||||
return node.calculateCoreUpgradeCost(n, player.hacknet_node_core_cost_mult);
|
getRamUpgradeCost:
|
||||||
},
|
(ctx: NetscriptContext) =>
|
||||||
getCacheUpgradeCost: function (_i: unknown, _n: unknown = 1): number {
|
(_i: unknown, _n: unknown = 1): number => {
|
||||||
const i = helper.number("getCacheUpgradeCost", "i", _i);
|
const i = ctx.helper.number("i", _i);
|
||||||
const n = helper.number("getCacheUpgradeCost", "n", _n);
|
const n = ctx.helper.number("n", _n);
|
||||||
if (!hasHacknetServers(player)) {
|
const node = getHacknetNode(ctx, i);
|
||||||
return Infinity;
|
return node.calculateRamUpgradeCost(n, player.hacknet_node_ram_cost_mult);
|
||||||
}
|
},
|
||||||
const node = getHacknetNode(i, "upgradeCache");
|
getCoreUpgradeCost:
|
||||||
if (!(node instanceof HacknetServer)) {
|
(ctx: NetscriptContext) =>
|
||||||
workerScript.log("hacknet.getCacheUpgradeCost", () => "Can only be called on hacknet servers");
|
(_i: unknown, _n: unknown = 1): number => {
|
||||||
return -1;
|
const i = ctx.helper.number("i", _i);
|
||||||
}
|
const n = ctx.helper.number("n", _n);
|
||||||
return node.calculateCacheUpgradeCost(n);
|
const node = getHacknetNode(ctx, i);
|
||||||
},
|
return node.calculateCoreUpgradeCost(n, player.hacknet_node_core_cost_mult);
|
||||||
numHashes: function (): number {
|
},
|
||||||
|
getCacheUpgradeCost:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_i: unknown, _n: unknown = 1): number => {
|
||||||
|
const i = ctx.helper.number("i", _i);
|
||||||
|
const n = ctx.helper.number("n", _n);
|
||||||
|
if (!hasHacknetServers(player)) {
|
||||||
|
return Infinity;
|
||||||
|
}
|
||||||
|
const node = getHacknetNode(ctx, i);
|
||||||
|
if (!(node instanceof HacknetServer)) {
|
||||||
|
workerScript.log("hacknet.getCacheUpgradeCost", () => "Can only be called on hacknet servers");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return node.calculateCacheUpgradeCost(n);
|
||||||
|
},
|
||||||
|
numHashes: () => (): number => {
|
||||||
if (!hasHacknetServers(player)) {
|
if (!hasHacknetServers(player)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return player.hashManager.hashes;
|
return player.hashManager.hashes;
|
||||||
},
|
},
|
||||||
hashCapacity: function (): number {
|
hashCapacity: () => (): number => {
|
||||||
if (!hasHacknetServers(player)) {
|
if (!hasHacknetServers(player)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return player.hashManager.capacity;
|
return player.hashManager.capacity;
|
||||||
},
|
},
|
||||||
hashCost: function (_upgName: unknown): number {
|
hashCost:
|
||||||
const upgName = helper.string("hashCost", "upgName", _upgName);
|
(ctx: NetscriptContext) =>
|
||||||
if (!hasHacknetServers(player)) {
|
(_upgName: unknown): number => {
|
||||||
return Infinity;
|
const upgName = ctx.helper.string("upgName", _upgName);
|
||||||
}
|
if (!hasHacknetServers(player)) {
|
||||||
|
return Infinity;
|
||||||
|
}
|
||||||
|
|
||||||
return player.hashManager.getUpgradeCost(upgName);
|
return player.hashManager.getUpgradeCost(upgName);
|
||||||
},
|
},
|
||||||
spendHashes: function (_upgName: unknown, _upgTarget: unknown = ""): boolean {
|
spendHashes:
|
||||||
const upgName = helper.string("spendHashes", "upgName", _upgName);
|
(ctx: NetscriptContext) =>
|
||||||
const upgTarget = helper.string("spendHashes", "upgTarget", _upgTarget);
|
(_upgName: unknown, _upgTarget: unknown = ""): boolean => {
|
||||||
if (!hasHacknetServers(player)) {
|
const upgName = ctx.helper.string("upgName", _upgName);
|
||||||
return false;
|
const upgTarget = ctx.helper.string("upgTarget", _upgTarget);
|
||||||
}
|
if (!hasHacknetServers(player)) {
|
||||||
return purchaseHashUpgrade(player, upgName, upgTarget);
|
return false;
|
||||||
},
|
}
|
||||||
getHashUpgrades: function (): string[] {
|
return purchaseHashUpgrade(player, upgName, upgTarget);
|
||||||
|
},
|
||||||
|
getHashUpgrades: () => (): string[] => {
|
||||||
if (!hasHacknetServers(player)) {
|
if (!hasHacknetServers(player)) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
return Object.values(HashUpgrades).map((upgrade: HashUpgrade) => upgrade.name);
|
return Object.values(HashUpgrades).map((upgrade: HashUpgrade) => upgrade.name);
|
||||||
},
|
},
|
||||||
getHashUpgradeLevel: function (_upgName: unknown): number {
|
getHashUpgradeLevel:
|
||||||
const upgName = helper.string("getHashUpgradeLevel", "upgName", _upgName);
|
(ctx: NetscriptContext) =>
|
||||||
const level = player.hashManager.upgrades[upgName];
|
(_upgName: unknown): number => {
|
||||||
if (level === undefined) {
|
const upgName = ctx.helper.string("upgName", _upgName);
|
||||||
throw helper.makeRuntimeErrorMsg("hacknet.hashUpgradeLevel", `Invalid Hash Upgrade: ${upgName}`);
|
const level = player.hashManager.upgrades[upgName];
|
||||||
}
|
if (level === undefined) {
|
||||||
return level;
|
throw ctx.makeRuntimeErrorMsg(`Invalid Hash Upgrade: ${upgName}`);
|
||||||
},
|
}
|
||||||
getStudyMult: function (): number {
|
return level;
|
||||||
|
},
|
||||||
|
getStudyMult: () => (): number => {
|
||||||
if (!hasHacknetServers(player)) {
|
if (!hasHacknetServers(player)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return player.hashManager.getStudyMult();
|
return player.hashManager.getStudyMult();
|
||||||
},
|
},
|
||||||
getTrainingMult: function (): number {
|
getTrainingMult: () => (): number => {
|
||||||
if (!hasHacknetServers(player)) {
|
if (!hasHacknetServers(player)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
if (script.filename === cbScript) {
|
if (script.filename === cbScript) {
|
||||||
const ramUsage = script.ramUsage;
|
const ramUsage = script.ramUsage;
|
||||||
const ramAvailable = home.maxRam - home.ramUsed;
|
const ramAvailable = home.maxRam - home.ramUsed;
|
||||||
if (ramUsage > ramAvailable) {
|
if (ramUsage > ramAvailable + 0.001) {
|
||||||
return; // Not enough RAM
|
return; // Not enough RAM
|
||||||
}
|
}
|
||||||
const runningScriptObj = new RunningScript(script, []); // No args
|
const runningScriptObj = new RunningScript(script, []); // No args
|
||||||
@ -123,7 +123,8 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
|
|||||||
_ctx.helper.checkSingularityAccess();
|
_ctx.helper.checkSingularityAccess();
|
||||||
const augName = _ctx.helper.string("augName", _augName);
|
const augName = _ctx.helper.string("augName", _augName);
|
||||||
const aug = getAugmentation(_ctx, augName);
|
const aug = getAugmentation(_ctx, augName);
|
||||||
return [aug.getCost(player).moneyCost, aug.getCost(player).repCost];
|
const costs = aug.getCost(player);
|
||||||
|
return [costs.repCost, costs.moneyCost];
|
||||||
},
|
},
|
||||||
getAugmentationPrereq: (_ctx: NetscriptContext) =>
|
getAugmentationPrereq: (_ctx: NetscriptContext) =>
|
||||||
function (_augName: unknown): string[] {
|
function (_augName: unknown): string[] {
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
import { INetscriptHelper } from "./INetscriptHelper";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
|
||||||
import { FactionWorkType } from "../Faction/FactionWorkTypeEnum";
|
import { FactionWorkType } from "../Faction/FactionWorkTypeEnum";
|
||||||
import { SleeveTaskType } from "../PersonObjects/Sleeve/SleeveTaskTypesEnum";
|
import { SleeveTaskType } from "../PersonObjects/Sleeve/SleeveTaskTypesEnum";
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
|
||||||
import { findSleevePurchasableAugs } from "../PersonObjects/Sleeve/SleeveHelpers";
|
import { findSleevePurchasableAugs } from "../PersonObjects/Sleeve/SleeveHelpers";
|
||||||
import { StaticAugmentations } from "../Augmentation/StaticAugmentations";
|
import { StaticAugmentations } from "../Augmentation/StaticAugmentations";
|
||||||
import { CityName } from "../Locations/data/CityNames";
|
import { CityName } from "../Locations/data/CityNames";
|
||||||
@ -17,22 +14,22 @@ import {
|
|||||||
SleeveTask,
|
SleeveTask,
|
||||||
} from "../ScriptEditor/NetscriptDefinitions";
|
} from "../ScriptEditor/NetscriptDefinitions";
|
||||||
import { checkEnum } from "../utils/helpers/checkEnum";
|
import { checkEnum } from "../utils/helpers/checkEnum";
|
||||||
|
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||||
|
|
||||||
export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): ISleeve {
|
export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||||
const checkSleeveAPIAccess = function (func: string): void {
|
const checkSleeveAPIAccess = function (ctx: NetscriptContext): void {
|
||||||
if (player.bitNodeN !== 10 && !player.sourceFileLvl(10)) {
|
if (player.bitNodeN !== 10 && !player.sourceFileLvl(10)) {
|
||||||
throw helper.makeRuntimeErrorMsg(
|
throw ctx.makeRuntimeErrorMsg(
|
||||||
`sleeve.${func}`,
|
|
||||||
"You do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10",
|
"You do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkSleeveNumber = function (func: string, sleeveNumber: number): void {
|
const checkSleeveNumber = function (ctx: NetscriptContext, sleeveNumber: number): void {
|
||||||
if (sleeveNumber >= player.sleeves.length || sleeveNumber < 0) {
|
if (sleeveNumber >= player.sleeves.length || sleeveNumber < 0) {
|
||||||
const msg = `Invalid sleeve number: ${sleeveNumber}`;
|
const msg = `Invalid sleeve number: ${sleeveNumber}`;
|
||||||
workerScript.log(func, () => msg);
|
ctx.log(() => msg);
|
||||||
throw helper.makeRuntimeErrorMsg(`sleeve.${func}`, msg);
|
throw ctx.makeRuntimeErrorMsg(msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -50,296 +47,299 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateRam = (funcName: string): void =>
|
|
||||||
helper.updateDynamicRam(funcName, getRamCost(player, "sleeve", funcName));
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getNumSleeves: function (): number {
|
getNumSleeves: (ctx: NetscriptContext) => (): number => {
|
||||||
updateRam("getNumSleeves");
|
checkSleeveAPIAccess(ctx);
|
||||||
checkSleeveAPIAccess("getNumSleeves");
|
|
||||||
return player.sleeves.length;
|
return player.sleeves.length;
|
||||||
},
|
},
|
||||||
setToShockRecovery: function (_sleeveNumber: unknown): boolean {
|
setToShockRecovery:
|
||||||
updateRam("setToShockRecovery");
|
(ctx: NetscriptContext) =>
|
||||||
const sleeveNumber = helper.number("setToShockRecovery", "sleeveNumber", _sleeveNumber);
|
(_sleeveNumber: unknown): boolean => {
|
||||||
checkSleeveAPIAccess("setToShockRecovery");
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||||
checkSleeveNumber("setToShockRecovery", sleeveNumber);
|
checkSleeveAPIAccess(ctx);
|
||||||
return player.sleeves[sleeveNumber].shockRecovery(player);
|
checkSleeveNumber(ctx, sleeveNumber);
|
||||||
},
|
return player.sleeves[sleeveNumber].shockRecovery(player);
|
||||||
setToSynchronize: function (_sleeveNumber: unknown): boolean {
|
},
|
||||||
updateRam("setToSynchronize");
|
setToSynchronize:
|
||||||
const sleeveNumber = helper.number("setToSynchronize", "sleeveNumber", _sleeveNumber);
|
(ctx: NetscriptContext) =>
|
||||||
checkSleeveAPIAccess("setToSynchronize");
|
(_sleeveNumber: unknown): boolean => {
|
||||||
checkSleeveNumber("setToSynchronize", sleeveNumber);
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||||
return player.sleeves[sleeveNumber].synchronize(player);
|
checkSleeveAPIAccess(ctx);
|
||||||
},
|
checkSleeveNumber(ctx, sleeveNumber);
|
||||||
setToCommitCrime: function (_sleeveNumber: unknown, _crimeRoughName: unknown): boolean {
|
return player.sleeves[sleeveNumber].synchronize(player);
|
||||||
updateRam("setToCommitCrime");
|
},
|
||||||
const sleeveNumber = helper.number("setToCommitCrime", "sleeveNumber", _sleeveNumber);
|
setToCommitCrime:
|
||||||
const crimeRoughName = helper.string("setToCommitCrime", "crimeName", _crimeRoughName);
|
(ctx: NetscriptContext) =>
|
||||||
checkSleeveAPIAccess("setToCommitCrime");
|
(_sleeveNumber: unknown, _crimeRoughName: unknown): boolean => {
|
||||||
checkSleeveNumber("setToCommitCrime", sleeveNumber);
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||||
const crime = findCrime(crimeRoughName);
|
const crimeRoughName = ctx.helper.string("crimeName", _crimeRoughName);
|
||||||
if (crime === null) {
|
checkSleeveAPIAccess(ctx);
|
||||||
return false;
|
checkSleeveNumber(ctx, sleeveNumber);
|
||||||
}
|
const crime = findCrime(crimeRoughName);
|
||||||
return player.sleeves[sleeveNumber].commitCrime(player, crime.name);
|
if (crime === null) {
|
||||||
},
|
return false;
|
||||||
setToUniversityCourse: function (_sleeveNumber: unknown, _universityName: unknown, _className: unknown): boolean {
|
|
||||||
updateRam("setToUniversityCourse");
|
|
||||||
const sleeveNumber = helper.number("setToUniversityCourse", "sleeveNumber", _sleeveNumber);
|
|
||||||
const universityName = helper.string("setToUniversityCourse", "universityName", _universityName);
|
|
||||||
const className = helper.string("setToUniversityCourse", "className", _className);
|
|
||||||
checkSleeveAPIAccess("setToUniversityCourse");
|
|
||||||
checkSleeveNumber("setToUniversityCourse", sleeveNumber);
|
|
||||||
return player.sleeves[sleeveNumber].takeUniversityCourse(player, universityName, className);
|
|
||||||
},
|
|
||||||
travel: function (_sleeveNumber: unknown, _cityName: unknown): boolean {
|
|
||||||
updateRam("travel");
|
|
||||||
const sleeveNumber = helper.number("travel", "sleeveNumber", _sleeveNumber);
|
|
||||||
const cityName = helper.string("travel", "cityName", _cityName);
|
|
||||||
checkSleeveAPIAccess("travel");
|
|
||||||
checkSleeveNumber("travel", sleeveNumber);
|
|
||||||
if (checkEnum(CityName, cityName)) {
|
|
||||||
return player.sleeves[sleeveNumber].travel(player, cityName);
|
|
||||||
} else {
|
|
||||||
throw helper.makeRuntimeErrorMsg("sleeve.setToCompanyWork", `Invalid city name: '${cityName}'.`);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setToCompanyWork: function (_sleeveNumber: unknown, acompanyName: unknown): boolean {
|
|
||||||
updateRam("setToCompanyWork");
|
|
||||||
const sleeveNumber = helper.number("setToCompanyWork", "sleeveNumber", _sleeveNumber);
|
|
||||||
const companyName = helper.string("setToCompanyWork", "companyName", acompanyName);
|
|
||||||
checkSleeveAPIAccess("setToCompanyWork");
|
|
||||||
checkSleeveNumber("setToCompanyWork", sleeveNumber);
|
|
||||||
|
|
||||||
// Cannot work at the same company that another sleeve is working at
|
|
||||||
for (let i = 0; i < player.sleeves.length; ++i) {
|
|
||||||
if (i === sleeveNumber) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
const other = player.sleeves[i];
|
return player.sleeves[sleeveNumber].commitCrime(player, crime.name);
|
||||||
if (other.currentTask === SleeveTaskType.Company && other.currentTaskLocation === companyName) {
|
},
|
||||||
throw helper.makeRuntimeErrorMsg(
|
setToUniversityCourse:
|
||||||
"sleeve.setToCompanyWork",
|
(ctx: NetscriptContext) =>
|
||||||
`Sleeve ${sleeveNumber} cannot work for company ${companyName} because Sleeve ${i} is already working for them.`,
|
(_sleeveNumber: unknown, _universityName: unknown, _className: unknown): boolean => {
|
||||||
);
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||||
|
const universityName = ctx.helper.string("universityName", _universityName);
|
||||||
|
const className = ctx.helper.string("className", _className);
|
||||||
|
checkSleeveAPIAccess(ctx);
|
||||||
|
checkSleeveNumber(ctx, sleeveNumber);
|
||||||
|
return player.sleeves[sleeveNumber].takeUniversityCourse(player, universityName, className);
|
||||||
|
},
|
||||||
|
travel:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_sleeveNumber: unknown, _cityName: unknown): boolean => {
|
||||||
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||||
|
const cityName = ctx.helper.string("cityName", _cityName);
|
||||||
|
checkSleeveAPIAccess(ctx);
|
||||||
|
checkSleeveNumber(ctx, sleeveNumber);
|
||||||
|
if (checkEnum(CityName, cityName)) {
|
||||||
|
return player.sleeves[sleeveNumber].travel(player, cityName);
|
||||||
|
} else {
|
||||||
|
throw ctx.makeRuntimeErrorMsg(`Invalid city name: '${cityName}'.`);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
setToCompanyWork:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_sleeveNumber: unknown, acompanyName: unknown): boolean => {
|
||||||
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||||
|
const companyName = ctx.helper.string("companyName", acompanyName);
|
||||||
|
checkSleeveAPIAccess(ctx);
|
||||||
|
checkSleeveNumber(ctx, sleeveNumber);
|
||||||
|
|
||||||
return player.sleeves[sleeveNumber].workForCompany(player, companyName);
|
// Cannot work at the same company that another sleeve is working at
|
||||||
},
|
|
||||||
setToFactionWork: function (
|
|
||||||
_sleeveNumber: unknown,
|
|
||||||
_factionName: unknown,
|
|
||||||
_workType: unknown,
|
|
||||||
): boolean | undefined {
|
|
||||||
updateRam("setToFactionWork");
|
|
||||||
const sleeveNumber = helper.number("setToFactionWork", "sleeveNumber", _sleeveNumber);
|
|
||||||
const factionName = helper.string("setToFactionWork", "factionName", _factionName);
|
|
||||||
const workType = helper.string("setToFactionWork", "workType", _workType);
|
|
||||||
checkSleeveAPIAccess("setToFactionWork");
|
|
||||||
checkSleeveNumber("setToFactionWork", sleeveNumber);
|
|
||||||
|
|
||||||
// Cannot work at the same faction that another sleeve is working at
|
|
||||||
for (let i = 0; i < player.sleeves.length; ++i) {
|
|
||||||
if (i === sleeveNumber) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const other = player.sleeves[i];
|
|
||||||
if (other.currentTask === SleeveTaskType.Faction && other.currentTaskLocation === factionName) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(
|
|
||||||
"sleeve.setToFactionWork",
|
|
||||||
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because Sleeve ${i} is already working for them.`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (player.gang && player.gang.facName == factionName) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(
|
|
||||||
"sleeve.setToFactionWork",
|
|
||||||
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because you have started a gang with them.`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return player.sleeves[sleeveNumber].workForFaction(player, factionName, workType);
|
|
||||||
},
|
|
||||||
setToGymWorkout: function (_sleeveNumber: unknown, _gymName: unknown, _stat: unknown): boolean {
|
|
||||||
updateRam("setToGymWorkout");
|
|
||||||
const sleeveNumber = helper.number("setToGymWorkout", "sleeveNumber", _sleeveNumber);
|
|
||||||
const gymName = helper.string("setToGymWorkout", "gymName", _gymName);
|
|
||||||
const stat = helper.string("setToGymWorkout", "stat", _stat);
|
|
||||||
checkSleeveAPIAccess("setToGymWorkout");
|
|
||||||
checkSleeveNumber("setToGymWorkout", sleeveNumber);
|
|
||||||
|
|
||||||
return player.sleeves[sleeveNumber].workoutAtGym(player, gymName, stat);
|
|
||||||
},
|
|
||||||
getSleeveStats: function (_sleeveNumber: unknown): SleeveSkills {
|
|
||||||
updateRam("getSleeveStats");
|
|
||||||
const sleeveNumber = helper.number("getSleeveStats", "sleeveNumber", _sleeveNumber);
|
|
||||||
checkSleeveAPIAccess("getSleeveStats");
|
|
||||||
checkSleeveNumber("getSleeveStats", sleeveNumber);
|
|
||||||
return getSleeveStats(sleeveNumber);
|
|
||||||
},
|
|
||||||
getTask: function (_sleeveNumber: unknown): SleeveTask {
|
|
||||||
updateRam("getTask");
|
|
||||||
const sleeveNumber = helper.number("getTask", "sleeveNumber", _sleeveNumber);
|
|
||||||
checkSleeveAPIAccess("getTask");
|
|
||||||
checkSleeveNumber("getTask", sleeveNumber);
|
|
||||||
|
|
||||||
const sl = player.sleeves[sleeveNumber];
|
|
||||||
return {
|
|
||||||
task: SleeveTaskType[sl.currentTask],
|
|
||||||
crime: sl.crimeType,
|
|
||||||
location: sl.currentTaskLocation,
|
|
||||||
gymStatType: sl.gymStatType,
|
|
||||||
factionWorkType: FactionWorkType[sl.factionWorkType],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
getInformation: function (_sleeveNumber: unknown): SleeveInformation {
|
|
||||||
updateRam("getInformation");
|
|
||||||
const sleeveNumber = helper.number("getInformation", "sleeveNumber", _sleeveNumber);
|
|
||||||
checkSleeveAPIAccess("getInformation");
|
|
||||||
checkSleeveNumber("getInformation", sleeveNumber);
|
|
||||||
|
|
||||||
const sl = player.sleeves[sleeveNumber];
|
|
||||||
return {
|
|
||||||
tor: false,
|
|
||||||
city: sl.city,
|
|
||||||
hp: sl.hp,
|
|
||||||
jobs: Object.keys(player.jobs), // technically sleeves have the same jobs as the player.
|
|
||||||
jobTitle: Object.values(player.jobs),
|
|
||||||
maxHp: sl.max_hp,
|
|
||||||
|
|
||||||
mult: {
|
|
||||||
agility: sl.agility_mult,
|
|
||||||
agilityExp: sl.agility_exp_mult,
|
|
||||||
charisma: sl.charisma_mult,
|
|
||||||
charismaExp: sl.charisma_exp_mult,
|
|
||||||
companyRep: sl.company_rep_mult,
|
|
||||||
crimeMoney: sl.crime_money_mult,
|
|
||||||
crimeSuccess: sl.crime_success_mult,
|
|
||||||
defense: sl.defense_mult,
|
|
||||||
defenseExp: sl.defense_exp_mult,
|
|
||||||
dexterity: sl.dexterity_mult,
|
|
||||||
dexterityExp: sl.dexterity_exp_mult,
|
|
||||||
factionRep: sl.faction_rep_mult,
|
|
||||||
hacking: sl.hacking_mult,
|
|
||||||
hackingExp: sl.hacking_exp_mult,
|
|
||||||
strength: sl.strength_mult,
|
|
||||||
strengthExp: sl.strength_exp_mult,
|
|
||||||
workMoney: sl.work_money_mult,
|
|
||||||
},
|
|
||||||
|
|
||||||
timeWorked: sl.currentTaskTime,
|
|
||||||
earningsForSleeves: {
|
|
||||||
workHackExpGain: sl.earningsForSleeves.hack,
|
|
||||||
workStrExpGain: sl.earningsForSleeves.str,
|
|
||||||
workDefExpGain: sl.earningsForSleeves.def,
|
|
||||||
workDexExpGain: sl.earningsForSleeves.dex,
|
|
||||||
workAgiExpGain: sl.earningsForSleeves.agi,
|
|
||||||
workChaExpGain: sl.earningsForSleeves.cha,
|
|
||||||
workMoneyGain: sl.earningsForSleeves.money,
|
|
||||||
},
|
|
||||||
earningsForPlayer: {
|
|
||||||
workHackExpGain: sl.earningsForPlayer.hack,
|
|
||||||
workStrExpGain: sl.earningsForPlayer.str,
|
|
||||||
workDefExpGain: sl.earningsForPlayer.def,
|
|
||||||
workDexExpGain: sl.earningsForPlayer.dex,
|
|
||||||
workAgiExpGain: sl.earningsForPlayer.agi,
|
|
||||||
workChaExpGain: sl.earningsForPlayer.cha,
|
|
||||||
workMoneyGain: sl.earningsForPlayer.money,
|
|
||||||
},
|
|
||||||
earningsForTask: {
|
|
||||||
workHackExpGain: sl.earningsForTask.hack,
|
|
||||||
workStrExpGain: sl.earningsForTask.str,
|
|
||||||
workDefExpGain: sl.earningsForTask.def,
|
|
||||||
workDexExpGain: sl.earningsForTask.dex,
|
|
||||||
workAgiExpGain: sl.earningsForTask.agi,
|
|
||||||
workChaExpGain: sl.earningsForTask.cha,
|
|
||||||
workMoneyGain: sl.earningsForTask.money,
|
|
||||||
},
|
|
||||||
workRepGain: sl.getRepGain(player),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
getSleeveAugmentations: function (_sleeveNumber: unknown): string[] {
|
|
||||||
updateRam("getSleeveAugmentations");
|
|
||||||
const sleeveNumber = helper.number("getSleeveAugmentations", "sleeveNumber", _sleeveNumber);
|
|
||||||
checkSleeveAPIAccess("getSleeveAugmentations");
|
|
||||||
checkSleeveNumber("getSleeveAugmentations", sleeveNumber);
|
|
||||||
|
|
||||||
const augs = [];
|
|
||||||
for (let i = 0; i < player.sleeves[sleeveNumber].augmentations.length; i++) {
|
|
||||||
augs.push(player.sleeves[sleeveNumber].augmentations[i].name);
|
|
||||||
}
|
|
||||||
return augs;
|
|
||||||
},
|
|
||||||
getSleevePurchasableAugs: function (_sleeveNumber: unknown): AugmentPair[] {
|
|
||||||
updateRam("getSleevePurchasableAugs");
|
|
||||||
const sleeveNumber = helper.number("getSleevePurchasableAugs", "sleeveNumber", _sleeveNumber);
|
|
||||||
checkSleeveAPIAccess("getSleevePurchasableAugs");
|
|
||||||
checkSleeveNumber("getSleevePurchasableAugs", sleeveNumber);
|
|
||||||
|
|
||||||
const purchasableAugs = findSleevePurchasableAugs(player.sleeves[sleeveNumber], player);
|
|
||||||
const augs = [];
|
|
||||||
for (let i = 0; i < purchasableAugs.length; i++) {
|
|
||||||
const aug = purchasableAugs[i];
|
|
||||||
augs.push({
|
|
||||||
name: aug.name,
|
|
||||||
cost: aug.baseCost,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return augs;
|
|
||||||
},
|
|
||||||
purchaseSleeveAug: function (_sleeveNumber: unknown, _augName: unknown): boolean {
|
|
||||||
updateRam("purchaseSleeveAug");
|
|
||||||
const sleeveNumber = helper.number("purchaseSleeveAug", "sleeveNumber", _sleeveNumber);
|
|
||||||
const augName = helper.string("purchaseSleeveAug", "augName", _augName);
|
|
||||||
checkSleeveAPIAccess("purchaseSleeveAug");
|
|
||||||
checkSleeveNumber("purchaseSleeveAug", sleeveNumber);
|
|
||||||
|
|
||||||
if (getSleeveStats(sleeveNumber).shock > 0) {
|
|
||||||
throw helper.makeRuntimeErrorMsg("sleeve.purchaseSleeveAug", `Sleeve shock too high: Sleeve ${sleeveNumber}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const aug = StaticAugmentations[augName];
|
|
||||||
if (!aug) {
|
|
||||||
throw helper.makeRuntimeErrorMsg("sleeve.purchaseSleeveAug", `Invalid aug: ${augName}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return player.sleeves[sleeveNumber].tryBuyAugmentation(player, aug);
|
|
||||||
},
|
|
||||||
setToBladeburnerAction: function (_sleeveNumber: unknown, _action: unknown, _contract?: unknown): boolean {
|
|
||||||
updateRam("setToBladeburnerAction");
|
|
||||||
const sleeveNumber = helper.number("setToBladeburnerAction", "sleeveNumber", _sleeveNumber);
|
|
||||||
const action = helper.string("setToBladeburnerAction", "action", _action);
|
|
||||||
let contract: string;
|
|
||||||
if (typeof _contract === "undefined") {
|
|
||||||
contract = "------";
|
|
||||||
} else {
|
|
||||||
contract = helper.string("setToBladeburnerAction", "contract", _contract);
|
|
||||||
}
|
|
||||||
checkSleeveAPIAccess("setToBladeburnerAction");
|
|
||||||
checkSleeveNumber("setToBladeburnerAction", sleeveNumber);
|
|
||||||
|
|
||||||
// Cannot Take on Contracts if another sleeve is performing that action
|
|
||||||
if (action === "Take on contracts") {
|
|
||||||
for (let i = 0; i < player.sleeves.length; ++i) {
|
for (let i = 0; i < player.sleeves.length; ++i) {
|
||||||
if (i === sleeveNumber) {
|
if (i === sleeveNumber) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const other = player.sleeves[i];
|
const other = player.sleeves[i];
|
||||||
if (other.currentTask === SleeveTaskType.Bladeburner && other.bbAction === action) {
|
if (other.currentTask === SleeveTaskType.Company && other.currentTaskLocation === companyName) {
|
||||||
throw helper.makeRuntimeErrorMsg(
|
throw ctx.makeRuntimeErrorMsg(
|
||||||
"sleeve.setToBladeburnerAction",
|
`Sleeve ${sleeveNumber} cannot work for company ${companyName} because Sleeve ${i} is already working for them.`,
|
||||||
`Sleeve ${sleeveNumber} cannot take of contracts because Sleeve ${i} is already performing that action.`,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return player.sleeves[sleeveNumber].bladeburner(player, action, contract);
|
return player.sleeves[sleeveNumber].workForCompany(player, companyName);
|
||||||
},
|
},
|
||||||
|
setToFactionWork:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_sleeveNumber: unknown, _factionName: unknown, _workType: unknown): boolean | undefined => {
|
||||||
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||||
|
const factionName = ctx.helper.string("factionName", _factionName);
|
||||||
|
const workType = ctx.helper.string("workType", _workType);
|
||||||
|
checkSleeveAPIAccess(ctx);
|
||||||
|
checkSleeveNumber(ctx, sleeveNumber);
|
||||||
|
|
||||||
|
// Cannot work at the same faction that another sleeve is working at
|
||||||
|
for (let i = 0; i < player.sleeves.length; ++i) {
|
||||||
|
if (i === sleeveNumber) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const other = player.sleeves[i];
|
||||||
|
if (other.currentTask === SleeveTaskType.Faction && other.currentTaskLocation === factionName) {
|
||||||
|
throw ctx.makeRuntimeErrorMsg(
|
||||||
|
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because Sleeve ${i} is already working for them.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.gang && player.gang.facName == factionName) {
|
||||||
|
throw ctx.makeRuntimeErrorMsg(
|
||||||
|
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because you have started a gang with them.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return player.sleeves[sleeveNumber].workForFaction(player, factionName, workType);
|
||||||
|
},
|
||||||
|
setToGymWorkout:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_sleeveNumber: unknown, _gymName: unknown, _stat: unknown): boolean => {
|
||||||
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||||
|
const gymName = ctx.helper.string("gymName", _gymName);
|
||||||
|
const stat = ctx.helper.string("stat", _stat);
|
||||||
|
checkSleeveAPIAccess(ctx);
|
||||||
|
checkSleeveNumber(ctx, sleeveNumber);
|
||||||
|
|
||||||
|
return player.sleeves[sleeveNumber].workoutAtGym(player, gymName, stat);
|
||||||
|
},
|
||||||
|
getSleeveStats:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_sleeveNumber: unknown): SleeveSkills => {
|
||||||
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||||
|
checkSleeveAPIAccess(ctx);
|
||||||
|
checkSleeveNumber(ctx, sleeveNumber);
|
||||||
|
return getSleeveStats(sleeveNumber);
|
||||||
|
},
|
||||||
|
getTask:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_sleeveNumber: unknown): SleeveTask => {
|
||||||
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||||
|
checkSleeveAPIAccess(ctx);
|
||||||
|
checkSleeveNumber(ctx, sleeveNumber);
|
||||||
|
|
||||||
|
const sl = player.sleeves[sleeveNumber];
|
||||||
|
return {
|
||||||
|
task: SleeveTaskType[sl.currentTask],
|
||||||
|
crime: sl.crimeType,
|
||||||
|
location: sl.currentTaskLocation,
|
||||||
|
gymStatType: sl.gymStatType,
|
||||||
|
factionWorkType: FactionWorkType[sl.factionWorkType],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getInformation:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_sleeveNumber: unknown): SleeveInformation => {
|
||||||
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||||
|
checkSleeveAPIAccess(ctx);
|
||||||
|
checkSleeveNumber(ctx, sleeveNumber);
|
||||||
|
|
||||||
|
const sl = player.sleeves[sleeveNumber];
|
||||||
|
return {
|
||||||
|
tor: false,
|
||||||
|
city: sl.city,
|
||||||
|
hp: sl.hp,
|
||||||
|
jobs: Object.keys(player.jobs), // technically sleeves have the same jobs as the player.
|
||||||
|
jobTitle: Object.values(player.jobs),
|
||||||
|
maxHp: sl.max_hp,
|
||||||
|
|
||||||
|
mult: {
|
||||||
|
agility: sl.agility_mult,
|
||||||
|
agilityExp: sl.agility_exp_mult,
|
||||||
|
charisma: sl.charisma_mult,
|
||||||
|
charismaExp: sl.charisma_exp_mult,
|
||||||
|
companyRep: sl.company_rep_mult,
|
||||||
|
crimeMoney: sl.crime_money_mult,
|
||||||
|
crimeSuccess: sl.crime_success_mult,
|
||||||
|
defense: sl.defense_mult,
|
||||||
|
defenseExp: sl.defense_exp_mult,
|
||||||
|
dexterity: sl.dexterity_mult,
|
||||||
|
dexterityExp: sl.dexterity_exp_mult,
|
||||||
|
factionRep: sl.faction_rep_mult,
|
||||||
|
hacking: sl.hacking_mult,
|
||||||
|
hackingExp: sl.hacking_exp_mult,
|
||||||
|
strength: sl.strength_mult,
|
||||||
|
strengthExp: sl.strength_exp_mult,
|
||||||
|
workMoney: sl.work_money_mult,
|
||||||
|
},
|
||||||
|
|
||||||
|
timeWorked: sl.currentTaskTime,
|
||||||
|
earningsForSleeves: {
|
||||||
|
workHackExpGain: sl.earningsForSleeves.hack,
|
||||||
|
workStrExpGain: sl.earningsForSleeves.str,
|
||||||
|
workDefExpGain: sl.earningsForSleeves.def,
|
||||||
|
workDexExpGain: sl.earningsForSleeves.dex,
|
||||||
|
workAgiExpGain: sl.earningsForSleeves.agi,
|
||||||
|
workChaExpGain: sl.earningsForSleeves.cha,
|
||||||
|
workMoneyGain: sl.earningsForSleeves.money,
|
||||||
|
},
|
||||||
|
earningsForPlayer: {
|
||||||
|
workHackExpGain: sl.earningsForPlayer.hack,
|
||||||
|
workStrExpGain: sl.earningsForPlayer.str,
|
||||||
|
workDefExpGain: sl.earningsForPlayer.def,
|
||||||
|
workDexExpGain: sl.earningsForPlayer.dex,
|
||||||
|
workAgiExpGain: sl.earningsForPlayer.agi,
|
||||||
|
workChaExpGain: sl.earningsForPlayer.cha,
|
||||||
|
workMoneyGain: sl.earningsForPlayer.money,
|
||||||
|
},
|
||||||
|
earningsForTask: {
|
||||||
|
workHackExpGain: sl.earningsForTask.hack,
|
||||||
|
workStrExpGain: sl.earningsForTask.str,
|
||||||
|
workDefExpGain: sl.earningsForTask.def,
|
||||||
|
workDexExpGain: sl.earningsForTask.dex,
|
||||||
|
workAgiExpGain: sl.earningsForTask.agi,
|
||||||
|
workChaExpGain: sl.earningsForTask.cha,
|
||||||
|
workMoneyGain: sl.earningsForTask.money,
|
||||||
|
},
|
||||||
|
workRepGain: sl.getRepGain(player),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getSleeveAugmentations:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_sleeveNumber: unknown): string[] => {
|
||||||
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||||
|
checkSleeveAPIAccess(ctx);
|
||||||
|
checkSleeveNumber(ctx, sleeveNumber);
|
||||||
|
|
||||||
|
const augs = [];
|
||||||
|
for (let i = 0; i < player.sleeves[sleeveNumber].augmentations.length; i++) {
|
||||||
|
augs.push(player.sleeves[sleeveNumber].augmentations[i].name);
|
||||||
|
}
|
||||||
|
return augs;
|
||||||
|
},
|
||||||
|
getSleevePurchasableAugs:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_sleeveNumber: unknown): AugmentPair[] => {
|
||||||
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||||
|
checkSleeveAPIAccess(ctx);
|
||||||
|
checkSleeveNumber(ctx, sleeveNumber);
|
||||||
|
|
||||||
|
const purchasableAugs = findSleevePurchasableAugs(player.sleeves[sleeveNumber], player);
|
||||||
|
const augs = [];
|
||||||
|
for (let i = 0; i < purchasableAugs.length; i++) {
|
||||||
|
const aug = purchasableAugs[i];
|
||||||
|
augs.push({
|
||||||
|
name: aug.name,
|
||||||
|
cost: aug.baseCost,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return augs;
|
||||||
|
},
|
||||||
|
purchaseSleeveAug:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_sleeveNumber: unknown, _augName: unknown): boolean => {
|
||||||
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||||
|
const augName = ctx.helper.string("augName", _augName);
|
||||||
|
checkSleeveAPIAccess(ctx);
|
||||||
|
checkSleeveNumber(ctx, sleeveNumber);
|
||||||
|
|
||||||
|
if (getSleeveStats(sleeveNumber).shock > 0) {
|
||||||
|
throw ctx.makeRuntimeErrorMsg(`Sleeve shock too high: Sleeve ${sleeveNumber}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const aug = StaticAugmentations[augName];
|
||||||
|
if (!aug) {
|
||||||
|
throw ctx.makeRuntimeErrorMsg(`Invalid aug: ${augName}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return player.sleeves[sleeveNumber].tryBuyAugmentation(player, aug);
|
||||||
|
},
|
||||||
|
setToBladeburnerAction:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_sleeveNumber: unknown, _action: unknown, _contract?: unknown): boolean => {
|
||||||
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||||
|
const action = ctx.helper.string("action", _action);
|
||||||
|
let contract: string;
|
||||||
|
if (typeof _contract === "undefined") {
|
||||||
|
contract = "------";
|
||||||
|
} else {
|
||||||
|
contract = ctx.helper.string("contract", _contract);
|
||||||
|
}
|
||||||
|
checkSleeveAPIAccess(ctx);
|
||||||
|
checkSleeveNumber(ctx, sleeveNumber);
|
||||||
|
|
||||||
|
// Cannot Take on Contracts if another sleeve is performing that action
|
||||||
|
if (action === "Take on contracts") {
|
||||||
|
for (let i = 0; i < player.sleeves.length; ++i) {
|
||||||
|
if (i === sleeveNumber) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const other = player.sleeves[i];
|
||||||
|
if (other.currentTask === SleeveTaskType.Bladeburner && other.bbAction === action) {
|
||||||
|
throw ctx.helper.makeRuntimeErrorMsg(
|
||||||
|
`Sleeve ${sleeveNumber} cannot take of contracts because Sleeve ${i} is already performing that action.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return player.sleeves[sleeveNumber].bladeburner(player, action, contract);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import { netscriptDelay } from "../NetscriptEvaluator";
|
|||||||
|
|
||||||
import { staneksGift } from "../CotMG/Helper";
|
import { staneksGift } from "../CotMG/Helper";
|
||||||
import { Fragments, FragmentById } from "../CotMG/Fragment";
|
import { Fragments, FragmentById } from "../CotMG/Fragment";
|
||||||
|
import { FragmentType } from "../CotMG/FragmentType";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Fragment as IFragment,
|
Fragment as IFragment,
|
||||||
@ -25,7 +26,7 @@ export function NetscriptStanek(
|
|||||||
): InternalAPI<IStanek> {
|
): InternalAPI<IStanek> {
|
||||||
function checkStanekAPIAccess(func: string): void {
|
function checkStanekAPIAccess(func: string): void {
|
||||||
if (!player.hasAugmentation(AugmentationNames.StaneksGift1, true)) {
|
if (!player.hasAugmentation(AugmentationNames.StaneksGift1, true)) {
|
||||||
helper.makeRuntimeErrorMsg(func, "Requires Stanek's Gift installed.");
|
throw helper.makeRuntimeErrorMsg(func, "Stanek's Gift is not installed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,15 +43,23 @@ export function NetscriptStanek(
|
|||||||
},
|
},
|
||||||
chargeFragment: (_ctx: NetscriptContext) =>
|
chargeFragment: (_ctx: NetscriptContext) =>
|
||||||
function (_rootX: unknown, _rootY: unknown): Promise<void> {
|
function (_rootX: unknown, _rootY: unknown): Promise<void> {
|
||||||
|
//Get the fragment object using the given coordinates
|
||||||
const rootX = _ctx.helper.number("rootX", _rootX);
|
const rootX = _ctx.helper.number("rootX", _rootX);
|
||||||
const rootY = _ctx.helper.number("rootY", _rootY);
|
const rootY = _ctx.helper.number("rootY", _rootY);
|
||||||
checkStanekAPIAccess("chargeFragment");
|
checkStanekAPIAccess("chargeFragment");
|
||||||
const fragment = staneksGift.findFragment(rootX, rootY);
|
const fragment = staneksGift.findFragment(rootX, rootY);
|
||||||
|
//Check whether the selected fragment can ge charged
|
||||||
if (!fragment) throw _ctx.makeRuntimeErrorMsg(`No fragment with root (${rootX}, ${rootY}).`);
|
if (!fragment) throw _ctx.makeRuntimeErrorMsg(`No fragment with root (${rootX}, ${rootY}).`);
|
||||||
|
if (fragment.fragment().type == FragmentType.Booster) {
|
||||||
|
throw _ctx.makeRuntimeErrorMsg(
|
||||||
|
`The fragment with root (${rootX}, ${rootY}) is a Booster Fragment and thus cannot be charged.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//Charge the fragment
|
||||||
const time = staneksGift.inBonus() ? 200 : 1000;
|
const time = staneksGift.inBonus() ? 200 : 1000;
|
||||||
return netscriptDelay(time, workerScript).then(function () {
|
return netscriptDelay(time, workerScript).then(function () {
|
||||||
const charge = staneksGift.charge(player, fragment, workerScript.scriptRef.threads);
|
staneksGift.charge(player, fragment, workerScript.scriptRef.threads);
|
||||||
_ctx.log(() => `Charged fragment for ${charge} charge.`);
|
_ctx.log(() => `Charged fragment with ${_ctx.workerScript.scriptRef.threads} threads.`);
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import { INetscriptHelper } from "./INetscriptHelper";
|
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
|
||||||
import { buyStock, sellStock, shortStock, sellShort } from "../StockMarket/BuyingAndSelling";
|
import { buyStock, sellStock, shortStock, sellShort } from "../StockMarket/BuyingAndSelling";
|
||||||
import { StockMarket, SymbolToStockMap, placeOrder, cancelOrder, initStockMarketFn } from "../StockMarket/StockMarket";
|
import { StockMarket, SymbolToStockMap, placeOrder, cancelOrder, initStockMarketFn } from "../StockMarket/StockMarket";
|
||||||
import { getBuyTransactionCost, getSellTransactionGain } from "../StockMarket/StockMarketHelpers";
|
import { getBuyTransactionCost, getSellTransactionGain } from "../StockMarket/StockMarketHelpers";
|
||||||
@ -16,301 +14,286 @@ import {
|
|||||||
} from "../StockMarket/StockMarketCosts";
|
} from "../StockMarket/StockMarketCosts";
|
||||||
import { Stock } from "../StockMarket/Stock";
|
import { Stock } from "../StockMarket/Stock";
|
||||||
import { TIX } from "../ScriptEditor/NetscriptDefinitions";
|
import { TIX } from "../ScriptEditor/NetscriptDefinitions";
|
||||||
|
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
||||||
|
|
||||||
export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): TIX {
|
export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript): InternalAPI<TIX> {
|
||||||
/**
|
/**
|
||||||
* Checks if the player has TIX API access. Throws an error if the player does not
|
* Checks if the player has TIX API access. Throws an error if the player does not
|
||||||
*/
|
*/
|
||||||
const checkTixApiAccess = function (callingFn: string): void {
|
const checkTixApiAccess = function (ctx: NetscriptContext): void {
|
||||||
if (!player.hasWseAccount) {
|
if (!player.hasWseAccount) {
|
||||||
throw helper.makeRuntimeErrorMsg(callingFn, `You don't have WSE Access! Cannot use ${callingFn}()`);
|
throw ctx.makeRuntimeErrorMsg(`You don't have WSE Access! Cannot use ${ctx.function}()`);
|
||||||
}
|
}
|
||||||
if (!player.hasTixApiAccess) {
|
if (!player.hasTixApiAccess) {
|
||||||
throw helper.makeRuntimeErrorMsg(callingFn, `You don't have TIX API Access! Cannot use ${callingFn}()`);
|
throw ctx.makeRuntimeErrorMsg(`You don't have TIX API Access! Cannot use ${ctx.function}()`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStockFromSymbol = function (symbol: string, callingFn: string): Stock {
|
const getStockFromSymbol = function (ctx: NetscriptContext, symbol: string): Stock {
|
||||||
const stock = SymbolToStockMap[symbol];
|
const stock = SymbolToStockMap[symbol];
|
||||||
if (stock == null) {
|
if (stock == null) {
|
||||||
throw helper.makeRuntimeErrorMsg(callingFn, `Invalid stock symbol: '${symbol}'`);
|
throw ctx.makeRuntimeErrorMsg(`Invalid stock symbol: '${symbol}'`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return stock;
|
return stock;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateRam = (funcName: string): void =>
|
|
||||||
helper.updateDynamicRam(funcName, getRamCost(player, "stock", funcName));
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getSymbols: function (): string[] {
|
getSymbols: (ctx: NetscriptContext) => (): string[] => {
|
||||||
updateRam("getSymbols");
|
checkTixApiAccess(ctx);
|
||||||
checkTixApiAccess("getSymbols");
|
|
||||||
return Object.values(StockSymbols);
|
return Object.values(StockSymbols);
|
||||||
},
|
},
|
||||||
getPrice: function (_symbol: unknown): number {
|
getPrice:
|
||||||
updateRam("getPrice");
|
(ctx: NetscriptContext) =>
|
||||||
const symbol = helper.string("getPrice", "symbol", _symbol);
|
(_symbol: unknown): number => {
|
||||||
checkTixApiAccess("getPrice");
|
const symbol = ctx.helper.string("symbol", _symbol);
|
||||||
const stock = getStockFromSymbol(symbol, "getPrice");
|
checkTixApiAccess(ctx);
|
||||||
|
const stock = getStockFromSymbol(ctx, symbol);
|
||||||
|
|
||||||
return stock.price;
|
return stock.price;
|
||||||
},
|
},
|
||||||
getAskPrice: function (_symbol: unknown): number {
|
getAskPrice:
|
||||||
updateRam("getAskPrice");
|
(ctx: NetscriptContext) =>
|
||||||
const symbol = helper.string("getAskPrice", "symbol", _symbol);
|
(_symbol: unknown): number => {
|
||||||
checkTixApiAccess("getAskPrice");
|
const symbol = ctx.helper.string("symbol", _symbol);
|
||||||
const stock = getStockFromSymbol(symbol, "getAskPrice");
|
checkTixApiAccess(ctx);
|
||||||
|
const stock = getStockFromSymbol(ctx, symbol);
|
||||||
|
|
||||||
return stock.getAskPrice();
|
return stock.getAskPrice();
|
||||||
},
|
},
|
||||||
getBidPrice: function (_symbol: unknown): number {
|
getBidPrice:
|
||||||
updateRam("getBidPrice");
|
(ctx: NetscriptContext) =>
|
||||||
const symbol = helper.string("getBidPrice", "symbol", _symbol);
|
(_symbol: unknown): number => {
|
||||||
checkTixApiAccess("getBidPrice");
|
const symbol = ctx.helper.string("symbol", _symbol);
|
||||||
const stock = getStockFromSymbol(symbol, "getBidPrice");
|
checkTixApiAccess(ctx);
|
||||||
|
const stock = getStockFromSymbol(ctx, symbol);
|
||||||
|
|
||||||
return stock.getBidPrice();
|
return stock.getBidPrice();
|
||||||
},
|
},
|
||||||
getPosition: function (_symbol: unknown): [number, number, number, number] {
|
getPosition:
|
||||||
updateRam("getPosition");
|
(ctx: NetscriptContext) =>
|
||||||
const symbol = helper.string("getPosition", "symbol", _symbol);
|
(_symbol: unknown): [number, number, number, number] => {
|
||||||
checkTixApiAccess("getPosition");
|
const symbol = ctx.helper.string("symbol", _symbol);
|
||||||
const stock = SymbolToStockMap[symbol];
|
checkTixApiAccess(ctx);
|
||||||
if (stock == null) {
|
const stock = SymbolToStockMap[symbol];
|
||||||
throw helper.makeRuntimeErrorMsg("getPosition", `Invalid stock symbol: ${symbol}`);
|
if (stock == null) {
|
||||||
}
|
throw ctx.makeRuntimeErrorMsg(`Invalid stock symbol: ${symbol}`);
|
||||||
return [stock.playerShares, stock.playerAvgPx, stock.playerShortShares, stock.playerAvgShortPx];
|
|
||||||
},
|
|
||||||
getMaxShares: function (_symbol: unknown): number {
|
|
||||||
updateRam("getMaxShares");
|
|
||||||
const symbol = helper.string("getMaxShares", "symbol", _symbol);
|
|
||||||
checkTixApiAccess("getMaxShares");
|
|
||||||
const stock = getStockFromSymbol(symbol, "getMaxShares");
|
|
||||||
|
|
||||||
return stock.maxShares;
|
|
||||||
},
|
|
||||||
getPurchaseCost: function (_symbol: unknown, _shares: unknown, _posType: unknown): number {
|
|
||||||
updateRam("getPurchaseCost");
|
|
||||||
const symbol = helper.string("getPurchaseCost", "symbol", _symbol);
|
|
||||||
let shares = helper.number("getPurchaseCost", "shares", _shares);
|
|
||||||
const posType = helper.string("getPurchaseCost", "posType", _posType);
|
|
||||||
checkTixApiAccess("getPurchaseCost");
|
|
||||||
const stock = getStockFromSymbol(symbol, "getPurchaseCost");
|
|
||||||
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;
|
|
||||||
},
|
|
||||||
getSaleGain: function (_symbol: unknown, _shares: unknown, _posType: unknown): number {
|
|
||||||
updateRam("getSaleGain");
|
|
||||||
const symbol = helper.string("getSaleGain", "symbol", _symbol);
|
|
||||||
let shares = helper.number("getSaleGain", "shares", _shares);
|
|
||||||
const posType = helper.string("getSaleGain", "posType", _posType);
|
|
||||||
checkTixApiAccess("getSaleGain");
|
|
||||||
const stock = getStockFromSymbol(symbol, "getSaleGain");
|
|
||||||
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;
|
|
||||||
},
|
|
||||||
buy: function (_symbol: unknown, _shares: unknown): number {
|
|
||||||
updateRam("buy");
|
|
||||||
const symbol = helper.string("buy", "symbol", _symbol);
|
|
||||||
const shares = helper.number("buy", "shares", _shares);
|
|
||||||
checkTixApiAccess("buy");
|
|
||||||
const stock = getStockFromSymbol(symbol, "buy");
|
|
||||||
const res = buyStock(stock, shares, workerScript, {});
|
|
||||||
return res ? stock.getAskPrice() : 0;
|
|
||||||
},
|
|
||||||
sell: function (_symbol: unknown, _shares: unknown): number {
|
|
||||||
updateRam("sell");
|
|
||||||
const symbol = helper.string("sell", "symbol", _symbol);
|
|
||||||
const shares = helper.number("sell", "shares", _shares);
|
|
||||||
checkTixApiAccess("sell");
|
|
||||||
const stock = getStockFromSymbol(symbol, "sell");
|
|
||||||
const res = sellStock(stock, shares, workerScript, {});
|
|
||||||
|
|
||||||
return res ? stock.getBidPrice() : 0;
|
|
||||||
},
|
|
||||||
short: function (_symbol: unknown, _shares: unknown): number {
|
|
||||||
updateRam("short");
|
|
||||||
const symbol = helper.string("short", "symbol", _symbol);
|
|
||||||
const shares = helper.number("short", "shares", _shares);
|
|
||||||
checkTixApiAccess("short");
|
|
||||||
if (player.bitNodeN !== 8) {
|
|
||||||
if (player.sourceFileLvl(8) <= 1) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(
|
|
||||||
"short",
|
|
||||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 2.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
return [stock.playerShares, stock.playerAvgPx, stock.playerShortShares, stock.playerAvgShortPx];
|
||||||
const stock = getStockFromSymbol(symbol, "short");
|
},
|
||||||
const res = shortStock(stock, shares, workerScript, {});
|
getMaxShares:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_symbol: unknown): number => {
|
||||||
|
const symbol = ctx.helper.string("symbol", _symbol);
|
||||||
|
checkTixApiAccess(ctx);
|
||||||
|
const stock = getStockFromSymbol(ctx, symbol);
|
||||||
|
|
||||||
return res ? stock.getBidPrice() : 0;
|
return stock.maxShares;
|
||||||
},
|
},
|
||||||
sellShort: function (_symbol: unknown, _shares: unknown): number {
|
getPurchaseCost:
|
||||||
updateRam("sellShort");
|
(ctx: NetscriptContext) =>
|
||||||
const symbol = helper.string("sellShort", "symbol", _symbol);
|
(_symbol: unknown, _shares: unknown, _posType: unknown): number => {
|
||||||
const shares = helper.number("sellShort", "shares", _shares);
|
const symbol = ctx.helper.string("symbol", _symbol);
|
||||||
checkTixApiAccess("sellShort");
|
let shares = ctx.helper.number("shares", _shares);
|
||||||
if (player.bitNodeN !== 8) {
|
const posType = ctx.helper.string("posType", _posType);
|
||||||
if (player.sourceFileLvl(8) <= 1) {
|
checkTixApiAccess(ctx);
|
||||||
throw helper.makeRuntimeErrorMsg(
|
const stock = getStockFromSymbol(ctx, symbol);
|
||||||
"sellShort",
|
shares = Math.round(shares);
|
||||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 2.",
|
|
||||||
);
|
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 stock = getStockFromSymbol(symbol, "sellShort");
|
|
||||||
const res = sellShort(stock, shares, workerScript, {});
|
|
||||||
|
|
||||||
return res ? stock.getAskPrice() : 0;
|
const res = getBuyTransactionCost(stock, shares, pos);
|
||||||
},
|
if (res == null) {
|
||||||
placeOrder: function (_symbol: unknown, _shares: unknown, _price: unknown, _type: unknown, _pos: unknown): boolean {
|
return Infinity;
|
||||||
updateRam("placeOrder");
|
}
|
||||||
const symbol = helper.string("placeOrder", "symbol", _symbol);
|
|
||||||
const shares = helper.number("placeOrder", "shares", _shares);
|
return res;
|
||||||
const price = helper.number("placeOrder", "price", _price);
|
},
|
||||||
const type = helper.string("placeOrder", "type", _type);
|
getSaleGain:
|
||||||
const pos = helper.string("placeOrder", "pos", _pos);
|
(ctx: NetscriptContext) =>
|
||||||
checkTixApiAccess("placeOrder");
|
(_symbol: unknown, _shares: unknown, _posType: unknown): number => {
|
||||||
|
const symbol = ctx.helper.string("symbol", _symbol);
|
||||||
|
let shares = ctx.helper.number("shares", _shares);
|
||||||
|
const posType = ctx.helper.string("posType", _posType);
|
||||||
|
checkTixApiAccess(ctx);
|
||||||
|
const stock = getStockFromSymbol(ctx, symbol);
|
||||||
|
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;
|
||||||
|
},
|
||||||
|
buy:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_symbol: unknown, _shares: unknown): number => {
|
||||||
|
const symbol = ctx.helper.string("symbol", _symbol);
|
||||||
|
const shares = ctx.helper.number("shares", _shares);
|
||||||
|
checkTixApiAccess(ctx);
|
||||||
|
const stock = getStockFromSymbol(ctx, symbol);
|
||||||
|
const res = buyStock(stock, shares, workerScript, {});
|
||||||
|
return res ? stock.getAskPrice() : 0;
|
||||||
|
},
|
||||||
|
sell:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_symbol: unknown, _shares: unknown): number => {
|
||||||
|
const symbol = ctx.helper.string("symbol", _symbol);
|
||||||
|
const shares = ctx.helper.number("shares", _shares);
|
||||||
|
checkTixApiAccess(ctx);
|
||||||
|
const stock = getStockFromSymbol(ctx, symbol);
|
||||||
|
const res = sellStock(stock, shares, workerScript, {});
|
||||||
|
|
||||||
|
return res ? stock.getBidPrice() : 0;
|
||||||
|
},
|
||||||
|
short:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_symbol: unknown, _shares: unknown): number => {
|
||||||
|
const symbol = ctx.helper.string("symbol", _symbol);
|
||||||
|
const shares = ctx.helper.number("shares", _shares);
|
||||||
|
checkTixApiAccess(ctx);
|
||||||
|
if (player.bitNodeN !== 8) {
|
||||||
|
if (player.sourceFileLvl(8) <= 1) {
|
||||||
|
throw ctx.makeRuntimeErrorMsg("You must either be in BitNode-8 or you must have Source-File 8 Level 2.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const stock = getStockFromSymbol(ctx, symbol);
|
||||||
|
const res = shortStock(stock, shares, workerScript, {});
|
||||||
|
|
||||||
|
return res ? stock.getBidPrice() : 0;
|
||||||
|
},
|
||||||
|
sellShort:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_symbol: unknown, _shares: unknown): number => {
|
||||||
|
const symbol = ctx.helper.string("symbol", _symbol);
|
||||||
|
const shares = ctx.helper.number("shares", _shares);
|
||||||
|
checkTixApiAccess(ctx);
|
||||||
|
if (player.bitNodeN !== 8) {
|
||||||
|
if (player.sourceFileLvl(8) <= 1) {
|
||||||
|
throw ctx.makeRuntimeErrorMsg("You must either be in BitNode-8 or you must have Source-File 8 Level 2.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const stock = getStockFromSymbol(ctx, symbol);
|
||||||
|
const res = sellShort(stock, shares, workerScript, {});
|
||||||
|
|
||||||
|
return res ? stock.getAskPrice() : 0;
|
||||||
|
},
|
||||||
|
placeOrder:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_symbol: unknown, _shares: unknown, _price: unknown, _type: unknown, _pos: unknown): boolean => {
|
||||||
|
const symbol = ctx.helper.string("symbol", _symbol);
|
||||||
|
const shares = ctx.helper.number("shares", _shares);
|
||||||
|
const price = ctx.helper.number("price", _price);
|
||||||
|
const type = ctx.helper.string("type", _type);
|
||||||
|
const pos = ctx.helper.string("pos", _pos);
|
||||||
|
checkTixApiAccess(ctx);
|
||||||
|
if (player.bitNodeN !== 8) {
|
||||||
|
if (player.sourceFileLvl(8) <= 2) {
|
||||||
|
throw ctx.makeRuntimeErrorMsg("You must either be in BitNode-8 or you must have Source-File 8 Level 3.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const stock = getStockFromSymbol(ctx, symbol);
|
||||||
|
|
||||||
|
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 ctx.makeRuntimeErrorMsg(`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 ctx.makeRuntimeErrorMsg(`Invalid position type: ${pos}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return placeOrder(stock, shares, price, orderType, orderPos, workerScript);
|
||||||
|
},
|
||||||
|
cancelOrder:
|
||||||
|
(ctx: NetscriptContext) =>
|
||||||
|
(_symbol: unknown, _shares: unknown, _price: unknown, _type: unknown, _pos: unknown): boolean => {
|
||||||
|
const symbol = ctx.helper.string("symbol", _symbol);
|
||||||
|
const shares = ctx.helper.number("shares", _shares);
|
||||||
|
const price = ctx.helper.number("price", _price);
|
||||||
|
const type = ctx.helper.string("type", _type);
|
||||||
|
const pos = ctx.helper.string("pos", _pos);
|
||||||
|
checkTixApiAccess(ctx);
|
||||||
|
if (player.bitNodeN !== 8) {
|
||||||
|
if (player.sourceFileLvl(8) <= 2) {
|
||||||
|
throw ctx.makeRuntimeErrorMsg("You must either be in BitNode-8 or you must have Source-File 8 Level 3.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const stock = getStockFromSymbol(ctx, symbol);
|
||||||
|
if (isNaN(shares) || isNaN(price)) {
|
||||||
|
throw ctx.makeRuntimeErrorMsg(`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 ctx.makeRuntimeErrorMsg(`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 ctx.makeRuntimeErrorMsg(`Invalid position type: ${pos}`);
|
||||||
|
}
|
||||||
|
const params = {
|
||||||
|
stock: stock,
|
||||||
|
shares: shares,
|
||||||
|
price: price,
|
||||||
|
type: orderType,
|
||||||
|
pos: orderPos,
|
||||||
|
};
|
||||||
|
return cancelOrder(params, workerScript);
|
||||||
|
},
|
||||||
|
getOrders: (ctx: NetscriptContext) => (): any => {
|
||||||
|
checkTixApiAccess(ctx);
|
||||||
if (player.bitNodeN !== 8) {
|
if (player.bitNodeN !== 8) {
|
||||||
if (player.sourceFileLvl(8) <= 2) {
|
if (player.sourceFileLvl(8) <= 2) {
|
||||||
throw helper.makeRuntimeErrorMsg(
|
throw ctx.makeRuntimeErrorMsg("You must either be in BitNode-8 or have Source-File 8 Level 3.");
|
||||||
"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: unknown,
|
|
||||||
_shares: unknown,
|
|
||||||
_price: unknown,
|
|
||||||
_type: unknown,
|
|
||||||
_pos: unknown,
|
|
||||||
): boolean {
|
|
||||||
updateRam("cancelOrder");
|
|
||||||
const symbol = helper.string("cancelOrder", "symbol", _symbol);
|
|
||||||
const shares = helper.number("cancelOrder", "shares", _shares);
|
|
||||||
const price = helper.number("cancelOrder", "price", _price);
|
|
||||||
const type = helper.string("cancelOrder", "type", _type);
|
|
||||||
const pos = helper.string("cancelOrder", "pos", _pos);
|
|
||||||
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 {
|
|
||||||
updateRam("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.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,103 +317,95 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
|||||||
|
|
||||||
return orders;
|
return orders;
|
||||||
},
|
},
|
||||||
getVolatility: function (_symbol: unknown): number {
|
getVolatility:
|
||||||
updateRam("getVolatility");
|
(ctx: NetscriptContext) =>
|
||||||
const symbol = helper.string("getVolatility", "symbol", _symbol);
|
(_symbol: unknown): number => {
|
||||||
if (!player.has4SDataTixApi) {
|
const symbol = ctx.helper.string("symbol", _symbol);
|
||||||
throw helper.makeRuntimeErrorMsg("getVolatility", "You don't have 4S Market Data TIX API Access!");
|
if (!player.has4SDataTixApi) {
|
||||||
}
|
throw ctx.makeRuntimeErrorMsg("You don't have 4S Market Data TIX API Access!");
|
||||||
const stock = getStockFromSymbol(symbol, "getVolatility");
|
}
|
||||||
|
const stock = getStockFromSymbol(ctx, symbol);
|
||||||
|
|
||||||
return stock.mv / 100; // Convert from percentage to decimal
|
return stock.mv / 100; // Convert from percentage to decimal
|
||||||
},
|
},
|
||||||
getForecast: function (_symbol: unknown): number {
|
getForecast:
|
||||||
updateRam("getForecast");
|
(ctx: NetscriptContext) =>
|
||||||
const symbol = helper.string("getForecast", "symbol", _symbol);
|
(_symbol: unknown): number => {
|
||||||
if (!player.has4SDataTixApi) {
|
const symbol = ctx.helper.string("symbol", _symbol);
|
||||||
throw helper.makeRuntimeErrorMsg("getForecast", "You don't have 4S Market Data TIX API Access!");
|
if (!player.has4SDataTixApi) {
|
||||||
}
|
throw ctx.makeRuntimeErrorMsg("You don't have 4S Market Data TIX API Access!");
|
||||||
const stock = getStockFromSymbol(symbol, "getForecast");
|
}
|
||||||
|
const stock = getStockFromSymbol(ctx, symbol);
|
||||||
let forecast = 50;
|
|
||||||
stock.b ? (forecast += stock.otlkMag) : (forecast -= stock.otlkMag);
|
|
||||||
return forecast / 100; // Convert from percentage to decimal
|
|
||||||
},
|
|
||||||
purchase4SMarketData: function (): boolean {
|
|
||||||
updateRam("purchase4SMarketData");
|
|
||||||
|
|
||||||
|
let forecast = 50;
|
||||||
|
stock.b ? (forecast += stock.otlkMag) : (forecast -= stock.otlkMag);
|
||||||
|
return forecast / 100; // Convert from percentage to decimal
|
||||||
|
},
|
||||||
|
purchase4SMarketData: (ctx: NetscriptContext) => (): boolean => {
|
||||||
if (player.has4SData) {
|
if (player.has4SData) {
|
||||||
workerScript.log("stock.purchase4SMarketData", () => "Already purchased 4S Market Data.");
|
ctx.log(() => "Already purchased 4S Market Data.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.money < getStockMarket4SDataCost()) {
|
if (player.money < getStockMarket4SDataCost()) {
|
||||||
workerScript.log("stock.purchase4SMarketData", () => "Not enough money to purchase 4S Market Data.");
|
ctx.log(() => "Not enough money to purchase 4S Market Data.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.has4SData = true;
|
player.has4SData = true;
|
||||||
player.loseMoney(getStockMarket4SDataCost(), "stock");
|
player.loseMoney(getStockMarket4SDataCost(), "stock");
|
||||||
workerScript.log("stock.purchase4SMarketData", () => "Purchased 4S Market Data");
|
ctx.log(() => "Purchased 4S Market Data");
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
purchase4SMarketDataTixApi: function (): boolean {
|
purchase4SMarketDataTixApi: (ctx: NetscriptContext) => (): boolean => {
|
||||||
updateRam("purchase4SMarketDataTixApi");
|
checkTixApiAccess(ctx);
|
||||||
checkTixApiAccess("purchase4SMarketDataTixApi");
|
|
||||||
|
|
||||||
if (player.has4SDataTixApi) {
|
if (player.has4SDataTixApi) {
|
||||||
workerScript.log("stock.purchase4SMarketDataTixApi", () => "Already purchased 4S Market Data TIX API");
|
ctx.log(() => "Already purchased 4S Market Data TIX API");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.money < getStockMarket4STixApiCost()) {
|
if (player.money < getStockMarket4STixApiCost()) {
|
||||||
workerScript.log(
|
ctx.log(() => "Not enough money to purchase 4S Market Data TIX API");
|
||||||
"stock.purchase4SMarketDataTixApi",
|
|
||||||
() => "Not enough money to purchase 4S Market Data TIX API",
|
|
||||||
);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.has4SDataTixApi = true;
|
player.has4SDataTixApi = true;
|
||||||
player.loseMoney(getStockMarket4STixApiCost(), "stock");
|
player.loseMoney(getStockMarket4STixApiCost(), "stock");
|
||||||
workerScript.log("stock.purchase4SMarketDataTixApi", () => "Purchased 4S Market Data TIX API");
|
ctx.log(() => "Purchased 4S Market Data TIX API");
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
purchaseWseAccount: function (): boolean {
|
purchaseWseAccount: (ctx: NetscriptContext) => (): boolean => {
|
||||||
updateRam("PurchaseWseAccount");
|
|
||||||
|
|
||||||
if (player.hasWseAccount) {
|
if (player.hasWseAccount) {
|
||||||
workerScript.log("stock.purchaseWseAccount", () => "Already purchased WSE Account");
|
ctx.log(() => "Already purchased WSE Account");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.money < getStockMarketWseCost()) {
|
if (player.money < getStockMarketWseCost()) {
|
||||||
workerScript.log("stock.purchaseWseAccount", () => "Not enough money to purchase WSE Account Access");
|
ctx.log(() => "Not enough money to purchase WSE Account Access");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.hasWseAccount = true;
|
player.hasWseAccount = true;
|
||||||
initStockMarketFn();
|
initStockMarketFn();
|
||||||
player.loseMoney(getStockMarketWseCost(), "stock");
|
player.loseMoney(getStockMarketWseCost(), "stock");
|
||||||
workerScript.log("stock.purchaseWseAccount", () => "Purchased WSE Account Access");
|
ctx.log(() => "Purchased WSE Account Access");
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
purchaseTixApi: function (): boolean {
|
purchaseTixApi: (ctx: NetscriptContext) => (): boolean => {
|
||||||
updateRam("purchaseTixApi");
|
|
||||||
|
|
||||||
if (player.hasTixApiAccess) {
|
if (player.hasTixApiAccess) {
|
||||||
workerScript.log("stock.purchaseTixApi", () => "Already purchased TIX API");
|
ctx.log(() => "Already purchased TIX API");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.money < getStockMarketTixApiCost()) {
|
if (player.money < getStockMarketTixApiCost()) {
|
||||||
workerScript.log("stock.purchaseTixApi", () => "Not enough money to purchase TIX API Access");
|
ctx.log(() => "Not enough money to purchase TIX API Access");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.hasTixApiAccess = true;
|
player.hasTixApiAccess = true;
|
||||||
player.loseMoney(getStockMarketTixApiCost(), "stock");
|
player.loseMoney(getStockMarketTixApiCost(), "stock");
|
||||||
workerScript.log("stock.purchaseTixApi", () => "Purchased TIX API");
|
ctx.log(() => "Purchased TIX API");
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
import { INetscriptHelper } from "./INetscriptHelper";
|
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
||||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
|
||||||
import {
|
import {
|
||||||
GameInfo,
|
GameInfo,
|
||||||
IStyleSettings,
|
IStyleSettings,
|
||||||
@ -14,88 +10,81 @@ import { defaultTheme } from "../Themes/Themes";
|
|||||||
import { defaultStyles } from "../Themes/Styles";
|
import { defaultStyles } from "../Themes/Styles";
|
||||||
import { CONSTANTS } from "../Constants";
|
import { CONSTANTS } from "../Constants";
|
||||||
import { hash } from "../hash/hash";
|
import { hash } from "../hash/hash";
|
||||||
|
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
||||||
|
import { Terminal } from "../../src/Terminal";
|
||||||
|
|
||||||
export function NetscriptUserInterface(
|
export function NetscriptUserInterface(): InternalAPI<IUserInterface> {
|
||||||
player: IPlayer,
|
|
||||||
workerScript: WorkerScript,
|
|
||||||
helper: INetscriptHelper,
|
|
||||||
): IUserInterface {
|
|
||||||
const updateRam = (funcName: string): void => helper.updateDynamicRam(funcName, getRamCost(player, "ui", funcName));
|
|
||||||
return {
|
return {
|
||||||
getTheme: function (): UserInterfaceTheme {
|
getTheme: () => (): UserInterfaceTheme => {
|
||||||
updateRam("getTheme");
|
|
||||||
return { ...Settings.theme };
|
return { ...Settings.theme };
|
||||||
},
|
},
|
||||||
|
|
||||||
getStyles: function (): IStyleSettings {
|
getStyles: () => (): IStyleSettings => {
|
||||||
updateRam("getStyles");
|
|
||||||
return { ...Settings.styles };
|
return { ...Settings.styles };
|
||||||
},
|
},
|
||||||
|
|
||||||
setTheme: function (newTheme: UserInterfaceTheme): void {
|
setTheme:
|
||||||
updateRam("setTheme");
|
(ctx: NetscriptContext) =>
|
||||||
const hex = /^(#)((?:[A-Fa-f0-9]{2}){3,4}|(?:[A-Fa-f0-9]{3}))$/;
|
(newTheme: UserInterfaceTheme): void => {
|
||||||
const currentTheme = { ...Settings.theme };
|
const hex = /^(#)((?:[A-Fa-f0-9]{2}){3,4}|(?:[A-Fa-f0-9]{3}))$/;
|
||||||
const errors: string[] = [];
|
const currentTheme = { ...Settings.theme };
|
||||||
for (const key of Object.keys(newTheme)) {
|
const errors: string[] = [];
|
||||||
if (!currentTheme[key]) {
|
for (const key of Object.keys(newTheme)) {
|
||||||
// Invalid key
|
if (!currentTheme[key]) {
|
||||||
errors.push(`Invalid key "${key}"`);
|
// Invalid key
|
||||||
} else if (!hex.test(newTheme[key] ?? "")) {
|
errors.push(`Invalid key "${key}"`);
|
||||||
errors.push(`Invalid color "${key}": ${newTheme[key]}`);
|
} else if (!hex.test(newTheme[key] ?? "")) {
|
||||||
} else {
|
errors.push(`Invalid color "${key}": ${newTheme[key]}`);
|
||||||
currentTheme[key] = newTheme[key];
|
} else {
|
||||||
|
currentTheme[key] = newTheme[key];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (errors.length === 0) {
|
if (errors.length === 0) {
|
||||||
Object.assign(Settings.theme, currentTheme);
|
Object.assign(Settings.theme, currentTheme);
|
||||||
ThemeEvents.emit();
|
ThemeEvents.emit();
|
||||||
workerScript.log("ui.setTheme", () => `Successfully set theme`);
|
ctx.log(() => `Successfully set theme`);
|
||||||
} else {
|
|
||||||
workerScript.log("ui.setTheme", () => `Failed to set theme. Errors: ${errors.join(", ")}`);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
setStyles: function (newStyles: IStyleSettings): void {
|
|
||||||
updateRam("setStyles");
|
|
||||||
|
|
||||||
const currentStyles = { ...Settings.styles };
|
|
||||||
const errors: string[] = [];
|
|
||||||
for (const key of Object.keys(newStyles)) {
|
|
||||||
if (!(currentStyles as any)[key]) {
|
|
||||||
// Invalid key
|
|
||||||
errors.push(`Invalid key "${key}"`);
|
|
||||||
} else {
|
} else {
|
||||||
(currentStyles as any)[key] = (newStyles as any)[key];
|
ctx.log(() => `Failed to set theme. Errors: ${errors.join(", ")}`);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
if (errors.length === 0) {
|
setStyles:
|
||||||
Object.assign(Settings.styles, currentStyles);
|
(ctx: NetscriptContext) =>
|
||||||
ThemeEvents.emit();
|
(newStyles: IStyleSettings): void => {
|
||||||
workerScript.log("ui.setStyles", () => `Successfully set styles`);
|
const currentStyles = { ...Settings.styles };
|
||||||
} else {
|
const errors: string[] = [];
|
||||||
workerScript.log("ui.setStyles", () => `Failed to set styles. Errors: ${errors.join(", ")}`);
|
for (const key of Object.keys(newStyles)) {
|
||||||
}
|
if (!(currentStyles as any)[key]) {
|
||||||
},
|
// Invalid key
|
||||||
|
errors.push(`Invalid key "${key}"`);
|
||||||
|
} else {
|
||||||
|
(currentStyles as any)[key] = (newStyles as any)[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resetTheme: function (): void {
|
if (errors.length === 0) {
|
||||||
updateRam("resetTheme");
|
Object.assign(Settings.styles, currentStyles);
|
||||||
|
ThemeEvents.emit();
|
||||||
|
ctx.log(() => `Successfully set styles`);
|
||||||
|
} else {
|
||||||
|
ctx.log(() => `Failed to set styles. Errors: ${errors.join(", ")}`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
resetTheme: (ctx: NetscriptContext) => (): void => {
|
||||||
Settings.theme = { ...defaultTheme };
|
Settings.theme = { ...defaultTheme };
|
||||||
ThemeEvents.emit();
|
ThemeEvents.emit();
|
||||||
workerScript.log("ui.resetTheme", () => `Reinitialized theme to default`);
|
ctx.log(() => `Reinitialized theme to default`);
|
||||||
},
|
},
|
||||||
|
|
||||||
resetStyles: function (): void {
|
resetStyles: (ctx: NetscriptContext) => (): void => {
|
||||||
updateRam("resetStyles");
|
|
||||||
Settings.styles = { ...defaultStyles };
|
Settings.styles = { ...defaultStyles };
|
||||||
ThemeEvents.emit();
|
ThemeEvents.emit();
|
||||||
workerScript.log("ui.resetStyles", () => `Reinitialized styles to default`);
|
ctx.log(() => `Reinitialized styles to default`);
|
||||||
},
|
},
|
||||||
|
|
||||||
getGameInfo: function (): GameInfo {
|
getGameInfo: () => (): GameInfo => {
|
||||||
updateRam("getGameInfo");
|
|
||||||
const version = CONSTANTS.VersionString;
|
const version = CONSTANTS.VersionString;
|
||||||
const commit = hash();
|
const commit = hash();
|
||||||
const platform = navigator.userAgent.toLowerCase().indexOf(" electron/") > -1 ? "Steam" : "Browser";
|
const platform = navigator.userAgent.toLowerCase().indexOf(" electron/") > -1 ? "Steam" : "Browser";
|
||||||
@ -108,5 +97,10 @@ export function NetscriptUserInterface(
|
|||||||
|
|
||||||
return gameInfo;
|
return gameInfo;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
clearTerminal: (ctx: NetscriptContext) => (): void => {
|
||||||
|
ctx.log(() => `Clearing terminal`);
|
||||||
|
Terminal.clear();
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -532,7 +532,7 @@ function createAndAddWorkerScript(
|
|||||||
const oneRamUsage = getRamUsageFromRunningScript(runningScriptObj);
|
const oneRamUsage = getRamUsageFromRunningScript(runningScriptObj);
|
||||||
const ramUsage = roundToTwo(oneRamUsage * threads);
|
const ramUsage = roundToTwo(oneRamUsage * threads);
|
||||||
const ramAvailable = server.maxRam - server.ramUsed;
|
const ramAvailable = server.maxRam - server.ramUsed;
|
||||||
if (ramUsage > ramAvailable) {
|
if (ramUsage > ramAvailable + 0.001) {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
`Not enough RAM to run script ${runningScriptObj.filename} with args ` +
|
`Not enough RAM to run script ${runningScriptObj.filename} with args ` +
|
||||||
`${arrayToString(runningScriptObj.args)}. This likely occurred because you re-loaded ` +
|
`${arrayToString(runningScriptObj.args)}. This likely occurred because you re-loaded ` +
|
||||||
@ -750,7 +750,7 @@ export function runScriptFromScript(
|
|||||||
if (server.hasAdminRights == false) {
|
if (server.hasAdminRights == false) {
|
||||||
workerScript.log(caller, () => `You do not have root access on '${server.hostname}'`);
|
workerScript.log(caller, () => `You do not have root access on '${server.hostname}'`);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (ramUsage > ramAvailable) {
|
} else if (ramUsage > ramAvailable + 0.001) {
|
||||||
workerScript.log(
|
workerScript.log(
|
||||||
caller,
|
caller,
|
||||||
() =>
|
() =>
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { Construction, CheckBox, CheckBoxOutlineBlank } from "@mui/icons-material";
|
import { CheckBox, CheckBoxOutlineBlank, Construction } from "@mui/icons-material";
|
||||||
import { Box, Button, Container, List, ListItemButton, Paper, Typography } from "@mui/material";
|
import { Box, Button, Container, List, ListItemButton, Paper, Typography } from "@mui/material";
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { Augmentation } from "../../../Augmentation/Augmentation";
|
import { Augmentation } from "../../../Augmentation/Augmentation";
|
||||||
import { StaticAugmentations } from "../../../Augmentation/StaticAugmentations";
|
|
||||||
import { AugmentationNames } from "../../../Augmentation/data/AugmentationNames";
|
import { AugmentationNames } from "../../../Augmentation/data/AugmentationNames";
|
||||||
|
import { StaticAugmentations } from "../../../Augmentation/StaticAugmentations";
|
||||||
import { CONSTANTS } from "../../../Constants";
|
import { CONSTANTS } from "../../../Constants";
|
||||||
import { hasAugmentationPrereqs } from "../../../Faction/FactionHelpers";
|
import { hasAugmentationPrereqs } from "../../../Faction/FactionHelpers";
|
||||||
import { LocationName } from "../../../Locations/data/LocationNames";
|
import { LocationName } from "../../../Locations/data/LocationNames";
|
||||||
import { Locations } from "../../../Locations/Locations";
|
import { Locations } from "../../../Locations/Locations";
|
||||||
|
import { PurchaseAugmentationsOrderSetting } from "../../../Settings/SettingEnums";
|
||||||
import { Settings } from "../../../Settings/Settings";
|
import { Settings } from "../../../Settings/Settings";
|
||||||
import { IMap } from "../../../types";
|
import { IMap } from "../../../types";
|
||||||
import { use } from "../../../ui/Context";
|
import { use } from "../../../ui/Context";
|
||||||
@ -15,8 +16,8 @@ import { ConfirmationModal } from "../../../ui/React/ConfirmationModal";
|
|||||||
import { Money } from "../../../ui/React/Money";
|
import { Money } from "../../../ui/React/Money";
|
||||||
import { convertTimeMsToTimeElapsedString, formatNumber } from "../../../utils/StringHelperFunctions";
|
import { convertTimeMsToTimeElapsedString, formatNumber } from "../../../utils/StringHelperFunctions";
|
||||||
import { IPlayer } from "../../IPlayer";
|
import { IPlayer } from "../../IPlayer";
|
||||||
import { getGraftingAvailableAugs, calculateGraftingTimeWithBonus } from "../GraftingHelpers";
|
|
||||||
import { GraftableAugmentation } from "../GraftableAugmentation";
|
import { GraftableAugmentation } from "../GraftableAugmentation";
|
||||||
|
import { calculateGraftingTimeWithBonus, getGraftingAvailableAugs } from "../GraftingHelpers";
|
||||||
|
|
||||||
const GraftableAugmentations: IMap<GraftableAugmentation> = {};
|
const GraftableAugmentations: IMap<GraftableAugmentation> = {};
|
||||||
|
|
||||||
@ -69,6 +70,21 @@ export const GraftingRoot = (): React.ReactElement => {
|
|||||||
setRerender((old) => !old);
|
setRerender((old) => !old);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getAugsSorted = (): string[] => {
|
||||||
|
const augs = getGraftingAvailableAugs(player);
|
||||||
|
switch (Settings.PurchaseAugmentationsOrder) {
|
||||||
|
case PurchaseAugmentationsOrderSetting.Cost:
|
||||||
|
return augs.sort((a, b) => GraftableAugmentations[a].cost - GraftableAugmentations[b].cost);
|
||||||
|
default:
|
||||||
|
return augs;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const switchSortOrder = (newOrder: PurchaseAugmentationsOrderSetting): void => {
|
||||||
|
Settings.PurchaseAugmentationsOrder = newOrder;
|
||||||
|
rerender();
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const id = setInterval(rerender, 200);
|
const id = setInterval(rerender, 200);
|
||||||
return () => clearInterval(id);
|
return () => clearInterval(id);
|
||||||
@ -91,13 +107,31 @@ export const GraftingRoot = (): React.ReactElement => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Box sx={{ my: 3 }}>
|
<Box sx={{ my: 3 }}>
|
||||||
<Typography variant="h5">Graft Augmentations</Typography>
|
<Paper sx={{ p: 1 }}>
|
||||||
|
<Typography variant="h5">Graft Augmentations</Typography>
|
||||||
|
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
|
||||||
|
<Button sx={{ width: "100%" }} onClick={() => switchSortOrder(PurchaseAugmentationsOrderSetting.Cost)}>
|
||||||
|
Sort by Cost
|
||||||
|
</Button>
|
||||||
|
<Button sx={{ width: "100%" }} onClick={() => switchSortOrder(PurchaseAugmentationsOrderSetting.Default)}>
|
||||||
|
Sort by Default Order
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Paper>
|
||||||
{getGraftingAvailableAugs(player).length > 0 ? (
|
{getGraftingAvailableAugs(player).length > 0 ? (
|
||||||
<Paper sx={{ my: 1, width: "fit-content", display: "grid", gridTemplateColumns: "1fr 3fr" }}>
|
<Paper sx={{ mb: 1, width: "fit-content", display: "grid", gridTemplateColumns: "1fr 3fr" }}>
|
||||||
<List sx={{ height: 400, overflowY: "scroll", borderRight: `1px solid ${Settings.theme.welllight}` }}>
|
<List sx={{ height: 400, overflowY: "scroll", borderRight: `1px solid ${Settings.theme.welllight}` }}>
|
||||||
{getGraftingAvailableAugs(player).map((k, i) => (
|
{getAugsSorted().map((k, i) => (
|
||||||
<ListItemButton key={i + 1} onClick={() => setSelectedAug(k)} selected={selectedAug === k}>
|
<ListItemButton key={i + 1} onClick={() => setSelectedAug(k)} selected={selectedAug === k}>
|
||||||
<Typography>{k}</Typography>
|
<Typography
|
||||||
|
sx={{
|
||||||
|
color: canGraft(player, GraftableAugmentations[k])
|
||||||
|
? Settings.theme.primary
|
||||||
|
: Settings.theme.disabled,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{k}
|
||||||
|
</Typography>
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
))}
|
))}
|
||||||
</List>
|
</List>
|
||||||
|
@ -13,7 +13,7 @@ import { GetServer, AddToAllServers, createUniqueRandomIp } from "../../Server/A
|
|||||||
import { SpecialServers } from "../../Server/data/SpecialServers";
|
import { SpecialServers } from "../../Server/data/SpecialServers";
|
||||||
|
|
||||||
export function hasTorRouter(this: IPlayer): boolean {
|
export function hasTorRouter(this: IPlayer): boolean {
|
||||||
return !!GetServer(SpecialServers.DarkWeb);
|
return this.getHomeComputer().serversOnNetwork.includes(SpecialServers.DarkWeb);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCurrentServer(this: IPlayer): BaseServer {
|
export function getCurrentServer(this: IPlayer): BaseServer {
|
||||||
|
@ -4,7 +4,14 @@ import { CONSTANTS } from "./Constants";
|
|||||||
import { Factions, loadFactions } from "./Faction/Factions";
|
import { Factions, loadFactions } from "./Faction/Factions";
|
||||||
import { loadAllGangs, AllGangs } from "./Gang/AllGangs";
|
import { loadAllGangs, AllGangs } from "./Gang/AllGangs";
|
||||||
import { Player, loadPlayer } from "./Player";
|
import { Player, loadPlayer } from "./Player";
|
||||||
import { saveAllServers, loadAllServers, GetAllServers } from "./Server/AllServers";
|
import {
|
||||||
|
saveAllServers,
|
||||||
|
loadAllServers,
|
||||||
|
GetAllServers,
|
||||||
|
createUniqueRandomIp,
|
||||||
|
AddToAllServers,
|
||||||
|
GetServer,
|
||||||
|
} from "./Server/AllServers";
|
||||||
import { Settings } from "./Settings/Settings";
|
import { Settings } from "./Settings/Settings";
|
||||||
import { loadStockMarket, StockMarket } from "./StockMarket/StockMarket";
|
import { loadStockMarket, StockMarket } from "./StockMarket/StockMarket";
|
||||||
import { staneksGift, loadStaneksGift } from "./CotMG/Helper";
|
import { staneksGift, loadStaneksGift } from "./CotMG/Helper";
|
||||||
@ -26,6 +33,8 @@ import { pushGameSaved } from "./Electron";
|
|||||||
import { defaultMonacoTheme } from "./ScriptEditor/ui/themes";
|
import { defaultMonacoTheme } from "./ScriptEditor/ui/themes";
|
||||||
import { FactionNames } from "./Faction/data/FactionNames";
|
import { FactionNames } from "./Faction/data/FactionNames";
|
||||||
import { Faction } from "./Faction/Faction";
|
import { Faction } from "./Faction/Faction";
|
||||||
|
import { safetlyCreateUniqueServer } from "./Server/ServerHelpers";
|
||||||
|
import { SpecialServers } from "./Server/data/SpecialServers";
|
||||||
|
|
||||||
/* SaveObject.js
|
/* SaveObject.js
|
||||||
* Defines the object used to save/load games
|
* Defines the object used to save/load games
|
||||||
@ -434,6 +443,22 @@ function evaluateVersionCompatibility(ver: string | number): void {
|
|||||||
Player.reapplyAllAugmentations(true);
|
Player.reapplyAllAugmentations(true);
|
||||||
Player.reapplyAllSourceFiles();
|
Player.reapplyAllSourceFiles();
|
||||||
}
|
}
|
||||||
|
if (ver < 18) {
|
||||||
|
// Create the darkweb for everyone but it won't be linked
|
||||||
|
const dw = GetServer(SpecialServers.DarkWeb);
|
||||||
|
if (!dw) {
|
||||||
|
const darkweb = safetlyCreateUniqueServer({
|
||||||
|
ip: createUniqueRandomIp(),
|
||||||
|
hostname: SpecialServers.DarkWeb,
|
||||||
|
organizationName: "",
|
||||||
|
isConnectedTo: false,
|
||||||
|
adminRights: false,
|
||||||
|
purchasedByPlayer: false,
|
||||||
|
maxRam: 1,
|
||||||
|
});
|
||||||
|
AddToAllServers(darkweb);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
24
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -560,7 +560,7 @@ export interface BitNodeMultipliers {
|
|||||||
/** Influences how much money the player earns when completing working their job. */
|
/** Influences how much money the player earns when completing working their job. */
|
||||||
CompanyWorkMoney: number;
|
CompanyWorkMoney: number;
|
||||||
/** Influences the money gain from dividends of corporations created by the player. */
|
/** Influences the money gain from dividends of corporations created by the player. */
|
||||||
CorporationSoftCap: number;
|
CorporationSoftcap: number;
|
||||||
/** Influences the valuation of corporations created by the player. */
|
/** Influences the valuation of corporations created by the player. */
|
||||||
CorporationValuation: number;
|
CorporationValuation: number;
|
||||||
/** Influences the base experience gained for each ability when the player commits a crime. */
|
/** Influences the base experience gained for each ability when the player commits a crime. */
|
||||||
@ -4405,6 +4405,13 @@ interface UserInterface {
|
|||||||
* RAM cost: 0 GB
|
* RAM cost: 0 GB
|
||||||
*/
|
*/
|
||||||
getGameInfo(): GameInfo;
|
getGameInfo(): GameInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the Terminal window, as if the player ran `clear` in the terminal
|
||||||
|
* @remarks
|
||||||
|
* RAM cost: 0.2 GB
|
||||||
|
*/
|
||||||
|
clearTerminal(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4988,6 +4995,21 @@ export interface NS {
|
|||||||
*/
|
*/
|
||||||
tail(fn?: FilenameOrPID, host?: string, ...args: any[]): void;
|
tail(fn?: FilenameOrPID, host?: string, ...args: any[]): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the tail window of a script.
|
||||||
|
* @remarks
|
||||||
|
* RAM cost: 0 GB
|
||||||
|
*
|
||||||
|
* Closes a script’s logs. This is functionally the same pressing the "Close" button on the tail window.
|
||||||
|
*
|
||||||
|
* If the function is called with no arguments, it will close the current script’s logs.
|
||||||
|
*
|
||||||
|
* Otherwise, the pid argument can be used to close the logs from another script.
|
||||||
|
*
|
||||||
|
* @param pid - Optional. PID of the script having its tail closed. If omitted, the current script is used.
|
||||||
|
*/
|
||||||
|
closeTail(pid?: number): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the list of servers connected to a server.
|
* Get the list of servers connected to a server.
|
||||||
* @remarks
|
* @remarks
|
||||||
|
@ -1565,4 +1565,12 @@ export const serverMetadata: IServerMetadata[] = [
|
|||||||
serverGrowth: 0,
|
serverGrowth: 0,
|
||||||
specialName: SpecialServers.WorldDaemon,
|
specialName: SpecialServers.WorldDaemon,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
hostname: SpecialServers.DarkWeb,
|
||||||
|
moneyAvailable: 0,
|
||||||
|
numOpenPortsRequired: 5,
|
||||||
|
organizationName: SpecialServers.DarkWeb,
|
||||||
|
requiredHackingSkill: 1,
|
||||||
|
specialName: SpecialServers.DarkWeb,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
@ -54,6 +54,11 @@ interface IDefaultSettings {
|
|||||||
*/
|
*/
|
||||||
EnableBashHotkeys: boolean;
|
EnableBashHotkeys: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Infinite loop safety net
|
||||||
|
*/
|
||||||
|
InfinityLoopSafety: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timestamps format
|
* Timestamps format
|
||||||
*/
|
*/
|
||||||
@ -201,6 +206,7 @@ export const defaultSettings: IDefaultSettings = {
|
|||||||
DisableOverviewProgressBars: false,
|
DisableOverviewProgressBars: false,
|
||||||
EnableBashHotkeys: false,
|
EnableBashHotkeys: false,
|
||||||
TimestampsFormat: "",
|
TimestampsFormat: "",
|
||||||
|
InfinityLoopSafety: true,
|
||||||
Locale: "en",
|
Locale: "en",
|
||||||
MaxRecentScriptsCapacity: 50,
|
MaxRecentScriptsCapacity: 50,
|
||||||
MaxLogCapacity: 50,
|
MaxLogCapacity: 50,
|
||||||
@ -241,6 +247,7 @@ export const Settings: ISettings & ISelfInitializer & ISelfLoading = {
|
|||||||
DisableOverviewProgressBars: defaultSettings.DisableOverviewProgressBars,
|
DisableOverviewProgressBars: defaultSettings.DisableOverviewProgressBars,
|
||||||
EnableBashHotkeys: defaultSettings.EnableBashHotkeys,
|
EnableBashHotkeys: defaultSettings.EnableBashHotkeys,
|
||||||
TimestampsFormat: defaultSettings.TimestampsFormat,
|
TimestampsFormat: defaultSettings.TimestampsFormat,
|
||||||
|
InfinityLoopSafety: defaultSettings.InfinityLoopSafety,
|
||||||
Locale: "en",
|
Locale: "en",
|
||||||
MaxRecentScriptsCapacity: defaultSettings.MaxRecentScriptsCapacity,
|
MaxRecentScriptsCapacity: defaultSettings.MaxRecentScriptsCapacity,
|
||||||
MaxLogCapacity: defaultSettings.MaxLogCapacity,
|
MaxLogCapacity: defaultSettings.MaxLogCapacity,
|
||||||
|
@ -67,8 +67,18 @@ SourceFiles["SourceFile5"] = new SourceFile(
|
|||||||
This Source-File grants a special new stat called Intelligence. Intelligence is unique because it is permanent and
|
This Source-File grants a special new stat called Intelligence. Intelligence is unique because it is permanent and
|
||||||
persistent (it never gets reset back to 1). However, gaining Intelligence experience is much slower than other
|
persistent (it never gets reset back to 1). However, gaining Intelligence experience is much slower than other
|
||||||
stats. Higher Intelligence levels will boost your production for many actions in the game. In addition, this
|
stats. Higher Intelligence levels will boost your production for many actions in the game. In addition, this
|
||||||
Source-File will unlock the getBitNodeMultipliers() Netscript function and let you start with Formulas.exe, and
|
Source-File will unlock:
|
||||||
will raise all of your hacking-related multipliers by:
|
<br />
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
The <code>getBitNodeMultipliers()</code> Netscript function
|
||||||
|
</li>
|
||||||
|
<li>Permanent access to Formulas.exe</li>
|
||||||
|
<li>
|
||||||
|
Access to BitNode multiplier information on the <b>Stats</b> page
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
It will also raise all of your hacking-related multipliers by:
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
Level 1: 8%
|
Level 1: 8%
|
||||||
|
@ -49,9 +49,11 @@ export function isValidFilename(filename: string): boolean {
|
|||||||
* not an entire path
|
* not an entire path
|
||||||
*/
|
*/
|
||||||
export function isValidDirectoryName(name: string): boolean {
|
export function isValidDirectoryName(name: string): boolean {
|
||||||
// Allows alphanumerics, hyphens, underscores, and percentage signs.
|
// A valid directory name:
|
||||||
// Name can begin with a single period, but otherwise cannot have any
|
// Must be at least 1 character long
|
||||||
const regex = /^.?[a-zA-Z0-9_-]+$/;
|
// Can only include characters in the character set [-.%a-zA-Z0-9_]
|
||||||
|
// Cannot end with a '.'
|
||||||
|
const regex = /^(?:[-.%]|\w)*[-%a-zA-Z0-9_]$/;
|
||||||
|
|
||||||
// match() returns null if no match is found
|
// match() returns null if no match is found
|
||||||
return name.match(regex) != null;
|
return name.match(regex) != null;
|
||||||
|
@ -463,6 +463,12 @@ export class Terminal implements ITerminal {
|
|||||||
this.contractOpen = true;
|
this.contractOpen = true;
|
||||||
const res = await contract.prompt();
|
const res = await contract.prompt();
|
||||||
|
|
||||||
|
//Check if the contract still exists by the time the promise is fullfilled
|
||||||
|
if (serv.getContract(contractName) == null) {
|
||||||
|
this.contractOpen = false;
|
||||||
|
return this.error("Contract no longer exists (Was it solved by a script?)");
|
||||||
|
}
|
||||||
|
|
||||||
switch (res) {
|
switch (res) {
|
||||||
case CodingContractResult.Success:
|
case CodingContractResult.Success:
|
||||||
if (contract.reward !== null) {
|
if (contract.reward !== null) {
|
||||||
|
@ -66,6 +66,13 @@ export function mv(
|
|||||||
|
|
||||||
if (destFile != null) {
|
if (destFile != null) {
|
||||||
// Already exists, will be overwritten, so we'll delete it
|
// Already exists, will be overwritten, so we'll delete it
|
||||||
|
|
||||||
|
// Command doesnt work if script is running
|
||||||
|
if (server.isRunning(destPath)) {
|
||||||
|
terminal.error(`Cannot use 'mv' on a script that is running`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const status = server.removeFile(destPath);
|
const status = server.removeFile(destPath);
|
||||||
if (!status.res) {
|
if (!status.res) {
|
||||||
terminal.error(`Something went wrong...please contact game dev (probably a bug)`);
|
terminal.error(`Something went wrong...please contact game dev (probably a bug)`);
|
||||||
|
@ -63,13 +63,11 @@ export function runScript(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ramUsage > ramAvailable) {
|
if (ramUsage > ramAvailable + 0.001) {
|
||||||
terminal.error(
|
terminal.error(
|
||||||
"This machine does not have enough RAM to run this script with " +
|
"This machine does not have enough RAM to run this script" +
|
||||||
numThreads +
|
(numThreads === 1 ? "" : ` with ${numThreads} threads`) +
|
||||||
" threads. Script requires " +
|
`. Script requires ${numeralWrapper.formatRAM(ramUsage)} of RAM`,
|
||||||
numeralWrapper.formatRAM(ramUsage) +
|
|
||||||
" of RAM",
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1382,7 +1382,8 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
|
|||||||
return [n + m, edges];
|
return [n + m, edges];
|
||||||
},
|
},
|
||||||
solver: (data: [number, [number, number][]], ans: string): boolean => {
|
solver: (data: [number, [number, number][]], ans: string): boolean => {
|
||||||
//Case where the player believes there is no solution
|
//Case where the player believes there is no solution.
|
||||||
|
//Attempt to construct one to check if this is correct.
|
||||||
if (ans == "[]") {
|
if (ans == "[]") {
|
||||||
//Helper function to get neighbourhood of a vertex
|
//Helper function to get neighbourhood of a vertex
|
||||||
function neighbourhood(vertex: number): number[] {
|
function neighbourhood(vertex: number): number[] {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { Paper, Table, TableBody, Box, IconButton, Typography, Container, Tooltip } from "@mui/material";
|
import { Paper, Table, TableBody, Box, IconButton, Typography, Container, Tooltip } from "@mui/material";
|
||||||
import { MoreHoriz, Info } from "@mui/icons-material";
|
import { MoreHoriz, Info } from "@mui/icons-material";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { BitNodes } from "../BitNode/BitNode";
|
import { BitNodes, defaultMultipliers, getBitNodeMultipliers } from "../BitNode/BitNode";
|
||||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
|
import { BitNodeMultipliersDisplay } from "../BitNode/ui/BitnodeMultipliersDescription";
|
||||||
import { HacknetServerConstants } from "../Hacknet/data/Constants";
|
import { HacknetServerConstants } from "../Hacknet/data/Constants";
|
||||||
import { getPurchaseServerLimit } from "../Server/ServerPurchases";
|
import { getPurchaseServerLimit } from "../Server/ServerPurchases";
|
||||||
import { Settings } from "../Settings/Settings";
|
import { Settings } from "../Settings/Settings";
|
||||||
@ -14,6 +15,7 @@ import { Modal } from "./React/Modal";
|
|||||||
import { Money } from "./React/Money";
|
import { Money } from "./React/Money";
|
||||||
import { StatsRow } from "./React/StatsRow";
|
import { StatsRow } from "./React/StatsRow";
|
||||||
import { StatsTable } from "./React/StatsTable";
|
import { StatsTable } from "./React/StatsTable";
|
||||||
|
import { isEqual } from "lodash";
|
||||||
|
|
||||||
interface EmployersModalProps {
|
interface EmployersModalProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@ -36,8 +38,22 @@ const EmployersModal = ({ open, onClose }: EmployersModalProps): React.ReactElem
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface IMultRow {
|
||||||
|
// The name of the multiplier
|
||||||
|
mult: string;
|
||||||
|
|
||||||
|
// The player's raw multiplier value
|
||||||
|
value: number;
|
||||||
|
|
||||||
|
// The player's effective multiplier value, affected by BitNode mults
|
||||||
|
effValue?: number;
|
||||||
|
|
||||||
|
// The text color for the row
|
||||||
|
color?: string;
|
||||||
|
}
|
||||||
|
|
||||||
interface MultTableProps {
|
interface MultTableProps {
|
||||||
rows: (string | number)[][];
|
rows: IMultRow[];
|
||||||
color: string;
|
color: string;
|
||||||
noMargin?: boolean;
|
noMargin?: boolean;
|
||||||
}
|
}
|
||||||
@ -48,29 +64,22 @@ function MultiplierTable(props: MultTableProps): React.ReactElement {
|
|||||||
<Table sx={{ display: "table", width: "100%", mb: (props.noMargin ?? false) === true ? 0 : 2 }}>
|
<Table sx={{ display: "table", width: "100%", mb: (props.noMargin ?? false) === true ? 0 : 2 }}>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{props.rows.map((data) => {
|
{props.rows.map((data) => {
|
||||||
const mult = data[0] as string,
|
const { mult, value, effValue = null, color = props.color } = data;
|
||||||
value = data[1] as number,
|
|
||||||
modded = data[2] as number | null;
|
|
||||||
|
|
||||||
if (modded && modded !== value && player.sourceFileLvl(5) > 0) {
|
if (effValue !== null && effValue !== value && player.sourceFileLvl(5) > 0) {
|
||||||
return (
|
return (
|
||||||
<StatsRow key={mult} name={mult} color={props.color} data={{}}>
|
<StatsRow key={mult} name={mult} color={color} data={{}}>
|
||||||
<>
|
<>
|
||||||
<Typography color={props.color}>
|
<Typography color={color}>
|
||||||
<span style={{ opacity: 0.5 }}>{numeralWrapper.formatPercentage(value)}</span>{" "}
|
<span style={{ opacity: 0.5 }}>{numeralWrapper.formatPercentage(value)}</span>{" "}
|
||||||
{numeralWrapper.formatPercentage(modded)}
|
{numeralWrapper.formatPercentage(effValue)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</>
|
</>
|
||||||
</StatsRow>
|
</StatsRow>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<StatsRow
|
<StatsRow key={mult} name={mult} color={color} data={{ content: numeralWrapper.formatPercentage(value) }} />
|
||||||
key={mult}
|
|
||||||
name={mult}
|
|
||||||
color={props.color}
|
|
||||||
data={{ content: numeralWrapper.formatPercentage(value) }}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
@ -82,16 +91,14 @@ function CurrentBitNode(): React.ReactElement {
|
|||||||
const player = use.Player();
|
const player = use.Player();
|
||||||
if (player.sourceFiles.length > 0) {
|
if (player.sourceFiles.length > 0) {
|
||||||
const index = "BitNode" + player.bitNodeN;
|
const index = "BitNode" + player.bitNodeN;
|
||||||
const lvl = player.sourceFileLvl(player.bitNodeN) + 1;
|
const lvl = Math.min(player.sourceFileLvl(player.bitNodeN) + 1, player.bitNodeN === 12 ? Infinity : 3);
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Paper sx={{ mb: 1, p: 1 }}>
|
||||||
<Paper sx={{ p: 1 }}>
|
<Typography variant="h5">
|
||||||
<Typography variant="h5">
|
BitNode {player.bitNodeN}: {BitNodes[index].name} (Level {lvl})
|
||||||
BitNode {player.bitNodeN}: {BitNodes[index].name} (Level {lvl})
|
</Typography>
|
||||||
</Typography>
|
<Typography sx={{ whiteSpace: "pre-wrap", overflowWrap: "break-word" }}>{BitNodes[index].info}</Typography>
|
||||||
<Typography sx={{ whiteSpace: "pre-wrap", overflowWrap: "break-word" }}>{BitNodes[index].info}</Typography>
|
</Paper>
|
||||||
</Paper>
|
|
||||||
</Box>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,6 +225,14 @@ export function CharacterStats(): React.ReactElement {
|
|||||||
}
|
}
|
||||||
timeRows.push(["Total", convertTimeMsToTimeElapsedString(player.totalPlaytime)]);
|
timeRows.push(["Total", convertTimeMsToTimeElapsedString(player.totalPlaytime)]);
|
||||||
|
|
||||||
|
let showBitNodeMults = false;
|
||||||
|
if (player.sourceFileLvl(5) > 0) {
|
||||||
|
const n = player.bitNodeN;
|
||||||
|
const maxSfLevel = n === 12 ? Infinity : 3;
|
||||||
|
const mults = getBitNodeMultipliers(n, Math.min(player.sourceFileLvl(n) + 1, maxSfLevel));
|
||||||
|
showBitNodeMults = !isEqual(mults, defaultMultipliers);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container maxWidth="lg" disableGutters sx={{ mx: 0 }}>
|
<Container maxWidth="lg" disableGutters sx={{ mx: 0 }}>
|
||||||
<Typography variant="h4">Stats</Typography>
|
<Typography variant="h4">Stats</Typography>
|
||||||
@ -332,186 +347,255 @@ export function CharacterStats(): React.ReactElement {
|
|||||||
</Table>
|
</Table>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ mb: 1 }}>
|
|
||||||
<Paper sx={{ p: 1 }}>
|
|
||||||
<Typography variant="h5" color="primary" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
|
|
||||||
Multipliers
|
|
||||||
{player.sourceFileLvl(5) > 0 && (
|
|
||||||
<Tooltip
|
|
||||||
title={
|
|
||||||
<Typography>
|
|
||||||
Displays your current multipliers.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
When there is a dim number next to a multiplier, that means that the multiplier in question is being
|
|
||||||
affected by BitNode multipliers.
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
The dim number is the raw multiplier, and the undimmed number is the effective multiplier, as
|
|
||||||
dictated by the BitNode.
|
|
||||||
</Typography>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Info sx={{ ml: 1, mb: 0.5 }} color="info" />
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</Typography>
|
|
||||||
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 1 }}>
|
|
||||||
<Box>
|
|
||||||
<MultiplierTable
|
|
||||||
rows={[
|
|
||||||
["Hacking Chance", player.hacking_chance_mult],
|
|
||||||
["Hacking Speed", player.hacking_speed_mult],
|
|
||||||
[
|
|
||||||
"Hacking Money",
|
|
||||||
player.hacking_money_mult,
|
|
||||||
player.hacking_money_mult * BitNodeMultipliers.ScriptHackMoney,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Hacking Growth",
|
|
||||||
player.hacking_grow_mult,
|
|
||||||
player.hacking_grow_mult * BitNodeMultipliers.ServerGrowthRate,
|
|
||||||
],
|
|
||||||
]}
|
|
||||||
color={Settings.theme.hack}
|
|
||||||
/>
|
|
||||||
<MultiplierTable
|
|
||||||
rows={[
|
|
||||||
[
|
|
||||||
"Hacking Level",
|
|
||||||
player.hacking_mult,
|
|
||||||
player.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"Hacking Experience",
|
|
||||||
player.hacking_exp_mult,
|
|
||||||
player.hacking_exp_mult * BitNodeMultipliers.HackExpGain,
|
|
||||||
],
|
|
||||||
]}
|
|
||||||
color={Settings.theme.hack}
|
|
||||||
/>
|
|
||||||
<MultiplierTable
|
|
||||||
rows={[
|
|
||||||
[
|
|
||||||
"Strength Level",
|
|
||||||
player.strength_mult,
|
|
||||||
player.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier,
|
|
||||||
],
|
|
||||||
["Strength Experience", player.strength_exp_mult],
|
|
||||||
]}
|
|
||||||
color={Settings.theme.combat}
|
|
||||||
/>
|
|
||||||
<MultiplierTable
|
|
||||||
rows={[
|
|
||||||
[
|
|
||||||
"Defense Level",
|
|
||||||
player.defense_mult,
|
|
||||||
player.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier,
|
|
||||||
],
|
|
||||||
["Defense Experience", player.defense_exp_mult],
|
|
||||||
]}
|
|
||||||
color={Settings.theme.combat}
|
|
||||||
/>
|
|
||||||
<MultiplierTable
|
|
||||||
rows={[
|
|
||||||
[
|
|
||||||
"Dexterity Level",
|
|
||||||
player.dexterity_mult,
|
|
||||||
player.dexterity_mult * BitNodeMultipliers.DexterityLevelMultiplier,
|
|
||||||
],
|
|
||||||
["Dexterity Experience", player.dexterity_exp_mult],
|
|
||||||
]}
|
|
||||||
color={Settings.theme.combat}
|
|
||||||
/>
|
|
||||||
<MultiplierTable
|
|
||||||
rows={[
|
|
||||||
[
|
|
||||||
"Agility Level",
|
|
||||||
player.agility_mult,
|
|
||||||
player.agility_mult * BitNodeMultipliers.AgilityLevelMultiplier,
|
|
||||||
],
|
|
||||||
["Agility Experience", player.agility_exp_mult],
|
|
||||||
]}
|
|
||||||
color={Settings.theme.combat}
|
|
||||||
/>
|
|
||||||
<MultiplierTable
|
|
||||||
rows={[
|
|
||||||
[
|
|
||||||
"Charisma Level",
|
|
||||||
player.charisma_mult,
|
|
||||||
player.charisma_mult * BitNodeMultipliers.CharismaLevelMultiplier,
|
|
||||||
],
|
|
||||||
["Charisma Experience", player.charisma_exp_mult],
|
|
||||||
]}
|
|
||||||
color={Settings.theme.cha}
|
|
||||||
noMargin
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box>
|
<Paper sx={{ p: 1, mb: 1 }}>
|
||||||
|
<Typography variant="h5" color="primary" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
|
||||||
|
Multipliers
|
||||||
|
{player.sourceFileLvl(5) > 0 && (
|
||||||
|
<Tooltip
|
||||||
|
title={
|
||||||
|
<Typography>
|
||||||
|
Displays your current multipliers.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
When there is a dim number next to a multiplier, that means that the multiplier in question is being
|
||||||
|
affected by BitNode multipliers.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
The dim number is the raw multiplier, and the undimmed number is the effective multiplier, as dictated
|
||||||
|
by the BitNode.
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Info sx={{ ml: 1, mb: 0.5 }} color="info" />
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</Typography>
|
||||||
|
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 1 }}>
|
||||||
|
<Box>
|
||||||
|
<MultiplierTable
|
||||||
|
rows={[
|
||||||
|
{
|
||||||
|
mult: "Hacking Chance",
|
||||||
|
value: player.hacking_chance_mult,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Hacking Speed",
|
||||||
|
value: player.hacking_speed_mult,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Hacking Money",
|
||||||
|
value: player.hacking_money_mult,
|
||||||
|
effValue: player.hacking_money_mult * BitNodeMultipliers.ScriptHackMoney,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Hacking Growth",
|
||||||
|
value: player.hacking_grow_mult,
|
||||||
|
effValue: player.hacking_grow_mult * BitNodeMultipliers.ServerGrowthRate,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
color={Settings.theme.hack}
|
||||||
|
/>
|
||||||
|
<MultiplierTable
|
||||||
|
rows={[
|
||||||
|
{
|
||||||
|
mult: "Hacking Level",
|
||||||
|
value: player.hacking_mult,
|
||||||
|
effValue: player.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Hacking Experience",
|
||||||
|
value: player.hacking_exp_mult,
|
||||||
|
effValue: player.hacking_exp_mult * BitNodeMultipliers.HackExpGain,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
color={Settings.theme.hack}
|
||||||
|
/>
|
||||||
|
<MultiplierTable
|
||||||
|
rows={[
|
||||||
|
{
|
||||||
|
mult: "Strength Level",
|
||||||
|
value: player.strength_mult,
|
||||||
|
effValue: player.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Strength Experience",
|
||||||
|
value: player.strength_exp_mult,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
color={Settings.theme.combat}
|
||||||
|
/>
|
||||||
|
<MultiplierTable
|
||||||
|
rows={[
|
||||||
|
{
|
||||||
|
mult: "Defense Level",
|
||||||
|
value: player.defense_mult,
|
||||||
|
effValue: player.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Defense Experience",
|
||||||
|
value: player.defense_exp_mult,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
color={Settings.theme.combat}
|
||||||
|
/>
|
||||||
|
<MultiplierTable
|
||||||
|
rows={[
|
||||||
|
{
|
||||||
|
mult: "Dexterity Level",
|
||||||
|
value: player.dexterity_mult,
|
||||||
|
effValue: player.dexterity_mult * BitNodeMultipliers.DexterityLevelMultiplier,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Dexterity Experience",
|
||||||
|
value: player.dexterity_exp_mult,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
color={Settings.theme.combat}
|
||||||
|
/>
|
||||||
|
<MultiplierTable
|
||||||
|
rows={[
|
||||||
|
{
|
||||||
|
mult: "Agility Level",
|
||||||
|
value: player.agility_mult,
|
||||||
|
effValue: player.agility_mult * BitNodeMultipliers.AgilityLevelMultiplier,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Agility Experience",
|
||||||
|
value: player.agility_exp_mult,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
color={Settings.theme.combat}
|
||||||
|
/>
|
||||||
|
<MultiplierTable
|
||||||
|
rows={[
|
||||||
|
{
|
||||||
|
mult: "Charisma Level",
|
||||||
|
value: player.charisma_mult,
|
||||||
|
effValue: player.charisma_mult * BitNodeMultipliers.CharismaLevelMultiplier,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Charisma Experience",
|
||||||
|
value: player.charisma_exp_mult,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
color={Settings.theme.cha}
|
||||||
|
noMargin
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box>
|
||||||
|
<MultiplierTable
|
||||||
|
rows={[
|
||||||
|
{
|
||||||
|
mult: "Hacknet Node Production",
|
||||||
|
value: player.hacknet_node_money_mult,
|
||||||
|
effValue: player.hacknet_node_money_mult * BitNodeMultipliers.HacknetNodeMoney,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Hacknet Node Purchase Cost",
|
||||||
|
value: player.hacknet_node_purchase_cost_mult,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Hacknet Node RAM Upgrade Cost",
|
||||||
|
value: player.hacknet_node_ram_cost_mult,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Hacknet Node Core Purchase Cost",
|
||||||
|
value: player.hacknet_node_core_cost_mult,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Hacknet Node Level Upgrade Cost",
|
||||||
|
value: player.hacknet_node_level_cost_mult,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
color={Settings.theme.primary}
|
||||||
|
/>
|
||||||
|
<MultiplierTable
|
||||||
|
rows={[
|
||||||
|
{
|
||||||
|
mult: "Company Reputation Gain",
|
||||||
|
value: player.company_rep_mult,
|
||||||
|
color: Settings.theme.rep,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Faction Reputation Gain",
|
||||||
|
value: player.faction_rep_mult,
|
||||||
|
effValue: player.faction_rep_mult * BitNodeMultipliers.FactionWorkRepGain,
|
||||||
|
color: Settings.theme.rep,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Salary",
|
||||||
|
value: player.work_money_mult,
|
||||||
|
effValue: player.work_money_mult * BitNodeMultipliers.CompanyWorkMoney,
|
||||||
|
color: Settings.theme.money,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
color={Settings.theme.money}
|
||||||
|
/>
|
||||||
|
<MultiplierTable
|
||||||
|
rows={[
|
||||||
|
{
|
||||||
|
mult: "Crime Success Chance",
|
||||||
|
value: player.crime_success_mult,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Crime Money",
|
||||||
|
value: player.crime_money_mult,
|
||||||
|
effValue: player.crime_money_mult * BitNodeMultipliers.CrimeMoney,
|
||||||
|
color: Settings.theme.money,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
color={Settings.theme.combat}
|
||||||
|
/>
|
||||||
|
{player.canAccessBladeburner() && (
|
||||||
<MultiplierTable
|
<MultiplierTable
|
||||||
rows={[
|
rows={[
|
||||||
[
|
{
|
||||||
"Hacknet Node production",
|
mult: "Bladeburner Success Chance",
|
||||||
player.hacknet_node_money_mult,
|
value: player.bladeburner_success_chance_mult,
|
||||||
player.hacknet_node_money_mult * BitNodeMultipliers.HacknetNodeMoney,
|
},
|
||||||
],
|
{
|
||||||
["Hacknet Node purchase cost", player.hacknet_node_purchase_cost_mult],
|
mult: "Bladeburner Max Stamina",
|
||||||
["Hacknet Node RAM upgrade cost", player.hacknet_node_ram_cost_mult],
|
value: player.bladeburner_max_stamina_mult,
|
||||||
["Hacknet Node Core purchase cost", player.hacknet_node_core_cost_mult],
|
},
|
||||||
["Hacknet Node level upgrade cost", player.hacknet_node_level_cost_mult],
|
{
|
||||||
|
mult: "Bladeburner Stamina Gain",
|
||||||
|
value: player.bladeburner_stamina_gain_mult,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
mult: "Bladeburner Field Analysis",
|
||||||
|
value: player.bladeburner_analysis_mult,
|
||||||
|
},
|
||||||
]}
|
]}
|
||||||
color={Settings.theme.primary}
|
color={Settings.theme.primary}
|
||||||
|
noMargin
|
||||||
/>
|
/>
|
||||||
<MultiplierTable
|
)}
|
||||||
rows={[
|
|
||||||
["Company reputation gain", player.company_rep_mult],
|
|
||||||
[
|
|
||||||
"Faction reputation gain",
|
|
||||||
player.faction_rep_mult,
|
|
||||||
player.faction_rep_mult * BitNodeMultipliers.FactionWorkRepGain,
|
|
||||||
],
|
|
||||||
["Salary", player.work_money_mult, player.work_money_mult * BitNodeMultipliers.CompanyWorkMoney],
|
|
||||||
]}
|
|
||||||
color={Settings.theme.money}
|
|
||||||
/>
|
|
||||||
<MultiplierTable
|
|
||||||
rows={[
|
|
||||||
["Crime success", player.crime_success_mult],
|
|
||||||
["Crime money", player.crime_money_mult, player.crime_money_mult * BitNodeMultipliers.CrimeMoney],
|
|
||||||
]}
|
|
||||||
color={Settings.theme.combat}
|
|
||||||
/>
|
|
||||||
{player.canAccessBladeburner() && (
|
|
||||||
<MultiplierTable
|
|
||||||
rows={[
|
|
||||||
["Bladeburner Success Chance", player.bladeburner_success_chance_mult],
|
|
||||||
["Bladeburner Max Stamina", player.bladeburner_max_stamina_mult],
|
|
||||||
["Bladeburner Stamina Gain", player.bladeburner_stamina_gain_mult],
|
|
||||||
["Bladeburner Field Analysis", player.bladeburner_analysis_mult],
|
|
||||||
]}
|
|
||||||
color={Settings.theme.primary}
|
|
||||||
noMargin
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
</Box>
|
</Box>
|
||||||
</Paper>
|
</Box>
|
||||||
</Box>
|
</Paper>
|
||||||
|
|
||||||
|
<Paper sx={{ p: 1, mb: 1 }}>
|
||||||
|
<Typography variant="h5">Time Played</Typography>
|
||||||
|
<Table>
|
||||||
|
<TableBody>
|
||||||
|
{timeRows.map(([name, content]) => (
|
||||||
|
<StatsRow key={name} name={name} color={Settings.theme.primary} data={{ content: content }} />
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</Paper>
|
||||||
|
|
||||||
<Box sx={{ mb: 1 }}>
|
|
||||||
<Paper sx={{ p: 1 }}>
|
|
||||||
<Typography variant="h5">Time Played</Typography>
|
|
||||||
<Table>
|
|
||||||
<TableBody>
|
|
||||||
{timeRows.map(([name, content]) => (
|
|
||||||
<StatsRow key={name} name={name} color={Settings.theme.primary} data={{ content: content }} />
|
|
||||||
))}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</Paper>
|
|
||||||
</Box>
|
|
||||||
<CurrentBitNode />
|
<CurrentBitNode />
|
||||||
|
|
||||||
|
{showBitNodeMults && (
|
||||||
|
<Paper sx={{ p: 1, mb: 1 }}>
|
||||||
|
<Typography variant="h5">BitNode Multipliers</Typography>
|
||||||
|
<BitNodeMultipliersDisplay n={player.bitNodeN} />
|
||||||
|
</Paper>
|
||||||
|
)}
|
||||||
|
|
||||||
<MoneyModal open={moneyOpen} onClose={() => setMoneyOpen(false)} />
|
<MoneyModal open={moneyOpen} onClose={() => setMoneyOpen(false)} />
|
||||||
<EmployersModal open={employersOpen} onClose={() => setEmployersOpen(false)} />
|
<EmployersModal open={employersOpen} onClose={() => setEmployersOpen(false)} />
|
||||||
</Container>
|
</Container>
|
||||||
|
@ -35,7 +35,7 @@ export function NSSelection(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal open={props.open} onClose={props.onClose}>
|
<Modal open={props.open} onClose={props.onClose} sx={{ zIndex: 999999 }}>
|
||||||
<Tabs variant="fullWidth" value={value} onChange={handleChange}>
|
<Tabs variant="fullWidth" value={value} onChange={handleChange}>
|
||||||
<Tab label="NS1" />
|
<Tab label="NS1" />
|
||||||
<Tab label="NS2" />
|
<Tab label="NS2" />
|
||||||
|
@ -18,10 +18,12 @@ import { Theme } from "@mui/material";
|
|||||||
import { findRunningScript } from "../../Script/ScriptHelpers";
|
import { findRunningScript } from "../../Script/ScriptHelpers";
|
||||||
import { Player } from "../../Player";
|
import { Player } from "../../Player";
|
||||||
import { debounce } from "lodash";
|
import { debounce } from "lodash";
|
||||||
|
import { Settings } from "../../Settings/Settings";
|
||||||
|
|
||||||
let layerCounter = 0;
|
let layerCounter = 0;
|
||||||
|
|
||||||
export const LogBoxEvents = new EventEmitter<[RunningScript]>();
|
export const LogBoxEvents = new EventEmitter<[RunningScript]>();
|
||||||
|
export const LogBoxCloserEvents = new EventEmitter<[number]>();
|
||||||
export const LogBoxClearEvents = new EventEmitter<[]>();
|
export const LogBoxClearEvents = new EventEmitter<[]>();
|
||||||
|
|
||||||
interface Log {
|
interface Log {
|
||||||
@ -50,6 +52,15 @@ export function LogBoxManager(): React.ReactElement {
|
|||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//Event used by ns.closeTail to close tail windows
|
||||||
|
useEffect(
|
||||||
|
() =>
|
||||||
|
LogBoxCloserEvents.subscribe((pid: number) => {
|
||||||
|
closePid(pid);
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
LogBoxClearEvents.subscribe(() => {
|
LogBoxClearEvents.subscribe(() => {
|
||||||
logs = [];
|
logs = [];
|
||||||
@ -57,11 +68,18 @@ export function LogBoxManager(): React.ReactElement {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//Close tail windows by their id
|
||||||
function close(id: string): void {
|
function close(id: string): void {
|
||||||
logs = logs.filter((l) => l.id !== id);
|
logs = logs.filter((l) => l.id !== id);
|
||||||
rerender();
|
rerender();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Close tail windows by their pid
|
||||||
|
function closePid(pid: number): void {
|
||||||
|
logs = logs.filter((log) => log.script.pid != pid);
|
||||||
|
rerender();
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{logs.map((log) => (
|
{logs.map((log) => (
|
||||||
@ -77,42 +95,18 @@ interface IProps {
|
|||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
const useStyles = makeStyles((_theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
title: {
|
|
||||||
"&.is-minimized + *": {
|
|
||||||
border: "none",
|
|
||||||
margin: 0,
|
|
||||||
"max-height": 0,
|
|
||||||
padding: 0,
|
|
||||||
"pointer-events": "none",
|
|
||||||
visibility: "hidden",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
logs: {
|
logs: {
|
||||||
overflowY: "scroll",
|
overflowY: "scroll",
|
||||||
overflowX: "hidden",
|
overflowX: "hidden",
|
||||||
scrollbarWidth: "auto",
|
scrollbarWidth: "auto",
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column-reverse",
|
flexDirection: "column-reverse",
|
||||||
|
whiteSpace: "pre-wrap",
|
||||||
},
|
},
|
||||||
titleButton: {
|
titleButton: {
|
||||||
padding: "1px 6px",
|
padding: "1px 0",
|
||||||
},
|
height: "100%",
|
||||||
success: {
|
|
||||||
color: theme.colors.success,
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
color: theme.palette.error.main,
|
|
||||||
},
|
|
||||||
primary: {
|
|
||||||
color: theme.palette.primary.main,
|
|
||||||
},
|
|
||||||
info: {
|
|
||||||
color: theme.palette.info.main,
|
|
||||||
},
|
|
||||||
warning: {
|
|
||||||
color: theme.palette.warning.main,
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@ -190,20 +184,20 @@ function LogWindow(props: IProps): React.ReactElement {
|
|||||||
setMinimized(!minimized);
|
setMinimized(!minimized);
|
||||||
}
|
}
|
||||||
|
|
||||||
function lineClass(s: string): string {
|
function lineColor(s: string): string {
|
||||||
if (s.match(/(^\[[^\]]+\] )?ERROR/) || s.match(/(^\[[^\]]+\] )?FAIL/)) {
|
if (s.match(/(^\[[^\]]+\] )?ERROR/) || s.match(/(^\[[^\]]+\] )?FAIL/)) {
|
||||||
return classes.error;
|
return Settings.theme.error;
|
||||||
}
|
}
|
||||||
if (s.match(/(^\[[^\]]+\] )?SUCCESS/)) {
|
if (s.match(/(^\[[^\]]+\] )?SUCCESS/)) {
|
||||||
return classes.success;
|
return Settings.theme.success;
|
||||||
}
|
}
|
||||||
if (s.match(/(^\[[^\]]+\] )?WARN/)) {
|
if (s.match(/(^\[[^\]]+\] )?WARN/)) {
|
||||||
return classes.warning;
|
return Settings.theme.warning;
|
||||||
}
|
}
|
||||||
if (s.match(/(^\[[^\]]+\] )?INFO/)) {
|
if (s.match(/(^\[[^\]]+\] )?INFO/)) {
|
||||||
return classes.info;
|
return Settings.theme.info;
|
||||||
}
|
}
|
||||||
return classes.primary;
|
return Settings.theme.primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
// And trigger fakeDrag when the window is resized
|
// And trigger fakeDrag when the window is resized
|
||||||
@ -242,74 +236,99 @@ function LogWindow(props: IProps): React.ReactElement {
|
|||||||
if (e.clientX < 0 || e.clientY < 0 || e.clientX > innerWidth || e.clientY > innerHeight) return false;
|
if (e.clientX < 0 || e.clientY < 0 || e.clientX > innerWidth || e.clientY > innerHeight) return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Max [width, height]
|
||||||
|
const minConstraints: [number, number] = [250, 33];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Draggable handle=".drag" onDrag={boundToBody} ref={rootRef}>
|
<Draggable handle=".drag" onDrag={boundToBody} ref={rootRef} onMouseDown={updateLayer}>
|
||||||
<Paper
|
<Box
|
||||||
style={{
|
display="flex"
|
||||||
display: "flex",
|
sx={{
|
||||||
flexFlow: "column",
|
flexFlow: "column",
|
||||||
position: "fixed",
|
position: "fixed",
|
||||||
left: "40%",
|
left: "40%",
|
||||||
top: "30%",
|
top: "30%",
|
||||||
zIndex: 1400,
|
zIndex: 1400,
|
||||||
|
minWidth: `${minConstraints[0]}px`,
|
||||||
|
minHeight: `${minConstraints[1]}px`,
|
||||||
|
...(minimized
|
||||||
|
? {
|
||||||
|
border: "none",
|
||||||
|
margin: 0,
|
||||||
|
maxHeight: 0,
|
||||||
|
padding: 0,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
border: `1px solid ${Settings.theme.welllight}`,
|
||||||
|
}),
|
||||||
}}
|
}}
|
||||||
ref={container}
|
ref={container}
|
||||||
>
|
>
|
||||||
<div onMouseDown={updateLayer}>
|
<ResizableBox
|
||||||
<Paper
|
height={500}
|
||||||
className={classes.title + " " + (minimized ? "is-minimized" : "")}
|
width={500}
|
||||||
style={{
|
minConstraints={minConstraints}
|
||||||
cursor: "grab",
|
handle={
|
||||||
}}
|
<span
|
||||||
>
|
style={{
|
||||||
<Box className="drag" display="flex" alignItems="center" ref={draggableRef}>
|
position: "absolute",
|
||||||
<Typography color="primary" variant="h6" sx={{ marginRight: "auto" }} title={title(true)}>
|
right: "-10px",
|
||||||
{title()}
|
bottom: "-16px",
|
||||||
|
cursor: "nw-resize",
|
||||||
|
display: minimized ? "none" : "inline-block",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ArrowForwardIosIcon color="primary" style={{ transform: "rotate(45deg)", fontSize: "1.75rem" }} />
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<Paper className="drag" sx={{ display: "flex", alignItems: "center", cursor: "grab" }} ref={draggableRef}>
|
||||||
|
<Typography
|
||||||
|
variant="h6"
|
||||||
|
sx={{ marginRight: "auto", textOverflow: "ellipsis", whiteSpace: "nowrap", overflow: "hidden" }}
|
||||||
|
title={title(true)}
|
||||||
|
>
|
||||||
|
{title(true)}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
{!workerScripts.has(script.pid) ? (
|
<span style={{ minWidth: "fit-content", height: `${minConstraints[1]}px` }}>
|
||||||
<Button className={classes.titleButton} onClick={run} onTouchEnd={run}>
|
{!workerScripts.has(script.pid) ? (
|
||||||
Run
|
<Button className={classes.titleButton} onClick={run} onTouchEnd={run}>
|
||||||
|
Run
|
||||||
|
</Button>
|
||||||
|
) : (
|
||||||
|
<Button className={classes.titleButton} onClick={kill} onTouchEnd={kill}>
|
||||||
|
Kill
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<Button className={classes.titleButton} onClick={minimize} onTouchEnd={minimize}>
|
||||||
|
{minimized ? "\u{1F5D6}" : "\u{1F5D5}"}
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
<Button className={classes.titleButton} onClick={props.onClose} onTouchEnd={props.onClose}>
|
||||||
<Button className={classes.titleButton} onClick={kill} onTouchEnd={kill}>
|
Close
|
||||||
Kill
|
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
</span>
|
||||||
<Button className={classes.titleButton} onClick={minimize} onTouchEnd={minimize}>
|
</Paper>
|
||||||
{minimized ? "\u{1F5D6}" : "\u{1F5D5}"}
|
|
||||||
</Button>
|
<Paper
|
||||||
<Button className={classes.titleButton} onClick={props.onClose} onTouchEnd={props.onClose}>
|
|
||||||
Close
|
|
||||||
</Button>
|
|
||||||
</Box>
|
|
||||||
</Paper>
|
|
||||||
<Paper sx={{ overflow: "scroll", overflowWrap: "break-word", whiteSpace: "pre-wrap" }}>
|
|
||||||
<ResizableBox
|
|
||||||
className={classes.logs}
|
className={classes.logs}
|
||||||
height={500}
|
sx={{ height: `calc(100% - ${minConstraints[1]}px)`, display: minimized ? "none" : "flex" }}
|
||||||
width={500}
|
|
||||||
minConstraints={[250, 30]}
|
|
||||||
handle={
|
|
||||||
<span style={{ position: "absolute", right: "-10px", bottom: "-13px", cursor: "nw-resize" }}>
|
|
||||||
<ArrowForwardIosIcon color="primary" style={{ transform: "rotate(45deg)" }} />
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<Box>
|
<span style={{ display: "flex", flexDirection: "column" }}>
|
||||||
{script.logs.map(
|
{script.logs.map(
|
||||||
(line: string, i: number): JSX.Element => (
|
(line: string, i: number): JSX.Element => (
|
||||||
<Typography key={i} className={lineClass(line)}>
|
<Typography key={i} sx={{ color: lineColor(line) }}>
|
||||||
{line}
|
{line}
|
||||||
<br />
|
<br />
|
||||||
</Typography>
|
</Typography>
|
||||||
),
|
),
|
||||||
)}
|
)}
|
||||||
</Box>
|
</span>
|
||||||
</ResizableBox>
|
</Paper>
|
||||||
</Paper>
|
</>
|
||||||
</div>
|
</ResizableBox>
|
||||||
</Paper>
|
</Box>
|
||||||
</Draggable>
|
</Draggable>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import React from "react";
|
|
||||||
import { Theme } from "@mui/material";
|
import { Theme } from "@mui/material";
|
||||||
import makeStyles from "@mui/styles/makeStyles";
|
|
||||||
import createStyles from "@mui/styles/createStyles";
|
|
||||||
import M from "@mui/material/Modal";
|
|
||||||
import Fade from "@mui/material/Fade";
|
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
|
import Fade from "@mui/material/Fade";
|
||||||
|
import M from "@mui/material/Modal";
|
||||||
|
import createStyles from "@mui/styles/createStyles";
|
||||||
|
import makeStyles from "@mui/styles/makeStyles";
|
||||||
|
import { SxProps } from "@mui/system";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
@ -12,7 +13,6 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||||||
display: "flex",
|
display: "flex",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
zIndex: 999999,
|
|
||||||
},
|
},
|
||||||
paper: {
|
paper: {
|
||||||
backgroundColor: theme.palette.background.default,
|
backgroundColor: theme.palette.background.default,
|
||||||
@ -35,6 +35,7 @@ interface IProps {
|
|||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
sx?: SxProps<Theme>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Modal = (props: IProps): React.ReactElement => {
|
export const Modal = (props: IProps): React.ReactElement => {
|
||||||
@ -49,6 +50,7 @@ export const Modal = (props: IProps): React.ReactElement => {
|
|||||||
onClose={props.onClose}
|
onClose={props.onClose}
|
||||||
closeAfterTransition
|
closeAfterTransition
|
||||||
className={classes.modal}
|
className={classes.modal}
|
||||||
|
sx={props.sx}
|
||||||
>
|
>
|
||||||
<Fade in={props.open}>
|
<Fade in={props.open}>
|
||||||
<div className={classes.paper}>
|
<div className={classes.paper}>
|
||||||
|
9
test/cypress/tsconfig.json
Normal file
9
test/cypress/tsconfig.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"checkJs": true,
|
||||||
|
"types": ["cypress", "@testing-library/cypress"]
|
||||||
|
},
|
||||||
|
"include": ["**/*"],
|
||||||
|
"exclude": []
|
||||||
|
}
|
@ -1,5 +1,3 @@
|
|||||||
import { jest, describe, expect } from "@jest/globals";
|
|
||||||
|
|
||||||
import { Player } from "../../../src/Player";
|
import { Player } from "../../../src/Player";
|
||||||
import { NetscriptFunctions } from "../../../src/NetscriptFunctions";
|
import { NetscriptFunctions } from "../../../src/NetscriptFunctions";
|
||||||
import { getRamCost, RamCostConstants } from "../../../src/Netscript/RamCostGenerator";
|
import { getRamCost, RamCostConstants } from "../../../src/Netscript/RamCostGenerator";
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import { jest, describe, expect } from "@jest/globals";
|
|
||||||
|
|
||||||
import { Player } from "../../../src/Player";
|
import { Player } from "../../../src/Player";
|
||||||
import { getRamCost, RamCostConstants } from "../../../src/Netscript/RamCostGenerator";
|
import { getRamCost, RamCostConstants } from "../../../src/Netscript/RamCostGenerator";
|
||||||
import { calculateRamUsage } from "../../../src/Script/RamCalculations";
|
import { calculateRamUsage } from "../../../src/Script/RamCalculations";
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
import { describe, expect, jest } from "@jest/globals";
|
|
||||||
|
|
||||||
// Player is needed for calculating costs like Singularity functions, that depend on acquired source files
|
// Player is needed for calculating costs like Singularity functions, that depend on acquired source files
|
||||||
import { Player } from "../../../src/Player";
|
import { Player } from "../../../src/Player";
|
||||||
|
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
import { jest, describe, expect, test } from "@jest/globals";
|
|
||||||
|
|
||||||
import { Script } from "../../../src/Script/Script";
|
import { Script } from "../../../src/Script/Script";
|
||||||
import { Player } from "../../../src/Player";
|
import { Player } from "../../../src/Player";
|
||||||
|
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
import { jest, describe, expect, test } from "@jest/globals";
|
|
||||||
|
|
||||||
import { CONSTANTS } from "../../src/Constants";
|
import { CONSTANTS } from "../../src/Constants";
|
||||||
import { Player } from "../../src/Player";
|
import { Player } from "../../src/Player";
|
||||||
import { IMap } from "../../src/types";
|
import { IMap } from "../../src/types";
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
import { jest, describe, expect, test } from "@jest/globals";
|
|
||||||
import { convertTimeMsToTimeElapsedString } from "../../src/utils/StringHelperFunctions";
|
import { convertTimeMsToTimeElapsedString } from "../../src/utils/StringHelperFunctions";
|
||||||
|
|
||||||
describe("StringHelperFunctions Tests", function () {
|
describe("StringHelperFunctions Tests", function () {
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
import { jest, describe, expect, test } from "@jest/globals";
|
|
||||||
import * as dirHelpers from "../../../src/Terminal/DirectoryHelpers";
|
import * as dirHelpers from "../../../src/Terminal/DirectoryHelpers";
|
||||||
|
|
||||||
describe("Terminal Directory Tests", function () {
|
describe("Terminal Directory Tests", function () {
|
||||||
@ -102,17 +100,28 @@ describe("Terminal Directory Tests", function () {
|
|||||||
expect(isValidDirectoryName(".a1")).toEqual(true);
|
expect(isValidDirectoryName(".a1")).toEqual(true);
|
||||||
expect(isValidDirectoryName("._foo")).toEqual(true);
|
expect(isValidDirectoryName("._foo")).toEqual(true);
|
||||||
expect(isValidDirectoryName("_foo")).toEqual(true);
|
expect(isValidDirectoryName("_foo")).toEqual(true);
|
||||||
|
expect(isValidDirectoryName("foo.dir")).toEqual(true);
|
||||||
|
expect(isValidDirectoryName("foov1.0.0.1")).toEqual(true);
|
||||||
|
expect(isValidDirectoryName("foov1..0..0..1")).toEqual(true);
|
||||||
|
expect(isValidDirectoryName("foov1-0-0-1")).toEqual(true);
|
||||||
|
expect(isValidDirectoryName("foov1-0-0-1-")).toEqual(true);
|
||||||
|
expect(isValidDirectoryName("foov1--0--0--1--")).toEqual(true);
|
||||||
|
expect(isValidDirectoryName("foov1_0_0_1")).toEqual(true);
|
||||||
|
expect(isValidDirectoryName("foov1_0_0_1_")).toEqual(true);
|
||||||
|
expect(isValidDirectoryName("foov1__0__0__1")).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return false for invalid directory names", function () {
|
it("should return false for invalid directory names", function () {
|
||||||
expect(isValidDirectoryName("")).toEqual(false);
|
expect(isValidDirectoryName("")).toEqual(false);
|
||||||
expect(isValidDirectoryName("foo.dir")).toEqual(false);
|
expect(isValidDirectoryName("👨💻")).toEqual(false);
|
||||||
expect(isValidDirectoryName("1.")).toEqual(false);
|
|
||||||
expect(isValidDirectoryName("foo.")).toEqual(false);
|
|
||||||
expect(isValidDirectoryName("dir#")).toEqual(false);
|
expect(isValidDirectoryName("dir#")).toEqual(false);
|
||||||
expect(isValidDirectoryName("dir!")).toEqual(false);
|
expect(isValidDirectoryName("dir!")).toEqual(false);
|
||||||
expect(isValidDirectoryName("dir*")).toEqual(false);
|
expect(isValidDirectoryName("dir*")).toEqual(false);
|
||||||
expect(isValidDirectoryName(".")).toEqual(false);
|
expect(isValidDirectoryName(".")).toEqual(false);
|
||||||
|
expect(isValidDirectoryName("..")).toEqual(false);
|
||||||
|
expect(isValidDirectoryName("1.")).toEqual(false);
|
||||||
|
expect(isValidDirectoryName("foo.")).toEqual(false);
|
||||||
|
expect(isValidDirectoryName("foov1.0.0.1.")).toEqual(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import { CityName } from "./../../../src/Locations/data/CityNames";
|
import { CityName } from "./../../../src/Locations/data/CityNames";
|
||||||
/* eslint-disable no-await-in-loop */
|
/* eslint-disable no-await-in-loop */
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
import { jest, describe, expect, test } from "@jest/globals";
|
|
||||||
|
|
||||||
import { Player } from "../../../src/Player";
|
import { Player } from "../../../src/Player";
|
||||||
import { determineAllPossibilitiesForTabCompletion } from "../../../src/Terminal/determineAllPossibilitiesForTabCompletion";
|
import { determineAllPossibilitiesForTabCompletion } from "../../../src/Terminal/determineAllPossibilitiesForTabCompletion";
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { describe, expect, test } from "@jest/globals";
|
|
||||||
import { numeralWrapper } from "../../../src/ui/numeralFormat";
|
import { numeralWrapper } from "../../../src/ui/numeralFormat";
|
||||||
|
|
||||||
let decimalFormat = "0.[000000]";
|
let decimalFormat = "0.[000000]";
|
||||||
|
9
test/tsconfig.json
Normal file
9
test/tsconfig.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowJs": true,
|
||||||
|
"types": ["jest"]
|
||||||
|
},
|
||||||
|
"include": ["**/*", "../src/**/*.d.ts"],
|
||||||
|
"exclude": ["cypress/**/*"]
|
||||||
|
}
|
@ -4,13 +4,13 @@
|
|||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "react",
|
"jsx": "react",
|
||||||
"lib": ["es2016", "dom", "es2017.object", "es2019"],
|
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "es6",
|
"noEmit": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"resolveJsonModule": true,
|
"target": "es2019"
|
||||||
"types": ["cypress", "@testing-library/cypress", "node"]
|
|
||||||
},
|
},
|
||||||
"exclude": ["node_modules"]
|
"include": ["src/**/*"]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user