mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-17 14:59:16 +02:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87c63cde59 | ||
|
|
383b02fdbb | ||
|
|
41de3102c7 | ||
|
|
783750051e | ||
|
|
0aa26df9d7 | ||
|
|
4355420349 | ||
|
|
f4ecbd9b48 | ||
|
|
528a8f30db | ||
|
|
500063e87e | ||
|
|
8d7f0488f8 | ||
|
|
62bdfb1875 | ||
|
|
8e5c10cc2f | ||
|
|
15a03dd532 | ||
|
|
8e58482db0 | ||
|
|
da746a63c3 | ||
|
|
2f677c7ec8 | ||
|
|
c5e29dafc4 | ||
|
|
880654c222 | ||
|
|
4fc6d393e4 | ||
|
|
7304e5379f | ||
|
|
793d9b34ce |
23
css/staneksgift.scss
Normal file
23
css/staneksgift.scss
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
.staneksgift_row {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.staneksgift_cell {
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
background-color: #808080;
|
||||||
|
font-color: white;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
border: 1px solid black;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.staneksgift_cell:first-child {
|
||||||
|
clear: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.staneksgift_container {
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
138
dist/vendor.bundle.js
vendored
138
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@@ -30,5 +30,6 @@ to reach out to the developer!
|
|||||||
Gang API <netscript/netscriptgangapi>
|
Gang API <netscript/netscriptgangapi>
|
||||||
Coding Contract API <netscript/netscriptcodingcontractapi>
|
Coding Contract API <netscript/netscriptcodingcontractapi>
|
||||||
Sleeve API <netscript/netscriptsleeveapi>
|
Sleeve API <netscript/netscriptsleeveapi>
|
||||||
|
Stanek API <netscript/netscriptstanekapi>
|
||||||
Formulas API <netscript/netscriptformulasapi>
|
Formulas API <netscript/netscriptformulasapi>
|
||||||
Miscellaneous <netscript/netscriptmisc>
|
Miscellaneous <netscript/netscriptmisc>
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
atExit() Netscript Function
|
|
||||||
============================
|
|
||||||
|
|
||||||
.. js:function:: atExit(f)
|
|
||||||
|
|
||||||
:RAM cost: 0 GB
|
|
||||||
:param function f: function to call when the script dies.
|
|
||||||
|
|
||||||
Runs when the script dies.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
.. code-block:: javascript
|
|
||||||
|
|
||||||
function onDeath() {
|
|
||||||
console.log('I died!!!')
|
|
||||||
}
|
|
||||||
atExit(onDeath);
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
autocomplete() Netscript Function
|
|
||||||
============================
|
|
||||||
|
|
||||||
.. warning:: This feature is not officially supported yet and the API might change.
|
|
||||||
|
|
||||||
.. js:function:: autocomplete(data, args)
|
|
||||||
|
|
||||||
:RAM cost: 0 GB
|
|
||||||
:param Object data: general data about the game you might want to autocomplete.
|
|
||||||
:param string[] args: current arguments.
|
|
||||||
|
|
||||||
data is an object with the following properties::
|
|
||||||
|
|
||||||
{
|
|
||||||
servers: list of all servers in the game.
|
|
||||||
txts: list of all text files on the current server.
|
|
||||||
scripts: list of all scripts on the current server.
|
|
||||||
}
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
.. code-block:: javascript
|
|
||||||
|
|
||||||
export function autocomplete(data, args) {
|
|
||||||
return [...data.servers]; // This script autocompletes the list of servers.
|
|
||||||
return [...data.servers, ...data.scripts]; // Autocomplete servers and scripts
|
|
||||||
return ["low", "medium", "high"]; // Autocomplete 3 specific strings.
|
|
||||||
}
|
|
||||||
|
|
||||||
Terminal:
|
|
||||||
|
|
||||||
.. code-block:: javascript
|
|
||||||
|
|
||||||
$ run demo.ns mega\t
|
|
||||||
// results in
|
|
||||||
$ run demo.ns megacorp
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
alert() Netscript Function
|
|
||||||
============================
|
|
||||||
|
|
||||||
.. js:function:: alert(message)
|
|
||||||
|
|
||||||
:RAM cost: 0 GB
|
|
||||||
:param string message: message to display
|
|
||||||
|
|
||||||
Spawns an alert box.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
.. code-block:: javascript
|
|
||||||
|
|
||||||
alert("Reached $1b");
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
toast() Netscript Function
|
|
||||||
============================
|
|
||||||
|
|
||||||
.. js:function:: toast(message[, variant])
|
|
||||||
|
|
||||||
:RAM cost: 0 GB
|
|
||||||
:param string message: message to display
|
|
||||||
:param success|info|warning|error variant: color of the toast
|
|
||||||
|
|
||||||
Spawns a toast (those bottom left notifications).
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
.. code-block:: javascript
|
|
||||||
|
|
||||||
toast("Reached $1b");
|
|
||||||
toast("Failed to hack home", "error");
|
|
||||||
@@ -10,4 +10,3 @@ they contain spoilers for the game.
|
|||||||
|
|
||||||
getBitNodeMultipliers() <advancedfunctions/getBitNodeMultipliers>
|
getBitNodeMultipliers() <advancedfunctions/getBitNodeMultipliers>
|
||||||
getServer() <advancedfunctions/getServer>
|
getServer() <advancedfunctions/getServer>
|
||||||
autocomplete() <advancedfunctions/autocomplete>
|
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ The player has access to all of these functions while in BitNode-4. Completing B
|
|||||||
getFactionRep() <singularityfunctions/getFactionRep>
|
getFactionRep() <singularityfunctions/getFactionRep>
|
||||||
getFactionFavor() <singularityfunctions/getFactionFavor>
|
getFactionFavor() <singularityfunctions/getFactionFavor>
|
||||||
getFactionFavorGain() <singularityfunctions/getFactionFavorGain>
|
getFactionFavorGain() <singularityfunctions/getFactionFavorGain>
|
||||||
upgradeHomeCores() <singularityfunctions/upgradeHomeCores>
|
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:caption: Level 3 Functions
|
:caption: Level 3 Functions
|
||||||
|
|||||||
20
doc/source/netscript/netscriptstanekapi.rst
Normal file
20
doc/source/netscript/netscriptstanekapi.rst
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
.. _netscriptstanek:
|
||||||
|
|
||||||
|
Netscript Stanek Functions
|
||||||
|
============================
|
||||||
|
|
||||||
|
.. warning:: This page contains spoilers for the game.
|
||||||
|
|
||||||
|
The Stanek API allow you to control Stanek's Gift.
|
||||||
|
|
||||||
|
All these function require Source-File 13-1 or to be in BitNode 13.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
charge() <stanekapi/charge>
|
||||||
|
fragmentDefinitions() <stanekapi/fragmentDefinitions>
|
||||||
|
placedFragments() <stanekapi/placedFragments>
|
||||||
|
clear() <stanekapi/clear>
|
||||||
|
canPlace() <stanekapi/canPlace>
|
||||||
|
place() <stanekapi/place>
|
||||||
|
fragmentAt() <stanekapi/fragmentAt>
|
||||||
|
deleteAt() <stanekapi/deleteAt>
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
upgradeHomeRam() Netscript Function
|
|
||||||
===================================
|
|
||||||
|
|
||||||
.. js:function:: upgradeHomeCores()
|
|
||||||
|
|
||||||
:RAM cost: 3 GB
|
|
||||||
|
|
||||||
If you are not in BitNode-4, then you must have Level 2 of Source-File 4 in order to use this function.
|
|
||||||
|
|
||||||
This function will upgrade amount of CORES on the player's home computer. The cost is the same as if you were to do it manually.
|
|
||||||
|
|
||||||
This function will return true if the player's home computer core count is successfully upgraded, and false otherwise.
|
|
||||||
15
doc/source/netscript/stanekapi/canPlace.rst
Normal file
15
doc/source/netscript/stanekapi/canPlace.rst
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
canPlace() Netscript Function
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
.. js:function:: canPlace(worldX, worldY, fragmentId)
|
||||||
|
|
||||||
|
:RAM cost: 0.5 GB
|
||||||
|
:param int worldX: World X against which to align the top left of the fragment.
|
||||||
|
:param int worldY: World Y against which to align the top left of the fragment.
|
||||||
|
:param int fragmentId: ID of the fragment to place.
|
||||||
|
:returns: `true` if the fragment can be placed at that position. `false` otherwise.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: javascript
|
||||||
|
canPlace(0, 4, 17); // returns true
|
||||||
21
doc/source/netscript/stanekapi/charge.rst
Normal file
21
doc/source/netscript/stanekapi/charge.rst
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
charge() Netscript Function
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
.. js:function:: charge(worldX, worldY)
|
||||||
|
|
||||||
|
:RAM cost: 0.4 GB
|
||||||
|
:param int worldX: World X of the fragment to charge.
|
||||||
|
:param int worldY: World Y of the fragment to charge.
|
||||||
|
|
||||||
|
Charge a fragment, increasing it's power but also it's heat. The
|
||||||
|
effectiveness of the charge depends on the amount of ram the running script
|
||||||
|
consumes as well as the fragments current heat. This operation takes time to
|
||||||
|
complete.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: javascript
|
||||||
|
charge(0, 4); // Finishes 5 seconds later.
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Netscript JS users: This function is `async`
|
||||||
13
doc/source/netscript/stanekapi/clear.rst
Normal file
13
doc/source/netscript/stanekapi/clear.rst
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
clear() Netscript Function
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
.. js:function:: clear()
|
||||||
|
|
||||||
|
:RAM cost: 0 GB
|
||||||
|
|
||||||
|
Completely clear Stanek's Gift.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: javascript
|
||||||
|
clear(); // No more fragments.
|
||||||
16
doc/source/netscript/stanekapi/deleteAt.rst
Normal file
16
doc/source/netscript/stanekapi/deleteAt.rst
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
deleteAt() Netscript Function
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
.. js:function:: deleteAt(worldX, worldY)
|
||||||
|
|
||||||
|
:RAM cost: 0.15 GB
|
||||||
|
:param int worldX: World X coordinate of the fragment to delete.
|
||||||
|
:param int worldY: World Y coordinate of the fragment to delete.
|
||||||
|
:returns: `true` if the fragment was deleted. `false` otherwise.
|
||||||
|
|
||||||
|
Delete the fragment located at `[worldX, worldY]`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: javascript
|
||||||
|
deleteAt(0, 4); // returns true
|
||||||
28
doc/source/netscript/stanekapi/fragmentAt.rst
Normal file
28
doc/source/netscript/stanekapi/fragmentAt.rst
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
fragmentAt() Netscript Function
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
.. js:function:: fragmentAt(worldX, worldY)
|
||||||
|
|
||||||
|
:RAM cost: 2 GB
|
||||||
|
:param int worldX: World X coordinate of the fragment.
|
||||||
|
:param int worldY: World Y coordinate of the fragment.
|
||||||
|
:returns: The fragment located at `[worldX, worldY]` in Stanek's Gift, or null.
|
||||||
|
|
||||||
|
.. code-block:: typescript
|
||||||
|
{
|
||||||
|
// In world coordinates
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
heat: number;
|
||||||
|
charge: number;
|
||||||
|
id: number;
|
||||||
|
shape: boolean[][];
|
||||||
|
type: string;
|
||||||
|
magnitude: number;
|
||||||
|
limit: number;
|
||||||
|
}
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: javascript
|
||||||
|
var fragment = fragmentAt(0, 4);
|
||||||
|
print(fragment); // {'heat': 50, 'charge': 98}
|
||||||
23
doc/source/netscript/stanekapi/fragmentDefinitions.rst
Normal file
23
doc/source/netscript/stanekapi/fragmentDefinitions.rst
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
fragmentDefinitions() Netscript Function
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
.. js:function:: fragmentDefinitions()
|
||||||
|
|
||||||
|
:RAM cost: 0 GB
|
||||||
|
:returns: The list of all fragment that can be embedded in Stanek's Gift.
|
||||||
|
|
||||||
|
.. code-block:: typescript
|
||||||
|
[
|
||||||
|
{
|
||||||
|
id: number;
|
||||||
|
shape: boolean[][];
|
||||||
|
type: string;
|
||||||
|
magnitude: number;
|
||||||
|
limit: number;
|
||||||
|
}
|
||||||
|
]
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: javascript
|
||||||
|
var fragments = fragmentDefinitions();
|
||||||
|
print(fragment); // prints all possible fragments
|
||||||
15
doc/source/netscript/stanekapi/place.rst
Normal file
15
doc/source/netscript/stanekapi/place.rst
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
place() Netscript Function
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
.. js:function:: place(worldX, worldY, fragmentId)
|
||||||
|
|
||||||
|
:RAM cost: 5 GB
|
||||||
|
:param int worldX: World X against which to align the top left of the fragment.
|
||||||
|
:param int worldY: World Y against which to align the top left of the fragment.
|
||||||
|
:param int fragmentId: ID of the fragment to place.
|
||||||
|
:returns: `true` if the fragment has been placed at that position. `false` otherwise.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: javascript
|
||||||
|
place(0, 4, 17); // returns true
|
||||||
27
doc/source/netscript/stanekapi/placedFragments.rst
Normal file
27
doc/source/netscript/stanekapi/placedFragments.rst
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
placedFragments() Netscript Function
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
.. js:function:: placedFragments()
|
||||||
|
|
||||||
|
:RAM cost: 5 GB
|
||||||
|
:returns: The list of all fragment that are embedded in Stanek's Gift.
|
||||||
|
|
||||||
|
.. code-block:: typescript
|
||||||
|
[
|
||||||
|
{
|
||||||
|
// In world coordinates
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
heat: number;
|
||||||
|
charge: number;
|
||||||
|
id: number;
|
||||||
|
shape: boolean[][];
|
||||||
|
type: string;
|
||||||
|
magnitude: number;
|
||||||
|
limit: number;
|
||||||
|
}
|
||||||
|
]
|
||||||
|
Example:
|
||||||
|
|
||||||
|
.. code-block:: javascript
|
||||||
|
var myFragments = placedFragments();
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
35063
package-lock.json
generated
35063
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
73
package.json
73
package.json
@@ -13,9 +13,10 @@
|
|||||||
"@emotion/react": "^11.4.1",
|
"@emotion/react": "^11.4.1",
|
||||||
"@emotion/styled": "^11.3.0",
|
"@emotion/styled": "^11.3.0",
|
||||||
"@monaco-editor/react": "^4.2.2",
|
"@monaco-editor/react": "^4.2.2",
|
||||||
"@mui/icons-material": "^5.0.3",
|
"@mui/icons-material": "^5.0.0-rc.1",
|
||||||
"@mui/material": "^5.0.3",
|
"@mui/lab": "^5.0.0-alpha.46",
|
||||||
"@mui/styles": "^5.0.1",
|
"@mui/material": "^5.0.0-rc.1",
|
||||||
|
"@mui/styles": "^5.0.0-rc.1",
|
||||||
"@types/escodegen": "^0.0.7",
|
"@types/escodegen": "^0.0.7",
|
||||||
"@types/js-beautify": "^1.13.2",
|
"@types/js-beautify": "^1.13.2",
|
||||||
"@types/numeral": "0.0.25",
|
"@types/numeral": "0.0.25",
|
||||||
@@ -24,23 +25,46 @@
|
|||||||
"@types/react-resizable": "^1.7.3",
|
"@types/react-resizable": "^1.7.3",
|
||||||
"acorn": "^8.4.1",
|
"acorn": "^8.4.1",
|
||||||
"acorn-walk": "^8.1.1",
|
"acorn-walk": "^8.1.1",
|
||||||
|
"ajv": "^5.1.5",
|
||||||
|
"ajv-keywords": "^2.0.0",
|
||||||
"arg": "^5.0.0",
|
"arg": "^5.0.0",
|
||||||
"better-react-mathjax": "^1.0.3",
|
"async": "^2.6.1",
|
||||||
"clsx": "^1.1.1",
|
"autosize": "^4.0.2",
|
||||||
|
"brace": "^0.11.1",
|
||||||
|
"codemirror": "^5.58.2",
|
||||||
"decimal.js": "7.2.3",
|
"decimal.js": "7.2.3",
|
||||||
|
"enhanced-resolve": "^4.0.0",
|
||||||
"escodegen": "^1.11.0",
|
"escodegen": "^1.11.0",
|
||||||
|
"escope": "^3.6.0",
|
||||||
"file-saver": "^1.3.8",
|
"file-saver": "^1.3.8",
|
||||||
|
"interpret": "^1.0.0",
|
||||||
"jquery": "^3.5.0",
|
"jquery": "^3.5.0",
|
||||||
|
"jshint": "^2.10.2",
|
||||||
|
"json-loader": "^0.5.4",
|
||||||
|
"jsplumb": "^2.6.8",
|
||||||
"jszip": "^3.7.0",
|
"jszip": "^3.7.0",
|
||||||
|
"loader-runner": "^2.3.0",
|
||||||
|
"loader-utils": "^1.1.0",
|
||||||
"material-ui-color": "^1.2.0",
|
"material-ui-color": "^1.2.0",
|
||||||
|
"mathjax-full": "^3.2.0",
|
||||||
|
"mathjax-react": "^1.0.6",
|
||||||
|
"memory-fs": "~0.4.1",
|
||||||
"monaco-editor": "^0.27.0",
|
"monaco-editor": "^0.27.0",
|
||||||
"notistack": "^2.0.2",
|
"node-sass": "^6.0.1",
|
||||||
|
"normalize.css": "^8.0.0",
|
||||||
"numeral": "2.0.6",
|
"numeral": "2.0.6",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-draggable": "^4.4.4",
|
"react-draggable": "^4.4.4",
|
||||||
|
"react-modal": "^3.12.1",
|
||||||
"react-resizable": "^3.0.4",
|
"react-resizable": "^3.0.4",
|
||||||
"sprintf-js": "^1.1.1"
|
"sprintf-js": "^1.1.1",
|
||||||
|
"tapable": "^1.0.0",
|
||||||
|
"treant-js": "^1.0.1",
|
||||||
|
"unused-webpack-plugin": "^2.4.0",
|
||||||
|
"uuid": "^3.2.1",
|
||||||
|
"w3c-blob": "0.0.1",
|
||||||
|
"webpack-deadcode-plugin": "^0.1.15"
|
||||||
},
|
},
|
||||||
"description": "A cyberpunk-themed incremental game",
|
"description": "A cyberpunk-themed incremental game",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -51,33 +75,65 @@
|
|||||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.1",
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.1",
|
||||||
"@testing-library/cypress": "^8.0.1",
|
"@testing-library/cypress": "^8.0.1",
|
||||||
"@types/file-saver": "^2.0.3",
|
"@types/file-saver": "^2.0.3",
|
||||||
|
"@types/jest": "^27.0.1",
|
||||||
"@types/lodash": "^4.14.168",
|
"@types/lodash": "^4.14.168",
|
||||||
|
"@types/node": "^16.9.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.22.0",
|
"@typescript-eslint/eslint-plugin": "^4.22.0",
|
||||||
"@typescript-eslint/parser": "^4.22.0",
|
"@typescript-eslint/parser": "^4.22.0",
|
||||||
"babel-jest": "^27.0.6",
|
"babel-jest": "^27.0.6",
|
||||||
"babel-loader": "^8.0.5",
|
"babel-loader": "^8.0.5",
|
||||||
|
"beautify-lint": "^1.0.3",
|
||||||
|
"benchmark": "^2.1.1",
|
||||||
|
"bundle-loader": "~0.5.0",
|
||||||
|
"css-loader": "^0.28.11",
|
||||||
"cypress": "^8.3.1",
|
"cypress": "^8.3.1",
|
||||||
"electron": "^14.0.1",
|
"electron": "^14.0.1",
|
||||||
"electron-packager": "^15.4.0",
|
"electron-packager": "^15.4.0",
|
||||||
|
"es6-promise-polyfill": "^1.1.1",
|
||||||
"eslint": "^7.24.0",
|
"eslint": "^7.24.0",
|
||||||
|
"eslint-plugin-node": "^11.1.0",
|
||||||
|
"file-loader": "^1.1.11",
|
||||||
"fork-ts-checker-webpack-plugin": "^6.3.3",
|
"fork-ts-checker-webpack-plugin": "^6.3.3",
|
||||||
"html-webpack-plugin": "^3.2.0",
|
"html-webpack-plugin": "^3.2.0",
|
||||||
"http-server": "^13.0.1",
|
"http-server": "^13.0.1",
|
||||||
|
"i18n-webpack-plugin": "^1.0.0",
|
||||||
|
"istanbul": "^0.4.5",
|
||||||
"jest": "^27.1.0",
|
"jest": "^27.1.0",
|
||||||
"js-beautify": "^1.5.10",
|
"js-beautify": "^1.5.10",
|
||||||
"jsdom": "^15.0.0",
|
"jsdom": "^15.0.0",
|
||||||
|
"jsdom-global": "^3.0.2",
|
||||||
|
"json5": "^1.0.1",
|
||||||
|
"less": "^3.9.0",
|
||||||
|
"less-loader": "^4.1.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"mini-css-extract-plugin": "^0.4.1",
|
"mini-css-extract-plugin": "^0.4.1",
|
||||||
|
"mkdirp": "^0.5.1",
|
||||||
|
"null-loader": "^1.0.0",
|
||||||
"prettier": "^2.3.2",
|
"prettier": "^2.3.2",
|
||||||
|
"raw-loader": "~0.5.0",
|
||||||
"react-refresh": "^0.10.0",
|
"react-refresh": "^0.10.0",
|
||||||
"regenerator-runtime": "^0.13.9",
|
"regenerator-runtime": "^0.13.9",
|
||||||
|
"sass-loader": "^7.0.3",
|
||||||
|
"script-loader": "~0.7.0",
|
||||||
|
"should": "^11.1.1",
|
||||||
|
"simple-git": "^1.96.0",
|
||||||
|
"sinon": "^2.3.2",
|
||||||
"source-map": "^0.7.3",
|
"source-map": "^0.7.3",
|
||||||
"start-server-and-test": "^1.14.0",
|
"start-server-and-test": "^1.14.0",
|
||||||
|
"style-loader": "^0.21.0",
|
||||||
|
"stylelint": "^9.2.1",
|
||||||
|
"stylelint-declaration-use-variable": "^1.6.1",
|
||||||
|
"stylelint-order": "^0.8.1",
|
||||||
"typescript": "^4.2.4",
|
"typescript": "^4.2.4",
|
||||||
|
"uglify-es": "^3.3.9",
|
||||||
|
"uglifyjs-webpack-plugin": "^1.3.0",
|
||||||
|
"url-loader": "^1.0.1",
|
||||||
|
"watchpack": "^1.6.0",
|
||||||
"webpack": "^4.46.0",
|
"webpack": "^4.46.0",
|
||||||
"webpack-cli": "^3.3.12",
|
"webpack-cli": "^3.3.12",
|
||||||
"webpack-dev-middleware": "^3.7.3",
|
"webpack-dev-middleware": "^3.7.3",
|
||||||
"webpack-dev-server": "^3.11.2"
|
"webpack-dev-server": "^3.11.2",
|
||||||
|
"worker-loader": "^2.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8 || <=9"
|
"node": ">=8 || <=9"
|
||||||
@@ -101,6 +157,7 @@
|
|||||||
"build:dev": "webpack --mode development",
|
"build:dev": "webpack --mode development",
|
||||||
"lint": "npm run lint:jsts & npm run lint:style",
|
"lint": "npm run lint:jsts & npm run lint:style",
|
||||||
"lint:jsts": "eslint --fix . --ext js,jsx,ts,tsx",
|
"lint:jsts": "eslint --fix . --ext js,jsx,ts,tsx",
|
||||||
|
"lint:style": "stylelint --fix ./css/*",
|
||||||
"preinstall": "node ./scripts/engines-check.js",
|
"preinstall": "node ./scripts/engines-check.js",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"test:watch": "jest --watch",
|
"test:watch": "jest --watch",
|
||||||
|
|||||||
@@ -2,433 +2,366 @@ const numSpaces = 4;
|
|||||||
const maxLineLength = 160;
|
const maxLineLength = 160;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
"env": {
|
env: {
|
||||||
"es6": true,
|
es6: true,
|
||||||
"node": true
|
node: true,
|
||||||
|
},
|
||||||
|
extends: "eslint:recommended",
|
||||||
|
parserOptions: {
|
||||||
|
ecmaFeatures: {
|
||||||
|
experimentalObjectRestSpread: true,
|
||||||
},
|
},
|
||||||
"extends": "eslint:recommended",
|
ecmaVersion: 8,
|
||||||
"parserOptions": {
|
sourceType: "module",
|
||||||
"ecmaFeatures": {
|
},
|
||||||
"experimentalObjectRestSpread": true
|
rules: {
|
||||||
},
|
"accessor-pairs": [
|
||||||
"ecmaVersion": 8,
|
"error",
|
||||||
"sourceType": "module"
|
{
|
||||||
},
|
getWithoutSet: false,
|
||||||
"rules": {
|
setWithoutGet: true,
|
||||||
"accessor-pairs": [
|
},
|
||||||
"error",
|
],
|
||||||
{
|
"array-bracket-newline": ["error"],
|
||||||
"getWithoutSet": false,
|
"array-bracket-spacing": ["error"],
|
||||||
"setWithoutGet": true
|
"array-callback-return": ["error"],
|
||||||
}
|
"array-element-newline": ["error"],
|
||||||
],
|
"arrow-body-style": ["error"],
|
||||||
"array-bracket-newline": ["error"],
|
"arrow-parens": ["error"],
|
||||||
"array-bracket-spacing": ["error"],
|
"arrow-spacing": ["error"],
|
||||||
"array-callback-return": ["error"],
|
"block-scoped-var": ["error"],
|
||||||
"array-element-newline": ["error"],
|
"block-spacing": ["error"],
|
||||||
"arrow-body-style": ["error"],
|
"brace-style": ["error"],
|
||||||
"arrow-parens": ["error"],
|
"callback-return": ["error"],
|
||||||
"arrow-spacing": ["error"],
|
camelcase: ["error"],
|
||||||
"block-scoped-var": ["error"],
|
"capitalized-comments": ["error"],
|
||||||
"block-spacing": ["error"],
|
"class-methods-use-this": ["error"],
|
||||||
"brace-style": ["error"],
|
"comma-dangle": ["error"],
|
||||||
"callback-return": ["error"],
|
"comma-spacing": ["error"],
|
||||||
"camelcase": ["error"],
|
"comma-style": ["error", "last"],
|
||||||
"capitalized-comments": ["error"],
|
complexity: ["error"],
|
||||||
"class-methods-use-this": ["error"],
|
"computed-property-spacing": ["error", "never"],
|
||||||
"comma-dangle": ["error"],
|
"consistent-return": ["error"],
|
||||||
"comma-spacing": ["error"],
|
"consistent-this": ["error"],
|
||||||
"comma-style": [
|
"constructor-super": ["error"],
|
||||||
"error",
|
curly: ["error"],
|
||||||
"last"
|
"default-case": ["error"],
|
||||||
],
|
"dot-location": ["error", "property"],
|
||||||
"complexity": ["error"],
|
"dot-notation": ["error"],
|
||||||
"computed-property-spacing": [
|
"eol-last": ["error"],
|
||||||
"error",
|
eqeqeq: ["error"],
|
||||||
"never"
|
"for-direction": ["error"],
|
||||||
],
|
"func-call-spacing": ["error"],
|
||||||
"consistent-return": ["error"],
|
"func-name-matching": ["error"],
|
||||||
"consistent-this": ["error"],
|
"func-names": ["error", "never"],
|
||||||
"constructor-super": ["error"],
|
"func-style": ["error"],
|
||||||
"curly": ["error"],
|
"function-paren-newline": ["error"],
|
||||||
"default-case": ["error"],
|
"generator-star-spacing": ["error", "before"],
|
||||||
"dot-location": [
|
"getter-return": [
|
||||||
"error",
|
"error",
|
||||||
"property"
|
{
|
||||||
],
|
allowImplicit: false,
|
||||||
"dot-notation": ["error"],
|
},
|
||||||
"eol-last": ["error"],
|
],
|
||||||
"eqeqeq": ["error"],
|
"global-require": ["error"],
|
||||||
"for-direction": ["error"],
|
"guard-for-in": ["error"],
|
||||||
"func-call-spacing": ["error"],
|
"handle-callback-err": ["error"],
|
||||||
"func-name-matching": ["error"],
|
"id-blacklist": ["error"],
|
||||||
"func-names": [
|
"id-length": ["error"],
|
||||||
"error",
|
"id-match": ["error"],
|
||||||
"never"
|
"implicit-arrow-linebreak": ["error", "beside"],
|
||||||
],
|
indent: [
|
||||||
"func-style": ["error"],
|
"error",
|
||||||
"function-paren-newline": ["error"],
|
numSpaces,
|
||||||
"generator-star-spacing": [
|
{
|
||||||
"error",
|
SwitchCase: 1,
|
||||||
"before"
|
},
|
||||||
],
|
],
|
||||||
"getter-return": [
|
"init-declarations": ["error"],
|
||||||
"error",
|
"jsx-quotes": ["error"],
|
||||||
{
|
"key-spacing": ["error"],
|
||||||
"allowImplicit": false
|
"keyword-spacing": ["error"],
|
||||||
}
|
"line-comment-position": ["error"],
|
||||||
],
|
"linebreak-style": ["error", "windows"],
|
||||||
"global-require": ["error"],
|
"lines-around-comment": ["error"],
|
||||||
"guard-for-in": ["error"],
|
"lines-between-class-members": ["error"],
|
||||||
"handle-callback-err": ["error"],
|
"max-depth": ["error"],
|
||||||
"id-blacklist": ["error"],
|
"max-len": ["error", maxLineLength],
|
||||||
"id-length": ["error"],
|
"max-lines": [
|
||||||
"id-match": ["error"],
|
"error",
|
||||||
"implicit-arrow-linebreak": [
|
{
|
||||||
"error",
|
skipBlankLines: true,
|
||||||
"beside"
|
skipComments: true,
|
||||||
],
|
},
|
||||||
"indent": [
|
],
|
||||||
"error",
|
"max-nested-callbacks": ["error"],
|
||||||
numSpaces,
|
"max-params": ["error"],
|
||||||
{
|
"max-statements": ["error"],
|
||||||
"SwitchCase": 1
|
"max-statements-per-line": ["error"],
|
||||||
}
|
"multiline-comment-style": ["off", "starred-block"],
|
||||||
],
|
"multiline-ternary": ["error", "never"],
|
||||||
"init-declarations": ["error"],
|
"new-cap": ["error"],
|
||||||
"jsx-quotes": ["error"],
|
"new-parens": ["error"],
|
||||||
"key-spacing": ["error"],
|
// TODO: configure this...
|
||||||
"keyword-spacing": ["error"],
|
"newline-before-return": ["error"],
|
||||||
"line-comment-position": ["error"],
|
"newline-per-chained-call": ["error"],
|
||||||
"linebreak-style": [
|
"no-alert": ["error"],
|
||||||
"error",
|
"no-array-constructor": ["error"],
|
||||||
"windows"
|
"no-await-in-loop": ["error"],
|
||||||
],
|
"no-bitwise": ["error"],
|
||||||
"lines-around-comment": ["error"],
|
"no-buffer-constructor": ["error"],
|
||||||
"lines-between-class-members": ["error"],
|
"no-caller": ["error"],
|
||||||
"max-depth": ["error"],
|
"no-case-declarations": ["error"],
|
||||||
"max-len": [
|
"no-catch-shadow": ["error"],
|
||||||
"error",
|
"no-class-assign": ["error"],
|
||||||
maxLineLength
|
"no-compare-neg-zero": ["error"],
|
||||||
],
|
"no-cond-assign": ["error", "except-parens"],
|
||||||
"max-lines": [
|
"no-confusing-arrow": ["error"],
|
||||||
"error",
|
"no-console": ["error"],
|
||||||
{
|
"no-const-assign": ["error"],
|
||||||
"skipBlankLines": true,
|
"no-constant-condition": [
|
||||||
"skipComments": true
|
"error",
|
||||||
}
|
{
|
||||||
],
|
checkLoops: false,
|
||||||
"max-nested-callbacks": ["error"],
|
},
|
||||||
"max-params": ["error"],
|
],
|
||||||
"max-statements": ["error"],
|
"no-continue": ["off"],
|
||||||
"max-statements-per-line": ["error"],
|
"no-control-regex": ["error"],
|
||||||
"multiline-comment-style": [
|
"no-debugger": ["error"],
|
||||||
"off",
|
"no-delete-var": ["error"],
|
||||||
"starred-block"
|
"no-div-regex": ["error"],
|
||||||
],
|
"no-dupe-args": ["error"],
|
||||||
"multiline-ternary": [
|
"no-dupe-class-members": ["error"],
|
||||||
"error",
|
"no-dupe-keys": ["error"],
|
||||||
"never"
|
"no-duplicate-case": ["error"],
|
||||||
],
|
"no-duplicate-imports": [
|
||||||
"new-cap": ["error"],
|
"error",
|
||||||
"new-parens": ["error"],
|
{
|
||||||
// TODO: configure this...
|
includeExports: true,
|
||||||
"newline-before-return": ["error"],
|
},
|
||||||
"newline-per-chained-call": ["error"],
|
],
|
||||||
"no-alert": ["error"],
|
"no-else-return": ["error"],
|
||||||
"no-array-constructor": ["error"],
|
"no-empty": [
|
||||||
"no-await-in-loop": ["error"],
|
"error",
|
||||||
"no-bitwise": ["error"],
|
{
|
||||||
"no-buffer-constructor": ["error"],
|
allowEmptyCatch: false,
|
||||||
"no-caller": ["error"],
|
},
|
||||||
"no-case-declarations": ["error"],
|
],
|
||||||
"no-catch-shadow": ["error"],
|
"no-empty-character-class": ["error"],
|
||||||
"no-class-assign": ["error"],
|
"no-empty-function": ["error"],
|
||||||
"no-compare-neg-zero": ["error"],
|
"no-empty-pattern": ["error"],
|
||||||
"no-cond-assign": [
|
"no-eq-null": ["error"],
|
||||||
"error",
|
"no-eval": ["error"],
|
||||||
"except-parens"
|
"no-ex-assign": ["error"],
|
||||||
],
|
"no-extend-native": ["error"],
|
||||||
"no-confusing-arrow": ["error"],
|
"no-extra-bind": ["error"],
|
||||||
"no-console": ["error"],
|
"no-extra-boolean-cast": ["error"],
|
||||||
"no-const-assign": ["error"],
|
"no-extra-label": ["error"],
|
||||||
"no-constant-condition": [
|
"no-extra-parens": [
|
||||||
"error",
|
"error",
|
||||||
{
|
"all",
|
||||||
"checkLoops": false
|
{
|
||||||
}
|
conditionalAssign: false,
|
||||||
],
|
},
|
||||||
"no-continue": ["off"],
|
],
|
||||||
"no-control-regex": ["error"],
|
"no-extra-semi": ["error"],
|
||||||
"no-debugger": ["error"],
|
"no-fallthrough": ["error"],
|
||||||
"no-delete-var": ["error"],
|
"no-floating-decimal": ["error"],
|
||||||
"no-div-regex": ["error"],
|
"no-func-assign": ["error"],
|
||||||
"no-dupe-args": ["error"],
|
"no-global-assign": ["error"],
|
||||||
"no-dupe-class-members": ["error"],
|
"no-implicit-coercion": ["error"],
|
||||||
"no-dupe-keys": ["error"],
|
"no-implicit-globals": ["error"],
|
||||||
"no-duplicate-case": ["error"],
|
"no-implied-eval": ["error"],
|
||||||
"no-duplicate-imports": [
|
"no-inline-comments": ["error"],
|
||||||
"error",
|
"no-inner-declarations": ["error", "both"],
|
||||||
{
|
"no-invalid-regexp": ["error"],
|
||||||
"includeExports": true
|
"no-invalid-this": ["error"],
|
||||||
}
|
"no-irregular-whitespace": [
|
||||||
],
|
"error",
|
||||||
"no-else-return": ["error"],
|
{
|
||||||
"no-empty": [
|
skipComments: false,
|
||||||
"error",
|
skipRegExps: false,
|
||||||
{
|
skipStrings: false,
|
||||||
"allowEmptyCatch": false
|
skipTemplates: false,
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
"no-empty-character-class": ["error"],
|
"no-iterator": ["error"],
|
||||||
"no-empty-function": ["error"],
|
"no-label-var": ["error"],
|
||||||
"no-empty-pattern": ["error"],
|
"no-labels": ["error"],
|
||||||
"no-eq-null": ["error"],
|
"no-lone-blocks": ["error"],
|
||||||
"no-eval": ["error"],
|
"no-lonely-if": ["error"],
|
||||||
"no-ex-assign": ["error"],
|
"no-loop-func": ["error"],
|
||||||
"no-extend-native": ["error"],
|
"no-magic-numbers": [
|
||||||
"no-extra-bind": ["error"],
|
"error",
|
||||||
"no-extra-boolean-cast": ["error"],
|
{
|
||||||
"no-extra-label": ["error"],
|
ignore: [-1, 0, 1],
|
||||||
"no-extra-parens": [
|
ignoreArrayIndexes: true,
|
||||||
"error",
|
},
|
||||||
"all",
|
],
|
||||||
{
|
"no-mixed-operators": ["error"],
|
||||||
"conditionalAssign": false
|
"no-mixed-requires": ["error"],
|
||||||
}
|
"no-mixed-spaces-and-tabs": ["error"],
|
||||||
],
|
"no-multi-assign": ["error"],
|
||||||
"no-extra-semi": ["error"],
|
"no-multi-spaces": ["error"],
|
||||||
"no-fallthrough": ["error"],
|
"no-multi-str": ["error"],
|
||||||
"no-floating-decimal": ["error"],
|
"no-multiple-empty-lines": [
|
||||||
"no-func-assign": ["error"],
|
"error",
|
||||||
"no-global-assign": ["error"],
|
{
|
||||||
"no-implicit-coercion": ["error"],
|
max: 1,
|
||||||
"no-implicit-globals": ["error"],
|
},
|
||||||
"no-implied-eval": ["error"],
|
],
|
||||||
"no-inline-comments": ["error"],
|
"no-native-reassign": ["error"],
|
||||||
"no-inner-declarations": [
|
"no-negated-condition": ["error"],
|
||||||
"error",
|
"no-negated-in-lhs": ["error"],
|
||||||
"both"
|
"no-nested-ternary": ["error"],
|
||||||
],
|
"no-new": ["error"],
|
||||||
"no-invalid-regexp": ["error"],
|
"no-new-func": ["error"],
|
||||||
"no-invalid-this": ["error"],
|
"no-new-object": ["error"],
|
||||||
"no-irregular-whitespace": [
|
"no-new-require": ["error"],
|
||||||
"error",
|
"no-new-symbol": ["error"],
|
||||||
{
|
"no-new-wrappers": ["error"],
|
||||||
"skipComments": false,
|
"no-obj-calls": ["error"],
|
||||||
"skipRegExps": false,
|
"no-octal": ["error"],
|
||||||
"skipStrings": false,
|
"no-octal-escape": ["error"],
|
||||||
"skipTemplates": false
|
"no-param-reassign": ["error"],
|
||||||
}
|
"no-path-concat": ["error"],
|
||||||
],
|
"no-plusplus": [
|
||||||
"no-iterator": ["error"],
|
"error",
|
||||||
"no-label-var": ["error"],
|
{
|
||||||
"no-labels": ["error"],
|
allowForLoopAfterthoughts: true,
|
||||||
"no-lone-blocks": ["error"],
|
},
|
||||||
"no-lonely-if": ["error"],
|
],
|
||||||
"no-loop-func": ["error"],
|
"no-process-env": ["error"],
|
||||||
"no-magic-numbers": [
|
"no-process-exit": ["error"],
|
||||||
"error",
|
"no-proto": ["error"],
|
||||||
{
|
"no-prototype-builtins": ["error"],
|
||||||
"ignore": [
|
"no-redeclare": ["error"],
|
||||||
-1,
|
"no-regex-spaces": ["error"],
|
||||||
0,
|
"no-restricted-globals": ["error"],
|
||||||
1
|
"no-restricted-imports": ["error"],
|
||||||
],
|
"no-restricted-modules": ["error"],
|
||||||
"ignoreArrayIndexes": true
|
"no-restricted-properties": [
|
||||||
}
|
"error",
|
||||||
],
|
{
|
||||||
"no-mixed-operators": ["error"],
|
message: "'log' is too general, use an appropriate level when logging.",
|
||||||
"no-mixed-requires": ["error"],
|
object: "console",
|
||||||
"no-mixed-spaces-and-tabs": ["error"],
|
property: "log",
|
||||||
"no-multi-assign": ["error"],
|
},
|
||||||
"no-multi-spaces": ["error"],
|
],
|
||||||
"no-multi-str": ["error"],
|
"no-restricted-syntax": ["error"],
|
||||||
"no-multiple-empty-lines": [
|
"no-return-assign": ["error"],
|
||||||
"error",
|
"no-return-await": ["error"],
|
||||||
{
|
"no-script-url": ["error"],
|
||||||
"max": 1
|
"no-self-assign": [
|
||||||
}
|
"error",
|
||||||
],
|
{
|
||||||
"no-native-reassign": ["error"],
|
props: false,
|
||||||
"no-negated-condition": ["error"],
|
},
|
||||||
"no-negated-in-lhs": ["error"],
|
],
|
||||||
"no-nested-ternary": ["error"],
|
"no-self-compare": ["error"],
|
||||||
"no-new": ["error"],
|
"no-sequences": ["error"],
|
||||||
"no-new-func": ["error"],
|
"no-shadow": ["error"],
|
||||||
"no-new-object": ["error"],
|
"no-shadow-restricted-names": ["error"],
|
||||||
"no-new-require": ["error"],
|
"no-spaced-func": ["error"],
|
||||||
"no-new-symbol": ["error"],
|
"no-sparse-arrays": ["error"],
|
||||||
"no-new-wrappers": ["error"],
|
"no-sync": ["error"],
|
||||||
"no-obj-calls": ["error"],
|
"no-tabs": ["error"],
|
||||||
"no-octal": ["error"],
|
"no-template-curly-in-string": ["error"],
|
||||||
"no-octal-escape": ["error"],
|
"no-ternary": ["off"],
|
||||||
"no-param-reassign": ["error"],
|
"no-this-before-super": ["error"],
|
||||||
"no-path-concat": ["error"],
|
"no-throw-literal": ["error"],
|
||||||
"no-plusplus": [
|
"no-trailing-spaces": ["error"],
|
||||||
"error",
|
"no-undef": ["error"],
|
||||||
{
|
"no-undef-init": ["error"],
|
||||||
"allowForLoopAfterthoughts": true
|
"no-undefined": ["error"],
|
||||||
}
|
"no-underscore-dangle": ["error"],
|
||||||
],
|
"no-unexpected-multiline": ["error"],
|
||||||
"no-process-env": ["error"],
|
"no-unmodified-loop-condition": ["error"],
|
||||||
"no-process-exit": ["error"],
|
"no-unneeded-ternary": ["error"],
|
||||||
"no-proto": ["error"],
|
"no-unreachable": ["error"],
|
||||||
"no-prototype-builtins": ["error"],
|
"no-unsafe-finally": ["error"],
|
||||||
"no-redeclare": ["error"],
|
"no-unsafe-negation": ["error"],
|
||||||
"no-regex-spaces": ["error"],
|
"no-unused-expressions": ["error"],
|
||||||
"no-restricted-globals": ["error"],
|
"no-unused-labels": ["error"],
|
||||||
"no-restricted-imports": ["error"],
|
"no-unused-vars": ["error"],
|
||||||
"no-restricted-modules": ["error"],
|
"no-use-before-define": ["error"],
|
||||||
"no-restricted-properties": [
|
"no-useless-call": ["error"],
|
||||||
"error",
|
"no-useless-computed-key": ["error"],
|
||||||
{
|
"no-useless-concat": ["error"],
|
||||||
"message": "'log' is too general, use an appropriate level when logging.",
|
"no-useless-constructor": ["error"],
|
||||||
"object": "console",
|
"no-useless-escape": ["error"],
|
||||||
"property": "log"
|
"no-useless-rename": [
|
||||||
}
|
"error",
|
||||||
],
|
{
|
||||||
"no-restricted-syntax": ["error"],
|
ignoreDestructuring: false,
|
||||||
"no-return-assign": ["error"],
|
ignoreExport: false,
|
||||||
"no-return-await": ["error"],
|
ignoreImport: false,
|
||||||
"no-script-url": ["error"],
|
},
|
||||||
"no-self-assign": [
|
],
|
||||||
"error",
|
"no-useless-return": ["error"],
|
||||||
{
|
"no-var": ["error"],
|
||||||
"props": false
|
"no-void": ["error"],
|
||||||
}
|
"no-warning-comments": ["error"],
|
||||||
],
|
"no-whitespace-before-property": ["error"],
|
||||||
"no-self-compare": ["error"],
|
"no-with": ["error"],
|
||||||
"no-sequences": ["error"],
|
"nonblock-statement-body-position": ["error", "below"],
|
||||||
"no-shadow": ["error"],
|
"object-curly-newline": ["error"],
|
||||||
"no-shadow-restricted-names": ["error"],
|
"object-curly-spacing": ["error"],
|
||||||
"no-spaced-func": ["error"],
|
"object-property-newline": ["error"],
|
||||||
"no-sparse-arrays": ["error"],
|
"object-shorthand": ["error"],
|
||||||
"no-sync": ["error"],
|
"one-var": ["off"],
|
||||||
"no-tabs": ["error"],
|
"one-var-declaration-per-line": ["error"],
|
||||||
"no-template-curly-in-string": ["error"],
|
"operator-assignment": ["error"],
|
||||||
"no-ternary": ["off"],
|
"operator-linebreak": ["error", "none"],
|
||||||
"no-this-before-super": ["error"],
|
"padded-blocks": ["off"],
|
||||||
"no-throw-literal": ["error"],
|
"padding-line-between-statements": ["error"],
|
||||||
"no-trailing-spaces": ["error"],
|
"prefer-arrow-callback": ["error"],
|
||||||
"no-undef": ["error"],
|
"prefer-const": ["error"],
|
||||||
"no-undef-init": ["error"],
|
"prefer-destructuring": ["off"],
|
||||||
"no-undefined": ["error"],
|
"prefer-numeric-literals": ["error"],
|
||||||
"no-underscore-dangle": ["error"],
|
"prefer-promise-reject-errors": ["off"],
|
||||||
"no-unexpected-multiline": ["error"],
|
"prefer-reflect": ["error"],
|
||||||
"no-unmodified-loop-condition": ["error"],
|
"prefer-rest-params": ["error"],
|
||||||
"no-unneeded-ternary": ["error"],
|
"prefer-spread": ["error"],
|
||||||
"no-unreachable": ["error"],
|
"prefer-template": ["error"],
|
||||||
"no-unsafe-finally": ["error"],
|
"quote-props": ["error"],
|
||||||
"no-unsafe-negation": ["error"],
|
quotes: ["error"],
|
||||||
"no-unused-expressions": ["error"],
|
radix: ["error", "as-needed"],
|
||||||
"no-unused-labels": ["error"],
|
"require-await": ["error"],
|
||||||
"no-unused-vars": ["error"],
|
"require-jsdoc": ["off"],
|
||||||
"no-use-before-define": ["error"],
|
"require-yield": ["error"],
|
||||||
"no-useless-call": ["error"],
|
"rest-spread-spacing": ["error", "never"],
|
||||||
"no-useless-computed-key": ["error"],
|
semi: ["error"],
|
||||||
"no-useless-concat": ["error"],
|
"semi-spacing": ["error"],
|
||||||
"no-useless-constructor": ["error"],
|
"semi-style": ["error", "last"],
|
||||||
"no-useless-escape": ["error"],
|
"sort-imports": ["error"],
|
||||||
"no-useless-rename": [
|
"sort-keys": ["error"],
|
||||||
"error",
|
"sort-vars": ["error"],
|
||||||
{
|
"space-before-blocks": ["error"],
|
||||||
"ignoreDestructuring": false,
|
"space-before-function-paren": ["off"],
|
||||||
"ignoreExport": false,
|
"space-in-parens": ["error"],
|
||||||
"ignoreImport": false
|
"space-infix-ops": ["error"],
|
||||||
}
|
"space-unary-ops": ["error"],
|
||||||
],
|
"spaced-comment": ["error"],
|
||||||
"no-useless-return": ["error"],
|
strict: ["error"],
|
||||||
"no-var": ["error"],
|
"switch-colon-spacing": [
|
||||||
"no-void": ["error"],
|
"error",
|
||||||
"no-warning-comments": ["error"],
|
{
|
||||||
"no-whitespace-before-property": ["error"],
|
after: true,
|
||||||
"no-with": ["error"],
|
before: false,
|
||||||
"nonblock-statement-body-position": [
|
},
|
||||||
"error",
|
],
|
||||||
"below"
|
"symbol-description": ["error"],
|
||||||
],
|
"template-curly-spacing": ["error"],
|
||||||
"object-curly-newline": ["error"],
|
"template-tag-spacing": ["error"],
|
||||||
"object-curly-spacing": ["error"],
|
"unicode-bom": ["error", "never"],
|
||||||
"object-property-newline": ["error"],
|
"use-isnan": ["error"],
|
||||||
"object-shorthand": ["error"],
|
"valid-jsdoc": ["error"],
|
||||||
"one-var": ["off"],
|
"valid-typeof": ["error"],
|
||||||
"one-var-declaration-per-line": ["error"],
|
"vars-on-top": ["error"],
|
||||||
"operator-assignment": ["error"],
|
"wrap-iife": ["error", "any"],
|
||||||
"operator-linebreak": [
|
"wrap-regex": ["error"],
|
||||||
"error",
|
"yield-star-spacing": ["error", "before"],
|
||||||
"none"
|
yoda: ["error", "never"],
|
||||||
],
|
},
|
||||||
"padded-blocks": ["off"],
|
|
||||||
"padding-line-between-statements": ["error"],
|
|
||||||
"prefer-arrow-callback": ["error"],
|
|
||||||
"prefer-const": ["error"],
|
|
||||||
"prefer-destructuring": ["off"],
|
|
||||||
"prefer-numeric-literals": ["error"],
|
|
||||||
"prefer-promise-reject-errors": ["off"],
|
|
||||||
"prefer-reflect": ["error"],
|
|
||||||
"prefer-rest-params": ["error"],
|
|
||||||
"prefer-spread": ["error"],
|
|
||||||
"prefer-template": ["error"],
|
|
||||||
"quote-props": ["error"],
|
|
||||||
"quotes": ["error"],
|
|
||||||
"radix": [
|
|
||||||
"error",
|
|
||||||
"as-needed"
|
|
||||||
],
|
|
||||||
"require-await": ["error"],
|
|
||||||
"require-jsdoc": ["off"],
|
|
||||||
"require-yield": ["error"],
|
|
||||||
"rest-spread-spacing": [
|
|
||||||
"error",
|
|
||||||
"never"
|
|
||||||
],
|
|
||||||
"semi": ["error"],
|
|
||||||
"semi-spacing": ["error"],
|
|
||||||
"semi-style": [
|
|
||||||
"error",
|
|
||||||
"last"
|
|
||||||
],
|
|
||||||
"sort-imports": ["error"],
|
|
||||||
"sort-keys": ["error"],
|
|
||||||
"sort-vars": ["error"],
|
|
||||||
"space-before-blocks": ["error"],
|
|
||||||
"space-before-function-paren": ["off"],
|
|
||||||
"space-in-parens": ["error"],
|
|
||||||
"space-infix-ops": ["error"],
|
|
||||||
"space-unary-ops": ["error"],
|
|
||||||
"spaced-comment": ["error"],
|
|
||||||
"strict": ["error"],
|
|
||||||
"switch-colon-spacing": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"after": true,
|
|
||||||
"before": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"symbol-description": ["error"],
|
|
||||||
"template-curly-spacing": ["error"],
|
|
||||||
"template-tag-spacing": ["error"],
|
|
||||||
"unicode-bom": [
|
|
||||||
"error",
|
|
||||||
"never"
|
|
||||||
],
|
|
||||||
"use-isnan": ["error"],
|
|
||||||
"valid-jsdoc": ["error"],
|
|
||||||
"valid-typeof": ["error"],
|
|
||||||
"vars-on-top": ["error"],
|
|
||||||
"wrap-iife": [
|
|
||||||
"error",
|
|
||||||
"any"
|
|
||||||
],
|
|
||||||
"wrap-regex": ["error"],
|
|
||||||
"yield-star-spacing": [
|
|
||||||
"error",
|
|
||||||
"before"
|
|
||||||
],
|
|
||||||
"yoda": [
|
|
||||||
"error",
|
|
||||||
"never"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,66 +8,74 @@ const path = require("path");
|
|||||||
const exec = require("child_process").exec;
|
const exec = require("child_process").exec;
|
||||||
const semver = require("./semver");
|
const semver = require("./semver");
|
||||||
|
|
||||||
const getPackageJson = () => new Promise((resolve, reject) => {
|
const getPackageJson = () =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
/* eslint-disable-next-line global-require */
|
/* eslint-disable-next-line global-require */
|
||||||
resolve(require(path.resolve(process.cwd(), "package.json")));
|
resolve(require(path.resolve(process.cwd(), "package.json")));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const getEngines = (data) => new Promise((resolve, reject) => {
|
const getEngines = (data) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
let versions = null;
|
let versions = null;
|
||||||
|
|
||||||
if (data.engines) {
|
if (data.engines) {
|
||||||
versions = data.engines;
|
versions = data.engines;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (versions) {
|
if (versions) {
|
||||||
resolve(versions);
|
resolve(versions);
|
||||||
} else {
|
} else {
|
||||||
reject("Missing or improper 'engines' property in 'package.json'");
|
reject("Missing or improper 'engines' property in 'package.json'");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const checkNpmVersion = (engines) => new Promise((resolve, reject) => {
|
const checkNpmVersion = (engines) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
exec("npm -v", (error, stdout, stderr) => {
|
exec("npm -v", (error, stdout, stderr) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
reject(`Unable to find NPM version\n${stderr}`);
|
reject(`Unable to find NPM version\n${stderr}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const npmVersion = stdout.trim();
|
const npmVersion = stdout.trim();
|
||||||
const engineVersion = engines.npm || ">=0";
|
const engineVersion = engines.npm || ">=0";
|
||||||
|
|
||||||
if (semver.satisfies(npmVersion, engineVersion)) {
|
if (semver.satisfies(npmVersion, engineVersion)) {
|
||||||
resolve();
|
resolve();
|
||||||
} else {
|
} else {
|
||||||
reject(`Incorrect npm version\n'package.json' specifies "${engineVersion}", you are currently running "${npmVersion}".`);
|
reject(
|
||||||
}
|
`Incorrect npm version\n'package.json' specifies "${engineVersion}", you are currently running "${npmVersion}".`,
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const checkNodeVersion = (engines) => new Promise((resolve, reject) => {
|
const checkNodeVersion = (engines) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
const nodeVersion = process.version.substring(1);
|
const nodeVersion = process.version.substring(1);
|
||||||
|
|
||||||
if (semver.satisfies(nodeVersion, engines.node)) {
|
if (semver.satisfies(nodeVersion, engines.node)) {
|
||||||
resolve(engines);
|
resolve(engines);
|
||||||
} else {
|
} else {
|
||||||
reject(`Incorrect node version\n'package.json' specifies "${engines.node}", you are currently running "${process.version}".`);
|
reject(
|
||||||
|
`Incorrect node version\n'package.json' specifies "${engines.node}", you are currently running "${process.version}".`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
getPackageJson()
|
getPackageJson()
|
||||||
.then(getEngines)
|
.then(getEngines)
|
||||||
.then(checkNodeVersion)
|
.then(checkNodeVersion)
|
||||||
.then(checkNpmVersion)
|
.then(checkNpmVersion)
|
||||||
.then(
|
.then(
|
||||||
() => true,
|
() => true,
|
||||||
(error) => {
|
(error) => {
|
||||||
// Specifically disable these as the error message gets lost in the normal unhandled output.
|
// Specifically disable these as the error message gets lost in the normal unhandled output.
|
||||||
/* eslint-disable no-console, no-process-exit */
|
/* eslint-disable no-console, no-process-exit */
|
||||||
console.error(error);
|
console.error(error);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -735,7 +735,7 @@ function initAugmentations(): void {
|
|||||||
|
|
||||||
const ENMCore = new Augmentation({
|
const ENMCore = new Augmentation({
|
||||||
name: AugmentationNames.ENMCore,
|
name: AugmentationNames.ENMCore,
|
||||||
repCost: 175e3,
|
repCost: 2.5e5,
|
||||||
moneyCost: 2.5e9,
|
moneyCost: 2.5e9,
|
||||||
info:
|
info:
|
||||||
"The Core library is an implant that upgrades the firmware of the Embedded Netburner Module. " +
|
"The Core library is an implant that upgrades the firmware of the Embedded Netburner Module. " +
|
||||||
@@ -2366,6 +2366,145 @@ function initAugmentations(): void {
|
|||||||
resetAugmentation(BladesSimulacrum);
|
resetAugmentation(BladesSimulacrum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special CotMG Augmentations
|
||||||
|
const ChurchOfTheMachineGodFactionName = "Church of the Machine God";
|
||||||
|
if (factionExists(ChurchOfTheMachineGodFactionName)) {
|
||||||
|
const StaneksGift1 = new Augmentation({
|
||||||
|
name: AugmentationNames.StaneksGift1,
|
||||||
|
repCost: 0,
|
||||||
|
moneyCost: 0,
|
||||||
|
info:
|
||||||
|
'Allison "Mother" Stanek imparts you with her gift. An ' +
|
||||||
|
"experimental Augmentation implanted at the base of the neck. " +
|
||||||
|
"It allows you to overclock your entire system by carefully " +
|
||||||
|
"changing the configuration.",
|
||||||
|
isSpecial: true,
|
||||||
|
hacking_chance_mult: 0.9,
|
||||||
|
hacking_speed_mult: 0.9,
|
||||||
|
hacking_money_mult: 0.9,
|
||||||
|
hacking_grow_mult: 0.9,
|
||||||
|
hacking_mult: 0.9,
|
||||||
|
strength_mult: 0.9,
|
||||||
|
defense_mult: 0.9,
|
||||||
|
dexterity_mult: 0.9,
|
||||||
|
agility_mult: 0.9,
|
||||||
|
charisma_mult: 0.9,
|
||||||
|
hacking_exp_mult: 0.9,
|
||||||
|
strength_exp_mult: 0.9,
|
||||||
|
defense_exp_mult: 0.9,
|
||||||
|
dexterity_exp_mult: 0.9,
|
||||||
|
agility_exp_mult: 0.9,
|
||||||
|
charisma_exp_mult: 0.9,
|
||||||
|
company_rep_mult: 0.9,
|
||||||
|
faction_rep_mult: 0.9,
|
||||||
|
crime_money_mult: 0.9,
|
||||||
|
crime_success_mult: 0.9,
|
||||||
|
hacknet_node_money_mult: 0.9,
|
||||||
|
hacknet_node_purchase_cost_mult: 1.1,
|
||||||
|
hacknet_node_ram_cost_mult: 1.1,
|
||||||
|
hacknet_node_core_cost_mult: 1.1,
|
||||||
|
hacknet_node_level_cost_mult: 1.1,
|
||||||
|
work_money_mult: 0.9,
|
||||||
|
stats: <>Its unstable nature decreases all your stats by 10%</>,
|
||||||
|
});
|
||||||
|
StaneksGift1.addToFactions([ChurchOfTheMachineGodFactionName]);
|
||||||
|
resetAugmentation(StaneksGift1);
|
||||||
|
|
||||||
|
const StaneksGift2 = new Augmentation({
|
||||||
|
name: AugmentationNames.StaneksGift2,
|
||||||
|
repCost: 1000,
|
||||||
|
moneyCost: 0,
|
||||||
|
info:
|
||||||
|
'TODO, something about Mother being bullshit and you get more control over her "gift"<br><br>' +
|
||||||
|
"The penalty for the gift is only 5%",
|
||||||
|
prereqs: [AugmentationNames.StaneksGift1],
|
||||||
|
isSpecial: true,
|
||||||
|
hacking_chance_mult: 0.95 / 0.9,
|
||||||
|
hacking_speed_mult: 0.95 / 0.9,
|
||||||
|
hacking_money_mult: 0.95 / 0.9,
|
||||||
|
hacking_grow_mult: 0.95 / 0.9,
|
||||||
|
hacking_mult: 0.95 / 0.9,
|
||||||
|
strength_mult: 0.95 / 0.9,
|
||||||
|
defense_mult: 0.95 / 0.9,
|
||||||
|
dexterity_mult: 0.95 / 0.9,
|
||||||
|
agility_mult: 0.95 / 0.9,
|
||||||
|
charisma_mult: 0.95 / 0.9,
|
||||||
|
hacking_exp_mult: 0.95 / 0.9,
|
||||||
|
strength_exp_mult: 0.95 / 0.9,
|
||||||
|
defense_exp_mult: 0.95 / 0.9,
|
||||||
|
dexterity_exp_mult: 0.95 / 0.9,
|
||||||
|
agility_exp_mult: 0.95 / 0.9,
|
||||||
|
charisma_exp_mult: 0.95 / 0.9,
|
||||||
|
company_rep_mult: 0.95 / 0.9,
|
||||||
|
faction_rep_mult: 0.95 / 0.9,
|
||||||
|
crime_money_mult: 0.95 / 0.9,
|
||||||
|
crime_success_mult: 0.95 / 0.9,
|
||||||
|
hacknet_node_money_mult: 0.95 / 0.9,
|
||||||
|
hacknet_node_purchase_cost_mult: 1.05 / 1.1,
|
||||||
|
hacknet_node_ram_cost_mult: 1.05 / 1.1,
|
||||||
|
hacknet_node_core_cost_mult: 1.05 / 1.1,
|
||||||
|
hacknet_node_level_cost_mult: 1.05 / 1.1,
|
||||||
|
work_money_mult: 0.95 / 0.9,
|
||||||
|
stats: null,
|
||||||
|
});
|
||||||
|
StaneksGift2.addToFactions([ChurchOfTheMachineGodFactionName]);
|
||||||
|
resetAugmentation(StaneksGift2);
|
||||||
|
|
||||||
|
const StaneksGift3 = new Augmentation({
|
||||||
|
name: AugmentationNames.StaneksGift3,
|
||||||
|
repCost: 10000,
|
||||||
|
moneyCost: 0,
|
||||||
|
info:
|
||||||
|
"TODO, learn more about Allisons scheme, gain full control over the gift.<br><br>" +
|
||||||
|
"Finally freed from the penalty of the gift.",
|
||||||
|
prereqs: [AugmentationNames.StaneksGift2],
|
||||||
|
isSpecial: true,
|
||||||
|
hacking_chance_mult: 1 / 0.95,
|
||||||
|
hacking_speed_mult: 1 / 0.95,
|
||||||
|
hacking_money_mult: 1 / 0.95,
|
||||||
|
hacking_grow_mult: 1 / 0.95,
|
||||||
|
hacking_mult: 1 / 0.95,
|
||||||
|
strength_mult: 1 / 0.95,
|
||||||
|
defense_mult: 1 / 0.95,
|
||||||
|
dexterity_mult: 1 / 0.95,
|
||||||
|
agility_mult: 1 / 0.95,
|
||||||
|
charisma_mult: 1 / 0.95,
|
||||||
|
hacking_exp_mult: 1 / 0.95,
|
||||||
|
strength_exp_mult: 1 / 0.95,
|
||||||
|
defense_exp_mult: 1 / 0.95,
|
||||||
|
dexterity_exp_mult: 1 / 0.95,
|
||||||
|
agility_exp_mult: 1 / 0.95,
|
||||||
|
charisma_exp_mult: 1 / 0.95,
|
||||||
|
company_rep_mult: 1 / 0.95,
|
||||||
|
faction_rep_mult: 1 / 0.95,
|
||||||
|
crime_money_mult: 1 / 0.95,
|
||||||
|
crime_success_mult: 1 / 0.95,
|
||||||
|
hacknet_node_money_mult: 1 / 0.95,
|
||||||
|
hacknet_node_purchase_cost_mult: 1 / 1.05,
|
||||||
|
hacknet_node_ram_cost_mult: 1 / 1.05,
|
||||||
|
hacknet_node_core_cost_mult: 1 / 1.05,
|
||||||
|
hacknet_node_level_cost_mult: 1 / 1.05,
|
||||||
|
work_money_mult: 1 / 0.95,
|
||||||
|
stats: null,
|
||||||
|
});
|
||||||
|
StaneksGift3.addToFactions([ChurchOfTheMachineGodFactionName]);
|
||||||
|
resetAugmentation(StaneksGift3);
|
||||||
|
|
||||||
|
const StaneksGiftAscension4 = new Augmentation({
|
||||||
|
name: AugmentationNames.StaneksGift4,
|
||||||
|
repCost: 500000000,
|
||||||
|
moneyCost: 0,
|
||||||
|
info:
|
||||||
|
"Allow Allison to install an Ascension port in her Gift. Allowing you to connect with the Machine God.<br><br>" +
|
||||||
|
"(hydro notes: Finishes the BN, eventually)",
|
||||||
|
prereqs: [AugmentationNames.StaneksGift3],
|
||||||
|
isSpecial: true,
|
||||||
|
stats: null,
|
||||||
|
});
|
||||||
|
StaneksGiftAscension4.addToFactions([ChurchOfTheMachineGodFactionName]);
|
||||||
|
resetAugmentation(StaneksGiftAscension4);
|
||||||
|
}
|
||||||
|
|
||||||
// Update costs based on how many have been purchased
|
// Update costs based on how many have been purchased
|
||||||
mult = Math.pow(
|
mult = Math.pow(
|
||||||
CONSTANTS.MultipleAugMultiplier * [1, 0.96, 0.94, 0.93][SourceFileFlags[11]],
|
CONSTANTS.MultipleAugMultiplier * [1, 0.96, 0.94, 0.93][SourceFileFlags[11]],
|
||||||
|
|||||||
@@ -108,6 +108,10 @@ export const AugmentationNames: {
|
|||||||
BladeArmorOmnibeam: string;
|
BladeArmorOmnibeam: string;
|
||||||
BladeArmorIPU: string;
|
BladeArmorIPU: string;
|
||||||
BladesSimulacrum: string;
|
BladesSimulacrum: string;
|
||||||
|
StaneksGift1: string;
|
||||||
|
StaneksGift2: string;
|
||||||
|
StaneksGift3: string;
|
||||||
|
StaneksGift4: string;
|
||||||
} = {
|
} = {
|
||||||
Targeting1: "Augmented Targeting I",
|
Targeting1: "Augmented Targeting I",
|
||||||
Targeting2: "Augmented Targeting II",
|
Targeting2: "Augmented Targeting II",
|
||||||
@@ -219,6 +223,11 @@ export const AugmentationNames: {
|
|||||||
BladeArmorIPU: "BLADE-51b Tesla Armor: IPU Upgrade",
|
BladeArmorIPU: "BLADE-51b Tesla Armor: IPU Upgrade",
|
||||||
BladesSimulacrum: "The Blade's Simulacrum",
|
BladesSimulacrum: "The Blade's Simulacrum",
|
||||||
|
|
||||||
|
StaneksGift1: "Stanek's Gift - Genesis",
|
||||||
|
StaneksGift2: "Stanek's Gift - Awakening",
|
||||||
|
StaneksGift3: "Stanek's Gift - Serenity",
|
||||||
|
StaneksGift4: "Stanek's Gift - Ascension",
|
||||||
|
|
||||||
//Wasteland Augs
|
//Wasteland Augs
|
||||||
//PepBoy: "P.E.P-Boy", Plasma Energy Projection System
|
//PepBoy: "P.E.P-Boy", Plasma Energy Projection System
|
||||||
//PepBoyForceField Generates plasma force fields
|
//PepBoyForceField Generates plasma force fields
|
||||||
|
|||||||
@@ -530,8 +530,38 @@ BitNodes["BitNode12"] = new BitNode(
|
|||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
BitNodes["BitNode13"] = new BitNode(
|
||||||
|
13,
|
||||||
|
2,
|
||||||
|
"They're lunatics",
|
||||||
|
"1 step back, 2 steps forward",
|
||||||
|
(
|
||||||
|
<>
|
||||||
|
With the invention of Augmentations in the 2040s a religious group known as the Church of the Machine God has
|
||||||
|
rallied far more support than anyone would have hoped.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Their leader, Allison "Mother" Stanek is said to have created her own Augmentation whose power goes beyond any
|
||||||
|
other. Find her in Chongquing and gain her trust.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
In this BitNode:
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Every is significantly reduced
|
||||||
|
<br />
|
||||||
|
Stanek's Gift power is significantly increased.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Destroying this BitNode will give you Source-File 13, or if you already have this Source-File it will upgrade its
|
||||||
|
level up to a maximum of 3. This Source-File lets the Church of the Machine God appear in other BitNodes.
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
Each level of this Source-File increases the size of Stanek's Gift.
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
);
|
||||||
// Books: Frontera, Shiner
|
// Books: Frontera, Shiner
|
||||||
BitNodes["BitNode13"] = new BitNode(13, 2, "fOS", "COMING SOON"); //Unlocks the new game mode and the rest of the BitNodes
|
|
||||||
BitNodes["BitNode14"] = new BitNode(14, 2, "", "COMING SOON");
|
BitNodes["BitNode14"] = new BitNode(14, 2, "", "COMING SOON");
|
||||||
BitNodes["BitNode15"] = new BitNode(15, 2, "", "COMING SOON");
|
BitNodes["BitNode15"] = new BitNode(15, 2, "", "COMING SOON");
|
||||||
BitNodes["BitNode16"] = new BitNode(16, 2, "", "COMING SOON");
|
BitNodes["BitNode16"] = new BitNode(16, 2, "", "COMING SOON");
|
||||||
@@ -553,6 +583,8 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
|||||||
BitNodeMultipliers[mult] = 1;
|
BitNodeMultipliers[mult] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Special case.
|
||||||
|
BitNodeMultipliers.StaneksGiftExtraSize = 0;
|
||||||
|
|
||||||
switch (p.bitNodeN) {
|
switch (p.bitNodeN) {
|
||||||
case 1: // Source Genesis (every multiplier is 1)
|
case 1: // Source Genesis (every multiplier is 1)
|
||||||
@@ -567,7 +599,6 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
|||||||
BitNodeMultipliers.FactionWorkRepGain = 0.5;
|
BitNodeMultipliers.FactionWorkRepGain = 0.5;
|
||||||
BitNodeMultipliers.FactionPassiveRepGain = 0;
|
BitNodeMultipliers.FactionPassiveRepGain = 0;
|
||||||
BitNodeMultipliers.GangKarmaRequirement = 0;
|
BitNodeMultipliers.GangKarmaRequirement = 0;
|
||||||
BitNodeMultipliers.PurchasedServerSoftcap = 1.4;
|
|
||||||
break;
|
break;
|
||||||
case 3: // Corporatocracy
|
case 3: // Corporatocracy
|
||||||
BitNodeMultipliers.HackingLevelMultiplier = 0.8;
|
BitNodeMultipliers.HackingLevelMultiplier = 0.8;
|
||||||
@@ -584,7 +615,6 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
|||||||
BitNodeMultipliers.HomeComputerRamCost = 1.5;
|
BitNodeMultipliers.HomeComputerRamCost = 1.5;
|
||||||
BitNodeMultipliers.PurchasedServerCost = 2;
|
BitNodeMultipliers.PurchasedServerCost = 2;
|
||||||
BitNodeMultipliers.GangKarmaRequirement = 3;
|
BitNodeMultipliers.GangKarmaRequirement = 3;
|
||||||
BitNodeMultipliers.PurchasedServerSoftcap = 1.4;
|
|
||||||
break;
|
break;
|
||||||
case 4: // The Singularity
|
case 4: // The Singularity
|
||||||
BitNodeMultipliers.ServerMaxMoney = 0.15;
|
BitNodeMultipliers.ServerMaxMoney = 0.15;
|
||||||
@@ -599,7 +629,6 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
|||||||
BitNodeMultipliers.HackExpGain = 0.4;
|
BitNodeMultipliers.HackExpGain = 0.4;
|
||||||
BitNodeMultipliers.CrimeExpGain = 0.5;
|
BitNodeMultipliers.CrimeExpGain = 0.5;
|
||||||
BitNodeMultipliers.FactionWorkRepGain = 0.75;
|
BitNodeMultipliers.FactionWorkRepGain = 0.75;
|
||||||
BitNodeMultipliers.PurchasedServerSoftcap = 1.3;
|
|
||||||
break;
|
break;
|
||||||
case 5: // Artificial intelligence
|
case 5: // Artificial intelligence
|
||||||
BitNodeMultipliers.ServerMaxMoney = 2;
|
BitNodeMultipliers.ServerMaxMoney = 2;
|
||||||
@@ -613,7 +642,6 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
|||||||
BitNodeMultipliers.AugmentationMoneyCost = 2;
|
BitNodeMultipliers.AugmentationMoneyCost = 2;
|
||||||
BitNodeMultipliers.HackExpGain = 0.5;
|
BitNodeMultipliers.HackExpGain = 0.5;
|
||||||
BitNodeMultipliers.CorporationValuation = 0.5;
|
BitNodeMultipliers.CorporationValuation = 0.5;
|
||||||
BitNodeMultipliers.PurchasedServerSoftcap = 1.3;
|
|
||||||
break;
|
break;
|
||||||
case 6: // Bladeburner
|
case 6: // Bladeburner
|
||||||
BitNodeMultipliers.HackingLevelMultiplier = 0.35;
|
BitNodeMultipliers.HackingLevelMultiplier = 0.35;
|
||||||
@@ -630,7 +658,6 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
|||||||
BitNodeMultipliers.HackExpGain = 0.25;
|
BitNodeMultipliers.HackExpGain = 0.25;
|
||||||
BitNodeMultipliers.DaedalusAugsRequirement = 1.166; // Results in 35 Augs needed
|
BitNodeMultipliers.DaedalusAugsRequirement = 1.166; // Results in 35 Augs needed
|
||||||
BitNodeMultipliers.GangKarmaRequirement = 5;
|
BitNodeMultipliers.GangKarmaRequirement = 5;
|
||||||
BitNodeMultipliers.PurchasedServerSoftcap = 2;
|
|
||||||
break;
|
break;
|
||||||
case 7: // Bladeburner 2079
|
case 7: // Bladeburner 2079
|
||||||
BitNodeMultipliers.BladeburnerRank = 0.6;
|
BitNodeMultipliers.BladeburnerRank = 0.6;
|
||||||
@@ -652,7 +679,6 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
|||||||
BitNodeMultipliers.FourSigmaMarketDataApiCost = 2;
|
BitNodeMultipliers.FourSigmaMarketDataApiCost = 2;
|
||||||
BitNodeMultipliers.DaedalusAugsRequirement = 1.166; // Results in 35 Augs needed
|
BitNodeMultipliers.DaedalusAugsRequirement = 1.166; // Results in 35 Augs needed
|
||||||
BitNodeMultipliers.GangKarmaRequirement = 5;
|
BitNodeMultipliers.GangKarmaRequirement = 5;
|
||||||
BitNodeMultipliers.PurchasedServerSoftcap = 2;
|
|
||||||
break;
|
break;
|
||||||
case 8: // Ghost of Wall Street
|
case 8: // Ghost of Wall Street
|
||||||
BitNodeMultipliers.ScriptHackMoney = 0.3;
|
BitNodeMultipliers.ScriptHackMoney = 0.3;
|
||||||
@@ -666,7 +692,6 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
|||||||
BitNodeMultipliers.CorporationValuation = 0;
|
BitNodeMultipliers.CorporationValuation = 0;
|
||||||
BitNodeMultipliers.CodingContractMoney = 0;
|
BitNodeMultipliers.CodingContractMoney = 0;
|
||||||
BitNodeMultipliers.GangKarmaRequirement = 10;
|
BitNodeMultipliers.GangKarmaRequirement = 10;
|
||||||
BitNodeMultipliers.PurchasedServerSoftcap = 5;
|
|
||||||
break;
|
break;
|
||||||
case 9: // Hacktocracy
|
case 9: // Hacktocracy
|
||||||
BitNodeMultipliers.HackingLevelMultiplier = 0.4;
|
BitNodeMultipliers.HackingLevelMultiplier = 0.4;
|
||||||
@@ -713,7 +738,6 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
|||||||
BitNodeMultipliers.PurchasedServerMaxRam = 0.5;
|
BitNodeMultipliers.PurchasedServerMaxRam = 0.5;
|
||||||
BitNodeMultipliers.BladeburnerRank = 0.8;
|
BitNodeMultipliers.BladeburnerRank = 0.8;
|
||||||
BitNodeMultipliers.GangKarmaRequirement = 3;
|
BitNodeMultipliers.GangKarmaRequirement = 3;
|
||||||
BitNodeMultipliers.PurchasedServerSoftcap = 1.2;
|
|
||||||
break;
|
break;
|
||||||
case 11: //The Big Crash
|
case 11: //The Big Crash
|
||||||
BitNodeMultipliers.HackingLevelMultiplier = 0.5;
|
BitNodeMultipliers.HackingLevelMultiplier = 0.5;
|
||||||
@@ -732,7 +756,6 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
|||||||
BitNodeMultipliers.CodingContractMoney = 0.25;
|
BitNodeMultipliers.CodingContractMoney = 0.25;
|
||||||
BitNodeMultipliers.FourSigmaMarketDataCost = 4;
|
BitNodeMultipliers.FourSigmaMarketDataCost = 4;
|
||||||
BitNodeMultipliers.FourSigmaMarketDataApiCost = 4;
|
BitNodeMultipliers.FourSigmaMarketDataApiCost = 4;
|
||||||
BitNodeMultipliers.PurchasedServerSoftcap = 2.2;
|
|
||||||
break;
|
break;
|
||||||
case 12: {
|
case 12: {
|
||||||
//The Recursion
|
//The Recursion
|
||||||
@@ -769,7 +792,6 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
|||||||
BitNodeMultipliers.PurchasedServerCost = inc;
|
BitNodeMultipliers.PurchasedServerCost = inc;
|
||||||
BitNodeMultipliers.PurchasedServerLimit = dec;
|
BitNodeMultipliers.PurchasedServerLimit = dec;
|
||||||
BitNodeMultipliers.PurchasedServerMaxRam = dec;
|
BitNodeMultipliers.PurchasedServerMaxRam = dec;
|
||||||
BitNodeMultipliers.PurchasedServerSoftcap = inc;
|
|
||||||
|
|
||||||
BitNodeMultipliers.ManualHackMoney = dec;
|
BitNodeMultipliers.ManualHackMoney = dec;
|
||||||
BitNodeMultipliers.ScriptHackMoney = dec;
|
BitNodeMultipliers.ScriptHackMoney = dec;
|
||||||
@@ -803,6 +825,47 @@ export function initBitNodeMultipliers(p: IPlayer): void {
|
|||||||
BitNodeMultipliers.BladeburnerSkillCost = inc;
|
BitNodeMultipliers.BladeburnerSkillCost = inc;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 13: {
|
||||||
|
BitNodeMultipliers.DaedalusAugsRequirement = 100;
|
||||||
|
|
||||||
|
BitNodeMultipliers.HackingLevelMultiplier = 0.2;
|
||||||
|
BitNodeMultipliers.StrengthLevelMultiplier = 0.2;
|
||||||
|
BitNodeMultipliers.DefenseLevelMultiplier = 0.2;
|
||||||
|
BitNodeMultipliers.DexterityLevelMultiplier = 0.2;
|
||||||
|
BitNodeMultipliers.AgilityLevelMultiplier = 0.2;
|
||||||
|
BitNodeMultipliers.CharismaLevelMultiplier = 0.2;
|
||||||
|
|
||||||
|
BitNodeMultipliers.ServerMaxMoney = 0.15;
|
||||||
|
BitNodeMultipliers.ServerStartingMoney = 0.75;
|
||||||
|
|
||||||
|
BitNodeMultipliers.ServerStartingSecurity = 2;
|
||||||
|
|
||||||
|
BitNodeMultipliers.ScriptHackMoney = 0.2;
|
||||||
|
BitNodeMultipliers.CompanyWorkMoney = 0.2;
|
||||||
|
BitNodeMultipliers.CrimeMoney = 0.2;
|
||||||
|
BitNodeMultipliers.HacknetNodeMoney = 0.2;
|
||||||
|
BitNodeMultipliers.CodingContractMoney = 0.2;
|
||||||
|
|
||||||
|
BitNodeMultipliers.CompanyWorkExpGain = 0.1;
|
||||||
|
BitNodeMultipliers.ClassGymExpGain = 0.1;
|
||||||
|
BitNodeMultipliers.FactionWorkExpGain = 0.1;
|
||||||
|
BitNodeMultipliers.HackExpGain = 0.1;
|
||||||
|
BitNodeMultipliers.CrimeExpGain = 0.1;
|
||||||
|
|
||||||
|
BitNodeMultipliers.FactionWorkRepGain = 0.4;
|
||||||
|
|
||||||
|
BitNodeMultipliers.FourSigmaMarketDataCost = 10;
|
||||||
|
BitNodeMultipliers.FourSigmaMarketDataApiCost = 10;
|
||||||
|
|
||||||
|
BitNodeMultipliers.CorporationValuation = 0.001;
|
||||||
|
|
||||||
|
BitNodeMultipliers.BladeburnerRank = 0.1;
|
||||||
|
BitNodeMultipliers.BladeburnerSkillCost = 5;
|
||||||
|
BitNodeMultipliers.GangKarmaRequirement = 20;
|
||||||
|
BitNodeMultipliers.StaneksGiftPowerMultiplier = 2;
|
||||||
|
BitNodeMultipliers.StaneksGiftExtraSize = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
console.warn("Player.bitNodeN invalid");
|
console.warn("Player.bitNodeN invalid");
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -156,11 +156,6 @@ interface IBitNodeMultipliers {
|
|||||||
*/
|
*/
|
||||||
PurchasedServerCost: number;
|
PurchasedServerCost: number;
|
||||||
|
|
||||||
/**
|
|
||||||
* Influence how much it costs to purchase a server
|
|
||||||
*/
|
|
||||||
PurchasedServerSoftcap: number;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Influences the maximum number of purchased servers you can have
|
* Influences the maximum number of purchased servers you can have
|
||||||
*/
|
*/
|
||||||
@@ -217,6 +212,16 @@ interface IBitNodeMultipliers {
|
|||||||
*/
|
*/
|
||||||
StrengthLevelMultiplier: number;
|
StrengthLevelMultiplier: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Influences the power of the gift.
|
||||||
|
*/
|
||||||
|
StaneksGiftPowerMultiplier: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Influences the size of the gift.
|
||||||
|
*/
|
||||||
|
StaneksGiftExtraSize: number;
|
||||||
|
|
||||||
// Index signature
|
// Index signature
|
||||||
[key: string]: number;
|
[key: string]: number;
|
||||||
}
|
}
|
||||||
@@ -242,7 +247,6 @@ export const BitNodeMultipliers: IBitNodeMultipliers = {
|
|||||||
HomeComputerRamCost: 1,
|
HomeComputerRamCost: 1,
|
||||||
|
|
||||||
PurchasedServerCost: 1,
|
PurchasedServerCost: 1,
|
||||||
PurchasedServerSoftcap: 1,
|
|
||||||
PurchasedServerLimit: 1,
|
PurchasedServerLimit: 1,
|
||||||
PurchasedServerMaxRam: 1,
|
PurchasedServerMaxRam: 1,
|
||||||
|
|
||||||
@@ -280,4 +284,7 @@ export const BitNodeMultipliers: IBitNodeMultipliers = {
|
|||||||
|
|
||||||
DaedalusAugsRequirement: 1,
|
DaedalusAugsRequirement: 1,
|
||||||
GangKarmaRequirement: 1,
|
GangKarmaRequirement: 1,
|
||||||
|
|
||||||
|
StaneksGiftPowerMultiplier: 1,
|
||||||
|
StaneksGiftExtraSize: 0,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ export function BitverseRoot(props: IProps): React.ReactElement {
|
|||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>O | | | \| | O / _/ | / O | |/ | | | O</Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>O | | | \| | O / _/ | / O | |/ | | | O</Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>| | | |O / | | O / | O O | | \ O| | | |</Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>| | | |O / | | O / | O O | | \ O| | | |</Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>| | |/ \/ / __| | |/ \ | \ | |__ \ \/ \| | |</Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>| | |/ \/ / __| | |/ \ | \ | |__ \ \/ \| | |</Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| O | |_/ |\| \ O \__| \_| | O |/ </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| O | |_/ |\| \ <BitNodePortal n={13} level={nextSourceFileFlags[13]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> \__| \_| | O |/ </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | | |_/ | | \| / | \_| | | </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | | |_/ | | \| / | \_| | | </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| / \| | / / \ |/ </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \| / \| | / / \ |/ </Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | <BitNodePortal n={10} level={nextSourceFileFlags[10]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | | / | <BitNodePortal n={11} level={nextSourceFileFlags[11]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | </Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | <BitNodePortal n={10} level={nextSourceFileFlags[10]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | | / | <BitNodePortal n={11} level={nextSourceFileFlags[11]} enter={enter} flume={props.flume} destroyedBitNode={destroyed} /> | </Typography>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { Skill } from "./Skill";
|
|||||||
import { City } from "./City";
|
import { City } from "./City";
|
||||||
import { IAction } from "./IAction";
|
import { IAction } from "./IAction";
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { IRouter, Page } from "../ui/Router";
|
import { IRouter } from "../ui/Router";
|
||||||
import { ConsoleHelpText } from "./data/Help";
|
import { ConsoleHelpText } from "./data/Help";
|
||||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||||
@@ -26,6 +26,7 @@ import { addOffset } from "../utils/helpers/addOffset";
|
|||||||
import { Faction } from "../Faction/Faction";
|
import { Faction } from "../Faction/Faction";
|
||||||
import { Factions, factionExists } from "../Faction/Factions";
|
import { Factions, factionExists } from "../Faction/Factions";
|
||||||
import { calculateHospitalizationCost } from "../Hospital/Hospital";
|
import { calculateHospitalizationCost } from "../Hospital/Hospital";
|
||||||
|
import { redPillFlag } from "../RedPill";
|
||||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||||
import { Settings } from "../Settings/Settings";
|
import { Settings } from "../Settings/Settings";
|
||||||
import { Augmentations } from "../Augmentation/Augmentations";
|
import { Augmentations } from "../Augmentation/Augmentations";
|
||||||
@@ -131,7 +132,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
return this.resetAction();
|
return this.resetAction();
|
||||||
}
|
}
|
||||||
this.actionTimeToComplete = action.getActionTime(this);
|
this.actionTimeToComplete = action.getActionTime(this);
|
||||||
} catch (e: any) {
|
} catch (e) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -144,11 +145,11 @@ export class Bladeburner implements IBladeburner {
|
|||||||
if (action.count < 1) {
|
if (action.count < 1) {
|
||||||
return this.resetAction();
|
return this.resetAction();
|
||||||
}
|
}
|
||||||
if (actionId.name === "Raid" && this.getCurrentCity().comms === 0) {
|
if (actionId.name === "Raid" && this.getCurrentCity().commsEst === 0) {
|
||||||
return this.resetAction();
|
return this.resetAction();
|
||||||
}
|
}
|
||||||
this.actionTimeToComplete = action.getActionTime(this);
|
this.actionTimeToComplete = action.getActionTime(this);
|
||||||
} catch (e: any) {
|
} catch (e) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -168,7 +169,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
throw new Error("Failed to get BlackOperation object for: " + actionId.name);
|
throw new Error("Failed to get BlackOperation object for: " + actionId.name);
|
||||||
}
|
}
|
||||||
this.actionTimeToComplete = action.getActionTime(this);
|
this.actionTimeToComplete = action.getActionTime(this);
|
||||||
} catch (e: any) {
|
} catch (e) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -183,7 +184,6 @@ export class Bladeburner implements IBladeburner {
|
|||||||
break;
|
break;
|
||||||
case ActionTypes["Diplomacy"]:
|
case ActionTypes["Diplomacy"]:
|
||||||
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
||||||
case ActionTypes["Incite Violence"]:
|
|
||||||
this.actionTimeToComplete = 60;
|
this.actionTimeToComplete = 60;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -220,7 +220,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
for (let i = 0; i < arrayOfCommands.length; ++i) {
|
for (let i = 0; i < arrayOfCommands.length; ++i) {
|
||||||
this.executeConsoleCommand(player, arrayOfCommands[i]);
|
this.executeConsoleCommand(player, arrayOfCommands[i]);
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -339,10 +339,6 @@ export class Bladeburner implements IBladeburner {
|
|||||||
action.type = ActionTypes["Hyperbolic Regeneration Chamber"];
|
action.type = ActionTypes["Hyperbolic Regeneration Chamber"];
|
||||||
action.name = "Hyperbolic Regeneration Chamber";
|
action.name = "Hyperbolic Regeneration Chamber";
|
||||||
break;
|
break;
|
||||||
case "incite violence":
|
|
||||||
action.type = ActionTypes["Incite Violence"];
|
|
||||||
action.name = "Incite Violence";
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1092,6 +1088,9 @@ export class Bladeburner implements IBladeburner {
|
|||||||
case "Investigation":
|
case "Investigation":
|
||||||
if (success) {
|
if (success) {
|
||||||
city.improvePopulationEstimateByPercentage(0.4 * this.skillMultipliers.successChanceEstimate);
|
city.improvePopulationEstimateByPercentage(0.4 * this.skillMultipliers.successChanceEstimate);
|
||||||
|
if (Math.random() < 0.02 * this.skillMultipliers.successChanceEstimate) {
|
||||||
|
city.improveCommunityEstimate(1);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.triggerPotentialMigration(this.city, 0.1);
|
this.triggerPotentialMigration(this.city, 0.1);
|
||||||
}
|
}
|
||||||
@@ -1099,6 +1098,9 @@ export class Bladeburner implements IBladeburner {
|
|||||||
case "Undercover Operation":
|
case "Undercover Operation":
|
||||||
if (success) {
|
if (success) {
|
||||||
city.improvePopulationEstimateByPercentage(0.8 * this.skillMultipliers.successChanceEstimate);
|
city.improvePopulationEstimateByPercentage(0.8 * this.skillMultipliers.successChanceEstimate);
|
||||||
|
if (Math.random() < 0.02 * this.skillMultipliers.successChanceEstimate) {
|
||||||
|
city.improveCommunityEstimate(1);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.triggerPotentialMigration(this.city, 0.15);
|
this.triggerPotentialMigration(this.city, 0.15);
|
||||||
}
|
}
|
||||||
@@ -1119,6 +1121,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
nonZero: true,
|
nonZero: true,
|
||||||
});
|
});
|
||||||
--city.comms;
|
--city.comms;
|
||||||
|
--city.commsEst;
|
||||||
} else {
|
} else {
|
||||||
const change = getRandomInt(-10, -5) / 10;
|
const change = getRandomInt(-10, -5) / 10;
|
||||||
city.changePopulationByPercentage(change, {
|
city.changePopulationByPercentage(change, {
|
||||||
@@ -1171,8 +1174,6 @@ export class Bladeburner implements IBladeburner {
|
|||||||
return GeneralActions["Diplomacy"];
|
return GeneralActions["Diplomacy"];
|
||||||
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
||||||
return GeneralActions["Hyperbolic Regeneration Chamber"];
|
return GeneralActions["Hyperbolic Regeneration Chamber"];
|
||||||
case ActionTypes["Incite Violence"]:
|
|
||||||
return GeneralActions["Incite Violence"];
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1297,7 +1298,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
action.level = action.maxLevel;
|
action.level = action.maxLevel;
|
||||||
} // Autolevel
|
} // Autolevel
|
||||||
this.startAction(player, this.action); // Repeat action
|
this.startAction(player, this.action); // Repeat action
|
||||||
} catch (e: any) {
|
} catch (e) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1386,7 +1387,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
this.log("You lost " + formatNumber(losses, 0) + " team members during " + action.name);
|
this.log("You lost " + formatNumber(losses, 0) + " team members during " + action.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1499,25 +1500,6 @@ export class Bladeburner implements IBladeburner {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ActionTypes["Incite Violence"]: {
|
|
||||||
for (const contract of Object.keys(this.contracts)) {
|
|
||||||
const growthF = Growths[contract];
|
|
||||||
if (!growthF) throw new Error("trying to generate count for action that doesn't exist? " + contract);
|
|
||||||
this.contracts[contract].count += (60 * 6 * growthF()) / BladeburnerConstants.ActionCountGrowthPeriod;
|
|
||||||
}
|
|
||||||
for (const operation of Object.keys(this.operations)) {
|
|
||||||
const growthF = Growths[operation];
|
|
||||||
if (!growthF) throw new Error("trying to generate count for action that doesn't exist? " + operation);
|
|
||||||
this.operations[operation].count += (60 * 6 * growthF()) / BladeburnerConstants.ActionCountGrowthPeriod;
|
|
||||||
}
|
|
||||||
if (this.logging.general) {
|
|
||||||
this.log(`Incited violence in the synthoid communities.`);
|
|
||||||
}
|
|
||||||
const city = this.cities[this.city];
|
|
||||||
city.chaos *= (city.chaos + 100) * 2;
|
|
||||||
this.startAction(player, this.action);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
console.error(`Bladeburner.completeAction() called for invalid action: ${this.action.type}`);
|
console.error(`Bladeburner.completeAction() called for invalid action: ${this.action.type}`);
|
||||||
break;
|
break;
|
||||||
@@ -1872,7 +1854,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
|
|
||||||
process(router: IRouter, player: IPlayer): void {
|
process(router: IRouter, player: IPlayer): void {
|
||||||
// Edge case condition...if Operation Daedalus is complete trigger the BitNode
|
// Edge case condition...if Operation Daedalus is complete trigger the BitNode
|
||||||
if (router.page() !== Page.BitVerse && this.blackops.hasOwnProperty("Operation Daedalus")) {
|
if (redPillFlag === false && this.blackops.hasOwnProperty("Operation Daedalus")) {
|
||||||
return router.toBitVerse(false, false);
|
return router.toBitVerse(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1985,7 +1967,6 @@ export class Bladeburner implements IBladeburner {
|
|||||||
"Field Analysis",
|
"Field Analysis",
|
||||||
"Diplomacy",
|
"Diplomacy",
|
||||||
"Hyperbolic Regeneration Chamber",
|
"Hyperbolic Regeneration Chamber",
|
||||||
"Incite Violence",
|
|
||||||
];
|
];
|
||||||
if (gen.includes(res.type)) {
|
if (gen.includes(res.type)) {
|
||||||
res.type = "General";
|
res.type = "General";
|
||||||
@@ -2075,7 +2056,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
this.startAction(player, actionId);
|
this.startAction(player, actionId);
|
||||||
workerScript.log("bladeburner.startAction", `Starting bladeburner action with type '${type}' and name ${name}"`);
|
workerScript.log("bladeburner.startAction", `Starting bladeburner action with type '${type}' and name ${name}"`);
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e) {
|
||||||
this.resetAction();
|
this.resetAction();
|
||||||
workerScript.log("bladeburner.startAction", errorLogText);
|
workerScript.log("bladeburner.startAction", errorLogText);
|
||||||
return false;
|
return false;
|
||||||
@@ -2110,7 +2091,6 @@ export class Bladeburner implements IBladeburner {
|
|||||||
return this.getRecruitmentTime(player);
|
return this.getRecruitmentTime(player);
|
||||||
case ActionTypes["Diplomacy"]:
|
case ActionTypes["Diplomacy"]:
|
||||||
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
||||||
case ActionTypes["Incite Violence"]:
|
|
||||||
return 60;
|
return 60;
|
||||||
default:
|
default:
|
||||||
workerScript.log("bladeburner.getActionTime", errorLogText);
|
workerScript.log("bladeburner.getActionTime", errorLogText);
|
||||||
@@ -2148,7 +2128,6 @@ export class Bladeburner implements IBladeburner {
|
|||||||
case ActionTypes["FieldAnalysis"]:
|
case ActionTypes["FieldAnalysis"]:
|
||||||
case ActionTypes["Diplomacy"]:
|
case ActionTypes["Diplomacy"]:
|
||||||
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
||||||
case ActionTypes["Incite Violence"]:
|
|
||||||
return [1, 1];
|
return [1, 1];
|
||||||
case ActionTypes["Recruitment"]: {
|
case ActionTypes["Recruitment"]: {
|
||||||
const recChance = this.getRecruitmentSuccessChance(player);
|
const recChance = this.getRecruitmentSuccessChance(player);
|
||||||
@@ -2191,7 +2170,6 @@ export class Bladeburner implements IBladeburner {
|
|||||||
case ActionTypes["FieldAnalysis"]:
|
case ActionTypes["FieldAnalysis"]:
|
||||||
case ActionTypes["Diplomacy"]:
|
case ActionTypes["Diplomacy"]:
|
||||||
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
||||||
case ActionTypes["Incite Violence"]:
|
|
||||||
return Infinity;
|
return Infinity;
|
||||||
default:
|
default:
|
||||||
workerScript.log("bladeburner.getActionCountRemaining", errorLogText);
|
workerScript.log("bladeburner.getActionCountRemaining", errorLogText);
|
||||||
|
|||||||
@@ -34,6 +34,11 @@ export class City {
|
|||||||
*/
|
*/
|
||||||
comms = 0;
|
comms = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Estimated number of communities in the city.
|
||||||
|
*/
|
||||||
|
commsEst = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Chaos level of the city.
|
* Chaos level of the city.
|
||||||
*/
|
*/
|
||||||
@@ -48,6 +53,8 @@ export class City {
|
|||||||
|
|
||||||
// Number of Synthoid communities population and estimate
|
// Number of Synthoid communities population and estimate
|
||||||
this.comms = getRandomInt(5, 150);
|
this.comms = getRandomInt(5, 150);
|
||||||
|
this.commsEst = this.comms + getRandomInt(-5, 5);
|
||||||
|
if (this.commsEst < 0) this.commsEst = 0;
|
||||||
this.chaos = 0;
|
this.chaos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,6 +113,23 @@ export class City {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
improveCommunityEstimate(n = 1): void {
|
||||||
|
if (isNaN(n)) {
|
||||||
|
throw new Error("NaN passed into City.improveCommunityEstimate()");
|
||||||
|
}
|
||||||
|
if (this.commsEst < this.comms) {
|
||||||
|
this.commsEst += n;
|
||||||
|
if (this.commsEst > this.comms) {
|
||||||
|
this.commsEst = this.comms;
|
||||||
|
}
|
||||||
|
} else if (this.commsEst > this.comms) {
|
||||||
|
this.commsEst -= n;
|
||||||
|
if (this.commsEst < this.comms) {
|
||||||
|
this.commsEst = this.comms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @params options:
|
* @params options:
|
||||||
* estChange(int): How much the estimate should change by
|
* estChange(int): How much the estimate should change by
|
||||||
|
|||||||
@@ -30,8 +30,4 @@ export const GeneralActions: IMap<Action> = {};
|
|||||||
GeneralActions[actionName] = new Action({
|
GeneralActions[actionName] = new Action({
|
||||||
name: actionName,
|
name: actionName,
|
||||||
});
|
});
|
||||||
actionName = "Incite Violence";
|
|
||||||
GeneralActions[actionName] = new Action({
|
|
||||||
name: actionName,
|
|
||||||
});
|
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { IBladeburner } from "./IBladeburner";
|
import { IBladeburner } from "./IBladeburner";
|
||||||
|
|
||||||
interface IStatsMultiplier {
|
export interface IStatsMultiplier {
|
||||||
[key: string]: number;
|
[key: string]: number;
|
||||||
|
|
||||||
hack: number;
|
hack: number;
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ export const ActionTypes: {
|
|||||||
"Field Analysis": number;
|
"Field Analysis": number;
|
||||||
Diplomacy: number;
|
Diplomacy: number;
|
||||||
"Hyperbolic Regeneration Chamber": number;
|
"Hyperbolic Regeneration Chamber": number;
|
||||||
"Incite Violence": number;
|
|
||||||
} = {
|
} = {
|
||||||
Idle: 1,
|
Idle: 1,
|
||||||
Contract: 2,
|
Contract: 2,
|
||||||
@@ -25,5 +24,4 @@ export const ActionTypes: {
|
|||||||
"Field Analysis": 7,
|
"Field Analysis": 7,
|
||||||
Diplomacy: 8,
|
Diplomacy: 8,
|
||||||
"Hyperbolic Regeneration Chamber": 9,
|
"Hyperbolic Regeneration Chamber": 9,
|
||||||
"Incite Violence": 10,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -62,7 +62,4 @@ export const GeneralActions: {
|
|||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
"Incite Violence": {
|
|
||||||
desc: <>Purposefully stir trouble in the synthoid community in order to gain a political edge.</>,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ export const Growths: {
|
|||||||
["Stealth Retirement Operation"]: () => number;
|
["Stealth Retirement Operation"]: () => number;
|
||||||
["Assassination"]: () => number;
|
["Assassination"]: () => number;
|
||||||
} = {
|
} = {
|
||||||
Tracking: () => getRandomInt(5, 75) / 20,
|
Tracking: () => getRandomInt(5, 75) / 10,
|
||||||
"Bounty Hunter": () => getRandomInt(5, 75) / 20,
|
"Bounty Hunter": () => getRandomInt(5, 75) / 10,
|
||||||
Retirement: () => getRandomInt(5, 75) / 20,
|
Retirement: () => getRandomInt(5, 75) / 10,
|
||||||
Investigation: () => getRandomInt(10, 40) / 20,
|
Investigation: () => getRandomInt(10, 40) / 10,
|
||||||
"Undercover Operation": () => getRandomInt(10, 40) / 20,
|
"Undercover Operation": () => getRandomInt(10, 40) / 10,
|
||||||
"Sting Operation": () => getRandomInt(3, 40) / 20,
|
"Sting Operation": () => getRandomInt(3, 40) / 10,
|
||||||
Raid: () => getRandomInt(2, 40) / 20,
|
Raid: () => getRandomInt(2, 40) / 10,
|
||||||
"Stealth Retirement Operation": () => getRandomInt(1, 20) / 20,
|
"Stealth Retirement Operation": () => getRandomInt(1, 20) / 10,
|
||||||
Assassination: () => getRandomInt(1, 20) / 20,
|
Assassination: () => getRandomInt(1, 20) / 10,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -55,18 +55,14 @@ export function ActionLevel({ action, isActive, bladeburner, rerender }: IProps)
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Box>
|
</Box>
|
||||||
<Tooltip title={isActive ? <Typography>WARNING: changing the level will restart the Operation</Typography> : ""}>
|
<Tooltip title={isActive ? <Typography>WARNING: changing the level will restart the Operation</Typography> : ""}>
|
||||||
<span>
|
<IconButton disabled={!canIncrease} onClick={increaseLevel}>
|
||||||
<IconButton disabled={!canIncrease} onClick={increaseLevel}>
|
<ArrowDropUpIcon />
|
||||||
<ArrowDropUpIcon />
|
</IconButton>
|
||||||
</IconButton>
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title={isActive ? <Typography>WARNING: changing the level will restart the Operation</Typography> : ""}>
|
<Tooltip title={isActive ? <Typography>WARNING: changing the level will restart the Operation</Typography> : ""}>
|
||||||
<span>
|
<IconButton disabled={!canDecrease} onClick={decreaseLevel}>
|
||||||
<IconButton disabled={!canDecrease} onClick={decreaseLevel}>
|
<ArrowDropDownIcon />
|
||||||
<ArrowDropDownIcon />
|
</IconButton>
|
||||||
</IconButton>
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -27,11 +27,7 @@ export function BlackOpElem(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
const isCompleted = props.bladeburner.blackops[props.action.name] != null;
|
const isCompleted = props.bladeburner.blackops[props.action.name] != null;
|
||||||
if (isCompleted) {
|
if (isCompleted) {
|
||||||
return (
|
return <h2 style={{ display: "block" }}>{props.action.name} (COMPLETED)</h2>;
|
||||||
<Paper sx={{ my: 1, p: 1 }}>
|
|
||||||
<Typography>{props.action.name} (COMPLETED)</Typography>
|
|
||||||
</Paper>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const isActive =
|
const isActive =
|
||||||
@@ -51,35 +47,33 @@ export function BlackOpElem(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper sx={{ my: 1, p: 1 }}>
|
<Paper sx={{ my: 1, p: 1 }}>
|
||||||
{isActive ? (
|
<Typography>
|
||||||
<>
|
{isActive ? (
|
||||||
|
<>
|
||||||
|
<>
|
||||||
|
<CopyableText value={props.action.name} /> (IN PROGRESS - {formatNumber(computedActionTimeCurrent, 0)} /{" "}
|
||||||
|
{formatNumber(props.bladeburner.actionTimeToComplete, 0)})
|
||||||
|
<p style={{ display: "block" }}>
|
||||||
|
{createProgressBarText({
|
||||||
|
progress: computedActionTimeCurrent / props.bladeburner.actionTimeToComplete,
|
||||||
|
})}
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
<>
|
<>
|
||||||
<CopyableText value={props.action.name} />
|
<CopyableText value={props.action.name} />
|
||||||
<Typography>
|
|
||||||
(IN PROGRESS - {formatNumber(computedActionTimeCurrent, 0)} /{" "}
|
<StartButton
|
||||||
{formatNumber(props.bladeburner.actionTimeToComplete, 0)})
|
bladeburner={props.bladeburner}
|
||||||
</Typography>
|
type={ActionTypes.BlackOperation}
|
||||||
<Typography>
|
name={props.action.name}
|
||||||
{createProgressBarText({
|
rerender={rerender}
|
||||||
progress: computedActionTimeCurrent / props.bladeburner.actionTimeToComplete,
|
/>
|
||||||
})}
|
<TeamSizeButton action={props.action} bladeburner={props.bladeburner} />
|
||||||
</Typography>
|
|
||||||
</>
|
</>
|
||||||
</>
|
)}
|
||||||
) : (
|
</Typography>
|
||||||
<>
|
|
||||||
<CopyableText value={props.action.name} />
|
|
||||||
|
|
||||||
<StartButton
|
|
||||||
bladeburner={props.bladeburner}
|
|
||||||
type={ActionTypes.BlackOperation}
|
|
||||||
name={props.action.name}
|
|
||||||
rerender={rerender}
|
|
||||||
/>
|
|
||||||
<TeamSizeButton action={props.action} bladeburner={props.bladeburner} />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<Typography>{actionData.desc}</Typography>
|
<Typography>{actionData.desc}</Typography>
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ export function GeneralActionElem(props: IProps): React.ReactElement {
|
|||||||
return 30;
|
return 30;
|
||||||
case "Diplomacy":
|
case "Diplomacy":
|
||||||
case "Hyperbolic Regeneration Chamber":
|
case "Hyperbolic Regeneration Chamber":
|
||||||
case "Incite Violence":
|
|
||||||
return 60;
|
return 60;
|
||||||
case "Recruitment":
|
case "Recruitment":
|
||||||
return props.bladeburner.getRecruitmentTime(props.player);
|
return props.bladeburner.getRecruitmentTime(props.player);
|
||||||
@@ -58,9 +57,8 @@ export function GeneralActionElem(props: IProps): React.ReactElement {
|
|||||||
<Paper sx={{ my: 1, p: 1 }}>
|
<Paper sx={{ my: 1, p: 1 }}>
|
||||||
{isActive ? (
|
{isActive ? (
|
||||||
<>
|
<>
|
||||||
<CopyableText value={props.action.name} />
|
|
||||||
<Typography>
|
<Typography>
|
||||||
(IN PROGRESS - {formatNumber(computedActionTimeCurrent, 0)} /{" "}
|
<CopyableText value={props.action.name} /> (IN PROGRESS - {formatNumber(computedActionTimeCurrent, 0)} /{" "}
|
||||||
{formatNumber(props.bladeburner.actionTimeToComplete, 0)})
|
{formatNumber(props.bladeburner.actionTimeToComplete, 0)})
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>
|
<Typography>
|
||||||
@@ -71,7 +69,9 @@ export function GeneralActionElem(props: IProps): React.ReactElement {
|
|||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Box display="flex" flexDirection="row" alignItems="center">
|
<Box display="flex" flexDirection="row" alignItems="center">
|
||||||
<CopyableText value={props.action.name} />
|
<Typography>
|
||||||
|
<CopyableText value={props.action.name} />
|
||||||
|
</Typography>
|
||||||
<StartButton
|
<StartButton
|
||||||
bladeburner={props.bladeburner}
|
bladeburner={props.bladeburner}
|
||||||
type={ActionTypes[props.action.name as string]}
|
type={ActionTypes[props.action.name as string]}
|
||||||
|
|||||||
@@ -117,7 +117,9 @@ export function Stats(props: IProps): React.ReactElement {
|
|||||||
</Typography>
|
</Typography>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Typography>Synthoid Communities: {formatNumber(props.bladeburner.getCurrentCity().comms, 0)}</Typography>
|
<Typography>
|
||||||
|
Est. Synthoid Communities: {formatNumber(props.bladeburner.getCurrentCity().comms, 0)}
|
||||||
|
</Typography>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Box>
|
</Box>
|
||||||
<br />
|
<br />
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
interface RNG {
|
export interface RNG {
|
||||||
random(): number;
|
random(): number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export function generateRandomContractOnHome(): void {
|
|||||||
serv.addContract(contract);
|
serv.addContract(contract);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IGenerateContractParams {
|
export interface IGenerateContractParams {
|
||||||
problemType?: string;
|
problemType?: string;
|
||||||
server?: string;
|
server?: string;
|
||||||
fn?: string;
|
fn?: string;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { CodingContractEvent } from "./ui/React/CodingContractModal";
|
|||||||
/* tslint:disable:no-magic-numbers completed-docs max-classes-per-file no-console */
|
/* tslint:disable:no-magic-numbers completed-docs max-classes-per-file no-console */
|
||||||
|
|
||||||
/* Represents different types of problems that a Coding Contract can have */
|
/* Represents different types of problems that a Coding Contract can have */
|
||||||
class CodingContractType {
|
export class CodingContractType {
|
||||||
/**
|
/**
|
||||||
* Function that generates a description of the problem
|
* Function that generates a description of the problem
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -45,3 +45,8 @@ export function initCompanies(): void {
|
|||||||
export function loadCompanies(saveString: string): void {
|
export function loadCompanies(saveString: string): void {
|
||||||
Companies = JSON.parse(saveString, Reviver);
|
Companies = JSON.parse(saveString, Reviver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Utility function to check if a string is valid company name
|
||||||
|
export function companyExists(name: string): boolean {
|
||||||
|
return Companies.hasOwnProperty(name);
|
||||||
|
}
|
||||||
|
|||||||
122
src/Constants.ts
122
src/Constants.ts
@@ -114,7 +114,7 @@ export const CONSTANTS: {
|
|||||||
TotalNumBitNodes: number;
|
TotalNumBitNodes: number;
|
||||||
LatestUpdate: string;
|
LatestUpdate: string;
|
||||||
} = {
|
} = {
|
||||||
Version: "0.57.0",
|
Version: "0.56.0",
|
||||||
|
|
||||||
// Speed (in ms) at which the main loop is updated
|
// Speed (in ms) at which the main loop is updated
|
||||||
_idleSpeed: 200,
|
_idleSpeed: 200,
|
||||||
@@ -281,55 +281,107 @@ export const CONSTANTS: {
|
|||||||
TotalNumBitNodes: 24,
|
TotalNumBitNodes: 24,
|
||||||
|
|
||||||
LatestUpdate: `
|
LatestUpdate: `
|
||||||
v0.57.0 - 2021-10-16 It was too cheap! (hydroflame & community)
|
v0.56.0 - 2021-10-11 Trimming the backlog (hydroflame & community)
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
||||||
** BREAKING (kindof) **
|
** BREAKING **
|
||||||
|
|
||||||
* purchased server cost now scales exponentially past 2^10.
|
* The 'write' function is now async. This helps when making scripts that write scripts.
|
||||||
I'm going to actually explain this one: Currently the cost of a 2^20GB server is 57b
|
|
||||||
Most players can get that before their first install. In an effort to nerf good players
|
|
||||||
a softcap was added. This softcap is different for every BN.
|
|
||||||
|
|
||||||
** Script Editor **
|
** Terminal **
|
||||||
|
|
||||||
* Added a theme that is close to monokai. Unfortunately a full monokai is impossible because
|
* 'grow' and 'weaken' have been added as terminal command. This should help player transition
|
||||||
Monaco doesn't have a very good tokenizer.
|
from commands to scripts. The tutorial also talks about it.
|
||||||
* Opening a file and connecting to a new server will still save the file on the server that the file
|
* 'cp' command added
|
||||||
was opened.
|
* Improved performance by rate limiting refresh.
|
||||||
|
|
||||||
|
** IP vs Hostname **
|
||||||
|
|
||||||
|
* The game now uses hostname as primary key for it's servers (yeah believe it or not IPs were
|
||||||
|
used until then). This has caused some issues with purchased servers (they couldn't be sold).
|
||||||
|
You might need to soft reset for the game to fully convert itself.
|
||||||
|
|
||||||
|
** Sleeve **
|
||||||
|
|
||||||
|
* Fixed bug where they couldn't train at Volhaven.
|
||||||
|
* No longer consume all bonus time at once, making it look buggy.
|
||||||
|
|
||||||
|
** SF9 **
|
||||||
|
|
||||||
|
* Now boosts hacknet production by 8/12/14%
|
||||||
|
|
||||||
|
** Hacknet Servers **
|
||||||
|
|
||||||
|
* production nerfed by 10%
|
||||||
|
* Max money increase gets weaker above 10t max money
|
||||||
|
|
||||||
|
** Corporation **
|
||||||
|
|
||||||
|
* Warehouse tooltip now also displays the amount of space taken by products.
|
||||||
|
* Changed research box completely to avoid dependency on Treant (Treant is a pita)
|
||||||
|
* All textbox should accept MAX/MP case insensitive.
|
||||||
|
* Fixed export popup not refreshing dropdowns correctly.
|
||||||
|
* Fixed product mku becoming zero
|
||||||
|
* Increased scaling of Wilson to avoid feedback loop.
|
||||||
|
* Can no longer get in debt by buying real estate
|
||||||
|
* Bonus time is consumed faster.
|
||||||
|
|
||||||
** Netscript **
|
** Netscript **
|
||||||
|
|
||||||
* New function: alert, which creates a textbox.
|
* isBusy takes bitverse and infiltration into account
|
||||||
* New function: toast, creates a notification in the bottom right.
|
* hospitalize can't be called when in infiltration.
|
||||||
* New function: upgradeHomeCores (@Saynt_Garmo)
|
* setToCommitCrime now accepts crime rough name instead of perfect name.
|
||||||
* New function: atExit, allows you to set a callback for when the script closes.
|
* disableLog All now works for bladeburner functions.
|
||||||
* New kindof function: autocomplete, this allows you to tell the game what it should
|
* Fixed netscript port for ns1.
|
||||||
autocomplete on the terminal.
|
|
||||||
|
|
||||||
** Augmentation **
|
** Augmentation **
|
||||||
|
|
||||||
* ENM Core (the Augmentation from The Black Hand with the highest rep cost) rep cost
|
* Added augmentation to Ti Di Hui that removes penalty for being unfocused.
|
||||||
reduced from 250 to 175. This will help new players transition from TBH to BitRunners more easily.
|
* Neuroflux no longer appears in special factions.
|
||||||
|
|
||||||
** Bladeburner **
|
** Script Editor **
|
||||||
|
|
||||||
* New general action: Incite Violence. This action adds other action counts but increases chaos.
|
* Ram check is debounced instead of refreshed every second.
|
||||||
|
* Added the vscode extension documentation to the game (it doesn't work well, thought)
|
||||||
|
* Fixed issue where autocomplete list would grow forever
|
||||||
|
* Added semi-monokai as theme.
|
||||||
|
* Fixed issue where modifying filename would mess it up.
|
||||||
|
* Font size can be changed now.
|
||||||
|
|
||||||
|
** Infiltration **
|
||||||
|
|
||||||
|
* Fixed issue where game controls would become unfocused.
|
||||||
|
|
||||||
** Misc. **
|
** Misc. **
|
||||||
|
|
||||||
* Current bladeburner action is shown on the character overview.
|
* Fixed loader incorrectly assuming some null values are incorrect.
|
||||||
* Fix blackop being #000 on #000.
|
* installBackdoor trigger Bitverse sequence
|
||||||
* The last clicked Tail Box goes in front of the others.
|
* Some improvements to the theme editor
|
||||||
* Fixed an issue where some values were loaded as 0 when they should be null.
|
* Improved documentation about where to learn javascript.
|
||||||
* Implemented toasts.
|
* Added some instructions for contributors.
|
||||||
* .msg are no longer saved in the text file.
|
* Fixed typo in corporation sell shares modal (@Saynt_Garmo)
|
||||||
* Tail boxes no longer display all the args, they use "..." after 30 characters.
|
* Fixed pagination being black on black in Active Scripts
|
||||||
* Fixed cancelation penalty bonus not being properly applied after the IP <-> hostname switch.
|
* Create Script tab renamed to Script Editor
|
||||||
* Fixed an exploit where you could send non-strings or numbers to other scripts.
|
* Fixed an issue where corp some textbox wouldn't update when changing city.
|
||||||
* Fixed issue when trying to work for a faction with a work type that doesn't exist while
|
* Fixed an issue where hacknet online time was always 0.
|
||||||
already working for that faction.
|
* Netscript function prompt fixed.
|
||||||
* Fixed not being able to work for the CIA. (Don't ask)
|
* Fixed miscalculation in growth.
|
||||||
|
* Script with syntax errors will try to be a tad more helpful.
|
||||||
|
* Corporations can no longer bribe bladeburners.
|
||||||
|
* Augmentation Graphene Branchiblade renamed to Brachi, like the rest of them.
|
||||||
|
* All ram is displayed in GB/TB/PB now.
|
||||||
|
* Game now saves when saving a file, this can be turned off.
|
||||||
|
* Several improvement to log window.
|
||||||
|
* Bladeburner current action returns General type instead of the name of the action.
|
||||||
|
* Bladeburner travel and Sleeve travel respect disable ASCII.
|
||||||
|
* Tutorial fits on small screens.
|
||||||
|
* Import is much slower but more consistent now.
|
||||||
|
* Fix intelligence not updating properly.
|
||||||
|
* Added SF -1: Time Compression
|
||||||
|
* ReadTheDoc theme now matches the game.
|
||||||
|
* Logbox should wrap text better
|
||||||
|
* Logbox behavior should feel better.
|
||||||
|
* Fix font for AutoLink.exe
|
||||||
* nerf noodle bar
|
* nerf noodle bar
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ export class Warehouse {
|
|||||||
updateSize(corporation: ICorporation, industry: IIndustry): void {
|
updateSize(corporation: ICorporation, industry: IIndustry): void {
|
||||||
try {
|
try {
|
||||||
this.size = this.level * 100 * corporation.getStorageMultiplier() * industry.getStorageMultiplier();
|
this.size = this.level * 100 * corporation.getStorageMultiplier() * industry.getStorageMultiplier();
|
||||||
} catch (e: any) {
|
} catch (e) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { IIndustry } from "../IIndustry";
|
import { IIndustry } from "../IIndustry";
|
||||||
import { MathJax, MathJaxContext } from "better-react-mathjax";
|
import { MathComponent } from "mathjax-react";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
division: IIndustry;
|
division: IIndustry;
|
||||||
@@ -19,8 +19,9 @@ export function IndustryProductEquation(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MathJaxContext>
|
<MathComponent
|
||||||
<MathJax>{"\\(" + reqs.join("+") + `\\Rightarrow` + prod.map((p) => `1 \\text{${p}}`).join("+") + "\\)"}</MathJax>
|
display={false}
|
||||||
</MathJaxContext>
|
tex={reqs.join("+") + String.raw`\Rightarrow` + prod.map((p) => String.raw`1\text{ }${p}`).join("+")}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,6 +76,11 @@ function MarketTA2(props: IMarketTA2Props): React.ReactElement {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Typography>
|
||||||
|
Note that Market-TA.II overrides Market-TA.I. This means that if both are enabled, then Market-TA.II will take
|
||||||
|
effect, not Market-TA.I
|
||||||
|
</Typography>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -88,7 +93,6 @@ interface IProps {
|
|||||||
|
|
||||||
// Create a popup that lets the player use the Market TA research for Materials
|
// Create a popup that lets the player use the Market TA research for Materials
|
||||||
export function MaterialMarketTaModal(props: IProps): React.ReactElement {
|
export function MaterialMarketTaModal(props: IProps): React.ReactElement {
|
||||||
const division = useDivision();
|
|
||||||
const setRerender = useState(false)[1];
|
const setRerender = useState(false)[1];
|
||||||
function rerender(): void {
|
function rerender(): void {
|
||||||
setRerender((old) => !old);
|
setRerender((old) => !old);
|
||||||
@@ -102,32 +106,28 @@ export function MaterialMarketTaModal(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal open={props.open} onClose={props.onClose}>
|
<Modal open={props.open} onClose={props.onClose}>
|
||||||
{!division.hasResearch("Market-TA.II") && (
|
<Typography variant="h4">Market-TA.I</Typography>
|
||||||
<>
|
<Typography>
|
||||||
<Typography variant="h4">Market-TA.I</Typography>
|
The maximum sale price you can mark this up to is {numeralWrapper.formatMoney(props.mat.bCost + markupLimit)}.
|
||||||
<Typography>
|
This means that if you set the sale price higher than this, you will begin to experience a loss in number of
|
||||||
The maximum sale price you can mark this up to is{" "}
|
sales
|
||||||
{numeralWrapper.formatMoney(props.mat.bCost + markupLimit)}. This means that if you set the sale price
|
</Typography>
|
||||||
higher than this, you will begin to experience a loss in number of sales
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={<Switch checked={props.mat.marketTa1} onChange={onMarketTA1} />}
|
control={<Switch checked={props.mat.marketTa1} onChange={onMarketTA1} />}
|
||||||
label={
|
label={
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={
|
title={
|
||||||
<Typography>
|
<Typography>
|
||||||
If this is enabled, then this Material will automatically be sold at the price identified by
|
If this is enabled, then this Material will automatically be sold at the price identified by Market-TA.I
|
||||||
Market-TA.I (i.e. the price shown above)
|
(i.e. the price shown above)
|
||||||
</Typography>
|
</Typography>
|
||||||
}
|
|
||||||
>
|
|
||||||
<Typography>Use Market-TA.I for Auto-Sale Price</Typography>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
}
|
||||||
/>
|
>
|
||||||
</>
|
<Typography>Use Market-TA.I for Auto-Sale Price</Typography>
|
||||||
)}
|
</Tooltip>
|
||||||
|
}
|
||||||
|
/>
|
||||||
<MarketTA2 mat={props.mat} />
|
<MarketTA2 mat={props.mat} />
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -66,6 +66,11 @@ function MarketTA2(props: ITa2Props): React.ReactElement {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Typography>
|
||||||
|
Note that Market-TA.II overrides Market-TA.I. This means that if both are enabled, then Market-TA.II will take
|
||||||
|
effect, not Market-TA.I
|
||||||
|
</Typography>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -78,7 +83,6 @@ interface IProps {
|
|||||||
|
|
||||||
// Create a popup that lets the player use the Market TA research for Products
|
// Create a popup that lets the player use the Market TA research for Products
|
||||||
export function ProductMarketTaModal(props: IProps): React.ReactElement {
|
export function ProductMarketTaModal(props: IProps): React.ReactElement {
|
||||||
const division = useDivision();
|
|
||||||
const markupLimit = props.product.rat / props.product.mku;
|
const markupLimit = props.product.rat / props.product.mku;
|
||||||
const setRerender = useState(false)[1];
|
const setRerender = useState(false)[1];
|
||||||
function rerender(): void {
|
function rerender(): void {
|
||||||
@@ -92,32 +96,29 @@ export function ProductMarketTaModal(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal open={props.open} onClose={props.onClose}>
|
<Modal open={props.open} onClose={props.onClose}>
|
||||||
{!division.hasResearch("Market-TA.II") && (
|
<Typography variant="h4">Market-TA.I</Typography>
|
||||||
<>
|
<Typography>
|
||||||
<Typography variant="h4">Market-TA.I</Typography>
|
The maximum sale price you can mark this up to is{" "}
|
||||||
<Typography>
|
{numeralWrapper.formatMoney(props.product.pCost + markupLimit)}. This means that if you set the sale price
|
||||||
The maximum sale price you can mark this up to is{" "}
|
higher than this, you will begin to experience a loss in number of sales
|
||||||
{numeralWrapper.formatMoney(props.product.pCost + markupLimit)}. This means that if you set the sale price
|
</Typography>
|
||||||
higher than this, you will begin to experience a loss in number of sales
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={<Switch checked={props.product.marketTa1} onChange={onChange} />}
|
control={<Switch checked={props.product.marketTa1} onChange={onChange} />}
|
||||||
label={
|
label={
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={
|
title={
|
||||||
<Typography>
|
<Typography>
|
||||||
If this is enabled, then this Material will automatically be sold at the price identified by
|
If this is enabled, then this Material will automatically be sold at the price identified by Market-TA.I
|
||||||
Market-TA.I (i.e. the price shown above)
|
(i.e. the price shown above)
|
||||||
</Typography>
|
</Typography>
|
||||||
}
|
|
||||||
>
|
|
||||||
<Typography>Use Market-TA.I for Auto-Sale Price</Typography>
|
|
||||||
</Tooltip>
|
|
||||||
}
|
}
|
||||||
/>
|
>
|
||||||
</>
|
<Typography>Use Market-TA.I for Auto-Sale Price</Typography>
|
||||||
)}
|
</Tooltip>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<MarketTA2 product={props.product} />
|
<MarketTA2 product={props.product} />
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
|||||||
90
src/CotMG/ActiveFragment.ts
Normal file
90
src/CotMG/ActiveFragment.ts
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
import { Fragment, FragmentById } from "./Fragment";
|
||||||
|
import { FragmentType } from "./FragmentType";
|
||||||
|
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
||||||
|
|
||||||
|
const noCharge = [FragmentType.None, FragmentType.Delete, FragmentType.Booster];
|
||||||
|
|
||||||
|
export interface IActiveFragmentParams {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
fragment: Fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ActiveFragment {
|
||||||
|
id: number;
|
||||||
|
charge: number;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
|
||||||
|
constructor(params?: IActiveFragmentParams) {
|
||||||
|
if (params) {
|
||||||
|
this.id = params.fragment.id;
|
||||||
|
this.x = params.x;
|
||||||
|
this.y = params.y;
|
||||||
|
this.charge = 1;
|
||||||
|
if (noCharge.includes(params.fragment.type)) this.charge = 0;
|
||||||
|
} else {
|
||||||
|
this.id = -1;
|
||||||
|
this.x = -1;
|
||||||
|
this.y = -1;
|
||||||
|
this.charge = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
collide(other: ActiveFragment): boolean {
|
||||||
|
const thisFragment = this.fragment();
|
||||||
|
const otherFragment = other.fragment();
|
||||||
|
// These 2 variables converts 'this' local coordinates to world to other local.
|
||||||
|
const dx: number = other.x - this.x;
|
||||||
|
const dy: number = other.y - this.y;
|
||||||
|
for (let j = 0; j < thisFragment.shape.length; j++) {
|
||||||
|
for (let i = 0; i < thisFragment.shape[j].length; i++) {
|
||||||
|
if (thisFragment.fullAt(i, j) && otherFragment.fullAt(i - dx, j - dy)) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment(): Fragment {
|
||||||
|
const fragment = FragmentById(this.id);
|
||||||
|
if (fragment === null) throw new Error("ActiveFragment id refers to unknown Fragment.");
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
fullAt(worldX: number, worldY: number): boolean {
|
||||||
|
return this.fragment().fullAt(worldX - this.x, worldY - this.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
neighboors(): number[][] {
|
||||||
|
return this.fragment()
|
||||||
|
.neighboors()
|
||||||
|
.map((cell) => [this.x + cell[0], this.y + cell[1]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(): ActiveFragment {
|
||||||
|
// We have to do a round trip because the constructor.
|
||||||
|
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, fragment: fragment });
|
||||||
|
c.charge = this.charge;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize an active fragment to a JSON save state.
|
||||||
|
*/
|
||||||
|
toJSON(): any {
|
||||||
|
return Generic_toJSON("ActiveFragment", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes an acive fragment from a JSON save state
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
|
static fromJSON(value: any): ActiveFragment {
|
||||||
|
return Generic_fromJSON(ActiveFragment, value.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Reviver.constructors.ActiveFragment = ActiveFragment;
|
||||||
329
src/CotMG/Fragment.ts
Normal file
329
src/CotMG/Fragment.ts
Normal file
@@ -0,0 +1,329 @@
|
|||||||
|
import { FragmentType } from "./FragmentType";
|
||||||
|
|
||||||
|
export const Fragments: Fragment[] = [];
|
||||||
|
|
||||||
|
export class Fragment {
|
||||||
|
id: number;
|
||||||
|
shape: boolean[][];
|
||||||
|
type: FragmentType;
|
||||||
|
power: number;
|
||||||
|
limit: number;
|
||||||
|
|
||||||
|
constructor(id: number, shape: boolean[][], type: FragmentType, power: number, limit: number) {
|
||||||
|
this.id = id;
|
||||||
|
this.shape = shape;
|
||||||
|
this.type = type;
|
||||||
|
this.power = power;
|
||||||
|
this.limit = limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
fullAt(x: number, y: number): boolean {
|
||||||
|
if (y < 0) return false;
|
||||||
|
if (y >= this.shape.length) return false;
|
||||||
|
if (x < 0) return false;
|
||||||
|
if (x >= this.shape[y].length) return false;
|
||||||
|
// Yes it's ordered y first.
|
||||||
|
return this.shape[y][x];
|
||||||
|
}
|
||||||
|
|
||||||
|
width(): number {
|
||||||
|
// check every line for robustness.
|
||||||
|
return Math.max(...this.shape.map((line) => line.length));
|
||||||
|
}
|
||||||
|
|
||||||
|
height(): number {
|
||||||
|
return this.shape.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// List of direct neighboors of this fragment.
|
||||||
|
neighboors(): number[][] {
|
||||||
|
const candidates: number[][] = [];
|
||||||
|
|
||||||
|
const add = (x: number, y: number): void => {
|
||||||
|
if (this.fullAt(x, y)) return;
|
||||||
|
if (candidates.some((coord) => coord[0] === x && coord[1] === y)) return;
|
||||||
|
candidates.push([x, y]);
|
||||||
|
};
|
||||||
|
for (let y = 0; y < this.shape.length; y++) {
|
||||||
|
for (let x = 0; x < this.shape[y].length; x++) {
|
||||||
|
// This cell is full, add all it's neighboors.
|
||||||
|
if (!this.shape[y][x]) continue;
|
||||||
|
add(x - 1, y);
|
||||||
|
add(x + 1, y);
|
||||||
|
add(x, y - 1);
|
||||||
|
add(x, y + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const cells: number[][] = [];
|
||||||
|
for (const candidate of candidates) {
|
||||||
|
if (cells.some((cell) => cell[0] === candidate[0] && cell[1] === candidate[1])) continue;
|
||||||
|
cells.push(candidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cells;
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(): Fragment {
|
||||||
|
return new Fragment(
|
||||||
|
this.id,
|
||||||
|
this.shape.map((a) => a.slice()),
|
||||||
|
this.type,
|
||||||
|
this.power,
|
||||||
|
this.limit,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function FragmentById(id: number): Fragment | null {
|
||||||
|
for (const fragment of Fragments) {
|
||||||
|
if (fragment.id === id) return fragment;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
const _ = false;
|
||||||
|
const X = true;
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
0, // id
|
||||||
|
[
|
||||||
|
// shape
|
||||||
|
[X, X, X],
|
||||||
|
[_, _, X],
|
||||||
|
[_, _, X],
|
||||||
|
],
|
||||||
|
FragmentType.Hacking, // type
|
||||||
|
1,
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
1, // id
|
||||||
|
[
|
||||||
|
// shape
|
||||||
|
[_, X, _],
|
||||||
|
[X, X, X],
|
||||||
|
[_, X, _],
|
||||||
|
],
|
||||||
|
FragmentType.Hacking, // type
|
||||||
|
1,
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
5, // id
|
||||||
|
[
|
||||||
|
// shape
|
||||||
|
[X, X],
|
||||||
|
],
|
||||||
|
FragmentType.HackingSpeed, // type
|
||||||
|
1.3,
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
6, // id
|
||||||
|
[
|
||||||
|
[X, _],
|
||||||
|
[X, X],
|
||||||
|
], // shape
|
||||||
|
FragmentType.HackingMoney, // type
|
||||||
|
2, // power
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
7, // id
|
||||||
|
[
|
||||||
|
[X, X],
|
||||||
|
[X, X],
|
||||||
|
], // shape
|
||||||
|
FragmentType.HackingGrow, // type
|
||||||
|
0.5, // power
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
8, // id
|
||||||
|
[
|
||||||
|
[X, X, X],
|
||||||
|
[_, X, _],
|
||||||
|
[X, X, X],
|
||||||
|
], // shape
|
||||||
|
FragmentType.Hacking, // type
|
||||||
|
1, // power
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
10, // id
|
||||||
|
[
|
||||||
|
[X, X],
|
||||||
|
[_, X],
|
||||||
|
], // shape
|
||||||
|
FragmentType.Strength, // type
|
||||||
|
2, // power
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
12, // id
|
||||||
|
[
|
||||||
|
[_, X],
|
||||||
|
[X, X],
|
||||||
|
], // shape
|
||||||
|
FragmentType.Defense, // type
|
||||||
|
2, // power
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
14, // id
|
||||||
|
[
|
||||||
|
[X, X],
|
||||||
|
[X, _],
|
||||||
|
], // shape
|
||||||
|
FragmentType.Dexterity, // type
|
||||||
|
2, // power
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
16, // id
|
||||||
|
[
|
||||||
|
[X, _],
|
||||||
|
[X, X],
|
||||||
|
], // shape
|
||||||
|
FragmentType.Agility, // type
|
||||||
|
2, // power
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
18, // id
|
||||||
|
[
|
||||||
|
[X, X],
|
||||||
|
[X, _],
|
||||||
|
], // shape
|
||||||
|
FragmentType.Charisma, // type
|
||||||
|
3, // power
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
20, // id
|
||||||
|
[
|
||||||
|
[X, _, _],
|
||||||
|
[X, X, _],
|
||||||
|
[X, X, X],
|
||||||
|
], // shape
|
||||||
|
FragmentType.HacknetMoney, // type
|
||||||
|
1, // power
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
21, // id
|
||||||
|
[
|
||||||
|
[X, X],
|
||||||
|
[_, X],
|
||||||
|
[_, X],
|
||||||
|
], // shape
|
||||||
|
FragmentType.HacknetCost, // type
|
||||||
|
-1, // power
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
25, // id
|
||||||
|
[
|
||||||
|
[X, X, X],
|
||||||
|
[_, X, _],
|
||||||
|
], // shape
|
||||||
|
FragmentType.Rep, // type
|
||||||
|
0.5, // power
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
27, // id
|
||||||
|
[
|
||||||
|
[X, _],
|
||||||
|
[_, X],
|
||||||
|
], // shape
|
||||||
|
FragmentType.WorkMoney, // type
|
||||||
|
10, // power
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
28, // id
|
||||||
|
[[X, X]], // shape
|
||||||
|
FragmentType.Crime, // type
|
||||||
|
2, // power
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
30, // id
|
||||||
|
[
|
||||||
|
[X, X, X],
|
||||||
|
[X, X, X],
|
||||||
|
[X, X, X],
|
||||||
|
], // shape
|
||||||
|
FragmentType.Bladeburner, // type
|
||||||
|
1.3, // power
|
||||||
|
1, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
2, // id
|
||||||
|
[
|
||||||
|
// shape
|
||||||
|
[X, X, X],
|
||||||
|
[X, _, X],
|
||||||
|
[X, X, X],
|
||||||
|
],
|
||||||
|
FragmentType.Booster, // type
|
||||||
|
1.1, // power
|
||||||
|
3, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
Fragments.push(
|
||||||
|
new Fragment(
|
||||||
|
31, // id
|
||||||
|
[
|
||||||
|
// shape
|
||||||
|
[X],
|
||||||
|
[X],
|
||||||
|
[X],
|
||||||
|
[X],
|
||||||
|
],
|
||||||
|
FragmentType.Booster, // type
|
||||||
|
1.1, // power
|
||||||
|
3, // limit
|
||||||
|
),
|
||||||
|
);
|
||||||
|
})();
|
||||||
|
|
||||||
|
export const NoneFragment = new Fragment(-2, [], FragmentType.None, 0, Infinity);
|
||||||
|
export const DeleteFragment = new Fragment(-2, [], FragmentType.Delete, 0, Infinity);
|
||||||
96
src/CotMG/FragmentType.ts
Normal file
96
src/CotMG/FragmentType.ts
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
export enum FragmentType {
|
||||||
|
// Special fragments for the UI
|
||||||
|
None,
|
||||||
|
Delete,
|
||||||
|
|
||||||
|
// Stats boosting fragments
|
||||||
|
HackingChance,
|
||||||
|
HackingSpeed,
|
||||||
|
HackingMoney,
|
||||||
|
HackingGrow,
|
||||||
|
Hacking,
|
||||||
|
Strength,
|
||||||
|
Defense,
|
||||||
|
Dexterity,
|
||||||
|
Agility,
|
||||||
|
Charisma,
|
||||||
|
HacknetMoney,
|
||||||
|
HacknetCost,
|
||||||
|
Rep,
|
||||||
|
WorkMoney,
|
||||||
|
Crime,
|
||||||
|
Bladeburner,
|
||||||
|
|
||||||
|
// utility fragments.
|
||||||
|
Booster,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Effect(tpe: FragmentType): string {
|
||||||
|
switch (tpe) {
|
||||||
|
case FragmentType.HackingChance: {
|
||||||
|
return "+x% hack() success chance";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FragmentType.HackingSpeed: {
|
||||||
|
return "+x% faster hack(), grow(), and weaken()";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FragmentType.HackingMoney: {
|
||||||
|
return "+x% hack() power";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FragmentType.HackingGrow: {
|
||||||
|
return "+x% grow() power";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FragmentType.Hacking: {
|
||||||
|
return "+x% hacking skill";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FragmentType.Strength: {
|
||||||
|
return "+x% strength skill";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FragmentType.Defense: {
|
||||||
|
return "+x% defense skill";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FragmentType.Dexterity: {
|
||||||
|
return "+x% dexterity skill";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FragmentType.Agility: {
|
||||||
|
return "+x% agility skill";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FragmentType.Charisma: {
|
||||||
|
return "+x% charisma skill";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FragmentType.HacknetMoney: {
|
||||||
|
return "+x% hacknet production";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FragmentType.HacknetCost: {
|
||||||
|
return "-x% all hacknet cost";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FragmentType.Rep: {
|
||||||
|
return "+x% reputation from factions and companies";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FragmentType.WorkMoney: {
|
||||||
|
return "+x% work money";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FragmentType.Crime: {
|
||||||
|
return "+x% crime money";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FragmentType.Bladeburner: {
|
||||||
|
return "+x% all bladeburner stats";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error("Calling effect for fragment type that doesn't have an effect " + tpe);
|
||||||
|
}
|
||||||
14
src/CotMG/Helper.tsx
Normal file
14
src/CotMG/Helper.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { Reviver } from "../utils/JSONReviver";
|
||||||
|
|
||||||
|
import { IStaneksGift } from "./IStaneksGift";
|
||||||
|
import { StaneksGift } from "./StaneksGift";
|
||||||
|
|
||||||
|
export let staneksGift: IStaneksGift = new StaneksGift();
|
||||||
|
|
||||||
|
export function loadStaneksGift(saveString: string): void {
|
||||||
|
if (saveString) {
|
||||||
|
staneksGift = JSON.parse(saveString, Reviver);
|
||||||
|
} else {
|
||||||
|
staneksGift = new StaneksGift();
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/CotMG/IStaneksGift.ts
Normal file
22
src/CotMG/IStaneksGift.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { ActiveFragment } from "./ActiveFragment";
|
||||||
|
import { Fragment } from "./Fragment";
|
||||||
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
|
||||||
|
export interface IStaneksGift {
|
||||||
|
storedCycles: number;
|
||||||
|
fragments: ActiveFragment[];
|
||||||
|
width(): number;
|
||||||
|
height(): number;
|
||||||
|
charge(worldX: number, worldY: number, ram: number): number;
|
||||||
|
process(p: IPlayer, n: number): void;
|
||||||
|
effect(fragment: ActiveFragment): number;
|
||||||
|
canPlace(x: number, y: number, fragment: Fragment): boolean;
|
||||||
|
place(x: number, y: number, fragment: Fragment): boolean;
|
||||||
|
fragmentAt(worldX: number, worldY: number): ActiveFragment | null;
|
||||||
|
deleteAt(worldX: number, worldY: number): boolean;
|
||||||
|
clear(): void;
|
||||||
|
count(fragment: Fragment): number;
|
||||||
|
inBonus(): boolean;
|
||||||
|
prestigeAugmentation(): void;
|
||||||
|
prestigeSourceFile(): void;
|
||||||
|
}
|
||||||
222
src/CotMG/StaneksGift.ts
Normal file
222
src/CotMG/StaneksGift.ts
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
import { Fragment } from "./Fragment";
|
||||||
|
import { ActiveFragment } from "./ActiveFragment";
|
||||||
|
import { FragmentType } from "./FragmentType";
|
||||||
|
import { IStaneksGift } from "./IStaneksGift";
|
||||||
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
import { Factions } from "../Faction/Factions";
|
||||||
|
import { CalculateEffect } from "./formulas/effect";
|
||||||
|
import { CalculateCharge } from "./formulas/charge";
|
||||||
|
import { StaneksGiftEvents } from "./StaneksGiftEvents";
|
||||||
|
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
||||||
|
import { CONSTANTS } from "../Constants";
|
||||||
|
import { StanekConstants } from "./data/Constants";
|
||||||
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
|
import { Player } from "../Player";
|
||||||
|
|
||||||
|
export class StaneksGift implements IStaneksGift {
|
||||||
|
storedCycles = 0;
|
||||||
|
fragments: ActiveFragment[] = [];
|
||||||
|
|
||||||
|
baseSize(): number {
|
||||||
|
return StanekConstants.BaseSize + BitNodeMultipliers.StaneksGiftExtraSize + Player.sourceFileLvl(13);
|
||||||
|
}
|
||||||
|
|
||||||
|
width(): number {
|
||||||
|
return Math.floor(this.baseSize() / 2 + 1);
|
||||||
|
}
|
||||||
|
height(): number {
|
||||||
|
return Math.floor(this.baseSize() / 2 + 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
charge(worldX: number, worldY: number, ram: number): number {
|
||||||
|
const af = this.fragmentAt(worldX, worldY);
|
||||||
|
if (af === null) return 0;
|
||||||
|
|
||||||
|
const charge = CalculateCharge(ram);
|
||||||
|
af.charge += charge;
|
||||||
|
|
||||||
|
Factions["Church of the Machine God"].playerReputation += Math.log(ram) / Math.log(2);
|
||||||
|
|
||||||
|
return ram;
|
||||||
|
}
|
||||||
|
|
||||||
|
inBonus(): boolean {
|
||||||
|
return (this.storedCycles * CONSTANTS._idleSpeed) / 1000 > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
process(p: IPlayer, numCycles = 1): void {
|
||||||
|
this.storedCycles += numCycles;
|
||||||
|
this.storedCycles -= 5;
|
||||||
|
this.storedCycles = Math.max(0, this.storedCycles);
|
||||||
|
this.updateMults(p);
|
||||||
|
StaneksGiftEvents.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
effect(fragment: ActiveFragment): number {
|
||||||
|
// Find all the neighbooring cells
|
||||||
|
const cells = fragment.neighboors();
|
||||||
|
// find the neighbooring active fragments.
|
||||||
|
const maybeFragments = cells.map((n) => this.fragmentAt(n[0], n[1]));
|
||||||
|
|
||||||
|
// Filter out nulls with typescript "Type guard". Whatever
|
||||||
|
let neighboors = maybeFragments.filter((v: ActiveFragment | null): v is ActiveFragment => !!v);
|
||||||
|
|
||||||
|
neighboors = neighboors.filter((fragment) => fragment.fragment().type === FragmentType.Booster);
|
||||||
|
let boost = 1;
|
||||||
|
for (const neighboor of neighboors) {
|
||||||
|
boost *= neighboor.fragment().power;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CalculateEffect(fragment.charge, fragment.fragment().power, boost);
|
||||||
|
}
|
||||||
|
|
||||||
|
canPlace(x: number, y: number, fragment: Fragment): boolean {
|
||||||
|
if (x + fragment.width() > this.width()) return false;
|
||||||
|
if (y + fragment.height() > this.height()) return false;
|
||||||
|
if (this.count(fragment) >= fragment.limit) return false;
|
||||||
|
const newFrag = new ActiveFragment({ x: x, y: y, fragment: fragment });
|
||||||
|
for (const aFrag of this.fragments) {
|
||||||
|
if (aFrag.collide(newFrag)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
place(x: number, y: number, fragment: Fragment): boolean {
|
||||||
|
if (!this.canPlace(x, y, fragment)) return false;
|
||||||
|
this.fragments.push(new ActiveFragment({ x: x, y: y, fragment: fragment }));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fragmentAt(worldX: number, worldY: number): ActiveFragment | null {
|
||||||
|
for (const aFrag of this.fragments) {
|
||||||
|
if (aFrag.fullAt(worldX, worldY)) {
|
||||||
|
return aFrag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
count(fragment: Fragment): number {
|
||||||
|
let amt = 0;
|
||||||
|
for (const aFrag of this.fragments) {
|
||||||
|
if (aFrag.fragment().id === fragment.id) amt++;
|
||||||
|
}
|
||||||
|
return amt;
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteAt(worldX: number, worldY: number): boolean {
|
||||||
|
for (let i = 0; i < this.fragments.length; i++) {
|
||||||
|
if (this.fragments[i].fullAt(worldX, worldY)) {
|
||||||
|
this.fragments.splice(i, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear(): void {
|
||||||
|
this.fragments = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMults(p: IPlayer): void {
|
||||||
|
p.reapplyAllAugmentations(true);
|
||||||
|
p.reapplyAllSourceFiles();
|
||||||
|
|
||||||
|
for (const aFrag of this.fragments) {
|
||||||
|
const fragment = aFrag.fragment();
|
||||||
|
|
||||||
|
const power = this.effect(aFrag);
|
||||||
|
switch (fragment.type) {
|
||||||
|
case FragmentType.HackingChance:
|
||||||
|
p.hacking_chance_mult *= power;
|
||||||
|
break;
|
||||||
|
case FragmentType.HackingSpeed:
|
||||||
|
p.hacking_speed_mult *= power;
|
||||||
|
break;
|
||||||
|
case FragmentType.HackingMoney:
|
||||||
|
p.hacking_money_mult *= power;
|
||||||
|
break;
|
||||||
|
case FragmentType.HackingGrow:
|
||||||
|
p.hacking_grow_mult *= power;
|
||||||
|
break;
|
||||||
|
case FragmentType.Hacking:
|
||||||
|
p.hacking_mult *= power;
|
||||||
|
p.hacking_exp_mult *= power;
|
||||||
|
break;
|
||||||
|
case FragmentType.Strength:
|
||||||
|
p.strength_mult *= power;
|
||||||
|
p.strength_exp_mult *= power;
|
||||||
|
break;
|
||||||
|
case FragmentType.Defense:
|
||||||
|
p.defense_mult *= power;
|
||||||
|
p.defense_exp_mult *= power;
|
||||||
|
break;
|
||||||
|
case FragmentType.Dexterity:
|
||||||
|
p.dexterity_mult *= power;
|
||||||
|
p.dexterity_exp_mult *= power;
|
||||||
|
break;
|
||||||
|
case FragmentType.Agility:
|
||||||
|
p.agility_mult *= power;
|
||||||
|
p.agility_exp_mult *= power;
|
||||||
|
break;
|
||||||
|
case FragmentType.Charisma:
|
||||||
|
p.charisma_mult *= power;
|
||||||
|
p.charisma_exp_mult *= power;
|
||||||
|
break;
|
||||||
|
case FragmentType.HacknetMoney:
|
||||||
|
p.hacknet_node_money_mult *= power;
|
||||||
|
break;
|
||||||
|
case FragmentType.HacknetCost:
|
||||||
|
p.hacknet_node_purchase_cost_mult *= power;
|
||||||
|
p.hacknet_node_ram_cost_mult *= power;
|
||||||
|
p.hacknet_node_core_cost_mult *= power;
|
||||||
|
p.hacknet_node_level_cost_mult *= power;
|
||||||
|
break;
|
||||||
|
case FragmentType.Rep:
|
||||||
|
p.company_rep_mult *= power;
|
||||||
|
p.faction_rep_mult *= power;
|
||||||
|
break;
|
||||||
|
case FragmentType.WorkMoney:
|
||||||
|
p.work_money_mult *= power;
|
||||||
|
break;
|
||||||
|
case FragmentType.Crime:
|
||||||
|
p.crime_success_mult *= power;
|
||||||
|
p.crime_money_mult *= power;
|
||||||
|
break;
|
||||||
|
case FragmentType.Bladeburner:
|
||||||
|
p.bladeburner_max_stamina_mult *= power;
|
||||||
|
p.bladeburner_stamina_gain_mult *= power;
|
||||||
|
p.bladeburner_analysis_mult *= power;
|
||||||
|
p.bladeburner_success_chance_mult *= power;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prestigeAugmentation(): void {
|
||||||
|
this.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
prestigeSourceFile(): void {
|
||||||
|
this.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize Staneks Gift to a JSON save state.
|
||||||
|
*/
|
||||||
|
toJSON(): any {
|
||||||
|
return Generic_toJSON("StaneksGift", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes Staneks Gift from a JSON save state
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
|
static fromJSON(value: any): StaneksGift {
|
||||||
|
return Generic_fromJSON(StaneksGift, value.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Reviver.constructors.StaneksGift = StaneksGift;
|
||||||
2
src/CotMG/StaneksGiftEvents.ts
Normal file
2
src/CotMG/StaneksGiftEvents.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
import { EventEmitter } from "../utils/EventEmitter";
|
||||||
|
export const StaneksGiftEvents = new EventEmitter<[]>();
|
||||||
7
src/CotMG/data/Constants.ts
Normal file
7
src/CotMG/data/Constants.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export const StanekConstants: {
|
||||||
|
RAMBonus: number;
|
||||||
|
BaseSize: number;
|
||||||
|
} = {
|
||||||
|
RAMBonus: 0.1,
|
||||||
|
BaseSize: 12,
|
||||||
|
};
|
||||||
5
src/CotMG/formulas/charge.ts
Normal file
5
src/CotMG/formulas/charge.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { StanekConstants } from "../data/Constants";
|
||||||
|
|
||||||
|
export function CalculateCharge(ram: number): number {
|
||||||
|
return ram * Math.pow(1 + Math.log2(ram) * StanekConstants.RAMBonus, 0.7);
|
||||||
|
}
|
||||||
3
src/CotMG/formulas/effect.ts
Normal file
3
src/CotMG/formulas/effect.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
export function CalculateEffect(charge: number, power: number, boost: number): number {
|
||||||
|
return 1 + (Math.log(charge + 1) / (Math.log(3) * 100)) * power * boost;
|
||||||
|
}
|
||||||
4
src/CotMG/notes
Normal file
4
src/CotMG/notes
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
incentive for more threads
|
||||||
|
boosters just multiply output, eg 20% * 1.5 = 30%
|
||||||
|
|
||||||
|
git remote add danielyxie git@github.com:danielyxie/bitburner.git
|
||||||
40
src/CotMG/ui/Cell.tsx
Normal file
40
src/CotMG/ui/Cell.tsx
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
import makeStyles from "@mui/styles/makeStyles";
|
||||||
|
import { TableCell as MuiTableCell, TableCellProps } from "@mui/material";
|
||||||
|
|
||||||
|
const useStyles = makeStyles({
|
||||||
|
root: {
|
||||||
|
border: "1px solid white",
|
||||||
|
width: "5px",
|
||||||
|
height: "5px",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const TableCell: React.FC<TableCellProps> = (props: TableCellProps) => {
|
||||||
|
return (
|
||||||
|
<MuiTableCell
|
||||||
|
{...props}
|
||||||
|
classes={{
|
||||||
|
root: useStyles().root,
|
||||||
|
...props.classes,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
type IProps = {
|
||||||
|
onMouseEnter?: () => void;
|
||||||
|
onClick?: () => void;
|
||||||
|
color: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Cell(cellProps: IProps): React.ReactElement {
|
||||||
|
return (
|
||||||
|
<TableCell
|
||||||
|
style={{ backgroundColor: cellProps.color }}
|
||||||
|
onMouseEnter={cellProps.onMouseEnter}
|
||||||
|
onClick={cellProps.onClick}
|
||||||
|
></TableCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
79
src/CotMG/ui/FragmentInspector.tsx
Normal file
79
src/CotMG/ui/FragmentInspector.tsx
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import React, { useState, useEffect } 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";
|
||||||
|
|
||||||
|
type IProps = {
|
||||||
|
gift: IStaneksGift;
|
||||||
|
fragment: ActiveFragment | null;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function FragmentInspector(props: IProps): React.ReactElement {
|
||||||
|
const [, setC] = useState(new Date());
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const id = setInterval(() => setC(new Date()), 250);
|
||||||
|
|
||||||
|
return () => clearInterval(id);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (props.fragment === null) {
|
||||||
|
return (
|
||||||
|
<Paper>
|
||||||
|
<Typography>
|
||||||
|
ID: N/A
|
||||||
|
<br />
|
||||||
|
Effect: N/A
|
||||||
|
<br />
|
||||||
|
Magnitude: N/A
|
||||||
|
<br />
|
||||||
|
Charge: N/A
|
||||||
|
<br />
|
||||||
|
Heat: N/A
|
||||||
|
<br />
|
||||||
|
Effect: N/A
|
||||||
|
<br />
|
||||||
|
[X, Y] N/A
|
||||||
|
<br />
|
||||||
|
[X, Y] {props.x}, {props.y}
|
||||||
|
</Typography>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const f = props.fragment.fragment();
|
||||||
|
|
||||||
|
let charge = numeralWrapper.formatStaneksGiftCharge(props.fragment.charge);
|
||||||
|
let effect = "N/A";
|
||||||
|
// Boosters and cooling don't deal with heat.
|
||||||
|
if ([FragmentType.Booster, FragmentType.None, FragmentType.Delete].includes(f.type)) {
|
||||||
|
charge = "N/A";
|
||||||
|
effect = `${f.power}x adjacent fragment power`;
|
||||||
|
} else {
|
||||||
|
effect = Effect(f.type).replace("x%", numeralWrapper.formatPercentage(props.gift.effect(props.fragment) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper>
|
||||||
|
<Typography>
|
||||||
|
ID: {props.fragment.id}
|
||||||
|
<br />
|
||||||
|
Effect: {effect}
|
||||||
|
<br />
|
||||||
|
Power: {numeralWrapper.formatStaneksGiftPower(f.power)}
|
||||||
|
<br />
|
||||||
|
Charge: {charge}
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
root [X, Y] {props.fragment.x}, {props.fragment.y}
|
||||||
|
<br />
|
||||||
|
[X, Y] {props.x}, {props.y}
|
||||||
|
</Typography>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
}
|
||||||
31
src/CotMG/ui/FragmentPreview.tsx
Normal file
31
src/CotMG/ui/FragmentPreview.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import { Cell } from "./Cell";
|
||||||
|
|
||||||
|
import TableRow from "@mui/material/TableRow";
|
||||||
|
|
||||||
|
import TableBody from "@mui/material/TableBody";
|
||||||
|
import { Table } from "../../ui/React/Table";
|
||||||
|
|
||||||
|
type IProps = {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
colorAt: (x: number, y: number) => string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function FragmentPreview(props: IProps): React.ReactElement {
|
||||||
|
// switch the width/length to make axis consistent.
|
||||||
|
const elems = [];
|
||||||
|
for (let j = 0; j < props.height; j++) {
|
||||||
|
const cells = [];
|
||||||
|
for (let i = 0; i < props.width; i++) {
|
||||||
|
cells.push(<Cell key={i} color={props.colorAt(i, j)} />);
|
||||||
|
}
|
||||||
|
elems.push(<TableRow key={j}>{cells}</TableRow>);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Table>
|
||||||
|
<TableBody>{elems}</TableBody>
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
}
|
||||||
91
src/CotMG/ui/FragmentSelector.tsx
Normal file
91
src/CotMG/ui/FragmentSelector.tsx
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import { Fragments, Fragment, NoneFragment, DeleteFragment } from "../Fragment";
|
||||||
|
import { FragmentType, Effect } from "../FragmentType";
|
||||||
|
import { IStaneksGift } from "../IStaneksGift";
|
||||||
|
import { FragmentPreview } from "./FragmentPreview";
|
||||||
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
|
||||||
|
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||||
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import Box from "@mui/material/Box";
|
||||||
|
|
||||||
|
type IOptionProps = {
|
||||||
|
gift: IStaneksGift;
|
||||||
|
fragment: Fragment;
|
||||||
|
selectFragment: (fragment: Fragment) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
function FragmentOption(props: IOptionProps): React.ReactElement {
|
||||||
|
const remaining =
|
||||||
|
props.fragment.limit !== Infinity ? (
|
||||||
|
<>{props.fragment.limit - props.gift.count(props.fragment)} remaining</>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<Box display="flex">
|
||||||
|
<Box sx={{ mx: 2 }}>
|
||||||
|
<FragmentPreview
|
||||||
|
width={props.fragment.width()}
|
||||||
|
height={props.fragment.height()}
|
||||||
|
colorAt={(x, y) => {
|
||||||
|
return !props.fragment.fullAt(x, y) ? "" : props.fragment.type === FragmentType.Booster ? "blue" : "green";
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Typography>
|
||||||
|
{props.fragment.type === FragmentType.Booster
|
||||||
|
? `${props.fragment.power}x adjacent fragment power`
|
||||||
|
: Effect(props.fragment.type)}
|
||||||
|
<br />
|
||||||
|
power: {numeralWrapper.formatStaneksGiftPower(props.fragment.power)}
|
||||||
|
<br />
|
||||||
|
{remaining}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
type IProps = {
|
||||||
|
gift: IStaneksGift;
|
||||||
|
selectFragment: (fragment: Fragment) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function FragmentSelector(props: IProps): React.ReactElement {
|
||||||
|
const [value, setValue] = useState<string | number>("None");
|
||||||
|
function onChange(event: SelectChangeEvent<string | number>): void {
|
||||||
|
const v = event.target.value;
|
||||||
|
setValue(v);
|
||||||
|
if (v === "None") {
|
||||||
|
props.selectFragment(NoneFragment);
|
||||||
|
return;
|
||||||
|
} else if (v === "Delete") {
|
||||||
|
props.selectFragment(DeleteFragment);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const fragment = Fragments.find((f) => f.id === v);
|
||||||
|
if (fragment === undefined) throw new Error("Fragment selector selected an undefined fragment with id " + v);
|
||||||
|
if (typeof v === "number") props.selectFragment(fragment);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Select sx={{ width: "100%" }} onChange={onChange} value={value}>
|
||||||
|
<MenuItem value="None">
|
||||||
|
<Typography>None</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem value="Delete">
|
||||||
|
<Typography>Delete</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
{Fragments.map((fragment) => (
|
||||||
|
<MenuItem key={fragment.id} value={fragment.id}>
|
||||||
|
<FragmentOption
|
||||||
|
key={fragment.id}
|
||||||
|
gift={props.gift}
|
||||||
|
selectFragment={props.selectFragment}
|
||||||
|
fragment={fragment}
|
||||||
|
/>
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
);
|
||||||
|
}
|
||||||
145
src/CotMG/ui/Grid.tsx
Normal file
145
src/CotMG/ui/Grid.tsx
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import { Fragment, NoneFragment } from "../Fragment";
|
||||||
|
import { ActiveFragment } from "../ActiveFragment";
|
||||||
|
import { FragmentType } from "../FragmentType";
|
||||||
|
import { IStaneksGift } from "../IStaneksGift";
|
||||||
|
import { Cell } from "./Cell";
|
||||||
|
import { FragmentInspector } from "./FragmentInspector";
|
||||||
|
import { FragmentSelector } from "./FragmentSelector";
|
||||||
|
import Box from "@mui/material/Box";
|
||||||
|
import Button from "@mui/material/Button";
|
||||||
|
import TableRow from "@mui/material/TableRow";
|
||||||
|
import TableBody from "@mui/material/TableBody";
|
||||||
|
import { Table } from "../../ui/React/Table";
|
||||||
|
|
||||||
|
function zeros(dimensions: number[]): any {
|
||||||
|
const array = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < dimensions[0]; ++i) {
|
||||||
|
array.push(dimensions.length == 1 ? 0 : zeros(dimensions.slice(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function randomColor(fragment: ActiveFragment): string {
|
||||||
|
// Can't set Math.random seed so copy casino. TODO refactor both RNG later.
|
||||||
|
let s1 = Math.pow((fragment.x + 1) * (fragment.y + 1), 10);
|
||||||
|
let s2 = s1;
|
||||||
|
let s3 = s1;
|
||||||
|
|
||||||
|
const colors = [];
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
s1 = (171 * s1) % 30269;
|
||||||
|
s2 = (172 * s2) % 30307;
|
||||||
|
s3 = (170 * s3) % 30323;
|
||||||
|
colors.push((s1 / 30269.0 + s2 / 30307.0 + s3 / 30323.0) % 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return `rgb(${colors[0] * 256}, ${colors[1] * 256}, ${colors[2] * 256})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
type GridProps = {
|
||||||
|
gift: IStaneksGift;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Grid(props: GridProps): React.ReactElement {
|
||||||
|
function calculateGrid(gift: IStaneksGift): any {
|
||||||
|
const newgrid = zeros([gift.width(), gift.height()]);
|
||||||
|
for (let i = 0; i < gift.width(); i++) {
|
||||||
|
for (let j = 0; j < gift.height(); j++) {
|
||||||
|
const fragment = gift.fragmentAt(i, j);
|
||||||
|
if (fragment === null) continue;
|
||||||
|
newgrid[i][j] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newgrid;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [grid, setGrid] = React.useState(calculateGrid(props.gift));
|
||||||
|
const [ghostGrid, setGhostGrid] = React.useState(zeros([props.gift.width(), props.gift.height()]));
|
||||||
|
const [pos, setPos] = React.useState([0, 0]);
|
||||||
|
const [selectedFragment, setSelectedFragment] = React.useState(NoneFragment);
|
||||||
|
|
||||||
|
function moveGhost(worldX: number, worldY: number): void {
|
||||||
|
const newgrid = zeros([props.gift.width(), props.gift.height()]);
|
||||||
|
for (let i = 0; i < selectedFragment.shape.length; i++) {
|
||||||
|
for (let j = 0; j < selectedFragment.shape[i].length; j++) {
|
||||||
|
if (!selectedFragment.shape[i][j]) continue;
|
||||||
|
if (worldX + j > newgrid.length - 1) continue;
|
||||||
|
if (worldY + i > newgrid[worldX + j].length - 1) continue;
|
||||||
|
newgrid[worldX + j][worldY + i] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setGhostGrid(newgrid);
|
||||||
|
setPos([worldX, worldY]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteAt(worldX: number, worldY: number): boolean {
|
||||||
|
return props.gift.deleteAt(worldX, worldY);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickAt(worldX: number, worldY: number): void {
|
||||||
|
if (selectedFragment.type == FragmentType.None) return;
|
||||||
|
if (selectedFragment.type == FragmentType.Delete) {
|
||||||
|
deleteAt(worldX, worldY);
|
||||||
|
} else {
|
||||||
|
if (!props.gift.canPlace(worldX, worldY, selectedFragment)) return;
|
||||||
|
props.gift.place(worldX, worldY, selectedFragment);
|
||||||
|
}
|
||||||
|
setGrid(calculateGrid(props.gift));
|
||||||
|
}
|
||||||
|
|
||||||
|
function color(worldX: number, worldY: number): string {
|
||||||
|
if (ghostGrid[worldX][worldY] && grid[worldX][worldY]) return "red";
|
||||||
|
if (ghostGrid[worldX][worldY]) return "white";
|
||||||
|
if (grid[worldX][worldY]) {
|
||||||
|
const fragment = props.gift.fragmentAt(worldX, worldY);
|
||||||
|
if (fragment === null) throw new Error("ActiveFragment should not be null");
|
||||||
|
return randomColor(fragment);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function clear(): void {
|
||||||
|
props.gift.clear();
|
||||||
|
setGrid(zeros([props.gift.width(), props.gift.height()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// switch the width/length to make axis consistent.
|
||||||
|
const elems = [];
|
||||||
|
for (let j = 0; j < props.gift.height(); j++) {
|
||||||
|
const cells = [];
|
||||||
|
for (let i = 0; i < props.gift.width(); i++) {
|
||||||
|
cells.push(
|
||||||
|
<Cell key={i} onMouseEnter={() => moveGhost(i, j)} onClick={() => clickAt(i, j)} color={color(i, j)} />,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
elems.push(
|
||||||
|
<TableRow key={j} className="staneksgift_row">
|
||||||
|
{cells}
|
||||||
|
</TableRow>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSelectedFragment(fragment: Fragment): void {
|
||||||
|
setSelectedFragment(fragment);
|
||||||
|
const newgrid = zeros([props.gift.width(), props.gift.height()]);
|
||||||
|
setGhostGrid(newgrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button onClick={clear}>Clear</Button>
|
||||||
|
<Box display="flex">
|
||||||
|
<Table>
|
||||||
|
<TableBody>{elems}</TableBody>
|
||||||
|
</Table>
|
||||||
|
<FragmentInspector gift={props.gift} x={pos[0]} y={pos[1]} fragment={props.gift.fragmentAt(pos[0], pos[1])} />
|
||||||
|
</Box>
|
||||||
|
<FragmentSelector gift={props.gift} selectFragment={updateSelectedFragment} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
36
src/CotMG/ui/StaneksGiftRoot.tsx
Normal file
36
src/CotMG/ui/StaneksGiftRoot.tsx
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
||||||
|
import { CONSTANTS } from "../../Constants";
|
||||||
|
import { StaneksGiftEvents } from "../StaneksGiftEvents";
|
||||||
|
import { Grid } from "./Grid";
|
||||||
|
import { IStaneksGift } from "../IStaneksGift";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
|
||||||
|
type IProps = {
|
||||||
|
staneksGift: IStaneksGift;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function StaneksGiftRoot({ staneksGift }: IProps): React.ReactElement {
|
||||||
|
const setRerender = useState(true)[1];
|
||||||
|
function rerender(): void {
|
||||||
|
setRerender((o) => !o);
|
||||||
|
}
|
||||||
|
useEffect(() => StaneksGiftEvents.subscribe(rerender), []);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Typography variant="h4">Stanek's Gift</Typography>
|
||||||
|
<Typography>
|
||||||
|
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
|
||||||
|
in order to become useful. The other kind of fragment is called booster fragments. They increase the efficiency
|
||||||
|
of the charged happening on fragments neighboring them (no diagonal)
|
||||||
|
</Typography>
|
||||||
|
{staneksGift.storedCycles > 5 && (
|
||||||
|
<Typography>
|
||||||
|
Bonus time: {convertTimeMsToTimeElapsedString(CONSTANTS._idleSpeed * staneksGift.storedCycles)}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
<Grid gift={staneksGift} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import { IPlayerOrSleeve } from "../PersonObjects/IPlayerOrSleeve";
|
|||||||
import { IRouter } from "../ui/Router";
|
import { IRouter } from "../ui/Router";
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
|
|
||||||
interface IConstructorParams {
|
export interface IConstructorParams {
|
||||||
hacking_success_weight?: number;
|
hacking_success_weight?: number;
|
||||||
strength_success_weight?: number;
|
strength_success_weight?: number;
|
||||||
defense_success_weight?: number;
|
defense_success_weight?: number;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { IPlayer } from "./PersonObjects/IPlayer";
|
|||||||
import { Bladeburner } from "./Bladeburner/Bladeburner";
|
import { Bladeburner } from "./Bladeburner/Bladeburner";
|
||||||
import { IEngine } from "./IEngine";
|
import { IEngine } from "./IEngine";
|
||||||
import { IRouter } from "./ui/Router";
|
import { IRouter } from "./ui/Router";
|
||||||
|
import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ import { Corporation } from "./DevMenu/ui/Corporation";
|
|||||||
import { CodingContracts } from "./DevMenu/ui/CodingContracts";
|
import { CodingContracts } from "./DevMenu/ui/CodingContracts";
|
||||||
import { StockMarket } from "./DevMenu/ui/StockMarket";
|
import { StockMarket } from "./DevMenu/ui/StockMarket";
|
||||||
import { Sleeves } from "./DevMenu/ui/Sleeves";
|
import { Sleeves } from "./DevMenu/ui/Sleeves";
|
||||||
|
import { Stanek } from "./DevMenu/ui/Stanek";
|
||||||
import { TimeSkip } from "./DevMenu/ui/TimeSkip";
|
import { TimeSkip } from "./DevMenu/ui/TimeSkip";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
|
|
||||||
@@ -52,6 +54,7 @@ export function DevMenuRoot(props: IProps): React.ReactElement {
|
|||||||
{props.player.hasWseAccount && <StockMarket />}
|
{props.player.hasWseAccount && <StockMarket />}
|
||||||
|
|
||||||
{props.player.sleeves.length > 0 && <Sleeves player={props.player} />}
|
{props.player.sleeves.length > 0 && <Sleeves player={props.player} />}
|
||||||
|
{props.player.augmentations.some((aug) => aug.name === AugmentationNames.StaneksGift1) && <Stanek />}
|
||||||
|
|
||||||
<TimeSkip player={props.player} engine={props.engine} />
|
<TimeSkip player={props.player} engine={props.engine} />
|
||||||
</>
|
</>
|
||||||
|
|||||||
79
src/DevMenu/ui/Stanek.tsx
Normal file
79
src/DevMenu/ui/Stanek.tsx
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { staneksGift } from "../../CotMG/Helper";
|
||||||
|
|
||||||
|
import Accordion from "@mui/material/Accordion";
|
||||||
|
import AccordionSummary from "@mui/material/AccordionSummary";
|
||||||
|
import AccordionDetails from "@mui/material/AccordionDetails";
|
||||||
|
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||||
|
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import { Adjuster } from "./Adjuster";
|
||||||
|
|
||||||
|
export function Stanek(): React.ReactElement {
|
||||||
|
function addCycles(): void {
|
||||||
|
staneksGift.storedCycles = 1e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
function modCycles(modify: number): (x: number) => void {
|
||||||
|
return function (cycles: number): void {
|
||||||
|
staneksGift.storedCycles += cycles * modify;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetCycles(): void {
|
||||||
|
staneksGift.storedCycles = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addCharge(): void {
|
||||||
|
staneksGift.fragments.forEach((f) => (f.charge = 1e21));
|
||||||
|
}
|
||||||
|
|
||||||
|
function modCharge(modify: number): (x: number) => void {
|
||||||
|
return function (cycles: number): void {
|
||||||
|
staneksGift.fragments.forEach((f) => (f.charge += cycles * modify));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetCharge(): void {
|
||||||
|
staneksGift.fragments.forEach((f) => (f.charge = 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Accordion TransitionProps={{ unmountOnExit: true }}>
|
||||||
|
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||||
|
<Typography>Stanek's Gift</Typography>
|
||||||
|
</AccordionSummary>
|
||||||
|
<AccordionDetails>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Adjuster
|
||||||
|
label="cycles"
|
||||||
|
placeholder="amt"
|
||||||
|
tons={addCycles}
|
||||||
|
add={modCycles(1)}
|
||||||
|
subtract={modCycles(-1)}
|
||||||
|
reset={resetCycles}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Adjuster
|
||||||
|
label="all charge"
|
||||||
|
placeholder="amt"
|
||||||
|
tons={addCharge}
|
||||||
|
add={modCharge(1)}
|
||||||
|
subtract={modCharge(-1)}
|
||||||
|
reset={resetCharge}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</AccordionDetails>
|
||||||
|
</Accordion>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -526,4 +526,47 @@ export const FactionInfos: IMap<FactionInfo> = {
|
|||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// prettier-ignore
|
||||||
|
"Church of the Machine God": new FactionInfo(<>
|
||||||
|
{" `` "}<br />
|
||||||
|
{" -odmmNmds: "}<br />
|
||||||
|
{" `hNmo:..-omNh. "}<br />
|
||||||
|
{" yMd` `hNh "}<br />
|
||||||
|
{" mMd oNm "}<br />
|
||||||
|
{" oMNo .mM/ "}<br />
|
||||||
|
{" `dMN+ -mM+ "}<br />
|
||||||
|
{" -mMNo -mN+ "}<br />
|
||||||
|
{" .+- :mMNo/mN/ "}<br />
|
||||||
|
{":yNMd. :NMNNN/ "}<br />
|
||||||
|
{"-mMMMh. /NMMh` "}<br />
|
||||||
|
{" .dMMMd. /NMMMy` "}<br />
|
||||||
|
{" `yMMMd. /NNyNMMh` "}<br />
|
||||||
|
{" `sMMMd. +Nm: +NMMh. "}<br />
|
||||||
|
{" oMMMm- oNm: /NMMd. "}<br />
|
||||||
|
{" +NMMmsMm- :mMMd. "}<br />
|
||||||
|
{" /NMMMm- -mMMd. "}<br />
|
||||||
|
{" /MMMm- -mMMd. "}<br />
|
||||||
|
{" `sMNMMm- .mMmo "}<br />
|
||||||
|
{" `sMd:hMMm. ./. "}<br />
|
||||||
|
{" `yMy` `yNMd` "}<br />
|
||||||
|
{" `hMs` oMMy "}<br />
|
||||||
|
{" `hMh sMN- "}<br />
|
||||||
|
{" /MM- .NMo "}<br />
|
||||||
|
{" +MM: :MM+ "}<br />
|
||||||
|
{" sNNo-.`.-omNy` "}<br />
|
||||||
|
{" -smNNNNmdo- "}<br />
|
||||||
|
{" `..` "}<br /><br />
|
||||||
|
Many cultures predict an end to humanity in the near future, a final
|
||||||
|
Armageddon that will end the world; but we disagree.
|
||||||
|
<br /><br />Note that for this faction, reputation can
|
||||||
|
only be gained by charging Stanek's gift.</>,
|
||||||
|
[],
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export function loadFactions(saveString: string): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function AddToFactions(faction: Faction): void {
|
export function AddToFactions(faction: Faction): void {
|
||||||
const name: string = faction.name;
|
const name: string = faction.name;
|
||||||
Factions[name] = faction;
|
Factions[name] = faction;
|
||||||
}
|
}
|
||||||
@@ -42,7 +42,7 @@ export function initFactions(): void {
|
|||||||
//Resets a faction during (re-)initialization. Saves the favor in the new
|
//Resets a faction during (re-)initialization. Saves the favor in the new
|
||||||
//Faction object and deletes the old Faction Object from "Factions". Then
|
//Faction object and deletes the old Faction Object from "Factions". Then
|
||||||
//reinserts the new Faction object
|
//reinserts the new Faction object
|
||||||
function resetFaction(newFactionObject: Faction): void {
|
export function resetFaction(newFactionObject: Faction): void {
|
||||||
if (!(newFactionObject instanceof Faction)) {
|
if (!(newFactionObject instanceof Faction)) {
|
||||||
throw new Error("Invalid argument 'newFactionObject' passed into resetFaction()");
|
throw new Error("Invalid argument 'newFactionObject' passed into resetFaction()");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { Reputation } from "../../ui/React/Reputation";
|
|||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||||
import { MathJax, MathJaxContext } from "better-react-mathjax";
|
import { MathComponent } from "mathjax-react";
|
||||||
|
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Paper from "@mui/material/Paper";
|
import Paper from "@mui/material/Paper";
|
||||||
@@ -98,9 +98,9 @@ export function DonateOption(props: IProps): React.ReactElement {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Typography>
|
<Typography>
|
||||||
<MathJaxContext>
|
<MathComponent
|
||||||
<MathJax>{`\\(reputation = \\frac{\\text{donation amount} \\cdot \\text{reputation multiplier}}{10^{${digits}}}\\)`}</MathJax>
|
tex={String.raw`reputation = \frac{\text{donation amount} \times \text{reputation multiplier}}{10^{${digits}}}`}
|
||||||
</MathJaxContext>
|
/>
|
||||||
</Typography>
|
</Typography>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { FactionInfo } from "../../Faction/FactionInfo";
|
|||||||
|
|
||||||
import { Reputation } from "../../ui/React/Reputation";
|
import { Reputation } from "../../ui/React/Reputation";
|
||||||
import { Favor } from "../../ui/React/Favor";
|
import { Favor } from "../../ui/React/Favor";
|
||||||
import { MathJax, MathJaxContext } from "better-react-mathjax";
|
import { MathComponent } from "mathjax-react";
|
||||||
|
|
||||||
import makeStyles from "@mui/styles/makeStyles";
|
import makeStyles from "@mui/styles/makeStyles";
|
||||||
import createStyles from "@mui/styles/createStyles";
|
import createStyles from "@mui/styles/createStyles";
|
||||||
@@ -57,14 +57,10 @@ export function Info(props: IProps): React.ReactElement {
|
|||||||
You will have <Favor favor={props.faction.favor + favorGain} /> faction favor after installing an
|
You will have <Favor favor={props.faction.favor + favorGain} /> faction favor after installing an
|
||||||
Augmentation.
|
Augmentation.
|
||||||
</Typography>
|
</Typography>
|
||||||
<MathJaxContext>
|
<MathComponent tex={String.raw`\large{r = \text{total faction reputation}}`} />
|
||||||
<MathJax>{"\\(\\huge{r = \\text{total faction reputation}}\\)"}</MathJax>
|
<MathComponent
|
||||||
</MathJaxContext>
|
tex={String.raw`\large{favor=\left\lfloor\log_{1.02}\left(\frac{r+25000}{25500}\right)\right\rfloor}`}
|
||||||
<MathJaxContext>
|
/>
|
||||||
<MathJax>
|
|
||||||
{"\\(\\huge{favor=\\left\\lfloor\\log_{1.02}\\left(\\frac{r+25000}{25500}\\right)\\right\\rfloor}\\)"}
|
|
||||||
</MathJax>
|
|
||||||
</MathJaxContext>
|
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -85,13 +81,8 @@ export function Info(props: IProps): React.ReactElement {
|
|||||||
favor is gained whenever you install an Augmentation. The amount of favor you gain depends on the total
|
favor is gained whenever you install an Augmentation. The amount of favor you gain depends on the total
|
||||||
amount of reputation you earned with this faction. Across all resets.
|
amount of reputation you earned with this faction. Across all resets.
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<MathComponent tex={String.raw`\large{r = reputation}`} />
|
||||||
<MathJaxContext>
|
<MathComponent tex={String.raw`\large{\Delta r = \Delta r \times \frac{100+favor}{100}}`} />
|
||||||
<MathJax>{"\\(\\huge{r = reputation}\\)"}</MathJax>
|
|
||||||
</MathJaxContext>
|
|
||||||
<MathJaxContext>
|
|
||||||
<MathJax>{"\\(\\huge{\\Delta r = \\Delta r \\times \\frac{100+favor}{100}}\\)"}</MathJax>
|
|
||||||
</MathJaxContext>
|
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export class Gang {
|
|||||||
this.processExperienceGains(cycles);
|
this.processExperienceGains(cycles);
|
||||||
this.processTerritoryAndPowerGains(cycles);
|
this.processTerritoryAndPowerGains(cycles);
|
||||||
this.storedCycles -= cycles;
|
this.storedCycles -= cycles;
|
||||||
} catch (e: any) {
|
} catch (e) {
|
||||||
console.error(`Exception caught when processing Gang: ${e}`);
|
console.error(`Exception caught when processing Gang: ${e}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -344,7 +344,7 @@ export class Gang {
|
|||||||
workerScript.log("ascend", `Ascended Gang member ${member.name}`);
|
workerScript.log("ascend", `Ascended Gang member ${member.name}`);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
} catch (e: any) {
|
} catch (e) {
|
||||||
if (workerScript == null) {
|
if (workerScript == null) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { ITaskParams } from "../ITaskParams";
|
|||||||
* Defines the parameters that can be used to initialize and describe a GangMemberTask
|
* Defines the parameters that can be used to initialize and describe a GangMemberTask
|
||||||
* (defined in Gang.js)
|
* (defined in Gang.js)
|
||||||
*/
|
*/
|
||||||
interface IGangMemberTaskMetadata {
|
export interface IGangMemberTaskMetadata {
|
||||||
/**
|
/**
|
||||||
* Description of the task
|
* Description of the task
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export enum UpgradeType {
|
|||||||
* Defines the parameters that can be used to initialize and describe a GangMemberUpgrade
|
* Defines the parameters that can be used to initialize and describe a GangMemberUpgrade
|
||||||
* (defined in Gang.js)
|
* (defined in Gang.js)
|
||||||
*/
|
*/
|
||||||
interface IGangMemberUpgradeMetadata {
|
export interface IGangMemberUpgradeMetadata {
|
||||||
cost: number;
|
cost: number;
|
||||||
mults: IMults;
|
mults: IMults;
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
@@ -512,6 +512,7 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
|||||||
|
|
||||||
const old = target.moneyMax;
|
const old = target.moneyMax;
|
||||||
target.changeMaximumMoney(upg.value);
|
target.changeMaximumMoney(upg.value);
|
||||||
|
console.log(target.moneyMax / old);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ Cities[CityName.Chongqing].asciiArt = `
|
|||||||
\\ o 78 [kuaigong international]
|
\\ o 78 [kuaigong international]
|
||||||
\\ /
|
\\ /
|
||||||
38 o----x--x------x------A------G--
|
38 o----x--x------x------A------G--
|
||||||
/ 39 | 41 [church]
|
/ 39 | 41 [church]
|
||||||
37 o + 79 o--x--x-C-0
|
37 o + 79 o--x--x-C-0
|
||||||
/ | /
|
/ | /
|
||||||
/ x-----+-----x-----0 [hospital]
|
/ x-----+-----x-----0 [hospital]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import Tooltip from "@mui/material/Tooltip";
|
|||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
import { MathJax, MathJaxContext } from "better-react-mathjax";
|
import { MathComponent } from "mathjax-react";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
p: IPlayer;
|
p: IPlayer;
|
||||||
@@ -19,7 +19,7 @@ export function CoresButton(props: IProps): React.ReactElement {
|
|||||||
return <Button>Upgrade 'home' cores - MAX</Button>;
|
return <Button>Upgrade 'home' cores - MAX</Button>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cost = props.p.getUpgradeHomeCoresCost();
|
const cost = 1e9 * Math.pow(7.5, homeComputer.cpuCores);
|
||||||
|
|
||||||
function buy(): void {
|
function buy(): void {
|
||||||
if (maxCores) return;
|
if (maxCores) return;
|
||||||
@@ -30,13 +30,7 @@ export function CoresButton(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip title={<MathComponent tex={String.raw`\large{cost = 10^9 \times 7.5 ^{\text{cores}}}`} />}>
|
||||||
title={
|
|
||||||
<MathJaxContext>
|
|
||||||
<MathJax>{`\\(\\large{cost = 10^9 \\cdot 7.5 ^{\\text{cores}}}\\)`}</MathJax>
|
|
||||||
</MathJaxContext>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span>
|
<span>
|
||||||
<Button disabled={!props.p.canAfford(cost)} onClick={buy}>
|
<Button disabled={!props.p.canAfford(cost)} onClick={buy}>
|
||||||
Upgrade 'home' cores ({homeComputer.cpuCores} -> {homeComputer.cpuCores + 1}) -
|
Upgrade 'home' cores ({homeComputer.cpuCores} -> {homeComputer.cpuCores + 1}) -
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
|
|||||||
import { purchaseRamForHomeComputer } from "../../Server/ServerPurchases";
|
import { purchaseRamForHomeComputer } from "../../Server/ServerPurchases";
|
||||||
|
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
|
import { MathComponent } from "mathjax-react";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
import { MathJax, MathJaxContext } from "better-react-mathjax";
|
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
p: IPlayer;
|
p: IPlayer;
|
||||||
@@ -29,13 +29,7 @@ export function RamButton(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip title={<MathComponent tex={String.raw`\large{cost = 3.2 \times 10^3 \times 1.58^{log_2{(ram)}}}`} />}>
|
||||||
title={
|
|
||||||
<MathJaxContext>
|
|
||||||
<MathJax>{`\\(\\large{cost = 3.2 \\cdot 10^3 \\cdot 1.58^{log_2{(ram)}}}\\)`}</MathJax>
|
|
||||||
</MathJaxContext>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span>
|
<span>
|
||||||
<Button disabled={!props.p.canAfford(cost)} onClick={buy}>
|
<Button disabled={!props.p.canAfford(cost)} onClick={buy}>
|
||||||
Upgrade 'home' RAM ({numeralWrapper.formatRAM(homeComputer.maxRam)} ->
|
Upgrade 'home' RAM ({numeralWrapper.formatRAM(homeComputer.maxRam)} ->
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ import Button from "@mui/material/Button";
|
|||||||
import { Location } from "../Location";
|
import { Location } from "../Location";
|
||||||
import { CreateCorporationModal } from "../../Corporation/ui/CreateCorporationModal";
|
import { CreateCorporationModal } from "../../Corporation/ui/CreateCorporationModal";
|
||||||
import { LocationName } from "../data/LocationNames";
|
import { LocationName } from "../data/LocationNames";
|
||||||
|
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
||||||
|
import { Factions } from "../../Faction/Factions";
|
||||||
|
import { joinFaction } from "../../Faction/FactionHelpers";
|
||||||
|
|
||||||
import { use } from "../../ui/Context";
|
import { use } from "../../ui/Context";
|
||||||
|
|
||||||
@@ -109,6 +112,21 @@ export function SpecialLocation(props: IProps): React.ReactElement {
|
|||||||
return <Button onClick={handleResleeving}>Re-Sleeve</Button>;
|
return <Button onClick={handleResleeving}>Re-Sleeve</Button>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleCotMG(): void {
|
||||||
|
const faction = Factions["Church of the Machine God"];
|
||||||
|
if (!player.factions.includes("Church of the Machine God")) {
|
||||||
|
joinFaction(faction);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
!player.augmentations.some((a) => a.name === AugmentationNames.StaneksGift1) &&
|
||||||
|
!player.queuedAugmentations.some((a) => a.name === AugmentationNames.StaneksGift1)
|
||||||
|
) {
|
||||||
|
player.queueAugmentation(AugmentationNames.StaneksGift1);
|
||||||
|
}
|
||||||
|
|
||||||
|
router.toFaction(faction);
|
||||||
|
}
|
||||||
|
|
||||||
function renderCotMG(): React.ReactElement {
|
function renderCotMG(): React.ReactElement {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const symbol = <Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>
|
const symbol = <Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>
|
||||||
@@ -140,15 +158,56 @@ export function SpecialLocation(props: IProps): React.ReactElement {
|
|||||||
{" sNNo-.`.-omNy` "}<br />
|
{" sNNo-.`.-omNy` "}<br />
|
||||||
{" -smNNNNmdo- "}<br />
|
{" -smNNNNmdo- "}<br />
|
||||||
{" `..` "}</Typography>
|
{" `..` "}</Typography>
|
||||||
|
if (player.factions.includes("Church of the Machine God")) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Typography>
|
||||||
|
<i>Allison "Mother" Stanek: Welcome back my child!</i>
|
||||||
|
</Typography>
|
||||||
|
{symbol}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!player.canAccessCotMG()) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Typography>
|
||||||
|
A decrepit altar stands in the middle of a dilapidated church.
|
||||||
|
<br />
|
||||||
|
<br />A symbol is carved in the altar.
|
||||||
|
</Typography>
|
||||||
|
<br />
|
||||||
|
{symbol}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
player.augmentations.filter((a) => a.name !== AugmentationNames.NeuroFluxGovernor).length > 0 ||
|
||||||
|
player.queuedAugmentations.filter((a) => a.name !== AugmentationNames.NeuroFluxGovernor).length > 0
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Typography>
|
||||||
|
<i>
|
||||||
|
Allison "Mother" Stanek: Begone you filth! My gift must be the first modification that your body should
|
||||||
|
have!
|
||||||
|
</i>
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Typography>
|
<Typography>
|
||||||
A decrepit altar stands in the middle of a dilapidated church.
|
<i>
|
||||||
<br />
|
Allison "Mother" Stanek: Welcome child, I see your body is pure. Are you ready to ascend beyond our human
|
||||||
<br />A symbol is carved in the altar.
|
form? If you are, accept my gift.
|
||||||
|
</i>
|
||||||
</Typography>
|
</Typography>
|
||||||
<br />
|
<Button onClick={handleCotMG}>Accept Stanek's Gift</Button>
|
||||||
{symbol}
|
{symbol}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ export function TechVendorLocation(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<br />
|
|
||||||
{purchaseServerButtons}
|
{purchaseServerButtons}
|
||||||
<br />
|
<br />
|
||||||
<Typography>
|
<Typography>
|
||||||
|
|||||||
@@ -13,14 +13,12 @@ import { Reviver } from "../utils/JSONReviver";
|
|||||||
function sendMessage(msg: Message, forced = false): void {
|
function sendMessage(msg: Message, forced = false): void {
|
||||||
msg.recvd = true;
|
msg.recvd = true;
|
||||||
if (forced || !Settings.SuppressMessages) {
|
if (forced || !Settings.SuppressMessages) {
|
||||||
showMessage(msg.filename);
|
showMessage(msg);
|
||||||
}
|
}
|
||||||
addMessageToServer(msg, "home");
|
addMessageToServer(msg, "home");
|
||||||
}
|
}
|
||||||
|
|
||||||
function showMessage(name: string): void {
|
function showMessage(msg: Message): void {
|
||||||
const msg = Messages[name];
|
|
||||||
if (!msg) throw new Error("trying to display unexistent message");
|
|
||||||
const txt =
|
const txt =
|
||||||
"Message received from unknown sender: <br><br>" +
|
"Message received from unknown sender: <br><br>" +
|
||||||
"<i>" +
|
"<i>" +
|
||||||
@@ -41,11 +39,12 @@ function addMessageToServer(msg: Message, serverHostname: string): void {
|
|||||||
}
|
}
|
||||||
for (let i = 0; i < server.messages.length; ++i) {
|
for (let i = 0; i < server.messages.length; ++i) {
|
||||||
const other = server.messages[i];
|
const other = server.messages[i];
|
||||||
if (msg.filename === other) {
|
if (typeof other === "string") continue;
|
||||||
|
if (msg.filename === other.filename) {
|
||||||
return; //Already exists
|
return; //Already exists
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
server.messages.push(msg.filename);
|
server.messages.push(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Checks if any of the 'timed' messages should be sent
|
//Checks if any of the 'timed' messages should be sent
|
||||||
@@ -217,4 +216,4 @@ function initMessages(): void {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Messages, checkForMessagesToSend, showMessage, loadMessages, initMessages };
|
export { Messages, checkForMessagesToSend, sendMessage, showMessage, loadMessages, initMessages, Message };
|
||||||
|
|||||||
11
src/Milestones/Quest.ts
Normal file
11
src/Milestones/Quest.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { Milestone } from "./Milestone";
|
||||||
|
|
||||||
|
export class Quest {
|
||||||
|
title: string;
|
||||||
|
milestones: Milestone[];
|
||||||
|
|
||||||
|
constructor(title: string, milestones: Milestone[]) {
|
||||||
|
this.title = title;
|
||||||
|
this.milestones = milestones;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,6 +54,15 @@ export const RamCostConstants: IMap<number> = {
|
|||||||
ScriptGangApiBaseRamCost: 4,
|
ScriptGangApiBaseRamCost: 4,
|
||||||
|
|
||||||
ScriptBladeburnerApiBaseRamCost: 4,
|
ScriptBladeburnerApiBaseRamCost: 4,
|
||||||
|
|
||||||
|
ScriptStanekCharge: 0.4,
|
||||||
|
ScriptStanekFragmentDefinitions: 0,
|
||||||
|
ScriptStanekPlacedFragments: 5,
|
||||||
|
ScriptStanekClear: 0,
|
||||||
|
ScriptStanekCanPlace: 0.5,
|
||||||
|
ScriptStanekPlace: 5,
|
||||||
|
ScriptStanekFragmentAt: 2,
|
||||||
|
ScriptStanekDeleteAt: 0.15,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const RamCosts: IMap<any> = {
|
export const RamCosts: IMap<any> = {
|
||||||
@@ -313,6 +322,17 @@ export const RamCosts: IMap<any> = {
|
|||||||
purchaseSleeveAug: () => RamCostConstants.ScriptSleeveBaseRamCost,
|
purchaseSleeveAug: () => RamCostConstants.ScriptSleeveBaseRamCost,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
stanek: {
|
||||||
|
charge: () => RamCostConstants.ScriptStanekCharge,
|
||||||
|
fragmentDefinitions: () => RamCostConstants.ScriptStanekFragmentDefinitions,
|
||||||
|
placedFragments: () => RamCostConstants.ScriptStanekPlacedFragments,
|
||||||
|
clear: () => RamCostConstants.ScriptStanekClear,
|
||||||
|
canPlace: () => RamCostConstants.ScriptStanekCanPlace,
|
||||||
|
place: () => RamCostConstants.ScriptStanekPlace,
|
||||||
|
fragmentAt: () => RamCostConstants.ScriptStanekFragmentAt,
|
||||||
|
deleteAt: () => RamCostConstants.ScriptStanekDeleteAt,
|
||||||
|
},
|
||||||
|
|
||||||
heart: {
|
heart: {
|
||||||
// Easter egg function
|
// Easter egg function
|
||||||
break: () => 0,
|
break: () => 0,
|
||||||
|
|||||||
@@ -106,11 +106,6 @@ export class WorkerScript {
|
|||||||
*/
|
*/
|
||||||
hostname: string;
|
hostname: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* Function called when the script ends.
|
|
||||||
*/
|
|
||||||
atExit: any;
|
|
||||||
|
|
||||||
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;
|
||||||
@@ -137,13 +132,15 @@ export class WorkerScript {
|
|||||||
if (!found) {
|
if (!found) {
|
||||||
throw new Error(`WorkerScript constructed with invalid script filename: ${this.name}`);
|
throw new Error(`WorkerScript constructed with invalid script filename: ${this.name}`);
|
||||||
}
|
}
|
||||||
this.scriptRef = runningScriptObj;
|
|
||||||
this.args = runningScriptObj.args.slice();
|
|
||||||
this.env = new Environment(null);
|
this.env = new Environment(null);
|
||||||
if (typeof nsFuncsGenerator === "function") {
|
if (typeof nsFuncsGenerator === "function") {
|
||||||
this.env.vars = nsFuncsGenerator(this);
|
this.env.vars = nsFuncsGenerator(this);
|
||||||
}
|
}
|
||||||
this.env.set("args", runningScriptObj.args.slice());
|
this.env.set("args", runningScriptObj.args.slice());
|
||||||
|
|
||||||
|
this.scriptRef = runningScriptObj;
|
||||||
|
this.args = runningScriptObj.args.slice();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { RunningScript } from "../Script/RunningScript";
|
|||||||
import { GetServer } from "../Server/AllServers";
|
import { GetServer } from "../Server/AllServers";
|
||||||
|
|
||||||
import { compareArrays } from "../utils/helpers/compareArrays";
|
import { compareArrays } from "../utils/helpers/compareArrays";
|
||||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
|
||||||
|
|
||||||
export function killWorkerScript(runningScriptObj: RunningScript, hostname: string, rerenderUi?: boolean): boolean;
|
export function killWorkerScript(runningScriptObj: RunningScript, hostname: string, rerenderUi?: boolean): boolean;
|
||||||
export function killWorkerScript(workerScript: WorkerScript): boolean;
|
export function killWorkerScript(workerScript: WorkerScript): boolean;
|
||||||
@@ -68,16 +67,6 @@ function killWorkerScriptByPid(pid: number, rerenderUi = true): boolean {
|
|||||||
function stopAndCleanUpWorkerScript(workerScript: WorkerScript, rerenderUi = true): void {
|
function stopAndCleanUpWorkerScript(workerScript: WorkerScript, rerenderUi = true): void {
|
||||||
workerScript.env.stopFlag = true;
|
workerScript.env.stopFlag = true;
|
||||||
killNetscriptDelay(workerScript);
|
killNetscriptDelay(workerScript);
|
||||||
if (typeof workerScript.atExit === "function") {
|
|
||||||
try {
|
|
||||||
workerScript.atExit();
|
|
||||||
} catch (e: any) {
|
|
||||||
dialogBoxCreate(
|
|
||||||
`Error trying to call atExit for script ${workerScript.name} on ${workerScript.hostname} ${workerScript.scriptRef.args} ${e}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
workerScript.atExit = undefined;
|
|
||||||
}
|
|
||||||
removeWorkerScript(workerScript, rerenderUi);
|
removeWorkerScript(workerScript, rerenderUi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,224 +0,0 @@
|
|||||||
import { INetscriptHelper } from "./INetscriptHelper";
|
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
||||||
import { purchaseAugmentation } from "../Faction/FactionHelpers";
|
|
||||||
import { startWorkerScript } from "../NetscriptWorker";
|
|
||||||
import { Augmentation } from "../Augmentation/Augmentation";
|
|
||||||
import { Augmentations } from "../Augmentation/Augmentations";
|
|
||||||
import { augmentationExists, installAugmentations } from "../Augmentation/AugmentationHelpers";
|
|
||||||
import { prestigeAugmentation } from "../Prestige";
|
|
||||||
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
|
||||||
import { killWorkerScript } from "../Netscript/killWorkerScript";
|
|
||||||
import { CONSTANTS } from "../Constants";
|
|
||||||
import { isString } from "../utils/helpers/isString";
|
|
||||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
|
||||||
import { RunningScript } from "../Script/RunningScript";
|
|
||||||
|
|
||||||
export interface INetscriptAugmentations {
|
|
||||||
getOwnedAugmentations(purchased?: any): any;
|
|
||||||
getOwnedSourceFiles(): any;
|
|
||||||
getAugmentationsFromFaction(facname: any): any;
|
|
||||||
getAugmentationCost(name: any): any;
|
|
||||||
getAugmentationPrereq(name: any): any;
|
|
||||||
getAugmentationPrice(name: any): any;
|
|
||||||
getAugmentationRepReq(name: any): any;
|
|
||||||
getAugmentationStats(name: any): any;
|
|
||||||
purchaseAugmentation(faction: any, name: any): any;
|
|
||||||
softReset(cbScript: any): any;
|
|
||||||
installAugmentations(cbScript: any): any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function NetscriptAugmentations(
|
|
||||||
player: IPlayer,
|
|
||||||
workerScript: WorkerScript,
|
|
||||||
helper: INetscriptHelper,
|
|
||||||
): INetscriptAugmentations {
|
|
||||||
const getAugmentation = function (func: any, name: any): Augmentation {
|
|
||||||
if (!augmentationExists(name)) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(func, `Invalid augmentation: '${name}'`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Augmentations[name];
|
|
||||||
};
|
|
||||||
const runAfterReset = function (cbScript = null): void {
|
|
||||||
//Run a script after reset
|
|
||||||
if (cbScript && isString(cbScript)) {
|
|
||||||
const home = player.getHomeComputer();
|
|
||||||
for (const script of home.scripts) {
|
|
||||||
if (script.filename === cbScript) {
|
|
||||||
const ramUsage = script.ramUsage;
|
|
||||||
const ramAvailable = home.maxRam - home.ramUsed;
|
|
||||||
if (ramUsage > ramAvailable) {
|
|
||||||
return; // Not enough RAM
|
|
||||||
}
|
|
||||||
const runningScriptObj = new RunningScript(script, []); // No args
|
|
||||||
runningScriptObj.threads = 1; // Only 1 thread
|
|
||||||
startWorkerScript(runningScriptObj, home);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
getOwnedAugmentations: function (purchased: any = false): any {
|
|
||||||
helper.updateDynamicRam("getOwnedAugmentations", getRamCost("getOwnedAugmentations"));
|
|
||||||
helper.checkSingularityAccess("getOwnedAugmentations", 3);
|
|
||||||
const res = [];
|
|
||||||
for (let i = 0; i < player.augmentations.length; ++i) {
|
|
||||||
res.push(player.augmentations[i].name);
|
|
||||||
}
|
|
||||||
if (purchased) {
|
|
||||||
for (let i = 0; i < player.queuedAugmentations.length; ++i) {
|
|
||||||
res.push(player.queuedAugmentations[i].name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
},
|
|
||||||
getOwnedSourceFiles: function (): any {
|
|
||||||
helper.updateDynamicRam("getOwnedSourceFiles", getRamCost("getOwnedSourceFiles"));
|
|
||||||
helper.checkSingularityAccess("getOwnedSourceFiles", 3);
|
|
||||||
const res = [];
|
|
||||||
for (let i = 0; i < player.sourceFiles.length; ++i) {
|
|
||||||
res.push({
|
|
||||||
n: player.sourceFiles[i].n,
|
|
||||||
lvl: player.sourceFiles[i].lvl,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
},
|
|
||||||
getAugmentationsFromFaction: function (facname: any): any {
|
|
||||||
helper.updateDynamicRam("getAugmentationsFromFaction", getRamCost("getAugmentationsFromFaction"));
|
|
||||||
helper.checkSingularityAccess("getAugmentationsFromFaction", 3);
|
|
||||||
const faction = helper.getFaction("getAugmentationsFromFaction", facname);
|
|
||||||
|
|
||||||
// If player has a gang with this faction, return all augmentations.
|
|
||||||
if (player.hasGangWith(facname)) {
|
|
||||||
const res = [];
|
|
||||||
for (const augName in Augmentations) {
|
|
||||||
const aug = Augmentations[augName];
|
|
||||||
if (!aug.isSpecial) {
|
|
||||||
res.push(augName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
return faction.augmentations.slice();
|
|
||||||
},
|
|
||||||
getAugmentationCost: function (name: any): any {
|
|
||||||
helper.updateDynamicRam("getAugmentationCost", getRamCost("getAugmentationCost"));
|
|
||||||
helper.checkSingularityAccess("getAugmentationCost", 3);
|
|
||||||
const aug = getAugmentation("getAugmentationCost", name);
|
|
||||||
return [aug.baseRepRequirement, aug.baseCost];
|
|
||||||
},
|
|
||||||
getAugmentationPrereq: function (name: any): any {
|
|
||||||
helper.updateDynamicRam("getAugmentationPrereq", getRamCost("getAugmentationPrereq"));
|
|
||||||
helper.checkSingularityAccess("getAugmentationPrereq", 3);
|
|
||||||
const aug = getAugmentation("getAugmentationPrereq", name);
|
|
||||||
return aug.prereqs.slice();
|
|
||||||
},
|
|
||||||
getAugmentationPrice: function (name: any): any {
|
|
||||||
helper.updateDynamicRam("getAugmentationPrice", getRamCost("getAugmentationPrice"));
|
|
||||||
helper.checkSingularityAccess("getAugmentationPrice", 3);
|
|
||||||
const aug = getAugmentation("getAugmentationPrice", name);
|
|
||||||
return aug.baseCost;
|
|
||||||
},
|
|
||||||
getAugmentationRepReq: function (name: any): any {
|
|
||||||
helper.updateDynamicRam("getAugmentationRepReq", getRamCost("getAugmentationRepReq"));
|
|
||||||
helper.checkSingularityAccess("getAugmentationRepReq", 3);
|
|
||||||
const aug = getAugmentation("getAugmentationRepReq", name);
|
|
||||||
return aug.baseRepRequirement;
|
|
||||||
},
|
|
||||||
getAugmentationStats: function (name: any): any {
|
|
||||||
helper.updateDynamicRam("getAugmentationStats", getRamCost("getAugmentationStats"));
|
|
||||||
helper.checkSingularityAccess("getAugmentationStats", 3);
|
|
||||||
const aug = getAugmentation("getAugmentationStats", name);
|
|
||||||
return Object.assign({}, aug.mults);
|
|
||||||
},
|
|
||||||
purchaseAugmentation: function (faction: any, name: any): any {
|
|
||||||
helper.updateDynamicRam("purchaseAugmentation", getRamCost("purchaseAugmentation"));
|
|
||||||
helper.checkSingularityAccess("purchaseAugmentation", 3);
|
|
||||||
const fac = helper.getFaction("purchaseAugmentation", faction);
|
|
||||||
const aug = getAugmentation("purchaseAugmentation", name);
|
|
||||||
|
|
||||||
let augs = [];
|
|
||||||
if (player.hasGangWith(faction)) {
|
|
||||||
for (const augName in Augmentations) {
|
|
||||||
const tempAug = Augmentations[augName];
|
|
||||||
if (!tempAug.isSpecial) {
|
|
||||||
augs.push(augName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
augs = fac.augmentations;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!augs.includes(name)) {
|
|
||||||
workerScript.log("purchaseAugmentation", `Faction '${faction}' does not have the '${name}' augmentation.`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isNeuroflux = aug.name === AugmentationNames.NeuroFluxGovernor;
|
|
||||||
if (!isNeuroflux) {
|
|
||||||
for (let j = 0; j < player.queuedAugmentations.length; ++j) {
|
|
||||||
if (player.queuedAugmentations[j].name === aug.name) {
|
|
||||||
workerScript.log("purchaseAugmentation", `You already have the '${name}' augmentation.`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (let j = 0; j < player.augmentations.length; ++j) {
|
|
||||||
if (player.augmentations[j].name === aug.name) {
|
|
||||||
workerScript.log("purchaseAugmentation", `You already have the '${name}' augmentation.`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fac.playerReputation < aug.baseRepRequirement) {
|
|
||||||
workerScript.log("purchaseAugmentation", `You do not have enough reputation with '${fac.name}'.`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = purchaseAugmentation(aug, fac, true);
|
|
||||||
workerScript.log("purchaseAugmentation", res);
|
|
||||||
if (isString(res) && res.startsWith("You purchased")) {
|
|
||||||
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
softReset: function (cbScript: any): any {
|
|
||||||
helper.updateDynamicRam("softReset", getRamCost("softReset"));
|
|
||||||
helper.checkSingularityAccess("softReset", 3);
|
|
||||||
|
|
||||||
workerScript.log("softReset", "Soft resetting. This will cause this script to be killed");
|
|
||||||
setTimeout(() => {
|
|
||||||
prestigeAugmentation();
|
|
||||||
runAfterReset(cbScript);
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
// Prevent workerScript from "finishing execution naturally"
|
|
||||||
workerScript.running = false;
|
|
||||||
killWorkerScript(workerScript);
|
|
||||||
},
|
|
||||||
installAugmentations: function (cbScript: any): any {
|
|
||||||
helper.updateDynamicRam("installAugmentations", getRamCost("installAugmentations"));
|
|
||||||
helper.checkSingularityAccess("installAugmentations", 3);
|
|
||||||
|
|
||||||
if (player.queuedAugmentations.length === 0) {
|
|
||||||
workerScript.log("installAugmentations", "You do not have any Augmentations to be installed.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain);
|
|
||||||
workerScript.log("installAugmentations", "Installing Augmentations. This will cause this script to be killed");
|
|
||||||
setTimeout(() => {
|
|
||||||
installAugmentations();
|
|
||||||
runAfterReset(cbScript);
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
workerScript.running = false; // Prevent workerScript from "finishing execution naturally"
|
|
||||||
killWorkerScript(workerScript);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,403 +0,0 @@
|
|||||||
import { INetscriptHelper } from "./INetscriptHelper";
|
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
||||||
import { Bladeburner } from "../Bladeburner/Bladeburner";
|
|
||||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
|
||||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
|
||||||
|
|
||||||
export interface INetscriptBladeburner {
|
|
||||||
getContractNames(): any;
|
|
||||||
getOperationNames(): any;
|
|
||||||
getBlackOpNames(): any;
|
|
||||||
getBlackOpRank(name?: any): any;
|
|
||||||
getGeneralActionNames(): any;
|
|
||||||
getSkillNames(): any;
|
|
||||||
startAction(type?: any, name?: any): any;
|
|
||||||
stopBladeburnerAction(): any;
|
|
||||||
getCurrentAction(): any;
|
|
||||||
getActionTime(type?: any, name?: any): any;
|
|
||||||
getActionEstimatedSuccessChance(type?: any, name?: any): any;
|
|
||||||
getActionRepGain(type?: any, name?: any, level?: any): any;
|
|
||||||
getActionCountRemaining(type?: any, name?: any): any;
|
|
||||||
getActionMaxLevel(type?: any, name?: any): any;
|
|
||||||
getActionCurrentLevel(type?: any, name?: any): any;
|
|
||||||
getActionAutolevel(type?: any, name?: any): any;
|
|
||||||
setActionAutolevel(type?: any, name?: any, autoLevel?: any): any;
|
|
||||||
setActionLevel(type?: any, name?: any, level?: any): any;
|
|
||||||
getRank(): any;
|
|
||||||
getSkillPoints(): any;
|
|
||||||
getSkillLevel(skillName?: any): any;
|
|
||||||
getSkillUpgradeCost(skillName?: any): any;
|
|
||||||
upgradeSkill(skillName: any): any;
|
|
||||||
getTeamSize(type?: any, name?: any): any;
|
|
||||||
setTeamSize(type?: any, name?: any, size?: any): any;
|
|
||||||
getCityEstimatedPopulation(cityName: any): any;
|
|
||||||
getCityEstimatedCommunities(cityName: any): any;
|
|
||||||
getCityChaos(cityName: any): any;
|
|
||||||
getCity(): any;
|
|
||||||
switchCity(cityName: any): any;
|
|
||||||
getStamina(): any;
|
|
||||||
joinBladeburnerFaction(): any;
|
|
||||||
joinBladeburnerDivision(): any;
|
|
||||||
getBonusTime(): any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function NetscriptBladeburner(
|
|
||||||
player: IPlayer,
|
|
||||||
workerScript: WorkerScript,
|
|
||||||
helper: INetscriptHelper,
|
|
||||||
): INetscriptBladeburner {
|
|
||||||
const checkBladeburnerAccess = function (func: any, skipjoined: any = false): void {
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
|
||||||
const apiAccess =
|
|
||||||
player.bitNodeN === 7 ||
|
|
||||||
player.sourceFiles.some((a) => {
|
|
||||||
return a.n === 7;
|
|
||||||
});
|
|
||||||
if (!apiAccess) {
|
|
||||||
const apiDenied = `You do not currently have access to the Bladeburner API. You must either be in BitNode-7 or have Source-File 7.`;
|
|
||||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, apiDenied);
|
|
||||||
}
|
|
||||||
if (!skipjoined) {
|
|
||||||
const bladeburnerAccess = bladeburner instanceof Bladeburner;
|
|
||||||
if (!bladeburnerAccess) {
|
|
||||||
const bladeburnerDenied = `You must be a member of the Bladeburner division to use this API.`;
|
|
||||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, bladeburnerDenied);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkBladeburnerCity = function (func: any, city: any): void {
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
|
||||||
if (!bladeburner.cities.hasOwnProperty(city)) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, `Invalid city: ${city}`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getBladeburnerActionObject = function (func: any, type: any, name: any): any {
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
|
||||||
const actionId = bladeburner.getActionIdFromTypeAndName(type, name);
|
|
||||||
if (!actionId) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, `Invalid action type='${type}', name='${name}'`);
|
|
||||||
}
|
|
||||||
const actionObj = bladeburner.getActionObject(actionId);
|
|
||||||
if (!actionObj) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, `Invalid action type='${type}', name='${name}'`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return actionObj;
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
getContractNames: function (): any {
|
|
||||||
helper.updateDynamicRam("getContractNames", getRamCost("bladeburner", "getContractNames"));
|
|
||||||
checkBladeburnerAccess("getContractNames");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return bladeburner.getContractNamesNetscriptFn();
|
|
||||||
},
|
|
||||||
getOperationNames: function (): any {
|
|
||||||
helper.updateDynamicRam("getOperationNames", getRamCost("bladeburner", "getOperationNames"));
|
|
||||||
checkBladeburnerAccess("getOperationNames");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return bladeburner.getOperationNamesNetscriptFn();
|
|
||||||
},
|
|
||||||
getBlackOpNames: function (): any {
|
|
||||||
helper.updateDynamicRam("getBlackOpNames", getRamCost("bladeburner", "getBlackOpNames"));
|
|
||||||
checkBladeburnerAccess("getBlackOpNames");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return bladeburner.getBlackOpNamesNetscriptFn();
|
|
||||||
},
|
|
||||||
getBlackOpRank: function (name: any = ""): any {
|
|
||||||
helper.updateDynamicRam("getBlackOpRank", getRamCost("bladeburner", "getBlackOpRank"));
|
|
||||||
checkBladeburnerAccess("getBlackOpRank");
|
|
||||||
const action: any = getBladeburnerActionObject("getBlackOpRank", "blackops", name);
|
|
||||||
return action.reqdRank;
|
|
||||||
},
|
|
||||||
getGeneralActionNames: function (): any {
|
|
||||||
helper.updateDynamicRam("getGeneralActionNames", getRamCost("bladeburner", "getGeneralActionNames"));
|
|
||||||
checkBladeburnerAccess("getGeneralActionNames");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return bladeburner.getGeneralActionNamesNetscriptFn();
|
|
||||||
},
|
|
||||||
getSkillNames: function (): any {
|
|
||||||
helper.updateDynamicRam("getSkillNames", getRamCost("bladeburner", "getSkillNames"));
|
|
||||||
checkBladeburnerAccess("getSkillNames");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return bladeburner.getSkillNamesNetscriptFn();
|
|
||||||
},
|
|
||||||
startAction: function (type: any = "", name: any = ""): any {
|
|
||||||
helper.updateDynamicRam("startAction", getRamCost("bladeburner", "startAction"));
|
|
||||||
checkBladeburnerAccess("startAction");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
try {
|
|
||||||
return bladeburner.startActionNetscriptFn(player, type, name, workerScript);
|
|
||||||
} catch (e: any) {
|
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.startAction", e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
stopBladeburnerAction: function (): any {
|
|
||||||
helper.updateDynamicRam("stopBladeburnerAction", getRamCost("bladeburner", "stopBladeburnerAction"));
|
|
||||||
checkBladeburnerAccess("stopBladeburnerAction");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return bladeburner.resetAction();
|
|
||||||
},
|
|
||||||
getCurrentAction: function (): any {
|
|
||||||
helper.updateDynamicRam("getCurrentAction", getRamCost("bladeburner", "getCurrentAction"));
|
|
||||||
checkBladeburnerAccess("getCurrentAction");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return bladeburner.getTypeAndNameFromActionId(bladeburner.action);
|
|
||||||
},
|
|
||||||
getActionTime: function (type: any = "", name: any = ""): any {
|
|
||||||
helper.updateDynamicRam("getActionTime", getRamCost("bladeburner", "getActionTime"));
|
|
||||||
checkBladeburnerAccess("getActionTime");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
try {
|
|
||||||
return bladeburner.getActionTimeNetscriptFn(player, type, name, workerScript);
|
|
||||||
} catch (e: any) {
|
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.getActionTime", e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getActionEstimatedSuccessChance: function (type: any = "", name: any = ""): any {
|
|
||||||
helper.updateDynamicRam(
|
|
||||||
"getActionEstimatedSuccessChance",
|
|
||||||
getRamCost("bladeburner", "getActionEstimatedSuccessChance"),
|
|
||||||
);
|
|
||||||
checkBladeburnerAccess("getActionEstimatedSuccessChance");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
try {
|
|
||||||
return bladeburner.getActionEstimatedSuccessChanceNetscriptFn(player, type, name, workerScript);
|
|
||||||
} catch (e: any) {
|
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.getActionEstimatedSuccessChance", e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getActionRepGain: function (type: any = "", name: any = "", level: any): any {
|
|
||||||
helper.updateDynamicRam("getActionRepGain", getRamCost("bladeburner", "getActionRepGain"));
|
|
||||||
checkBladeburnerAccess("getActionRepGain");
|
|
||||||
const action = getBladeburnerActionObject("getActionRepGain", type, name);
|
|
||||||
let rewardMultiplier;
|
|
||||||
if (level == null || isNaN(level)) {
|
|
||||||
rewardMultiplier = Math.pow(action.rewardFac, action.level - 1);
|
|
||||||
} else {
|
|
||||||
rewardMultiplier = Math.pow(action.rewardFac, level - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return action.rankGain * rewardMultiplier * BitNodeMultipliers.BladeburnerRank;
|
|
||||||
},
|
|
||||||
getActionCountRemaining: function (type: any = "", name: any = ""): any {
|
|
||||||
helper.updateDynamicRam("getActionCountRemaining", getRamCost("bladeburner", "getActionCountRemaining"));
|
|
||||||
checkBladeburnerAccess("getActionCountRemaining");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
try {
|
|
||||||
return bladeburner.getActionCountRemainingNetscriptFn(type, name, workerScript);
|
|
||||||
} catch (e: any) {
|
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.getActionCountRemaining", e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getActionMaxLevel: function (type: any = "", name: any = ""): any {
|
|
||||||
helper.updateDynamicRam("getActionMaxLevel", getRamCost("bladeburner", "getActionMaxLevel"));
|
|
||||||
checkBladeburnerAccess("getActionMaxLevel");
|
|
||||||
const action = getBladeburnerActionObject("getActionMaxLevel", type, name);
|
|
||||||
return action.maxLevel;
|
|
||||||
},
|
|
||||||
getActionCurrentLevel: function (type: any = "", name: any = ""): any {
|
|
||||||
helper.updateDynamicRam("getActionCurrentLevel", getRamCost("bladeburner", "getActionCurrentLevel"));
|
|
||||||
checkBladeburnerAccess("getActionCurrentLevel");
|
|
||||||
const action = getBladeburnerActionObject("getActionCurrentLevel", type, name);
|
|
||||||
return action.level;
|
|
||||||
},
|
|
||||||
getActionAutolevel: function (type: any = "", name: any = ""): any {
|
|
||||||
helper.updateDynamicRam("getActionAutolevel", getRamCost("bladeburner", "getActionAutolevel"));
|
|
||||||
checkBladeburnerAccess("getActionAutolevel");
|
|
||||||
const action = getBladeburnerActionObject("getActionCurrentLevel", type, name);
|
|
||||||
return action.autoLevel;
|
|
||||||
},
|
|
||||||
setActionAutolevel: function (type: any = "", name: any = "", autoLevel: any = true): any {
|
|
||||||
helper.updateDynamicRam("setActionAutolevel", getRamCost("bladeburner", "setActionAutolevel"));
|
|
||||||
checkBladeburnerAccess("setActionAutolevel");
|
|
||||||
const action = getBladeburnerActionObject("setActionAutolevel", type, name);
|
|
||||||
action.autoLevel = autoLevel;
|
|
||||||
},
|
|
||||||
setActionLevel: function (type: any = "", name: any = "", level: any = 1): any {
|
|
||||||
helper.updateDynamicRam("setActionLevel", getRamCost("bladeburner", "setActionLevel"));
|
|
||||||
checkBladeburnerAccess("setActionLevel");
|
|
||||||
const action = getBladeburnerActionObject("setActionLevel", type, name);
|
|
||||||
if (level < 1 || level > action.maxLevel) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(
|
|
||||||
"bladeburner.setActionLevel",
|
|
||||||
`Level must be between 1 and ${action.maxLevel}, is ${level}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
action.level = level;
|
|
||||||
},
|
|
||||||
getRank: function (): any {
|
|
||||||
helper.updateDynamicRam("getRank", getRamCost("bladeburner", "getRank"));
|
|
||||||
checkBladeburnerAccess("getRank");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return bladeburner.rank;
|
|
||||||
},
|
|
||||||
getSkillPoints: function (): any {
|
|
||||||
helper.updateDynamicRam("getSkillPoints", getRamCost("bladeburner", "getSkillPoints"));
|
|
||||||
checkBladeburnerAccess("getSkillPoints");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return bladeburner.skillPoints;
|
|
||||||
},
|
|
||||||
getSkillLevel: function (skillName: any = ""): any {
|
|
||||||
helper.updateDynamicRam("getSkillLevel", getRamCost("bladeburner", "getSkillLevel"));
|
|
||||||
checkBladeburnerAccess("getSkillLevel");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
try {
|
|
||||||
return bladeburner.getSkillLevelNetscriptFn(skillName, workerScript);
|
|
||||||
} catch (e: any) {
|
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.getSkillLevel", e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getSkillUpgradeCost: function (skillName: any = ""): any {
|
|
||||||
helper.updateDynamicRam("getSkillUpgradeCost", getRamCost("bladeburner", "getSkillUpgradeCost"));
|
|
||||||
checkBladeburnerAccess("getSkillUpgradeCost");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
try {
|
|
||||||
return bladeburner.getSkillUpgradeCostNetscriptFn(skillName, workerScript);
|
|
||||||
} catch (e: any) {
|
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.getSkillUpgradeCost", e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
upgradeSkill: function (skillName: any): any {
|
|
||||||
helper.updateDynamicRam("upgradeSkill", getRamCost("bladeburner", "upgradeSkill"));
|
|
||||||
checkBladeburnerAccess("upgradeSkill");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
try {
|
|
||||||
return bladeburner.upgradeSkillNetscriptFn(skillName, workerScript);
|
|
||||||
} catch (e: any) {
|
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.upgradeSkill", e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getTeamSize: function (type: any = "", name: any = ""): any {
|
|
||||||
helper.updateDynamicRam("getTeamSize", getRamCost("bladeburner", "getTeamSize"));
|
|
||||||
checkBladeburnerAccess("getTeamSize");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
try {
|
|
||||||
return bladeburner.getTeamSizeNetscriptFn(type, name, workerScript);
|
|
||||||
} catch (e: any) {
|
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.getTeamSize", e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setTeamSize: function (type: any = "", name: any = "", size: any): any {
|
|
||||||
helper.updateDynamicRam("setTeamSize", getRamCost("bladeburner", "setTeamSize"));
|
|
||||||
checkBladeburnerAccess("setTeamSize");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
try {
|
|
||||||
return bladeburner.setTeamSizeNetscriptFn(type, name, size, workerScript);
|
|
||||||
} catch (e: any) {
|
|
||||||
throw helper.makeRuntimeErrorMsg("bladeburner.setTeamSize", e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getCityEstimatedPopulation: function (cityName: any): any {
|
|
||||||
helper.updateDynamicRam("getCityEstimatedPopulation", getRamCost("bladeburner", "getCityEstimatedPopulation"));
|
|
||||||
checkBladeburnerAccess("getCityEstimatedPopulation");
|
|
||||||
checkBladeburnerCity("getCityEstimatedPopulation", cityName);
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return bladeburner.cities[cityName].popEst;
|
|
||||||
},
|
|
||||||
getCityEstimatedCommunities: function (cityName: any): any {
|
|
||||||
helper.updateDynamicRam("getCityEstimatedCommunities", getRamCost("bladeburner", "getCityEstimatedCommunities"));
|
|
||||||
checkBladeburnerAccess("getCityEstimatedCommunities");
|
|
||||||
checkBladeburnerCity("getCityEstimatedCommunities", cityName);
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return bladeburner.cities[cityName].commsEst;
|
|
||||||
},
|
|
||||||
getCityChaos: function (cityName: any): any {
|
|
||||||
helper.updateDynamicRam("getCityChaos", getRamCost("bladeburner", "getCityChaos"));
|
|
||||||
checkBladeburnerAccess("getCityChaos");
|
|
||||||
checkBladeburnerCity("getCityChaos", cityName);
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return bladeburner.cities[cityName].chaos;
|
|
||||||
},
|
|
||||||
getCity: function (): any {
|
|
||||||
helper.updateDynamicRam("getCity", getRamCost("bladeburner", "getCity"));
|
|
||||||
checkBladeburnerAccess("getCityChaos");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return bladeburner.city;
|
|
||||||
},
|
|
||||||
switchCity: function (cityName: any): any {
|
|
||||||
helper.updateDynamicRam("switchCity", getRamCost("bladeburner", "switchCity"));
|
|
||||||
checkBladeburnerAccess("switchCity");
|
|
||||||
checkBladeburnerCity("switchCity", cityName);
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return (bladeburner.city = cityName);
|
|
||||||
},
|
|
||||||
getStamina: function (): any {
|
|
||||||
helper.updateDynamicRam("getStamina", getRamCost("bladeburner", "getStamina"));
|
|
||||||
checkBladeburnerAccess("getStamina");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return [bladeburner.stamina, bladeburner.maxStamina];
|
|
||||||
},
|
|
||||||
joinBladeburnerFaction: function (): any {
|
|
||||||
helper.updateDynamicRam("joinBladeburnerFaction", getRamCost("bladeburner", "joinBladeburnerFaction"));
|
|
||||||
checkBladeburnerAccess("joinBladeburnerFaction", true);
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return bladeburner.joinBladeburnerFactionNetscriptFn(workerScript);
|
|
||||||
},
|
|
||||||
joinBladeburnerDivision: function (): any {
|
|
||||||
helper.updateDynamicRam("joinBladeburnerDivision", getRamCost("bladeburner", "joinBladeburnerDivision"));
|
|
||||||
if (player.bitNodeN === 7 || player.sourceFileLvl(7) > 0) {
|
|
||||||
if (player.bitNodeN === 8) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (player.bladeburner instanceof Bladeburner) {
|
|
||||||
return true; // Already member
|
|
||||||
} else if (
|
|
||||||
player.strength >= 100 &&
|
|
||||||
player.defense >= 100 &&
|
|
||||||
player.dexterity >= 100 &&
|
|
||||||
player.agility >= 100
|
|
||||||
) {
|
|
||||||
player.bladeburner = new Bladeburner(player);
|
|
||||||
workerScript.log("joinBladeburnerDivision", "You have been accepted into the Bladeburner division");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
workerScript.log(
|
|
||||||
"joinBladeburnerDivision",
|
|
||||||
"You do not meet the requirements for joining the Bladeburner division",
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getBonusTime: function (): any {
|
|
||||||
helper.updateDynamicRam("getBonusTime", getRamCost("bladeburner", "getBonusTime"));
|
|
||||||
checkBladeburnerAccess("getBonusTime");
|
|
||||||
const bladeburner = player.bladeburner;
|
|
||||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
|
||||||
return Math.round(bladeburner.storedCycles / 5);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
import { INetscriptHelper } from "./INetscriptHelper";
|
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
||||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
|
||||||
import { is2DArray } from "../utils/helpers/is2DArray";
|
|
||||||
import { CodingContract } from "../CodingContracts";
|
|
||||||
|
|
||||||
export interface INetscriptCodingContract {
|
|
||||||
attempt(answer: any, fn: any, ip?: any, options?: { returnReward: any }): any;
|
|
||||||
getContractType(fn: any, ip?: any): any;
|
|
||||||
getData(fn: any, ip?: any): any;
|
|
||||||
getDescription(fn: any, ip?: any): any;
|
|
||||||
getNumTriesRemaining(fn: any, ip?: any): any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function NetscriptCodingContract(
|
|
||||||
player: IPlayer,
|
|
||||||
workerScript: WorkerScript,
|
|
||||||
helper: INetscriptHelper,
|
|
||||||
): INetscriptCodingContract {
|
|
||||||
const getCodingContract = function (func: any, ip: any, fn: any): CodingContract {
|
|
||||||
const server = helper.getServer(ip, func);
|
|
||||||
const contract = server.getContract(fn);
|
|
||||||
if (contract == null) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(`codingcontract.${func}`, `Cannot find contract '${fn}' on server '${ip}'`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return contract;
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
attempt: function (answer: any, fn: any, ip: any = workerScript.hostname, { returnReward }: any = {}): any {
|
|
||||||
helper.updateDynamicRam("attempt", getRamCost("codingcontract", "attempt"));
|
|
||||||
const contract = getCodingContract("attempt", ip, fn);
|
|
||||||
|
|
||||||
// Convert answer to string. If the answer is a 2D array, then we have to
|
|
||||||
// manually add brackets for the inner arrays
|
|
||||||
if (is2DArray(answer)) {
|
|
||||||
const answerComponents = [];
|
|
||||||
for (let i = 0; i < answer.length; ++i) {
|
|
||||||
answerComponents.push(["[", answer[i].toString(), "]"].join(""));
|
|
||||||
}
|
|
||||||
|
|
||||||
answer = answerComponents.join(",");
|
|
||||||
} else {
|
|
||||||
answer = String(answer);
|
|
||||||
}
|
|
||||||
|
|
||||||
const creward = contract.reward;
|
|
||||||
if (creward === null) throw new Error("Somehow solved a contract that didn't have a reward");
|
|
||||||
|
|
||||||
const serv = helper.getServer(ip, "codingcontract.attempt");
|
|
||||||
if (contract.isSolution(answer)) {
|
|
||||||
const reward = player.gainCodingContractReward(creward, contract.getDifficulty());
|
|
||||||
workerScript.log("attempt", `Successfully completed Coding Contract '${fn}'. Reward: ${reward}`);
|
|
||||||
serv.removeContract(fn);
|
|
||||||
return returnReward ? reward : true;
|
|
||||||
} else {
|
|
||||||
++contract.tries;
|
|
||||||
if (contract.tries >= contract.getMaxNumTries()) {
|
|
||||||
workerScript.log("attempt", `Coding Contract attempt '${fn}' failed. Contract is now self-destructing`);
|
|
||||||
serv.removeContract(fn);
|
|
||||||
} else {
|
|
||||||
workerScript.log(
|
|
||||||
"attempt",
|
|
||||||
`Coding Contract attempt '${fn}' failed. ${contract.getMaxNumTries() - contract.tries} attempts remaining.`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnReward ? "" : false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getContractType: function (fn: any, ip: any = workerScript.hostname): any {
|
|
||||||
helper.updateDynamicRam("getContractType", getRamCost("codingcontract", "getContractType"));
|
|
||||||
const contract = getCodingContract("getContractType", ip, fn);
|
|
||||||
return contract.getType();
|
|
||||||
},
|
|
||||||
getData: function (fn: any, ip: any = workerScript.hostname): any {
|
|
||||||
helper.updateDynamicRam("getData", getRamCost("codingcontract", "getData"));
|
|
||||||
const contract = getCodingContract("getData", ip, fn);
|
|
||||||
const data = contract.getData();
|
|
||||||
if (data.constructor === Array) {
|
|
||||||
// For two dimensional arrays, we have to copy the internal arrays using
|
|
||||||
// slice() as well. As of right now, no contract has arrays that have
|
|
||||||
// more than two dimensions
|
|
||||||
const copy = data.slice();
|
|
||||||
for (let i = 0; i < copy.length; ++i) {
|
|
||||||
if (data[i].constructor === Array) {
|
|
||||||
copy[i] = data[i].slice();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return copy;
|
|
||||||
} else {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getDescription: function (fn: any, ip: any = workerScript.hostname): any {
|
|
||||||
helper.updateDynamicRam("getDescription", getRamCost("codingcontract", "getDescription"));
|
|
||||||
const contract = getCodingContract("getDescription", ip, fn);
|
|
||||||
return contract.getDescription();
|
|
||||||
},
|
|
||||||
getNumTriesRemaining: function (fn: any, ip: any = workerScript.hostname): any {
|
|
||||||
helper.updateDynamicRam("getNumTriesRemaining", getRamCost("codingcontract", "getNumTriesRemaining"));
|
|
||||||
const contract = getCodingContract("getNumTriesRemaining", ip, fn);
|
|
||||||
return contract.getMaxNumTries() - contract.tries;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,305 +0,0 @@
|
|||||||
import { INetscriptHelper } from "./INetscriptHelper";
|
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
||||||
|
|
||||||
import { OfficeSpace } from "../Corporation/OfficeSpace";
|
|
||||||
import { Employee } from "../Corporation/Employee";
|
|
||||||
import { Product } from "../Corporation/Product";
|
|
||||||
import { Material } from "../Corporation/Material";
|
|
||||||
import { Warehouse } from "../Corporation/Warehouse";
|
|
||||||
import { IIndustry } from "../Corporation/IIndustry";
|
|
||||||
|
|
||||||
import {
|
|
||||||
NewIndustry,
|
|
||||||
NewCity,
|
|
||||||
UnlockUpgrade,
|
|
||||||
LevelUpgrade,
|
|
||||||
IssueDividends,
|
|
||||||
SellMaterial,
|
|
||||||
SellProduct,
|
|
||||||
SetSmartSupply,
|
|
||||||
BuyMaterial,
|
|
||||||
AssignJob,
|
|
||||||
UpgradeOfficeSize,
|
|
||||||
ThrowParty,
|
|
||||||
PurchaseWarehouse,
|
|
||||||
UpgradeWarehouse,
|
|
||||||
BuyCoffee,
|
|
||||||
HireAdVert,
|
|
||||||
MakeProduct,
|
|
||||||
Research,
|
|
||||||
ExportMaterial,
|
|
||||||
CancelExportMaterial,
|
|
||||||
SetMaterialMarketTA1,
|
|
||||||
SetMaterialMarketTA2,
|
|
||||||
SetProductMarketTA1,
|
|
||||||
SetProductMarketTA2,
|
|
||||||
} from "../Corporation/Actions";
|
|
||||||
import { CorporationUnlockUpgrades } from "../Corporation/data/CorporationUnlockUpgrades";
|
|
||||||
import { CorporationUpgrades } from "../Corporation/data/CorporationUpgrades";
|
|
||||||
|
|
||||||
export interface INetscriptCorporation {
|
|
||||||
expandIndustry(industryName: any, divisionName: any): any;
|
|
||||||
expandCity(divisionName: any, cityName: any): any;
|
|
||||||
unlockUpgrade(upgradeName: any): any;
|
|
||||||
levelUpgrade(upgradeName: any): any;
|
|
||||||
issueDividends(percent: any): any;
|
|
||||||
sellMaterial(divisionName: any, cityName: any, materialName: any, amt: any, price: any): any;
|
|
||||||
sellProduct(divisionName: any, cityName: any, productName: any, amt: any, price: any, all: any): any;
|
|
||||||
discontinueProduct(divisionName: any, productName: any): any;
|
|
||||||
setSmartSupply(divisionName: any, cityName: any, enabled: any): any;
|
|
||||||
buyMaterial(divisionName: any, cityName: any, materialName: any, amt: any): any;
|
|
||||||
employees(divisionName: any, cityName: any): any;
|
|
||||||
assignJob(divisionName: any, cityName: any, employeeName: any, job: any): any;
|
|
||||||
hireEmployee(divisionName: any, cityName: any): any;
|
|
||||||
upgradeOfficeSize(divisionName: any, cityName: any, size: any): any;
|
|
||||||
throwParty(divisionName: any, cityName: any, costPerEmployee: any): any;
|
|
||||||
purchaseWarehouse(divisionName: any, cityName: any): any;
|
|
||||||
upgradeWarehouse(divisionName: any, cityName: any): any;
|
|
||||||
buyCoffee(divisionName: any, cityName: any): any;
|
|
||||||
hireAdVert(divisionName: any): any;
|
|
||||||
makeProduct(divisionName: any, cityName: any, productName: any, designInvest: any, marketingInvest: any): any;
|
|
||||||
research(divisionName: any, researchName: any): any;
|
|
||||||
exportMaterial(
|
|
||||||
sourceDivision: any,
|
|
||||||
sourceCity: any,
|
|
||||||
targetDivision: any,
|
|
||||||
targetCity: any,
|
|
||||||
materialName: any,
|
|
||||||
amt: any,
|
|
||||||
): any;
|
|
||||||
cancelExportMaterial(
|
|
||||||
sourceDivision: any,
|
|
||||||
sourceCity: any,
|
|
||||||
targetDivision: any,
|
|
||||||
targetCity: any,
|
|
||||||
materialName: any,
|
|
||||||
amt: any,
|
|
||||||
): any;
|
|
||||||
setMaterialMarketTA1(divisionName: any, cityName: any, materialName: any, on: any): any;
|
|
||||||
setMaterialMarketTA2(divisionName: any, cityName: any, materialName: any, on: any): any;
|
|
||||||
setProductMarketTA1(divisionName: any, productName: any, on: any): any;
|
|
||||||
setProductMarketTA2(divisionName: any, productName: any, on: any): any;
|
|
||||||
getDivision(divisionName: any): any;
|
|
||||||
getOffice(divisionName: any, cityName: any): any;
|
|
||||||
getWarehouse(divisionName: any, cityName: any): any;
|
|
||||||
getMaterial(divisionName: any, cityName: any, materialName: any): any;
|
|
||||||
getProduct(divisionName: any, productName: any): any;
|
|
||||||
getEmployee(divisionName: any, cityName: any, employeeName: any): any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function NetscriptCorporation(
|
|
||||||
player: IPlayer,
|
|
||||||
workerScript: WorkerScript,
|
|
||||||
helper: INetscriptHelper,
|
|
||||||
): INetscriptCorporation {
|
|
||||||
function getDivision(divisionName: any): IIndustry {
|
|
||||||
const corporation = player.corporation;
|
|
||||||
if (corporation === null) throw new Error("cannot be called without a corporation");
|
|
||||||
const division = corporation.divisions.find((div) => div.name === divisionName);
|
|
||||||
if (division === undefined) throw new Error(`No division named '${divisionName}'`);
|
|
||||||
return division;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOffice(divisionName: any, cityName: any): OfficeSpace {
|
|
||||||
const division = getDivision(divisionName);
|
|
||||||
if (!(cityName in division.offices)) throw new Error(`Invalid city name '${cityName}'`);
|
|
||||||
const office = division.offices[cityName];
|
|
||||||
if (office === 0) throw new Error(`${division.name} has not expanded to '${cityName}'`);
|
|
||||||
return office;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getWarehouse(divisionName: any, cityName: any): Warehouse {
|
|
||||||
const division = getDivision(divisionName);
|
|
||||||
if (!(cityName in division.warehouses)) throw new Error(`Invalid city name '${cityName}'`);
|
|
||||||
const warehouse = division.warehouses[cityName];
|
|
||||||
if (warehouse === 0) throw new Error(`${division.name} has not expanded to '${cityName}'`);
|
|
||||||
return warehouse;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getMaterial(divisionName: any, cityName: any, materialName: any): Material {
|
|
||||||
const warehouse = getWarehouse(divisionName, cityName);
|
|
||||||
const material = warehouse.materials[materialName];
|
|
||||||
if (material === undefined) throw new Error(`Invalid material name: '${materialName}'`);
|
|
||||||
return material;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getProduct(divisionName: any, productName: any): Product {
|
|
||||||
const division = getDivision(divisionName);
|
|
||||||
const product = division.products[productName];
|
|
||||||
if (product === undefined) throw new Error(`Invalid product name: '${productName}'`);
|
|
||||||
return product;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getEmployee(divisionName: any, cityName: any, employeeName: any): Employee {
|
|
||||||
const office = getOffice(divisionName, cityName);
|
|
||||||
const employee = office.employees.find((e) => e.name === employeeName);
|
|
||||||
if (employee === undefined) throw new Error(`Invalid employee name: '${employeeName}'`);
|
|
||||||
return employee;
|
|
||||||
}
|
|
||||||
// Hi, if you're reading this you're a bit nosy.
|
|
||||||
// There's a corporation API but it's very imbalanced right now.
|
|
||||||
// It's here so players can test with if they want.
|
|
||||||
return {
|
|
||||||
expandIndustry: function (industryName: any, divisionName: any): any {
|
|
||||||
const corporation = player.corporation;
|
|
||||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
|
||||||
NewIndustry(corporation, industryName, divisionName);
|
|
||||||
},
|
|
||||||
expandCity: function (divisionName: any, cityName: any): any {
|
|
||||||
const division = getDivision(divisionName);
|
|
||||||
const corporation = player.corporation;
|
|
||||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
|
||||||
NewCity(corporation, division, cityName);
|
|
||||||
},
|
|
||||||
unlockUpgrade: function (upgradeName: any): any {
|
|
||||||
const upgrade = Object.values(CorporationUnlockUpgrades).find((upgrade) => upgrade[2] === upgradeName);
|
|
||||||
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
|
||||||
const corporation = player.corporation;
|
|
||||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
|
||||||
UnlockUpgrade(corporation, upgrade);
|
|
||||||
},
|
|
||||||
levelUpgrade: function (upgradeName: any): any {
|
|
||||||
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade[4] === upgradeName);
|
|
||||||
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
|
||||||
const corporation = player.corporation;
|
|
||||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
|
||||||
LevelUpgrade(corporation, upgrade);
|
|
||||||
},
|
|
||||||
issueDividends: function (percent: any): any {
|
|
||||||
const corporation = player.corporation;
|
|
||||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
|
||||||
IssueDividends(corporation, percent);
|
|
||||||
},
|
|
||||||
sellMaterial: function (divisionName: any, cityName: any, materialName: any, amt: any, price: any): any {
|
|
||||||
const material = getMaterial(divisionName, cityName, materialName);
|
|
||||||
SellMaterial(material, amt, price);
|
|
||||||
},
|
|
||||||
sellProduct: function (divisionName: any, cityName: any, productName: any, amt: any, price: any, all: any): any {
|
|
||||||
const product = getProduct(divisionName, productName);
|
|
||||||
SellProduct(product, cityName, amt, price, all);
|
|
||||||
},
|
|
||||||
discontinueProduct: function (divisionName: any, productName: any): any {
|
|
||||||
getDivision(divisionName).discontinueProduct(getProduct(divisionName, productName));
|
|
||||||
},
|
|
||||||
setSmartSupply: function (divisionName: any, cityName: any, enabled: any): any {
|
|
||||||
const warehouse = getWarehouse(divisionName, cityName);
|
|
||||||
SetSmartSupply(warehouse, enabled);
|
|
||||||
},
|
|
||||||
// setSmartSupplyUseLeftovers: function (): any {},
|
|
||||||
buyMaterial: function (divisionName: any, cityName: any, materialName: any, amt: any): any {
|
|
||||||
const material = getMaterial(divisionName, cityName, materialName);
|
|
||||||
BuyMaterial(material, amt);
|
|
||||||
},
|
|
||||||
employees: function (divisionName: any, cityName: any): any {
|
|
||||||
const office = getOffice(divisionName, cityName);
|
|
||||||
return office.employees.map((e) => Object.assign({}, e));
|
|
||||||
},
|
|
||||||
assignJob: function (divisionName: any, cityName: any, employeeName: any, job: any): any {
|
|
||||||
const employee = getEmployee(divisionName, cityName, employeeName);
|
|
||||||
AssignJob(employee, job);
|
|
||||||
},
|
|
||||||
hireEmployee: function (divisionName: any, cityName: any): any {
|
|
||||||
const office = getOffice(divisionName, cityName);
|
|
||||||
office.hireRandomEmployee();
|
|
||||||
},
|
|
||||||
upgradeOfficeSize: function (divisionName: any, cityName: any, size: any): any {
|
|
||||||
const office = getOffice(divisionName, cityName);
|
|
||||||
const corporation = player.corporation;
|
|
||||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
|
||||||
UpgradeOfficeSize(corporation, office, size);
|
|
||||||
},
|
|
||||||
throwParty: function (divisionName: any, cityName: any, costPerEmployee: any): any {
|
|
||||||
const office = getOffice(divisionName, cityName);
|
|
||||||
const corporation = player.corporation;
|
|
||||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
|
||||||
ThrowParty(corporation, office, costPerEmployee);
|
|
||||||
},
|
|
||||||
purchaseWarehouse: function (divisionName: any, cityName: any): any {
|
|
||||||
const corporation = player.corporation;
|
|
||||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
|
||||||
PurchaseWarehouse(corporation, getDivision(divisionName), cityName);
|
|
||||||
},
|
|
||||||
upgradeWarehouse: function (divisionName: any, cityName: any): any {
|
|
||||||
const corporation = player.corporation;
|
|
||||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
|
||||||
UpgradeWarehouse(corporation, getDivision(divisionName), getWarehouse(divisionName, cityName));
|
|
||||||
},
|
|
||||||
buyCoffee: function (divisionName: any, cityName: any): any {
|
|
||||||
const corporation = player.corporation;
|
|
||||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
|
||||||
BuyCoffee(corporation, getDivision(divisionName), getOffice(divisionName, cityName));
|
|
||||||
},
|
|
||||||
hireAdVert: function (divisionName: any): any {
|
|
||||||
const corporation = player.corporation;
|
|
||||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
|
||||||
HireAdVert(corporation, getDivision(divisionName), getOffice(divisionName, "Sector-12"));
|
|
||||||
},
|
|
||||||
makeProduct: function (
|
|
||||||
divisionName: any,
|
|
||||||
cityName: any,
|
|
||||||
productName: any,
|
|
||||||
designInvest: any,
|
|
||||||
marketingInvest: any,
|
|
||||||
): any {
|
|
||||||
const corporation = player.corporation;
|
|
||||||
if (corporation === null) throw new Error("Should not be called without a corporation");
|
|
||||||
MakeProduct(corporation, getDivision(divisionName), cityName, productName, designInvest, marketingInvest);
|
|
||||||
},
|
|
||||||
research: function (divisionName: any, researchName: any): any {
|
|
||||||
Research(getDivision(divisionName), researchName);
|
|
||||||
},
|
|
||||||
exportMaterial: function (
|
|
||||||
sourceDivision: any,
|
|
||||||
sourceCity: any,
|
|
||||||
targetDivision: any,
|
|
||||||
targetCity: any,
|
|
||||||
materialName: any,
|
|
||||||
amt: any,
|
|
||||||
): any {
|
|
||||||
ExportMaterial(targetDivision, targetCity, getMaterial(sourceDivision, sourceCity, materialName), amt + "");
|
|
||||||
},
|
|
||||||
cancelExportMaterial: function (
|
|
||||||
sourceDivision: any,
|
|
||||||
sourceCity: any,
|
|
||||||
targetDivision: any,
|
|
||||||
targetCity: any,
|
|
||||||
materialName: any,
|
|
||||||
amt: any,
|
|
||||||
): any {
|
|
||||||
CancelExportMaterial(targetDivision, targetCity, getMaterial(sourceDivision, sourceCity, materialName), amt + "");
|
|
||||||
},
|
|
||||||
setMaterialMarketTA1: function (divisionName: any, cityName: any, materialName: any, on: any): any {
|
|
||||||
SetMaterialMarketTA1(getMaterial(divisionName, cityName, materialName), on);
|
|
||||||
},
|
|
||||||
setMaterialMarketTA2: function (divisionName: any, cityName: any, materialName: any, on: any) {
|
|
||||||
SetMaterialMarketTA2(getMaterial(divisionName, cityName, materialName), on);
|
|
||||||
},
|
|
||||||
setProductMarketTA1: function (divisionName: any, productName: any, on: any): any {
|
|
||||||
SetProductMarketTA1(getProduct(divisionName, productName), on);
|
|
||||||
},
|
|
||||||
setProductMarketTA2: function (divisionName: any, productName: any, on: any) {
|
|
||||||
SetProductMarketTA2(getProduct(divisionName, productName), on);
|
|
||||||
},
|
|
||||||
// If you modify these objects you will affect them for real, it's not
|
|
||||||
// copies.
|
|
||||||
getDivision: function (divisionName: any): any {
|
|
||||||
return getDivision(divisionName);
|
|
||||||
},
|
|
||||||
getOffice: function (divisionName: any, cityName: any): any {
|
|
||||||
return getOffice(divisionName, cityName);
|
|
||||||
},
|
|
||||||
getWarehouse: function (divisionName: any, cityName: any): any {
|
|
||||||
return getWarehouse(divisionName, cityName);
|
|
||||||
},
|
|
||||||
getMaterial: function (divisionName: any, cityName: any, materialName: any): any {
|
|
||||||
return getMaterial(divisionName, cityName, materialName);
|
|
||||||
},
|
|
||||||
getProduct: function (divisionName: any, productName: any): any {
|
|
||||||
return getProduct(divisionName, productName);
|
|
||||||
},
|
|
||||||
getEmployee: function (divisionName: any, cityName: any, employeeName: any): any {
|
|
||||||
return getEmployee(divisionName, cityName, employeeName);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
import { toNative } from "./toNative";
|
|
||||||
import * as libarg from "arg";
|
|
||||||
|
|
||||||
export function Flags(vargs: string[]): any {
|
|
||||||
return function (data: any): any {
|
|
||||||
data = toNative(data);
|
|
||||||
// We always want the help flag.
|
|
||||||
const args: {
|
|
||||||
[key: string]: any;
|
|
||||||
} = {};
|
|
||||||
|
|
||||||
for (const d of data) {
|
|
||||||
let t: any = String;
|
|
||||||
if (typeof d[1] === "number") {
|
|
||||||
t = Number;
|
|
||||||
} else if (typeof d[1] === "boolean") {
|
|
||||||
t = Boolean;
|
|
||||||
} else if (Array.isArray(d[1])) {
|
|
||||||
t = [String];
|
|
||||||
}
|
|
||||||
const numDashes = d[0].length > 1 ? 2 : 1;
|
|
||||||
args["-".repeat(numDashes) + d[0]] = t;
|
|
||||||
}
|
|
||||||
const ret = libarg(args, { argv: vargs });
|
|
||||||
for (const d of data) {
|
|
||||||
if (!ret.hasOwnProperty("--" + d[0]) || !ret.hasOwnProperty("-" + d[0])) ret[d[0]] = d[1];
|
|
||||||
}
|
|
||||||
for (const key of Object.keys(ret)) {
|
|
||||||
if (!key.startsWith("-")) continue;
|
|
||||||
const value = ret[key];
|
|
||||||
delete ret[key];
|
|
||||||
const numDashes = key.length === 2 ? 1 : 2;
|
|
||||||
ret[key.slice(numDashes)] = value;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,187 +0,0 @@
|
|||||||
import { INetscriptHelper } from "./INetscriptHelper";
|
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
||||||
import { calculateServerGrowth } from "../Server/formulas/grow";
|
|
||||||
import {
|
|
||||||
calculateMoneyGainRate,
|
|
||||||
calculateLevelUpgradeCost,
|
|
||||||
calculateRamUpgradeCost,
|
|
||||||
calculateCoreUpgradeCost,
|
|
||||||
calculateNodeCost,
|
|
||||||
} from "../Hacknet/formulas/HacknetNodes";
|
|
||||||
import {
|
|
||||||
calculateHashGainRate as HScalculateHashGainRate,
|
|
||||||
calculateLevelUpgradeCost as HScalculateLevelUpgradeCost,
|
|
||||||
calculateRamUpgradeCost as HScalculateRamUpgradeCost,
|
|
||||||
calculateCoreUpgradeCost as HScalculateCoreUpgradeCost,
|
|
||||||
calculateCacheUpgradeCost as HScalculateCacheUpgradeCost,
|
|
||||||
calculateServerCost as HScalculateServerCost,
|
|
||||||
} from "../Hacknet/formulas/HacknetServers";
|
|
||||||
import { HacknetNodeConstants, HacknetServerConstants } from "../Hacknet/data/Constants";
|
|
||||||
import { calculateSkill, calculateExp } from "../PersonObjects/formulas/skill";
|
|
||||||
import {
|
|
||||||
calculateHackingChance,
|
|
||||||
calculateHackingExpGain,
|
|
||||||
calculatePercentMoneyHacked,
|
|
||||||
calculateHackingTime,
|
|
||||||
calculateGrowTime,
|
|
||||||
calculateWeakenTime,
|
|
||||||
} from "../Hacking";
|
|
||||||
|
|
||||||
export interface INetscriptFormulas {
|
|
||||||
basic: {
|
|
||||||
calculateSkill(exp: any, mult?: any): any;
|
|
||||||
calculateExp(skill: any, mult?: any): any;
|
|
||||||
hackChance(server: any, player: any): any;
|
|
||||||
hackExp(server: any, player: any): any;
|
|
||||||
hackPercent(server: any, player: any): any;
|
|
||||||
growPercent(server: any, threads: any, player: any, cores?: any): any;
|
|
||||||
hackTime(server: any, player: any): any;
|
|
||||||
growTime(server: any, player: any): any;
|
|
||||||
weakenTime(server: any, player: any): any;
|
|
||||||
};
|
|
||||||
hacknetNodes: {
|
|
||||||
moneyGainRate(level: any, ram: any, cores: any, mult?: any): any;
|
|
||||||
levelUpgradeCost(startingLevel: any, extraLevels?: any, costMult?: any): any;
|
|
||||||
ramUpgradeCost(startingRam: any, extraLevels?: any, costMult?: any): any;
|
|
||||||
coreUpgradeCost(startingCore: any, extraCores?: any, costMult?: any): any;
|
|
||||||
hacknetNodeCost(n: any, mult: any): any;
|
|
||||||
constants(): any;
|
|
||||||
};
|
|
||||||
hacknetServers: {
|
|
||||||
hashGainRate(level: any, ramUsed: any, maxRam: any, cores: any, mult?: any): any;
|
|
||||||
levelUpgradeCost(startingLevel: any, extraLevels?: any, costMult?: any): any;
|
|
||||||
ramUpgradeCost(startingRam: any, extraLevels?: any, costMult?: any): any;
|
|
||||||
coreUpgradeCost(startingCore: any, extraCores?: any, costMult?: any): any;
|
|
||||||
cacheUpgradeCost(startingCache: any, extraCache?: any): any;
|
|
||||||
hashUpgradeCost(upgName: any, level: any): any;
|
|
||||||
hacknetServerCost(n: any, mult: any): any;
|
|
||||||
constants(): any;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function NetscriptFormulas(
|
|
||||||
player: IPlayer,
|
|
||||||
workerScript: WorkerScript,
|
|
||||||
helper: INetscriptHelper,
|
|
||||||
): INetscriptFormulas {
|
|
||||||
const checkFormulasAccess = function (func: any, n: any): void {
|
|
||||||
if (
|
|
||||||
(player.sourceFileLvl(5) < 1 && player.bitNodeN !== 5) ||
|
|
||||||
(player.sourceFileLvl(n) < 1 && player.bitNodeN !== n)
|
|
||||||
) {
|
|
||||||
let extra = "";
|
|
||||||
if (n !== 5) {
|
|
||||||
extra = ` and Source-File ${n}-1`;
|
|
||||||
}
|
|
||||||
throw helper.makeRuntimeErrorMsg(`formulas.${func}`, `Requires Source-File 5-1${extra} to run.`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
basic: {
|
|
||||||
calculateSkill: function (exp: any, mult: any = 1): any {
|
|
||||||
checkFormulasAccess("basic.calculateSkill", 5);
|
|
||||||
return calculateSkill(exp, mult);
|
|
||||||
},
|
|
||||||
calculateExp: function (skill: any, mult: any = 1): any {
|
|
||||||
checkFormulasAccess("basic.calculateExp", 5);
|
|
||||||
return calculateExp(skill, mult);
|
|
||||||
},
|
|
||||||
hackChance: function (server: any, player: any): any {
|
|
||||||
checkFormulasAccess("basic.hackChance", 5);
|
|
||||||
return calculateHackingChance(server, player);
|
|
||||||
},
|
|
||||||
hackExp: function (server: any, player: any): any {
|
|
||||||
checkFormulasAccess("basic.hackExp", 5);
|
|
||||||
return calculateHackingExpGain(server, player);
|
|
||||||
},
|
|
||||||
hackPercent: function (server: any, player: any): any {
|
|
||||||
checkFormulasAccess("basic.hackPercent", 5);
|
|
||||||
return calculatePercentMoneyHacked(server, player);
|
|
||||||
},
|
|
||||||
growPercent: function (server: any, threads: any, player: any, cores: any = 1): any {
|
|
||||||
checkFormulasAccess("basic.growPercent", 5);
|
|
||||||
return calculateServerGrowth(server, threads, player, cores);
|
|
||||||
},
|
|
||||||
hackTime: function (server: any, player: any): any {
|
|
||||||
checkFormulasAccess("basic.hackTime", 5);
|
|
||||||
return calculateHackingTime(server, player);
|
|
||||||
},
|
|
||||||
growTime: function (server: any, player: any): any {
|
|
||||||
checkFormulasAccess("basic.growTime", 5);
|
|
||||||
return calculateGrowTime(server, player);
|
|
||||||
},
|
|
||||||
weakenTime: function (server: any, player: any): any {
|
|
||||||
checkFormulasAccess("basic.weakenTime", 5);
|
|
||||||
return calculateWeakenTime(server, player);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
hacknetNodes: {
|
|
||||||
moneyGainRate: function (level: any, ram: any, cores: any, mult: any = 1): any {
|
|
||||||
checkFormulasAccess("hacknetNodes.moneyGainRate", 5);
|
|
||||||
return calculateMoneyGainRate(level, ram, cores, mult);
|
|
||||||
},
|
|
||||||
levelUpgradeCost: function (startingLevel: any, extraLevels: any = 1, costMult: any = 1): any {
|
|
||||||
checkFormulasAccess("hacknetNodes.levelUpgradeCost", 5);
|
|
||||||
return calculateLevelUpgradeCost(startingLevel, extraLevels, costMult);
|
|
||||||
},
|
|
||||||
ramUpgradeCost: function (startingRam: any, extraLevels: any = 1, costMult: any = 1): any {
|
|
||||||
checkFormulasAccess("hacknetNodes.ramUpgradeCost", 5);
|
|
||||||
return calculateRamUpgradeCost(startingRam, extraLevels, costMult);
|
|
||||||
},
|
|
||||||
coreUpgradeCost: function (startingCore: any, extraCores: any = 1, costMult: any = 1): any {
|
|
||||||
checkFormulasAccess("hacknetNodes.coreUpgradeCost", 5);
|
|
||||||
return calculateCoreUpgradeCost(startingCore, extraCores, costMult);
|
|
||||||
},
|
|
||||||
hacknetNodeCost: function (n: any, mult: any): any {
|
|
||||||
checkFormulasAccess("hacknetNodes.hacknetNodeCost", 5);
|
|
||||||
return calculateNodeCost(n, mult);
|
|
||||||
},
|
|
||||||
constants: function (): any {
|
|
||||||
checkFormulasAccess("hacknetNodes.constants", 5);
|
|
||||||
return Object.assign({}, HacknetNodeConstants);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
hacknetServers: {
|
|
||||||
hashGainRate: function (level: any, ramUsed: any, maxRam: any, cores: any, mult: any = 1): any {
|
|
||||||
checkFormulasAccess("hacknetServers.hashGainRate", 9);
|
|
||||||
return HScalculateHashGainRate(level, ramUsed, maxRam, cores, mult);
|
|
||||||
},
|
|
||||||
levelUpgradeCost: function (startingLevel: any, extraLevels: any = 1, costMult: any = 1): any {
|
|
||||||
checkFormulasAccess("hacknetServers.levelUpgradeCost", 9);
|
|
||||||
return HScalculateLevelUpgradeCost(startingLevel, extraLevels, costMult);
|
|
||||||
},
|
|
||||||
ramUpgradeCost: function (startingRam: any, extraLevels: any = 1, costMult: any = 1): any {
|
|
||||||
checkFormulasAccess("hacknetServers.ramUpgradeCost", 9);
|
|
||||||
return HScalculateRamUpgradeCost(startingRam, extraLevels, costMult);
|
|
||||||
},
|
|
||||||
coreUpgradeCost: function (startingCore: any, extraCores: any = 1, costMult: any = 1): any {
|
|
||||||
checkFormulasAccess("hacknetServers.coreUpgradeCost", 9);
|
|
||||||
return HScalculateCoreUpgradeCost(startingCore, extraCores, costMult);
|
|
||||||
},
|
|
||||||
cacheUpgradeCost: function (startingCache: any, extraCache: any = 1): any {
|
|
||||||
checkFormulasAccess("hacknetServers.cacheUpgradeCost", 9);
|
|
||||||
return HScalculateCacheUpgradeCost(startingCache, extraCache);
|
|
||||||
},
|
|
||||||
hashUpgradeCost: function (upgName: any, level: any): any {
|
|
||||||
checkFormulasAccess("hacknetServers.hashUpgradeCost", 9);
|
|
||||||
const upg = player.hashManager.getUpgrade(upgName);
|
|
||||||
if (!upg) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(
|
|
||||||
"formulas.hacknetServers.calculateHashUpgradeCost",
|
|
||||||
`Invalid Hash Upgrade: ${upgName}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return upg.getCost(level);
|
|
||||||
},
|
|
||||||
hacknetServerCost: function (n: any, mult: any): any {
|
|
||||||
checkFormulasAccess("hacknetServers.hacknetServerCost", 9);
|
|
||||||
return HScalculateServerCost(n, mult);
|
|
||||||
},
|
|
||||||
constants: function (): any {
|
|
||||||
checkFormulasAccess("hacknetServers.constants", 9);
|
|
||||||
return Object.assign({}, HacknetServerConstants);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,7 @@
|
|||||||
import { BaseServer } from "../Server/BaseServer";
|
|
||||||
import { Faction } from "../Faction/Faction";
|
|
||||||
|
|
||||||
export interface INetscriptHelper {
|
export interface INetscriptHelper {
|
||||||
updateDynamicRam(functionName: string, ram: number): void;
|
updateDynamicRam(functionName: string, ram: number): void;
|
||||||
makeRuntimeErrorMsg(functionName: string, message: string): void;
|
makeRuntimeErrorMsg(functionName: string, message: string): void;
|
||||||
string(funcName: string, argName: string, v: any): string;
|
string(funcName: string, argName: string, v: any): string;
|
||||||
number(funcName: string, argName: string, v: any): number;
|
number(funcName: string, argName: string, v: any): number;
|
||||||
boolean(v: any): boolean;
|
boolean(v: any): boolean;
|
||||||
getServer(ip: any, fn: any): BaseServer;
|
|
||||||
checkSingularityAccess(func: string, n: number): void;
|
|
||||||
getFaction(func: string, name: string): Faction;
|
|
||||||
}
|
}
|
||||||
|
|||||||
85
src/NetscriptFunctions/Stanek.ts
Normal file
85
src/NetscriptFunctions/Stanek.ts
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
import { INetscriptHelper } from "./INetscriptHelper";
|
||||||
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
|
import { netscriptDelay } from "../NetscriptEvaluator";
|
||||||
|
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||||
|
|
||||||
|
import { staneksGift } from "../CotMG/Helper";
|
||||||
|
import { Fragments, FragmentById } from "../CotMG/Fragment";
|
||||||
|
|
||||||
|
export interface INetscriptStanek {
|
||||||
|
charge(worldX: number, worldY: number): any;
|
||||||
|
fragmentDefinitions(): any;
|
||||||
|
placedFragments(): any;
|
||||||
|
clear(): void;
|
||||||
|
canPlace(worldX: number, worldY: number, fragmentId: number): boolean;
|
||||||
|
place(worldX: number, worldY: number, fragmentId: number): boolean;
|
||||||
|
fragmentAt(worldX: number, worldY: number): any;
|
||||||
|
deleteAt(worldX: number, worldY: number): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NetscriptStanek(
|
||||||
|
player: IPlayer,
|
||||||
|
workerScript: WorkerScript,
|
||||||
|
helper: INetscriptHelper,
|
||||||
|
): INetscriptStanek {
|
||||||
|
return {
|
||||||
|
charge: function (worldX: any, worldY: any): any {
|
||||||
|
helper.updateDynamicRam("charge", getRamCost("stanek", "charge"));
|
||||||
|
//checkStanekAPIAccess("charge");
|
||||||
|
const fragment = staneksGift.fragmentAt(worldX, worldY);
|
||||||
|
if (!fragment) throw helper.makeRuntimeErrorMsg("stanek.charge", `No fragment at (${worldX}, ${worldY})`);
|
||||||
|
const time = staneksGift.inBonus() ? 200 : 1000;
|
||||||
|
return netscriptDelay(time, workerScript).then(function () {
|
||||||
|
if (workerScript.env.stopFlag) {
|
||||||
|
return Promise.reject(workerScript);
|
||||||
|
}
|
||||||
|
const ram = workerScript.scriptRef.ramUsage * workerScript.scriptRef.threads;
|
||||||
|
return Promise.resolve(staneksGift.charge(worldX, worldY, ram));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fragmentDefinitions: function () {
|
||||||
|
helper.updateDynamicRam("fragmentDefinitions", getRamCost("stanek", "fragmentDefinitions"));
|
||||||
|
//checkStanekAPIAccess("fragmentDefinitions");
|
||||||
|
return Fragments.map((f) => f.copy());
|
||||||
|
},
|
||||||
|
placedFragments: function () {
|
||||||
|
helper.updateDynamicRam("placedFragments", getRamCost("stanek", "placedFragments"));
|
||||||
|
//checkStanekAPIAccess("placedFragments");
|
||||||
|
return staneksGift.fragments.map((af) => {
|
||||||
|
return { ...af.copy(), ...af.fragment().copy() };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
clear: function () {
|
||||||
|
helper.updateDynamicRam("clear", getRamCost("stanek", "clear"));
|
||||||
|
//checkStanekAPIAccess("clear");
|
||||||
|
staneksGift.clear();
|
||||||
|
},
|
||||||
|
canPlace: function (worldX: any, worldY: any, fragmentId: any): any {
|
||||||
|
helper.updateDynamicRam("canPlace", getRamCost("stanek", "canPlace"));
|
||||||
|
//checkStanekAPIAccess("canPlace");
|
||||||
|
const fragment = FragmentById(fragmentId);
|
||||||
|
if (!fragment) throw helper.makeRuntimeErrorMsg("stanek.canPlace", `Invalid fragment id: ${fragmentId}`);
|
||||||
|
return staneksGift.canPlace(worldX, worldY, fragment);
|
||||||
|
},
|
||||||
|
place: function (worldX: any, worldY: any, fragmentId: any): any {
|
||||||
|
helper.updateDynamicRam("place", getRamCost("stanek", "place"));
|
||||||
|
//checkStanekAPIAccess("place");
|
||||||
|
const fragment = FragmentById(fragmentId);
|
||||||
|
if (!fragment) throw helper.makeRuntimeErrorMsg("stanek.place", `Invalid fragment id: ${fragmentId}`);
|
||||||
|
return staneksGift.place(worldX, worldY, fragment);
|
||||||
|
},
|
||||||
|
fragmentAt: function (worldX: any, worldY: any): any {
|
||||||
|
helper.updateDynamicRam("fragmentAt", getRamCost("stanek", "fragmentAt"));
|
||||||
|
//checkStanekAPIAccess("fragmentAt");
|
||||||
|
const fragment = staneksGift.fragmentAt(worldX, worldY);
|
||||||
|
if (fragment !== null) return fragment.copy();
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
deleteAt: function (worldX: any, worldY: any): any {
|
||||||
|
helper.updateDynamicRam("deleteAt", getRamCost("stanek", "deleteAt"));
|
||||||
|
//checkStanekAPIAccess("deleteAt");
|
||||||
|
return staneksGift.deleteAt(worldX, worldY);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,377 +0,0 @@
|
|||||||
import { INetscriptHelper } from "./INetscriptHelper";
|
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
||||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
|
||||||
import { buyStock, sellStock, shortStock, sellShort } from "../StockMarket/BuyingAndSelling";
|
|
||||||
import { StockMarket, SymbolToStockMap, placeOrder, cancelOrder } from "../StockMarket/StockMarket";
|
|
||||||
import { getBuyTransactionCost, getSellTransactionGain } from "../StockMarket/StockMarketHelpers";
|
|
||||||
import { OrderTypes } from "../StockMarket/data/OrderTypes";
|
|
||||||
import { PositionTypes } from "../StockMarket/data/PositionTypes";
|
|
||||||
import { StockSymbols } from "../StockMarket/data/StockSymbols";
|
|
||||||
import { getStockMarket4SDataCost, getStockMarket4STixApiCost } from "../StockMarket/StockMarketCosts";
|
|
||||||
import { Stock } from "../StockMarket/Stock";
|
|
||||||
|
|
||||||
export interface INetscriptStockMarket {
|
|
||||||
getStockSymbols(): any;
|
|
||||||
getStockPrice(symbol: any): any;
|
|
||||||
getStockAskPrice(symbol: any): any;
|
|
||||||
getStockBidPrice(symbol: any): any;
|
|
||||||
getStockPosition(symbol: any): any;
|
|
||||||
getStockMaxShares(symbol: any): any;
|
|
||||||
getStockPurchaseCost(symbol: any, shares: any, posType: any): any;
|
|
||||||
getStockSaleGain(symbol: any, shares: any, posType: any): any;
|
|
||||||
buyStock(symbol: any, shares: any): any;
|
|
||||||
sellStock(symbol: any, shares: any): any;
|
|
||||||
shortStock(symbol: any, shares: any): any;
|
|
||||||
sellShort(symbol: any, shares: any): any;
|
|
||||||
placeOrder(symbol: any, shares: any, price: any, type: any, pos: any): any;
|
|
||||||
cancelOrder(symbol: any, shares: any, price: any, type: any, pos: any): any;
|
|
||||||
getOrders(): any;
|
|
||||||
getStockVolatility(symbol: any): any;
|
|
||||||
getStockForecast(symbol: any): any;
|
|
||||||
purchase4SMarketData(): void;
|
|
||||||
purchase4SMarketDataTixApi(): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function NetscriptStockMarket(
|
|
||||||
player: IPlayer,
|
|
||||||
workerScript: WorkerScript,
|
|
||||||
helper: INetscriptHelper,
|
|
||||||
): INetscriptStockMarket {
|
|
||||||
/**
|
|
||||||
* Checks if the player has TIX API access. Throws an error if the player does not
|
|
||||||
*/
|
|
||||||
const checkTixApiAccess = function (callingFn: string): void {
|
|
||||||
if (!player.hasWseAccount) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(callingFn, `You don't have WSE Access! Cannot use ${callingFn}()`);
|
|
||||||
}
|
|
||||||
if (!player.hasTixApiAccess) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(callingFn, `You don't have TIX API Access! Cannot use ${callingFn}()`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getStockFromSymbol = function (symbol: string, callingFn: string): Stock {
|
|
||||||
const stock = SymbolToStockMap[symbol];
|
|
||||||
if (stock == null) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(callingFn, `Invalid stock symbol: '${symbol}'`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return stock;
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
getStockSymbols: function (): any {
|
|
||||||
helper.updateDynamicRam("getStockSymbols", getRamCost("getStockSymbols"));
|
|
||||||
checkTixApiAccess("getStockSymbols");
|
|
||||||
return Object.values(StockSymbols);
|
|
||||||
},
|
|
||||||
getStockPrice: function (symbol: any): any {
|
|
||||||
helper.updateDynamicRam("getStockPrice", getRamCost("getStockPrice"));
|
|
||||||
checkTixApiAccess("getStockPrice");
|
|
||||||
const stock = getStockFromSymbol(symbol, "getStockPrice");
|
|
||||||
|
|
||||||
return stock.price;
|
|
||||||
},
|
|
||||||
getStockAskPrice: function (symbol: any): any {
|
|
||||||
helper.updateDynamicRam("getStockAskPrice", getRamCost("getStockAskPrice"));
|
|
||||||
checkTixApiAccess("getStockAskPrice");
|
|
||||||
const stock = getStockFromSymbol(symbol, "getStockAskPrice");
|
|
||||||
|
|
||||||
return stock.getAskPrice();
|
|
||||||
},
|
|
||||||
getStockBidPrice: function (symbol: any): any {
|
|
||||||
helper.updateDynamicRam("getStockBidPrice", getRamCost("getStockBidPrice"));
|
|
||||||
checkTixApiAccess("getStockBidPrice");
|
|
||||||
const stock = getStockFromSymbol(symbol, "getStockBidPrice");
|
|
||||||
|
|
||||||
return stock.getBidPrice();
|
|
||||||
},
|
|
||||||
getStockPosition: function (symbol: any): any {
|
|
||||||
helper.updateDynamicRam("getStockPosition", getRamCost("getStockPosition"));
|
|
||||||
checkTixApiAccess("getStockPosition");
|
|
||||||
const stock = SymbolToStockMap[symbol];
|
|
||||||
if (stock == null) {
|
|
||||||
throw helper.makeRuntimeErrorMsg("getStockPosition", `Invalid stock symbol: ${symbol}`);
|
|
||||||
}
|
|
||||||
return [stock.playerShares, stock.playerAvgPx, stock.playerShortShares, stock.playerAvgShortPx];
|
|
||||||
},
|
|
||||||
getStockMaxShares: function (symbol: any): any {
|
|
||||||
helper.updateDynamicRam("getStockMaxShares", getRamCost("getStockMaxShares"));
|
|
||||||
checkTixApiAccess("getStockMaxShares");
|
|
||||||
const stock = getStockFromSymbol(symbol, "getStockMaxShares");
|
|
||||||
|
|
||||||
return stock.maxShares;
|
|
||||||
},
|
|
||||||
getStockPurchaseCost: function (symbol: any, shares: any, posType: any): any {
|
|
||||||
helper.updateDynamicRam("getStockPurchaseCost", getRamCost("getStockPurchaseCost"));
|
|
||||||
checkTixApiAccess("getStockPurchaseCost");
|
|
||||||
const stock = getStockFromSymbol(symbol, "getStockPurchaseCost");
|
|
||||||
shares = Math.round(shares);
|
|
||||||
|
|
||||||
let pos;
|
|
||||||
const sanitizedPosType = posType.toLowerCase();
|
|
||||||
if (sanitizedPosType.includes("l")) {
|
|
||||||
pos = PositionTypes.Long;
|
|
||||||
} else if (sanitizedPosType.includes("s")) {
|
|
||||||
pos = PositionTypes.Short;
|
|
||||||
} else {
|
|
||||||
return Infinity;
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = getBuyTransactionCost(stock, shares, pos);
|
|
||||||
if (res == null) {
|
|
||||||
return Infinity;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
},
|
|
||||||
getStockSaleGain: function (symbol: any, shares: any, posType: any): any {
|
|
||||||
helper.updateDynamicRam("getStockSaleGain", getRamCost("getStockSaleGain"));
|
|
||||||
checkTixApiAccess("getStockSaleGain");
|
|
||||||
const stock = getStockFromSymbol(symbol, "getStockSaleGain");
|
|
||||||
shares = Math.round(shares);
|
|
||||||
|
|
||||||
let pos;
|
|
||||||
const sanitizedPosType = posType.toLowerCase();
|
|
||||||
if (sanitizedPosType.includes("l")) {
|
|
||||||
pos = PositionTypes.Long;
|
|
||||||
} else if (sanitizedPosType.includes("s")) {
|
|
||||||
pos = PositionTypes.Short;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = getSellTransactionGain(stock, shares, pos);
|
|
||||||
if (res == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
},
|
|
||||||
buyStock: function (symbol: any, shares: any): any {
|
|
||||||
helper.updateDynamicRam("buyStock", getRamCost("buyStock"));
|
|
||||||
checkTixApiAccess("buyStock");
|
|
||||||
const stock = getStockFromSymbol(symbol, "buyStock");
|
|
||||||
const res = buyStock(stock, shares, workerScript, {});
|
|
||||||
return res ? stock.price : 0;
|
|
||||||
},
|
|
||||||
sellStock: function (symbol: any, shares: any): any {
|
|
||||||
helper.updateDynamicRam("sellStock", getRamCost("sellStock"));
|
|
||||||
checkTixApiAccess("sellStock");
|
|
||||||
const stock = getStockFromSymbol(symbol, "sellStock");
|
|
||||||
const res = sellStock(stock, shares, workerScript, {});
|
|
||||||
|
|
||||||
return res ? stock.price : 0;
|
|
||||||
},
|
|
||||||
shortStock: function (symbol: any, shares: any): any {
|
|
||||||
helper.updateDynamicRam("shortStock", getRamCost("shortStock"));
|
|
||||||
checkTixApiAccess("shortStock");
|
|
||||||
if (player.bitNodeN !== 8) {
|
|
||||||
if (player.sourceFileLvl(8) <= 1) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(
|
|
||||||
"shortStock",
|
|
||||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 2.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const stock = getStockFromSymbol(symbol, "shortStock");
|
|
||||||
const res = shortStock(stock, shares, workerScript, {});
|
|
||||||
|
|
||||||
return res ? stock.price : 0;
|
|
||||||
},
|
|
||||||
sellShort: function (symbol: any, shares: any): any {
|
|
||||||
helper.updateDynamicRam("sellShort", getRamCost("sellShort"));
|
|
||||||
checkTixApiAccess("sellShort");
|
|
||||||
if (player.bitNodeN !== 8) {
|
|
||||||
if (player.sourceFileLvl(8) <= 1) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(
|
|
||||||
"sellShort",
|
|
||||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 2.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const stock = getStockFromSymbol(symbol, "sellShort");
|
|
||||||
const res = sellShort(stock, shares, workerScript, {});
|
|
||||||
|
|
||||||
return res ? stock.price : 0;
|
|
||||||
},
|
|
||||||
placeOrder: function (symbol: any, shares: any, price: any, type: any, pos: any): any {
|
|
||||||
helper.updateDynamicRam("placeOrder", getRamCost("placeOrder"));
|
|
||||||
checkTixApiAccess("placeOrder");
|
|
||||||
if (player.bitNodeN !== 8) {
|
|
||||||
if (player.sourceFileLvl(8) <= 2) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(
|
|
||||||
"placeOrder",
|
|
||||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 3.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const stock = getStockFromSymbol(symbol, "placeOrder");
|
|
||||||
|
|
||||||
let orderType;
|
|
||||||
let orderPos;
|
|
||||||
const ltype = type.toLowerCase();
|
|
||||||
if (ltype.includes("limit") && ltype.includes("buy")) {
|
|
||||||
orderType = OrderTypes.LimitBuy;
|
|
||||||
} else if (ltype.includes("limit") && ltype.includes("sell")) {
|
|
||||||
orderType = OrderTypes.LimitSell;
|
|
||||||
} else if (ltype.includes("stop") && ltype.includes("buy")) {
|
|
||||||
orderType = OrderTypes.StopBuy;
|
|
||||||
} else if (ltype.includes("stop") && ltype.includes("sell")) {
|
|
||||||
orderType = OrderTypes.StopSell;
|
|
||||||
} else {
|
|
||||||
throw helper.makeRuntimeErrorMsg("placeOrder", `Invalid order type: ${type}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const lpos = pos.toLowerCase();
|
|
||||||
if (lpos.includes("l")) {
|
|
||||||
orderPos = PositionTypes.Long;
|
|
||||||
} else if (lpos.includes("s")) {
|
|
||||||
orderPos = PositionTypes.Short;
|
|
||||||
} else {
|
|
||||||
throw helper.makeRuntimeErrorMsg("placeOrder", `Invalid position type: ${pos}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return placeOrder(stock, shares, price, orderType, orderPos, workerScript);
|
|
||||||
},
|
|
||||||
cancelOrder: function (symbol: any, shares: any, price: any, type: any, pos: any): any {
|
|
||||||
helper.updateDynamicRam("cancelOrder", getRamCost("cancelOrder"));
|
|
||||||
checkTixApiAccess("cancelOrder");
|
|
||||||
if (player.bitNodeN !== 8) {
|
|
||||||
if (player.sourceFileLvl(8) <= 2) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(
|
|
||||||
"cancelOrder",
|
|
||||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 3.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const stock = getStockFromSymbol(symbol, "cancelOrder");
|
|
||||||
if (isNaN(shares) || isNaN(price)) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(
|
|
||||||
"cancelOrder",
|
|
||||||
`Invalid shares or price. Must be numeric. shares=${shares}, price=${price}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
let orderType;
|
|
||||||
let orderPos;
|
|
||||||
const ltype = type.toLowerCase();
|
|
||||||
if (ltype.includes("limit") && ltype.includes("buy")) {
|
|
||||||
orderType = OrderTypes.LimitBuy;
|
|
||||||
} else if (ltype.includes("limit") && ltype.includes("sell")) {
|
|
||||||
orderType = OrderTypes.LimitSell;
|
|
||||||
} else if (ltype.includes("stop") && ltype.includes("buy")) {
|
|
||||||
orderType = OrderTypes.StopBuy;
|
|
||||||
} else if (ltype.includes("stop") && ltype.includes("sell")) {
|
|
||||||
orderType = OrderTypes.StopSell;
|
|
||||||
} else {
|
|
||||||
throw helper.makeRuntimeErrorMsg("cancelOrder", `Invalid order type: ${type}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const lpos = pos.toLowerCase();
|
|
||||||
if (lpos.includes("l")) {
|
|
||||||
orderPos = PositionTypes.Long;
|
|
||||||
} else if (lpos.includes("s")) {
|
|
||||||
orderPos = PositionTypes.Short;
|
|
||||||
} else {
|
|
||||||
throw helper.makeRuntimeErrorMsg("cancelOrder", `Invalid position type: ${pos}`);
|
|
||||||
}
|
|
||||||
const params = {
|
|
||||||
stock: stock,
|
|
||||||
shares: shares,
|
|
||||||
price: price,
|
|
||||||
type: orderType,
|
|
||||||
pos: orderPos,
|
|
||||||
};
|
|
||||||
return cancelOrder(params, workerScript);
|
|
||||||
},
|
|
||||||
getOrders: function (): any {
|
|
||||||
helper.updateDynamicRam("getOrders", getRamCost("getOrders"));
|
|
||||||
checkTixApiAccess("getOrders");
|
|
||||||
if (player.bitNodeN !== 8) {
|
|
||||||
if (player.sourceFileLvl(8) <= 2) {
|
|
||||||
throw helper.makeRuntimeErrorMsg(
|
|
||||||
"getOrders",
|
|
||||||
"You must either be in BitNode-8 or have Source-File 8 Level 3.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const orders: any = {};
|
|
||||||
|
|
||||||
const stockMarketOrders = StockMarket["Orders"];
|
|
||||||
for (const symbol in stockMarketOrders) {
|
|
||||||
const orderBook = stockMarketOrders[symbol];
|
|
||||||
if (orderBook.constructor === Array && orderBook.length > 0) {
|
|
||||||
orders[symbol] = [];
|
|
||||||
for (let i = 0; i < orderBook.length; ++i) {
|
|
||||||
orders[symbol].push({
|
|
||||||
shares: orderBook[i].shares,
|
|
||||||
price: orderBook[i].price,
|
|
||||||
type: orderBook[i].type,
|
|
||||||
position: orderBook[i].pos,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return orders;
|
|
||||||
},
|
|
||||||
getStockVolatility: function (symbol: any): any {
|
|
||||||
helper.updateDynamicRam("getStockVolatility", getRamCost("getStockVolatility"));
|
|
||||||
if (!player.has4SDataTixApi) {
|
|
||||||
throw helper.makeRuntimeErrorMsg("getStockVolatility", "You don't have 4S Market Data TIX API Access!");
|
|
||||||
}
|
|
||||||
const stock = getStockFromSymbol(symbol, "getStockVolatility");
|
|
||||||
|
|
||||||
return stock.mv / 100; // Convert from percentage to decimal
|
|
||||||
},
|
|
||||||
getStockForecast: function (symbol: any): any {
|
|
||||||
helper.updateDynamicRam("getStockForecast", getRamCost("getStockForecast"));
|
|
||||||
if (!player.has4SDataTixApi) {
|
|
||||||
throw helper.makeRuntimeErrorMsg("getStockForecast", "You don't have 4S Market Data TIX API Access!");
|
|
||||||
}
|
|
||||||
const stock = getStockFromSymbol(symbol, "getStockForecast");
|
|
||||||
|
|
||||||
let forecast = 50;
|
|
||||||
stock.b ? (forecast += stock.otlkMag) : (forecast -= stock.otlkMag);
|
|
||||||
return forecast / 100; // Convert from percentage to decimal
|
|
||||||
},
|
|
||||||
purchase4SMarketData: function () {
|
|
||||||
helper.updateDynamicRam("purchase4SMarketData", getRamCost("purchase4SMarketData"));
|
|
||||||
checkTixApiAccess("purchase4SMarketData");
|
|
||||||
|
|
||||||
if (player.has4SData) {
|
|
||||||
workerScript.log("purchase4SMarketData", "Already purchased 4S Market Data.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (player.money.lt(getStockMarket4SDataCost())) {
|
|
||||||
workerScript.log("purchase4SMarketData", "Not enough money to purchase 4S Market Data.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
player.has4SData = true;
|
|
||||||
player.loseMoney(getStockMarket4SDataCost());
|
|
||||||
workerScript.log("purchase4SMarketData", "Purchased 4S Market Data");
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
purchase4SMarketDataTixApi: function () {
|
|
||||||
helper.updateDynamicRam("purchase4SMarketDataTixApi", getRamCost("purchase4SMarketDataTixApi"));
|
|
||||||
checkTixApiAccess("purchase4SMarketDataTixApi");
|
|
||||||
|
|
||||||
if (player.has4SDataTixApi) {
|
|
||||||
workerScript.log("purchase4SMarketDataTixApi", "Already purchased 4S Market Data TIX API");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (player.money.lt(getStockMarket4STixApiCost())) {
|
|
||||||
workerScript.log("purchase4SMarketDataTixApi", "Not enough money to purchase 4S Market Data TIX API");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
player.has4SDataTixApi = true;
|
|
||||||
player.loseMoney(getStockMarket4STixApiCost());
|
|
||||||
workerScript.log("purchase4SMarketDataTixApi", "Purchased 4S Market Data TIX API");
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
import { Interpreter } from "../ThirdParty/JSInterpreter";
|
|
||||||
|
|
||||||
const defaultInterpreter = new Interpreter("", () => undefined);
|
|
||||||
|
|
||||||
// the acorn interpreter has a bug where it doesn't convert arrays correctly.
|
|
||||||
// so we have to more or less copy it here.
|
|
||||||
export function toNative(pseudoObj: any): any {
|
|
||||||
if (pseudoObj == null) return null;
|
|
||||||
if (
|
|
||||||
!pseudoObj.hasOwnProperty("properties") ||
|
|
||||||
!pseudoObj.hasOwnProperty("getter") ||
|
|
||||||
!pseudoObj.hasOwnProperty("setter") ||
|
|
||||||
!pseudoObj.hasOwnProperty("proto")
|
|
||||||
) {
|
|
||||||
return pseudoObj; // it wasn't a pseudo object anyway.
|
|
||||||
}
|
|
||||||
|
|
||||||
let nativeObj: any;
|
|
||||||
if (pseudoObj.hasOwnProperty("class") && pseudoObj.class === "Array") {
|
|
||||||
nativeObj = [];
|
|
||||||
const length = defaultInterpreter.getProperty(pseudoObj, "length");
|
|
||||||
for (let i = 0; i < length; i++) {
|
|
||||||
if (defaultInterpreter.hasProperty(pseudoObj, i)) {
|
|
||||||
nativeObj[i] = toNative(defaultInterpreter.getProperty(pseudoObj, i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Object.
|
|
||||||
nativeObj = {};
|
|
||||||
for (const key in pseudoObj.properties) {
|
|
||||||
const val = pseudoObj.properties[key];
|
|
||||||
nativeObj[key] = toNative(val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nativeObj;
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user