Merge pull request #923 from danielyxie/dev

0.51.7
This commit is contained in:
hydroflame 2021-05-03 12:18:18 -04:00 committed by GitHub
commit ad9c7ec696
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
313 changed files with 3326 additions and 3169 deletions

@ -2,3 +2,7 @@ node_modules/
doc/build/ doc/build/
dist/ dist/
tests/*.bundle.* tests/*.bundle.*
src/ThirdParty/*
src/ScriptEditor/CodeMirrorNetscriptMode.js
src/ScriptEditor/CodeMirrorNetscriptLint.js
src/JSInterpreter.js

@ -76,7 +76,7 @@ module.exports = {
"imports": "always-multiline", "imports": "always-multiline",
"exports": "always-multiline", "exports": "always-multiline",
"functions": "always-multiline", "functions": "always-multiline",
} },
], ],
"comma-spacing": [ "comma-spacing": [
"off", "off",
@ -102,14 +102,14 @@ module.exports = {
"error", "error",
], ],
"curly": [ "curly": [
"off" "off",
], ],
"default-case": [ "default-case": [
"off" "off",
], ],
"dot-location": [ "dot-location": [
"error", "error",
"property" "property",
], ],
"dot-notation": [ "dot-notation": [
"off", "off",
@ -310,104 +310,104 @@ module.exports = {
"error", "error",
], ],
"no-div-regex": [ "no-div-regex": [
"error" "error",
], ],
"no-dupe-args": [ "no-dupe-args": [
"error" "error",
], ],
"no-dupe-class-members": [ "no-dupe-class-members": [
"error" "error",
], ],
"no-dupe-keys": [ "no-dupe-keys": [
"error" "error",
], ],
"no-duplicate-case": [ "no-duplicate-case": [
"error" "error",
], ],
"no-duplicate-imports": [ "no-duplicate-imports": [
"error", "error",
{ {
"includeExports": true "includeExports": true,
} },
], ],
"no-else-return": [ "no-else-return": [
"off" "off",
], ],
"no-empty": [ "no-empty": [
"off", "off",
{ {
"allowEmptyCatch": false "allowEmptyCatch": false,
} },
], ],
"no-empty-character-class": [ "no-empty-character-class": [
"error" "error",
], ],
"no-empty-function": [ "no-empty-function": [
"off" "off",
], ],
"no-empty-pattern": [ "no-empty-pattern": [
"error" "error",
], ],
"no-eq-null": [ "no-eq-null": [
"off" "off",
], ],
"no-ex-assign": [ "no-ex-assign": [
"off" "off",
], ],
"no-extra-boolean-cast": [ "no-extra-boolean-cast": [
"error" "error",
], ],
"no-extra-parens": [ "no-extra-parens": [
"off" "off",
], ],
"no-extra-semi": [ "no-extra-semi": [
"off" "off",
], ],
"no-eval": [ "no-eval": [
"off" "off",
], ],
"no-extend-native": [ "no-extend-native": [
"off" "off",
], ],
"no-extra-bind": [ "no-extra-bind": [
"error" "error",
], ],
"no-extra-label": [ "no-extra-label": [
"error" "error",
], ],
"no-fallthrough": [ "no-fallthrough": [
"off" "off",
], ],
"no-floating-decimal": [ "no-floating-decimal": [
"off" "off",
], ],
"no-func-assign": [ "no-func-assign": [
"error" "error",
], ],
"no-global-assign": [ "no-global-assign": [
"error" "error",
], ],
"no-implicit-coercion": [ "no-implicit-coercion": [
"off" "off",
], ],
"no-implicit-globals": [ "no-implicit-globals": [
"error" "error",
], ],
"no-implied-eval": [ "no-implied-eval": [
"error" "error",
], ],
"no-inline-comments": [ "no-inline-comments": [
"off" "off",
], ],
"no-inner-declarations": [ "no-inner-declarations": [
"off", "off",
"both" "both",
], ],
"no-invalid-regexp": [ "no-invalid-regexp": [
"error" "error",
], ],
"no-invalid-this": [ "no-invalid-this": [
"off" "off",
], ],
"no-irregular-whitespace": [ "no-irregular-whitespace": [
"error", "error",
@ -415,451 +415,461 @@ module.exports = {
"skipStrings": false, "skipStrings": false,
"skipComments": false, "skipComments": false,
"skipRegExps": false, "skipRegExps": false,
"skipTemplates": false "skipTemplates": false,
} },
], ],
"no-iterator": [ "no-iterator": [
"error" "error",
], ],
"no-label-var": [ "no-label-var": [
"error" "error",
], ],
"no-labels": [ "no-labels": [
"off" "off",
], ],
"no-lone-blocks": [ "no-lone-blocks": [
"error" "error",
], ],
"no-lonely-if": [ "no-lonely-if": [
"off" "off",
], ],
"no-loop-func": [ "no-loop-func": [
"off" "off",
], ],
"no-magic-numbers": [ "no-magic-numbers": [
"off" "off",
], ],
"no-mixed-operators": [ "no-mixed-operators": [
"off" "off",
], ],
"no-mixed-requires": [ "no-mixed-requires": [
"error" "error",
], ],
"no-mixed-spaces-and-tabs": [ "no-mixed-spaces-and-tabs": [
"off" "off",
], ],
"no-multi-assign": [ "no-multi-assign": [
"off" "off",
], ],
"no-multi-spaces": [ "no-multi-spaces": [
"off" "off",
], ],
"no-multi-str": [ "no-multi-str": [
"error" "error",
], ],
"no-multiple-empty-lines": [ "no-multiple-empty-lines": [
"off", "off",
{ {
"max": 1 "max": 1,
} },
], ],
"no-native-reassign": [ "no-native-reassign": [
"error" "error",
], ],
"no-negated-condition": [ "no-negated-condition": [
"off" "off",
], ],
"no-negated-in-lhs": [ "no-negated-in-lhs": [
"error" "error",
], ],
"no-nested-ternary": [ "no-nested-ternary": [
"off" "off",
], ],
"no-new": [ "no-new": [
"error" "error",
], ],
"no-new-func": [ "no-new-func": [
"error" "error",
], ],
"no-new-object": [ "no-new-object": [
"error" "error",
], ],
"no-new-require": [ "no-new-require": [
"error" "error",
], ],
"no-new-symbol": [ "no-new-symbol": [
"error" "error",
], ],
"no-new-wrappers": [ "no-new-wrappers": [
"error" "error",
], ],
"no-octal": [ "no-octal": [
"error" "error",
], ],
"no-octal-escape": [ "no-octal-escape": [
"error" "error",
], ],
"no-obj-calls": [ "no-obj-calls": [
"error" "error",
], ],
"no-param-reassign": [ "no-param-reassign": [
"off" "off",
], ],
"no-path-concat": [ "no-path-concat": [
"error" "error",
], ],
"no-plusplus": [ "no-plusplus": [
"off" "off",
], ],
"no-process-env": [ "no-process-env": [
"off" "off",
], ],
"no-process-exit": [ "no-process-exit": [
"error" "error",
], ],
"no-proto": [ "no-proto": [
"error" "error",
], ],
"no-prototype-builtins": [ "no-prototype-builtins": [
"off" "off",
], ],
"no-redeclare": [ "no-redeclare": [
"off" "off",
], ],
"no-regex-spaces": [ "no-regex-spaces": [
"error" "error",
], ],
"no-restricted-globals": [ "no-restricted-globals": [
"error" "error",
], ],
"no-restricted-imports": [ "no-restricted-imports": [
"error" "error",
], ],
"no-restricted-modules": [ "no-restricted-modules": [
"error" "error",
], ],
"no-restricted-properties": [ "no-restricted-properties": [
"off", "off",
{ {
"object": "console", "object": "console",
"property": "log", "property": "log",
"message": "'log' is too general, use an appropriate level when logging." "message": "'log' is too general, use an appropriate level when logging.",
} },
], ],
"no-restricted-syntax": [ "no-restricted-syntax": [
"error" "error",
], ],
"no-return-assign": [ "no-return-assign": [
"off" "off",
], ],
"no-return-await": [ "no-return-await": [
"error" "error",
], ],
"no-script-url": [ "no-script-url": [
"error" "error",
], ],
"no-self-assign": [ "no-self-assign": [
"error", "error",
{ {
"props": false "props": false,
} },
], ],
"no-self-compare": [ "no-self-compare": [
"error" "error",
], ],
"no-sequences": [ "no-sequences": [
"error" "error",
], ],
"no-shadow": [ "no-shadow": [
"off" "off",
], ],
"no-shadow-restricted-names": [ "no-shadow-restricted-names": [
"error" "error",
], ],
"no-spaced-func": [ "no-spaced-func": [
"off" "off",
], ],
"no-sparse-arrays": [ "no-sparse-arrays": [
"error" "error",
], ],
"no-sync": [ "no-sync": [
"error" "error",
], ],
"no-tabs": [ "no-tabs": [
"off" "off",
], ],
"no-template-curly-in-string": [ "no-template-curly-in-string": [
"error" "error",
], ],
"no-ternary": [ "no-ternary": [
"off" "off",
], ],
"no-this-before-super": [ "no-this-before-super": [
"off" "off",
], ],
"no-throw-literal": [ "no-throw-literal": [
"error" "error",
], ],
"no-trailing-spaces": [ "no-trailing-spaces": [
"off" "off",
], ],
"no-undef": [ "no-undef": [
"off" "off",
], ],
"no-undef-init": [ "no-undef-init": [
"error" "error",
], ],
"no-undefined": [ "no-undefined": [
"off" "off",
], ],
"no-underscore-dangle": [ "no-underscore-dangle": [
"off" "off",
], ],
"no-unexpected-multiline": [ "no-unexpected-multiline": [
"error" "error",
], ],
"no-unmodified-loop-condition": [ "no-unmodified-loop-condition": [
"error" "error",
], ],
"no-unneeded-ternary": [ "no-unneeded-ternary": [
"off" "off",
], ],
"no-unreachable": [ "no-unreachable": [
"off" "off",
], ],
"no-unsafe-finally": [ "no-unsafe-finally": [
"error" "error",
], ],
"no-unsafe-negation": [ "no-unsafe-negation": [
"error" "error",
], ],
"no-unused-expressions": [ "no-unused-expressions": [
"off" "off",
], ],
"no-unused-labels": [ "no-unused-labels": [
"error" "error",
], ],
"no-unused-vars": [ "no-unused-vars": [
"off" "off",
], ],
"no-use-before-define": [ "no-use-before-define": [
"off" "off",
], ],
"no-useless-call": [ "no-useless-call": [
"off" "off",
], ],
"no-useless-computed-key": [ "no-useless-computed-key": [
"error" "error",
], ],
"no-useless-concat": [ "no-useless-concat": [
"off" "off",
], ],
"no-useless-constructor": [ "no-useless-constructor": [
"error" "error",
], ],
"no-useless-escape": [ "no-useless-escape": [
"off" "off",
], ],
"no-useless-rename": [ "no-useless-rename": [
"error", "error",
{ {
"ignoreDestructuring": false, "ignoreDestructuring": false,
"ignoreExport": false, "ignoreExport": false,
"ignoreImport": false "ignoreImport": false,
} },
], ],
"no-useless-return": [ "no-useless-return": [
"off" "off",
], ],
"no-var": [ "no-var": [
"off" "off",
], ],
"no-void": [ "no-void": [
"off" "off",
], ],
"no-warning-comments": [ "no-warning-comments": [
"off" "off",
], ],
"no-whitespace-before-property": [ "no-whitespace-before-property": [
"error" "error",
], ],
"no-with": [ "no-with": [
"error" "error",
], ],
"nonblock-statement-body-position": [ "nonblock-statement-body-position": [
"off", "off",
"below" "below",
], ],
"object-curly-newline": [ "object-curly-newline": [
"off" "off",
], ],
"object-curly-spacing": [ "object-curly-spacing": [
"off" "off",
], ],
"object-property-newline": [ "object-property-newline": [
"off" "off",
], ],
"object-shorthand": [ "object-shorthand": [
"off" "off",
], ],
"one-var": [ "one-var": [
"off" "off",
], ],
"one-var-declaration-per-line": [ "one-var-declaration-per-line": [
"off" "off",
], ],
"operator-assignment": [ "operator-assignment": [
"off" "off",
], ],
"operator-linebreak": [ "operator-linebreak": [
"off", "off",
"none" "none",
], ],
"padded-blocks": [ "padded-blocks": [
"off" "off",
], ],
"padding-line-between-statements": [ "padding-line-between-statements": [
"error" "error",
], ],
"prefer-arrow-callback": [ "prefer-arrow-callback": [
"off" "off",
], ],
"prefer-const": [ "prefer-const": [
"off" "off",
], ],
"prefer-destructuring": [ "prefer-destructuring": [
"off" "off",
], ],
"prefer-numeric-literals": [ "prefer-numeric-literals": [
"error" "error",
], ],
"prefer-promise-reject-errors": [ "prefer-promise-reject-errors": [
"off" "off",
], ],
"prefer-reflect": [ "prefer-reflect": [
"off" "off",
], ],
"prefer-rest-params": [ "prefer-rest-params": [
"off" "off",
], ],
"prefer-spread": [ "prefer-spread": [
"off" "off",
], ],
"prefer-template": [ "prefer-template": [
"off" "off",
], ],
"quote-props": [ "quote-props": [
"off" "off",
], ],
"quotes": [ "quotes": [
"off" "off",
], ],
"radix": [ "radix": [
"off", "off",
"as-needed" "as-needed",
], ],
"require-await": [ "require-await": [
"off" "off",
], ],
"require-jsdoc": [ "require-jsdoc": [
"off" "off",
], ],
"require-yield": [ "require-yield": [
"error" "error",
], ],
"rest-spread-spacing": [ "rest-spread-spacing": [
"error", "error",
"never" "never",
], ],
"semi": [ "semi": [
"off" "off",
], ],
"semi-spacing": [ "semi-spacing": [
"off" "off",
], ],
"semi-style": [ "semi-style": [
"error", "error",
"last" "last",
], ],
"sort-imports": [ "sort-imports": [
"off" "off",
], ],
"sort-keys": [ "sort-keys": [
"off" "off",
], ],
"sort-vars": [ "sort-vars": [
"off" "off",
], ],
"space-before-blocks": [ "space-before-blocks": [
"off" "off",
], ],
"space-before-function-paren": [ "space-before-function-paren": [
"off" "off",
], ],
"space-in-parens": [ "space-in-parens": [
"off" "off",
], ],
"space-infix-ops": [ "space-infix-ops": [
"off" "off",
], ],
"space-unary-ops": [ "space-unary-ops": [
"off" "off",
], ],
"spaced-comment": [ "spaced-comment": [
"off" "off",
], ],
"strict": [ "strict": [
"off" "off",
], ],
"switch-colon-spacing": [ "switch-colon-spacing": [
"error", "error",
{ {
"after": true, "after": true,
"before": false "before": false,
} },
], ],
"symbol-description": [ "symbol-description": [
"error" "error",
], ],
"template-curly-spacing": [ "template-curly-spacing": [
"error" "error",
], ],
"template-tag-spacing": [ "template-tag-spacing": [
"error" "error",
], ],
"unicode-bom": [ "unicode-bom": [
"error", "error",
"never" "never",
], ],
"use-isnan": [ "use-isnan": [
"error" "error",
], ],
"valid-jsdoc": [ "valid-jsdoc": [
"off" "off",
], ],
"valid-typeof": [ "valid-typeof": [
"error" "error",
], ],
"vars-on-top": [ "vars-on-top": [
"off" "off",
], ],
"wrap-iife": [ "wrap-iife": [
"error", "error",
"any" "any",
], ],
"wrap-regex": [ "wrap-regex": [
"off" "off",
], ],
"yield-star-spacing": [ "yield-star-spacing": [
"error", "error",
"before" "before",
], ],
"yoda": [ "yoda": [
"error", "error",
"never" "never",
] ],
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/explicit-function-return-type": "off",
}, },
"overrides": [ "overrides": [
{
// enable the rule specifically for TypeScript files
"files": ["*.ts", "*.tsx"],
"rules": {
"@typescript-eslint/explicit-function-return-type": ["error"],
"@typescript-eslint/explicit-module-boundary-types": ["error"],
},
},
{ {
// TypeScript configuration // TypeScript configuration
"files": [ "**/*.ts", "**/*.tsx" ], "files": [ "**/*.ts", "**/*.tsx" ],
@ -888,7 +898,7 @@ module.exports = {
"singleline": { "singleline": {
"delimiter": "semi", "delimiter": "semi",
"requireLast": false, "requireLast": false,
} },
}], }],
"@typescript-eslint/member-ordering": ["error", { "@typescript-eslint/member-ordering": ["error", {
"default": [ "default": [
@ -900,11 +910,11 @@ module.exports = {
"instance-method", "instance-method",
"abstract-method", "abstract-method",
"static-method", "static-method",
] ],
}], }],
"@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-use-before-define": "off", "@typescript-eslint/no-use-before-define": "off",
} },
} },
] ],
}; };

@ -43,9 +43,9 @@
background-color: #444; background-color: #444;
} }
.character-stat-cell { .character-stat-cell {
text-align: right; text-align: right;
} }
#character-hack-wrapper td, #character-hack-wrapper td,
#character-agi-wrapper td { #character-agi-wrapper td {

@ -6,7 +6,7 @@
#codemirror-form-wrapper { #codemirror-form-wrapper {
height: 80%; height: 80%;
margin: 10px 0px 0px 6px; margin: 10px 0 0 6px;
} }
.CodeMirror { .CodeMirror {
@ -22,11 +22,11 @@
* Highlight matches * Highlight matches
*/ */
.cm-matchhighlight { .cm-matchhighlight {
background-color: #8F908A; background-color: #8f908a;
} }
.CodeMirror-selection-highlight-scrollbar { .CodeMirror-selection-highlight-scrollbar {
background-color: #8F908A; background-color: #8f908a;
} }
/** /**
@ -35,7 +35,7 @@
.cm-whitespace::before { .cm-whitespace::before {
position: absolute; position: absolute;
pointer-events: none; pointer-events: none;
color: #404F7D; color: #404f7d;
} }
/** /**

@ -1,14 +1,14 @@
.add-exp-button { .add-exp-button {
margin-right: 0px; margin-right: 0;
} }
.remove-exp-button { .remove-exp-button {
margin-left:0px; margin-left:0;
} }
.exp-input { .exp-input {
margin-right: 0px; margin-right: 0;
margin-left:0px; margin-left:0;
margin-top: 5px; margin-top: 5px;
margin-bottom: 5px; margin-bottom: 5px;
@ -23,14 +23,14 @@
} }
.touch-right { .touch-right {
margin-right: 0px; margin-right: 0;
} }
.touch-left { .touch-left {
margin-left: 0px; margin-left: 0;
} }
.touch-sides { .touch-sides {
margin-left: 0px; margin-left: 0;
margin-right: 0px; margin-right: 0;
} }

2
css/grid.min.css vendored

File diff suppressed because one or more lines are too long

@ -17,7 +17,7 @@
} }
&.level-2 { &.level-2 {
color: #48D1CC; color: #48d1cc;
} }
&.level-3 { &.level-3 {

@ -1,4 +1,4 @@
/** /**
* Styling for the Re-Sleeving Page * Styling for the Re-Sleeving Page
*/ */
@import "theme"; @import "theme";
@ -15,7 +15,7 @@
.resleeve-panel { .resleeve-panel {
display: inline-block; display: inline-block;
margin: 0px; margin: 0;
padding: 2px; padding: 2px;
} }

@ -20,7 +20,7 @@
.sleeve-panel { .sleeve-panel {
display: inline-block; display: inline-block;
margin: 0px; margin: 0;
padding: 2px; padding: 2px;
select { select {

@ -393,8 +393,8 @@ input[type=checkbox] {
outline: none; outline: none;
opacity: 0.7; opacity: 0.7;
height: 10px; height: 10px;
-webkit-transition: .2s; -webkit-transition: 0.2s;
transition: opacity .2s; transition: opacity 0.2s;
margin: 3px; margin: 3px;
} }

@ -7,16 +7,16 @@
.Treant.Treant-loaded .pseudo { visibility: visible; } .Treant.Treant-loaded .pseudo { visibility: visible; }
.Treant > .pseudo { width: 0; height: 0; border: none; padding: 0; } .Treant > .pseudo { width: 0; height: 0; border: none; padding: 0; }
.Treant .collapse-switch { width: 3px; height: 3px; display: block; border: 1px solid black; position: absolute; top: 1px; right: 1px; cursor: pointer; } .Treant .collapse-switch { width: 3px; height: 3px; display: block; border: 1px solid black; position: absolute; top: 1px; right: 1px; cursor: pointer; }
.Treant .collapsed .collapse-switch { background-color: #868DEE; } .Treant .collapsed .collapse-switch { background-color: #868dee; }
.Treant > .node img { border: none; float: left; } .Treant > .node img { border: none; float: left; }
.Treant > .node { .Treant > .node {
cursor: pointer; cursor: pointer;
padding: 4px; padding: 4px;
min-width: 60px; min-width: 60px;
text-align: center; text-align: center;
border: 2px solid #E8E8E3; border: 2px solid #e8e8e3;
border-radius: 2px; border-radius: 2px;
box-shadow: 1px 1px 1px rgba(0,0,0,.5); box-shadow: 1px 1px 1px rgba(0,0,0,0.5);
font-size: 12px; font-size: 12px;
} }

@ -11,7 +11,7 @@ user's physical and mental faculties.
Augmentations provide persistent upgrades in the form of multipliers. Augmentations provide persistent upgrades in the form of multipliers.
These multipliers apply to a wide variety of things such as stats, These multipliers apply to a wide variety of things such as stats,
experience gain, and hacking, just to name a few. Your multipliers experience gain, and hacking, just to name a few. Your multipliers
can be viewed in the 'Character' page (:ref:`keyboard shortcut <shortcuts>` Alt + c) can be viewed in the 'Character' page (:ref:`keyboard shortcut <shortcuts>` Alt + c).
How to acquire Augmentations How to acquire Augmentations
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

@ -0,0 +1,15 @@
getServerMaxRam() Netscript Function
====================================
.. js:function:: getServerMaxRam(hostname)
:RAM cost: 0.05 GB
:param string hostname: Hostname of target server.
:returns: Total ram available on that server. In GB.
Example:
.. code-block:: javascript
maxRam = getServerMaxRam("helios"); // returns: 16
print("helios has "+maxRam + "GB");

@ -3,6 +3,8 @@ getServerRam() Netscript Function
.. js:function:: getServerRam(hostname) .. js:function:: getServerRam(hostname)
.. warning:: This function is deprecated.
:RAM cost: 0.1 GB :RAM cost: 0.1 GB
:param string hostname: Hostname of target server. :param string hostname: Hostname of target server.
:returns: An array of 2 number, first number is the total RAM, second the :returns: An array of 2 number, first number is the total RAM, second the

@ -0,0 +1,15 @@
getServerUsedRam() Netscript Function
=====================================
.. js:function:: getServerUsedRam(hostname)
:RAM cost: 0.05 GB
:param string hostname: Hostname of target server.
:returns: Used ram on that server. In GB.
Example:
.. code-block:: javascript
usedRam = getServerUsedRam("harakiri-sushi"); // returns: 5.6
print("harakiri-sushi uses "+usedRam + "GB");

@ -5,13 +5,13 @@ Netscript Bladeburner API
Netscript provides the following API for interacting with the game's Bladeburner mechanic. Netscript provides the following API for interacting with the game's Bladeburner mechanic.
The Bladeburner API is **not** immediately available to the player and must be unlocked The Bladeburner API is **not** immediately available to the player and must be unlocked
later in the game later in the game.
.. warning:: This page contains spoilers for the game .. warning:: This page contains spoilers for the game
The Bladeburner API is unlocked in BitNode-7. If you are in BitNode-7, you will The Bladeburner API is unlocked in BitNode-7. If you are in BitNode-7, you will
automatically gain access to this API. Otherwise, you must have Source-File 7 in automatically gain access to this API. Otherwise, you must have Source-File 7 in
order to use this API in other BitNodes order to use this API in other BitNodes.
**Bladeburner API functions must be accessed through the 'bladeburner' namespace** **Bladeburner API functions must be accessed through the 'bladeburner' namespace**
@ -157,7 +157,7 @@ identifier by attaching the Bladeburner API functions to an object::
} }
BladeburnerHandler.prototype.handle = function() { BladeburnerHandler.prototype.handle = function() {
//If we're doing something else manually (without Simlacrum), //If we're doing something else manually (without Simulacrum),
//it overrides Bladeburner stuff //it overrides Bladeburner stuff
if (!this.hasSimulacrum() && this.ns.isBusy()) { if (!this.hasSimulacrum() && this.ns.isBusy()) {
this.ns.print("Idling bc player is busy with some other action"); this.ns.print("Idling bc player is busy with some other action");

@ -54,7 +54,8 @@ This includes information such as function signatures, what they do, and their r
getServerMinSecurityLevel() <basicfunctions/getServerMinSecurityLevel> getServerMinSecurityLevel() <basicfunctions/getServerMinSecurityLevel>
getServerRequiredHackingLevel() <basicfunctions/getServerRequiredHackingLevel> getServerRequiredHackingLevel() <basicfunctions/getServerRequiredHackingLevel>
getServerNumPortsRequired() <basicfunctions/getServerNumPortsRequired> getServerNumPortsRequired() <basicfunctions/getServerNumPortsRequired>
getServerRam() <basicfunctions/getServerRam> getServerMaxRam() <basicfunctions/getServerMaxRam>
getServerUsedRam() <basicfunctions/getServerUsedRam>
serverExists() <basicfunctions/serverExists> serverExists() <basicfunctions/serverExists>
fileExists() <basicfunctions/fileExists> fileExists() <basicfunctions/fileExists>
isRunning() <basicfunctions/isRunning> isRunning() <basicfunctions/isRunning>
@ -90,3 +91,8 @@ This includes information such as function signatures, what they do, and their r
wget() <basicfunctions/wget> wget() <basicfunctions/wget>
getFavorToDonate() <basicfunctions/getFavorToDonate> getFavorToDonate() <basicfunctions/getFavorToDonate>
flags() <basicfunctions/flags> flags() <basicfunctions/flags>
.. toctree::
:caption: Deprecated:
getServerRam() <basicfunctions/getServerRam>

@ -86,7 +86,7 @@ The following is an example of one way a script can be used to automate the
purchasing and upgrading of Hacknet Nodes. purchasing and upgrading of Hacknet Nodes.
This script attempts to purchase Hacknet Nodes until the player has a total of 8. Then This script attempts to purchase Hacknet Nodes until the player has a total of 8. Then
it gradually upgrades those Node's to a minimum of level 140, 64 GB RAM, and 8 cores it gradually upgrades those Node's to a minimum of level 80, 16 GB RAM, and 8 cores
.. code:: javascript .. code:: javascript
@ -129,3 +129,16 @@ it gradually upgrades those Node's to a minimum of level 140, 64 GB RAM, and 8 c
}; };
print("All nodes upgraded to 16GB RAM"); print("All nodes upgraded to 16GB RAM");
for (var i = 0; i < cnt; i++) {
while (hacknet.getNodeStats(i).cores < 8) {
var cost = hacknet.getCoreUpgradeCost(i, 1);
while (myMoney() < cost) {
print("Need $" + cost + " . Have $" + myMoney());
sleep(3000);
}
res = hacknet.upgradeCore(i, 1);
};
};
print("All nodes upgraded to 8 cores");

@ -327,8 +327,8 @@
Would you like to join? <br/> <br/> Would you like to join? <br/> <br/>
Warning: Joining this faction may prevent you from joining other factions during this run! Warning: Joining this faction may prevent you from joining other factions during this run!
</p> </p>
<button id="faction-invitation-box-yes" class="popup-box-button"> Yes </button> <button id="faction-invitation-box-yes" class="popup-box-button"> Join! </button>
<button id="faction-invitation-box-no" class="popup-box-button"> No </button> <button id="faction-invitation-box-no" class="popup-box-button"> Decide later. </button>
</div> </div>
</div> </div>

@ -117,8 +117,8 @@
"build:dev": "webpack --mode development", "build:dev": "webpack --mode development",
"build:test": "webpack --config webpack.config-test.js", "build:test": "webpack --config webpack.config-test.js",
"lint": "npm run lint:jsts & npm run lint:style", "lint": "npm run lint:jsts & npm run lint:style",
"lint:jsts": "eslint '*.{js,jsx,ts,tsx}' './src/**/*.{js,jsx,ts,tsx}' './test/**/*.{js,jsx,ts,tsx}' './utils/**/*.{js,jsx,ts,tsx}'", "lint:jsts": "eslint --fix '*.{js,jsx,ts,tsx}' './src/**/*.{js,jsx,ts,tsx}' './test/**/*.{js,jsx,ts,tsx}' './utils/**/*.{js,jsx,ts,tsx}'",
"lint:style": "stylelint ./css/*", "lint:style": "stylelint --fix ./css/*",
"preinstall": "node ./scripts/engines-check.js", "preinstall": "node ./scripts/engines-check.js",
"test": "mochapack --webpack-config webpack.config-test.js -r jsdom-global/register ./test/index.js", "test": "mochapack --webpack-config webpack.config-test.js -r jsdom-global/register ./test/index.js",
"watch": "webpack --watch --mode production", "watch": "webpack --watch --mode production",

@ -22,12 +22,12 @@ export function loadGlobalAliases(saveString: string): void {
// Prints all aliases to terminal // Prints all aliases to terminal
export function printAliases(): void { export function printAliases(): void {
for (var name in Aliases) { for (const name in Aliases) {
if (Aliases.hasOwnProperty(name)) { if (Aliases.hasOwnProperty(name)) {
post("alias " + name + "=" + Aliases[name]); post("alias " + name + "=" + Aliases[name]);
} }
} }
for (var name in GlobalAliases) { for (const name in GlobalAliases) {
if (GlobalAliases.hasOwnProperty(name)) { if (GlobalAliases.hasOwnProperty(name)) {
post("global alias " + name + "=" + GlobalAliases[name]); post("global alias " + name + "=" + GlobalAliases[name]);
} }
@ -36,8 +36,8 @@ export function printAliases(): void {
// Returns true if successful, false otherwise // Returns true if successful, false otherwise
export function parseAliasDeclaration(dec: string, global = false): boolean { export function parseAliasDeclaration(dec: string, global = false): boolean {
var re = /^([_|\w|!|%|,|@]+)="(.+)"$/; const re = /^([_|\w|!|%|,|@]+)="(.+)"$/;
var matches = dec.match(re); const matches = dec.match(re);
if (matches == null || matches.length != 3) {return false;} if (matches == null || matches.length != 3) {return false;}
if (global){ if (global){
addGlobalAlias(matches[1],matches[2]); addGlobalAlias(matches[1],matches[2]);
@ -100,17 +100,17 @@ export function substituteAliases(origCommand: string): string {
// For the unalias command, dont substite // For the unalias command, dont substite
if (commandArray[0] === "unalias") { return commandArray.join(" "); } if (commandArray[0] === "unalias") { return commandArray.join(" "); }
var alias = getAlias(commandArray[0]); const alias = getAlias(commandArray[0]);
if (alias != null) { if (alias != null) {
commandArray[0] = alias; commandArray[0] = alias;
} else { } else {
var alias = getGlobalAlias(commandArray[0]); const alias = getGlobalAlias(commandArray[0]);
if (alias != null) { if (alias != null) {
commandArray[0] = alias; commandArray[0] = alias;
} }
} }
for (var i = 0; i < commandArray.length; ++i) { for (let i = 0; i < commandArray.length; ++i) {
var alias = getGlobalAlias(commandArray[i]); const alias = getGlobalAlias(commandArray[i]);
if (alias != null) { if (alias != null) {
commandArray[i] = alias; commandArray[i] = alias;
} }

@ -9,7 +9,7 @@ import { Factions } from "../Faction/Factions";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
interface IConstructorParams { interface IConstructorParams {
info: string; info: string | JSX.Element;
isSpecial?: boolean; isSpecial?: boolean;
moneyCost: number; moneyCost: number;
name: string; name: string;
@ -49,31 +49,27 @@ interface IConstructorParams {
} }
export class Augmentation { export class Augmentation {
// Initiatizes a Augmentation object from a JSON save state.
static fromJSON(value: any): Augmentation {
return Generic_fromJSON(Augmentation, value.data);
}
// How much money this costs to buy // How much money this costs to buy
baseCost: number = 0; baseCost = 0;
// How much faction reputation is required to unlock this // How much faction reputation is required to unlock this
baseRepRequirement: number = 0; baseRepRequirement = 0;
// Description of what this Aug is and what it does // Description of what this Aug is and what it does
info: string = ""; info: string | JSX.Element;
// Any Augmentation not immediately available in BitNode-1 is special (e.g. Bladeburner augs) // Any Augmentation not immediately available in BitNode-1 is special (e.g. Bladeburner augs)
isSpecial: boolean = false; isSpecial = false;
// Augmentation level - for repeatable Augs like NeuroFlux Governor // Augmentation level - for repeatable Augs like NeuroFlux Governor
level: number = 0; level = 0;
// Name of Augmentation // Name of Augmentation
name: string = ""; name = "";
// Whether the player owns this Augmentation // Whether the player owns this Augmentation
owned: boolean = false; owned = false;
// Array of names of all prerequisites // Array of names of all prerequisites
prereqs: string[] = []; prereqs: string[] = [];
@ -83,7 +79,7 @@ export class Augmentation {
mults: IMap<number> = {} mults: IMap<number> = {}
// Initial cost. Doesn't change when you purchase multiple Augmentation // Initial cost. Doesn't change when you purchase multiple Augmentation
startingCost: number = 0; startingCost = 0;
constructor(params: IConstructorParams={ info: "", moneyCost: 0, name: "", repCost: 0 }) { constructor(params: IConstructorParams={ info: "", moneyCost: 0, name: "", repCost: 0 }) {
this.name = params.name; this.name = params.name;
@ -141,7 +137,7 @@ export class Augmentation {
console.warn(`In Augmentation.addToFactions(), could not find faction with this name: ${factionList[i]}`); console.warn(`In Augmentation.addToFactions(), could not find faction with this name: ${factionList[i]}`);
continue; continue;
} }
faction!.augmentations.push(this.name); faction.augmentations.push(this.name);
} }
} }
@ -154,7 +150,7 @@ export class Augmentation {
console.warn(`Invalid Faction object in addToAllFactions(). Key value: ${fac}`); console.warn(`Invalid Faction object in addToAllFactions(). Key value: ${fac}`);
continue; continue;
} }
facObj!.augmentations.push(this.name); facObj.augmentations.push(this.name);
} }
} }
} }
@ -163,6 +159,12 @@ export class Augmentation {
toJSON(): any { toJSON(): any {
return Generic_toJSON("Augmentation", this); return Generic_toJSON("Augmentation", this);
} }
// Initiatizes a Augmentation object from a JSON save state.
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Augmentation {
return Generic_fromJSON(Augmentation, value.data);
}
} }
Reviver.constructors.Augmentation = Augmentation; Reviver.constructors.Augmentation = Augmentation;

@ -8,29 +8,13 @@ import { AugmentationsRoot } from "./ui/Root";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { CONSTANTS } from "../Constants"; import { CONSTANTS } from "../Constants";
import { Factions, factionExists } from "../Faction/Factions"; import { Factions, factionExists } from "../Faction/Factions";
import { startWorkerScript } from "../NetscriptWorker";
import { Player } from "../Player"; import { Player } from "../Player";
import { prestigeAugmentation } from "../Prestige"; import { prestigeAugmentation } from "../Prestige";
import { saveObject } from "../SaveObject"; import { saveObject } from "../SaveObject";
import { RunningScript } from "../Script/RunningScript";
import { Script } from "../Script/Script";
import { Server } from "../Server/Server";
import { OwnedAugmentationsOrderSetting } from "../Settings/SettingEnums";
import { Settings } from "../Settings/Settings";
import { Page, routing } from "../ui/navigationTracking"; import { Page, routing } from "../ui/navigationTracking";
import { dialogBoxCreate } from "../../utils/DialogBox"; import { dialogBoxCreate } from "../../utils/DialogBox";
import { createAccordionElement } from "../../utils/uiHelpers/createAccordionElement";
import {
Reviver,
Generic_toJSON,
Generic_fromJSON
} from "../../utils/JSONReviver";
import { formatNumber } from "../../utils/StringHelperFunctions";
import { clearObject } from "../../utils/helpers/clearObject"; import { clearObject } from "../../utils/helpers/clearObject";
import { createElement } from "../../utils/uiHelpers/createElement";
import { isString } from "../../utils/helpers/isString";
import { removeChildrenFromElement } from "../../utils/uiHelpers/removeChildrenFromElement";
import { Money } from "../ui/React/Money"; import { Money } from "../ui/React/Money";
import React from "react"; import React from "react";
@ -76,7 +60,7 @@ function initAugmentations() {
"This augmentation increases the player's dexterity by 10%.", "This augmentation increases the player's dexterity by 10%.",
dexterity_mult: 1.1, dexterity_mult: 1.1,
}); });
Targeting1.addToFactions(["Slum Snakes", "The Dark Army", "The Syndicate", "Sector-12", "Volhaven", "Ishima", Targeting1.addToFactions(["Slum Snakes", "The Dark Army", "The Syndicate", "Sector-12", "Ishima",
"OmniTek Incorporated", "KuaiGong International", "Blade Industries"]); "OmniTek Incorporated", "KuaiGong International", "Blade Industries"]);
if (augmentationExists(AugmentationNames.Targeting1)) { if (augmentationExists(AugmentationNames.Targeting1)) {
delete Augmentations[AugmentationNames.Targeting1]; delete Augmentations[AugmentationNames.Targeting1];
@ -91,7 +75,7 @@ function initAugmentations() {
prereqs:[AugmentationNames.Targeting1], prereqs:[AugmentationNames.Targeting1],
dexterity_mult: 1.2, dexterity_mult: 1.2,
}); });
Targeting2.addToFactions(["The Dark Army", "The Syndicate", "Sector-12", "Volhaven", "Ishima", Targeting2.addToFactions(["The Dark Army", "The Syndicate", "Sector-12",
"OmniTek Incorporated", "KuaiGong International", "Blade Industries"]); "OmniTek Incorporated", "KuaiGong International", "Blade Industries"]);
if (augmentationExists(AugmentationNames.Targeting2)) { if (augmentationExists(AugmentationNames.Targeting2)) {
delete Augmentations[AugmentationNames.Targeting2]; delete Augmentations[AugmentationNames.Targeting2];
@ -152,7 +136,7 @@ function initAugmentations() {
strength_mult: 1.1, strength_mult: 1.1,
defense_mult: 1.1, defense_mult: 1.1,
}); });
CombatRib1.addToFactions(["Slum Snakes", "The Dark Army", "The Syndicate", "Sector-12", "Volhaven", "Ishima", CombatRib1.addToFactions(["Slum Snakes", "The Dark Army", "The Syndicate", "Volhaven", "Ishima",
"OmniTek Incorporated", "KuaiGong International", "Blade Industries"]); "OmniTek Incorporated", "KuaiGong International", "Blade Industries"]);
if (augmentationExists(AugmentationNames.CombatRib1)) { if (augmentationExists(AugmentationNames.CombatRib1)) {
delete Augmentations[AugmentationNames.CombatRib1]; delete Augmentations[AugmentationNames.CombatRib1];
@ -168,7 +152,7 @@ function initAugmentations() {
strength_mult: 1.14, strength_mult: 1.14,
defense_mult: 1.14, defense_mult: 1.14,
}); });
CombatRib2.addToFactions(["The Dark Army", "The Syndicate", "Sector-12", "Volhaven", "Ishima", CombatRib2.addToFactions(["The Dark Army", "The Syndicate", "Volhaven",
"OmniTek Incorporated", "KuaiGong International", "Blade Industries"]); "OmniTek Incorporated", "KuaiGong International", "Blade Industries"]);
if (augmentationExists(AugmentationNames.CombatRib2)) { if (augmentationExists(AugmentationNames.CombatRib2)) {
delete Augmentations[AugmentationNames.CombatRib2]; delete Augmentations[AugmentationNames.CombatRib2];
@ -404,7 +388,7 @@ function initAugmentations() {
info:"The body is injected with a chemical that artificially induces synaptic potentiation, " + info:"The body is injected with a chemical that artificially induces synaptic potentiation, " +
"otherwise known as the strengthening of synapses. This results in a enhanced cognitive abilities.<br><br>" + "otherwise known as the strengthening of synapses. This results in a enhanced cognitive abilities.<br><br>" +
"This augmentation:<br>" + "This augmentation:<br>" +
"Increases the player's hacking speed by 2% <br>" + "Increases the player's hacking speed by 2%.<br>" +
"Increases the player's hacking chance by 5%.<br>" + "Increases the player's hacking chance by 5%.<br>" +
"Increases the player's hacking experience gain rate by 5%.", "Increases the player's hacking experience gain rate by 5%.",
hacking_speed_mult: 1.02, hacking_speed_mult: 1.02,
@ -444,7 +428,7 @@ function initAugmentations() {
"This augmentation increases the player's hacking speed by 3%.", "This augmentation increases the player's hacking speed by 3%.",
hacking_speed_mult: 1.03, hacking_speed_mult: 1.03,
}); });
SynapticEnhancement.addToFactions(["CyberSec"]); SynapticEnhancement.addToFactions(["CyberSec", "Aevum"]);
if (augmentationExists(AugmentationNames.SynapticEnhancement)) { if (augmentationExists(AugmentationNames.SynapticEnhancement)) {
delete Augmentations[AugmentationNames.SynapticEnhancement]; delete Augmentations[AugmentationNames.SynapticEnhancement];
} }
@ -772,7 +756,7 @@ function initAugmentations() {
"when working for a company by 20%.", "when working for a company by 20%.",
company_rep_mult: 1.2, company_rep_mult: 1.2,
}); });
NuoptimalInjectorImplant.addToFactions(["Tian Di Hui", "Volhaven", "New Tokyo", "Chongqing", "Ishima", NuoptimalInjectorImplant.addToFactions(["Tian Di Hui", "Volhaven", "New Tokyo", "Chongqing",
"Clarke Incorporated", "Four Sigma", "Bachman & Associates"]); "Clarke Incorporated", "Four Sigma", "Bachman & Associates"]);
if (augmentationExists(AugmentationNames.NuoptimalInjectorImplant)) { if (augmentationExists(AugmentationNames.NuoptimalInjectorImplant)) {
delete Augmentations[AugmentationNames.NuoptimalInjectorImplant]; delete Augmentations[AugmentationNames.NuoptimalInjectorImplant];
@ -1080,7 +1064,7 @@ function initAugmentations() {
agility_exp_mult: 1.1, agility_exp_mult: 1.1,
charisma_exp_mult: 1.1, charisma_exp_mult: 1.1,
}); });
Neurotrainer1.addToFactions(["CyberSec"]); Neurotrainer1.addToFactions(["CyberSec", "Aevum"]);
if (augmentationExists(AugmentationNames.Neurotrainer1)) { if (augmentationExists(AugmentationNames.Neurotrainer1)) {
delete Augmentations[AugmentationNames.Neurotrainer1]; delete Augmentations[AugmentationNames.Neurotrainer1];
} }
@ -1256,7 +1240,7 @@ function initAugmentations() {
// Daedalus // Daedalus
const RedPill = new Augmentation({ const RedPill = new Augmentation({
name:AugmentationNames.TheRedPill, repCost:1e6, moneyCost:0, name:AugmentationNames.TheRedPill, repCost:1e6, moneyCost:0,
info:"It's time to leave the cave." info:"It's time to leave the cave.",
}); });
RedPill.addToFactions(["Daedalus"]); RedPill.addToFactions(["Daedalus"]);
if (augmentationExists(AugmentationNames.TheRedPill)) { if (augmentationExists(AugmentationNames.TheRedPill)) {
@ -1332,7 +1316,7 @@ function initAugmentations() {
"capable of psychoanalyzing and profiling the personality of " + "capable of psychoanalyzing and profiling the personality of " +
"others using optical imaging software.<br><br>" + "others using optical imaging software.<br><br>" +
"This augmentation:<br>" + "This augmentation:<br>" +
"Increases the player's charisma by 50%. <br>" + "Increases the player's charisma by 50%.<br>" +
"Increases the player's charisma experience gain rate by 50%.<br>" + "Increases the player's charisma experience gain rate by 50%.<br>" +
"Increases the amount of reputation the player gains for a company by 25%.<br>" + "Increases the amount of reputation the player gains for a company by 25%.<br>" +
"Increases the amount of reputation the player gains for a faction by 25%.", "Increases the amount of reputation the player gains for a faction by 25%.",
@ -1556,7 +1540,7 @@ function initAugmentations() {
and upload the assets.<br /><br /> and upload the assets.<br /><br />
This augmentation:<br /> This augmentation:<br />
Lets the player start with {Money(1e6)} after a reset.<br /> Lets the player start with {Money(1e6)} after a reset.<br />
Lets the player start with the BruteSSH.exe program after a reset.</> Lets the player start with the BruteSSH.exe program after a reset.</>,
}); });
CashRoot.addToFactions(["Sector-12"]); CashRoot.addToFactions(["Sector-12"]);
if (augmentationExists(AugmentationNames.CashRoot)) { if (augmentationExists(AugmentationNames.CashRoot)) {
@ -1743,7 +1727,7 @@ function initAugmentations() {
"to induce wakefulness and concentration, suppress fear, reduce empathy, and " + "to induce wakefulness and concentration, suppress fear, reduce empathy, and " +
"improve reflexes and memory-recall among other things.<br><br>" + "improve reflexes and memory-recall among other things.<br><br>" +
"This augmentation:<br>" + "This augmentation:<br>" +
"Increases the player's sucess chance in Bladeburner contracts/operations by 3%.<br>" + "Increases the player's success chance in Bladeburner contracts/operations by 3%.<br>" +
"Increases the player's effectiveness in Bladeburner Field Analysis by 5%.<br>" + "Increases the player's effectiveness in Bladeburner Field Analysis by 5%.<br>" +
"Increases the player's Bladeburner stamina gain rate by 2%.", "Increases the player's Bladeburner stamina gain rate by 2%.",
bladeburner_success_chance_mult: 1.03, bladeburner_success_chance_mult: 1.03,
@ -2098,7 +2082,7 @@ export function displayAugmentationsContent(contentEl) {
exportGameFn={saveObject.exportGame.bind(saveObject)} exportGameFn={saveObject.exportGame.bind(saveObject)}
installAugmentationsFn={installAugmentations} installAugmentationsFn={installAugmentations}
/>, />,
contentEl contentEl,
); );
} }

@ -1,4 +1,4 @@
import { Augmentation } from "./Augmentation"; import { Augmentation } from "./Augmentation";
import { IMap } from "../types"; import { IMap } from "../types";
export let Augmentations: IMap<Augmentation> = {}; export const Augmentations: IMap<Augmentation> = {};

@ -1,8 +1,8 @@
export class PlayerOwnedAugmentation { export class PlayerOwnedAugmentation {
level: number = 1; level = 1;
name: string = ""; name = "";
constructor(name: string = "") { constructor(name = "") {
this.name = name; this.name = name;
} }
} }

@ -1,6 +1,6 @@
import { IMap } from "../../types"; import { IMap } from "../../types";
export let AugmentationNames: IMap<string> = { export const AugmentationNames: IMap<string> = {
Targeting1: "Augmented Targeting I", Targeting1: "Augmented Targeting I",
Targeting2: "Augmented Targeting II", Targeting2: "Augmented Targeting II",
Targeting3: "Augmented Targeting III", Targeting3: "Augmented Targeting III",

@ -15,7 +15,9 @@ import { SourceFileMinus1 } from "./SourceFileMinus1";
import { Settings } from "../../Settings/Settings"; import { Settings } from "../../Settings/Settings";
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums"; import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
type IProps = {} type IProps = {
// nothing special.
}
type IState = { type IState = {
rerenderFlag: boolean; rerenderFlag: boolean;
@ -39,7 +41,7 @@ export class InstalledAugmentationsAndSourceFiles extends React.Component<IProps
this.listRef = React.createRef(); this.listRef = React.createRef();
} }
collapseAllHeaders() { collapseAllHeaders(): void {
const ul = this.listRef.current; const ul = this.listRef.current;
if (ul == null) { return; } if (ul == null) { return; }
const tickers = ul.getElementsByClassName("accordion-header"); const tickers = ul.getElementsByClassName("accordion-header");
@ -55,7 +57,7 @@ export class InstalledAugmentationsAndSourceFiles extends React.Component<IProps
} }
} }
expandAllHeaders() { expandAllHeaders(): void {
const ul = this.listRef.current; const ul = this.listRef.current;
if (ul == null) { return; } if (ul == null) { return; }
const tickers = ul.getElementsByClassName("accordion-header"); const tickers = ul.getElementsByClassName("accordion-header");
@ -71,7 +73,7 @@ export class InstalledAugmentationsAndSourceFiles extends React.Component<IProps
} }
} }
rerender() { rerender(): void {
this.setState((prevState) => { this.setState((prevState) => {
return { return {
rerenderFlag: !prevState.rerenderFlag, rerenderFlag: !prevState.rerenderFlag,
@ -79,17 +81,17 @@ export class InstalledAugmentationsAndSourceFiles extends React.Component<IProps
}); });
} }
sortByAcquirementTime() { sortByAcquirementTime(): void {
Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.AcquirementTime; Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.AcquirementTime;
this.rerender(); this.rerender();
} }
sortInOrder() { sortInOrder(): void {
Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.Alphabetically Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.Alphabetically
this.rerender(); this.rerender();
} }
render() { render(): React.ReactNode {
return ( return (
<> <>
<ListConfiguration <ListConfiguration

@ -7,7 +7,7 @@ import { Player } from "../../Player";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { Augmentations} from "../Augmentations"; import { Augmentations} from "../Augmentations";
function calculateAugmentedStats() { function calculateAugmentedStats(): any {
const augP: any = {}; const augP: any = {};
for(const aug of Player.queuedAugmentations) { for(const aug of Player.queuedAugmentations) {
const augObj = Augmentations[aug.name]; const augObj = Augmentations[aug.name];
@ -22,12 +22,12 @@ function calculateAugmentedStats() {
export function PlayerMultipliers(): React.ReactElement { export function PlayerMultipliers(): React.ReactElement {
const mults = calculateAugmentedStats(); const mults = calculateAugmentedStats();
function MultiplierTable(rows: any[]): React.ReactElement { function MultiplierTable(rows: any[]): React.ReactElement {
function improvements(r: number) { function improvements(r: number): JSX.Element[] {
let elems: any[] = []; let elems: JSX.Element[] = [];
if(r) { if(r) {
elems = [ elems = [
<td key="2">&nbsp;{"=>"}&nbsp;</td>, <td key="2">&nbsp;{"=>"}&nbsp;</td>,
<td key="3">{numeralWrapper.formatPercentage(r)}</td> <td key="3">{numeralWrapper.formatPercentage(r)}</td>,
]; ];
} }
return elems; return elems;
@ -51,38 +51,38 @@ export function PlayerMultipliers(): React.ReactElement {
['Hacking Chance ', Player.hacking_chance_mult, Player.hacking_chance_mult*mults.hacking_chance_mult], ['Hacking Chance ', Player.hacking_chance_mult, Player.hacking_chance_mult*mults.hacking_chance_mult],
['Hacking Speed ', Player.hacking_speed_mult, Player.hacking_speed_mult*mults.hacking_speed_mult], ['Hacking Speed ', Player.hacking_speed_mult, Player.hacking_speed_mult*mults.hacking_speed_mult],
['Hacking Money ', Player.hacking_money_mult, Player.hacking_money_mult*mults.hacking_money_mult], ['Hacking Money ', Player.hacking_money_mult, Player.hacking_money_mult*mults.hacking_money_mult],
['Hacking Growth ', Player.hacking_grow_mult, Player.hacking_grow_mult*mults.hacking_grow_mult] ['Hacking Growth ', Player.hacking_grow_mult, Player.hacking_grow_mult*mults.hacking_grow_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([
['Hacking Level ', Player.hacking_mult, Player.hacking_mult*mults.hacking_mult], ['Hacking Level ', Player.hacking_mult, Player.hacking_mult*mults.hacking_mult],
['Hacking Experience ', Player.hacking_exp_mult, Player.hacking_exp_mult*mults.hacking_exp_mult] ['Hacking Experience ', Player.hacking_exp_mult, Player.hacking_exp_mult*mults.hacking_exp_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([
['Strength Level ', Player.strength_mult, Player.strength_mult*mults.strength_mult], ['Strength Level ', Player.strength_mult, Player.strength_mult*mults.strength_mult],
['Strength Experience ', Player.strength_exp_mult, Player.strength_exp_mult*mults.strength_exp_mult] ['Strength Experience ', Player.strength_exp_mult, Player.strength_exp_mult*mults.strength_exp_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([
['Defense Level ', Player.defense_mult, Player.defense_mult*mults.defense_mult], ['Defense Level ', Player.defense_mult, Player.defense_mult*mults.defense_mult],
['Defense Experience ', Player.defense_exp_mult, Player.defense_exp_mult*mults.defense_exp_mult] ['Defense Experience ', Player.defense_exp_mult, Player.defense_exp_mult*mults.defense_exp_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([
['Dexterity Level ', Player.dexterity_mult, Player.dexterity_mult*mults.dexterity_mult], ['Dexterity Level ', Player.dexterity_mult, Player.dexterity_mult*mults.dexterity_mult],
['Dexterity Experience ', Player.dexterity_exp_mult, Player.dexterity_exp_mult*mults.dexterity_exp_mult] ['Dexterity Experience ', Player.dexterity_exp_mult, Player.dexterity_exp_mult*mults.dexterity_exp_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([
['Agility Level ', Player.agility_mult, Player.agility_mult*mults.agility_mult], ['Agility Level ', Player.agility_mult, Player.agility_mult*mults.agility_mult],
['Agility Experience ', Player.agility_exp_mult, Player.agility_exp_mult*mults.agility_exp_mult] ['Agility Experience ', Player.agility_exp_mult, Player.agility_exp_mult*mults.agility_exp_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([
['Charisma Level ', Player.charisma_mult, Player.charisma_mult*mults.charisma_mult], ['Charisma Level ', Player.charisma_mult, Player.charisma_mult*mults.charisma_mult],
['Charisma Experience ', Player.charisma_exp_mult, Player.charisma_exp_mult*mults.charisma_exp_mult] ['Charisma Experience ', Player.charisma_exp_mult, Player.charisma_exp_mult*mults.charisma_exp_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([
@ -90,13 +90,13 @@ export function PlayerMultipliers(): React.ReactElement {
['Hacknet Node purchase cost ', Player.hacknet_node_purchase_cost_mult, Player.hacknet_node_purchase_cost_mult*mults.hacknet_node_purchase_cost_mult], ['Hacknet Node purchase cost ', Player.hacknet_node_purchase_cost_mult, Player.hacknet_node_purchase_cost_mult*mults.hacknet_node_purchase_cost_mult],
['Hacknet Node RAM upgrade cost ', Player.hacknet_node_ram_cost_mult, Player.hacknet_node_ram_cost_mult*mults.hacknet_node_ram_cost_mult], ['Hacknet Node RAM upgrade cost ', Player.hacknet_node_ram_cost_mult, Player.hacknet_node_ram_cost_mult*mults.hacknet_node_ram_cost_mult],
['Hacknet Node Core purchase cost ', Player.hacknet_node_core_cost_mult, Player.hacknet_node_core_cost_mult*mults.hacknet_node_core_cost_mult], ['Hacknet Node Core purchase cost ', Player.hacknet_node_core_cost_mult, Player.hacknet_node_core_cost_mult*mults.hacknet_node_core_cost_mult],
['Hacknet Node level upgrade cost ', Player.hacknet_node_level_cost_mult, Player.hacknet_node_level_cost_mult*mults.hacknet_node_level_cost_mult] ['Hacknet Node level upgrade cost ', Player.hacknet_node_level_cost_mult, Player.hacknet_node_level_cost_mult*mults.hacknet_node_level_cost_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([
['Company reputation gain ', Player.company_rep_mult, Player.company_rep_mult*mults.company_rep_mult], ['Company reputation gain ', Player.company_rep_mult, Player.company_rep_mult*mults.company_rep_mult],
['Faction reputation gain ', Player.faction_rep_mult, Player.faction_rep_mult*mults.faction_rep_mult], ['Faction reputation gain ', Player.faction_rep_mult, Player.faction_rep_mult*mults.faction_rep_mult],
['Salary ', Player.work_money_mult, Player.work_money_mult*mults.work_money_mult] ['Salary ', Player.work_money_mult, Player.work_money_mult*mults.work_money_mult],
])}<br /> ])}<br />
{MultiplierTable([ {MultiplierTable([

@ -22,7 +22,7 @@ export function PurchasedAugmentations(): React.ReactElement {
augs.push( augs.push(
<li key={`${ownedAug.name}${ownedAug.level}`}> <li key={`${ownedAug.name}${ownedAug.level}`}>
<AugmentationAccordion aug={aug} level={level} /> <AugmentationAccordion aug={aug} level={level} />
</li> </li>,
) )
} }

@ -25,7 +25,7 @@ export class AugmentationsRoot extends React.Component<IProps, IState> {
super(props); super(props);
} }
render() { render(): React.ReactNode {
return ( return (
<div id="augmentations-content"> <div id="augmentations-content">
<h1>Purchased Augmentations</h1> <h1>Purchased Augmentations</h1>

@ -5,15 +5,12 @@
import * as React from "react"; import * as React from "react";
import { Player } from "../../Player"; import { Player } from "../../Player";
import { Settings } from "../../Settings/Settings";
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
import { SourceFiles } from "../../SourceFile/SourceFiles";
import { Exploit, ExploitName } from "../../Exploits/Exploit"; import { Exploit, ExploitName } from "../../Exploits/Exploit";
import { Accordion } from "../../ui/React/Accordion"; import { Accordion } from "../../ui/React/Accordion";
export function SourceFileMinus1(): React.ReactElement { export function SourceFileMinus1(): React.ReactElement {
let exploits = Player.exploits; const exploits = Player.exploits;
if(exploits.length === 0) { if(exploits.length === 0) {
return <></> return <></>

@ -16,7 +16,7 @@ class BitNode {
number: number; number: number;
constructor(n: number, name: string, desc: string="", info: string="") { constructor(n: number, name: string, desc="", info="") {
this.number = n; this.number = n;
this.name = name; this.name = name;
this.desc = desc; this.desc = desc;
@ -236,8 +236,7 @@ BitNodes["BitNode12"] = new BitNode(12, "The Recursion", "Repeat.",
"To iterate is human, to recurse divine.<br><br>" + "To iterate is human, to recurse divine.<br><br>" +
"Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give you Source-File 12, or " + "Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give you Source-File 12, or " +
"if you already have this Source-File it will upgrade its level. There is no maximum level for Source-File 12. Each level " + "if you already have this Source-File it will upgrade its level. There is no maximum level for Source-File 12. Each level " +
"of Source-File 12 will increase all of your multipliers by 1%. This effect is multiplicative with itself. " + "of Source-File 12 lets you start any BitNodes with NeuroFlux Governor equal to the level of this source file.");
"In other words, level N of this Source-File will result in a multiplier of 1.01^N (or 0.99^N for multipliers that decrease)");
// Books: Frontera, Shiner // Books: Frontera, Shiner
BitNodes["BitNode13"] = new BitNode(13, "fOS", "COMING SOON"); //Unlocks the new game mode and the rest of the BitNodes BitNodes["BitNode13"] = new BitNode(13, "fOS", "COMING SOON"); //Unlocks the new game mode and the rest of the BitNodes
BitNodes["BitNode14"] = new BitNode(14, "", "COMING SOON"); BitNodes["BitNode14"] = new BitNode(14, "", "COMING SOON");
@ -252,11 +251,11 @@ BitNodes["BitNode22"] = new BitNode(22, "", "COMING SOON");
BitNodes["BitNode23"] = new BitNode(23, "", "COMING SOON"); BitNodes["BitNode23"] = new BitNode(23, "", "COMING SOON");
BitNodes["BitNode24"] = new BitNode(24, "", "COMING SOON"); BitNodes["BitNode24"] = new BitNode(24, "", "COMING SOON");
export function initBitNodeMultipliers(p: IPlayer) { export function initBitNodeMultipliers(p: IPlayer): void {
if (p.bitNodeN == null) { if (p.bitNodeN == null) {
p.bitNodeN = 1; p.bitNodeN = 1;
} }
for (var mult in BitNodeMultipliers) { for (const mult in BitNodeMultipliers) {
if (BitNodeMultipliers.hasOwnProperty(mult)) { if (BitNodeMultipliers.hasOwnProperty(mult)) {
BitNodeMultipliers[mult] = 1; BitNodeMultipliers[mult] = 1;
} }
@ -433,15 +432,15 @@ export function initBitNodeMultipliers(p: IPlayer) {
BitNodeMultipliers.FourSigmaMarketDataCost = 4; BitNodeMultipliers.FourSigmaMarketDataCost = 4;
BitNodeMultipliers.FourSigmaMarketDataApiCost = 4; BitNodeMultipliers.FourSigmaMarketDataApiCost = 4;
break; break;
case 12: //The Recursion case 12: { //The Recursion
var sf12Lvl = 0; let sf12Lvl = 0;
for (var i = 0; i < p.sourceFiles.length; i++) { for (let i = 0; i < p.sourceFiles.length; i++) {
if (p.sourceFiles[i].n === 12) { if (p.sourceFiles[i].n === 12) {
sf12Lvl = p.sourceFiles[i].lvl; sf12Lvl = p.sourceFiles[i].lvl;
} }
} }
var inc = Math.pow(1.02, sf12Lvl); const inc = Math.pow(1.02, sf12Lvl);
var dec = 1/inc; const dec = 1/inc;
// Multiplier for number of augs needed for Daedalus increases // Multiplier for number of augs needed for Daedalus increases
// up to a maximum of 1.34, which results in 40 Augs required // up to a maximum of 1.34, which results in 40 Augs required
@ -499,6 +498,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
BitNodeMultipliers.BladeburnerRank = dec; BitNodeMultipliers.BladeburnerRank = dec;
BitNodeMultipliers.BladeburnerSkillCost = inc; BitNodeMultipliers.BladeburnerSkillCost = inc;
break; break;
}
default: default:
console.warn("Player.bitNodeN invalid"); console.warn("Player.bitNodeN invalid");
break; break;

@ -1,7 +1,6 @@
import { Augmentations } from "./Augmentation/Augmentations"; import { Augmentations } from "./Augmentation/Augmentations";
import { AugmentationNames } from "./Augmentation/data/AugmentationNames"; import { AugmentationNames } from "./Augmentation/data/AugmentationNames";
import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers"; import { BitNodeMultipliers } from "./BitNode/BitNodeMultipliers";
import { CONSTANTS } from "./Constants";
import { Engine } from "./engine"; import { Engine } from "./engine";
import { Faction } from "./Faction/Faction"; import { Faction } from "./Faction/Faction";
import { Factions, factionExists } from "./Faction/Factions"; import { Factions, factionExists } from "./Faction/Factions";
@ -17,17 +16,19 @@ import { dialogBoxCreate } from "../utils/DialogBox";
import { import {
Reviver, Reviver,
Generic_toJSON, Generic_toJSON,
Generic_fromJSON Generic_fromJSON,
} from "../utils/JSONReviver"; } from "../utils/JSONReviver";
import { setTimeoutRef } from "./utils/SetTimeoutRef"; import { setTimeoutRef } from "./utils/SetTimeoutRef";
import { formatNumber } from "../utils/StringHelperFunctions"; import {
formatNumber,
convertTimeMsToTimeElapsedString,
} from "../utils/StringHelperFunctions";
import { ConsoleHelpText } from "./Bladeburner/data/Help"; import { ConsoleHelpText } from "./Bladeburner/data/Help";
import { City } from "./Bladeburner/City"; import { City } from "./Bladeburner/City";
import { BladeburnerConstants } from "./Bladeburner/data/Constants"; import { BladeburnerConstants } from "./Bladeburner/data/Constants";
import { Skill } from "./Bladeburner/Skill"; import { Skill } from "./Bladeburner/Skill";
import { Skills } from "./Bladeburner/Skills"; import { Skills } from "./Bladeburner/Skills";
import { SkillNames } from "./Bladeburner/data/SkillNames";
import { Operation } from "./Bladeburner/Operation"; import { Operation } from "./Bladeburner/Operation";
import { BlackOperation } from "./Bladeburner/BlackOperation"; import { BlackOperation } from "./Bladeburner/BlackOperation";
import { BlackOperations } from "./Bladeburner/BlackOperations"; import { BlackOperations } from "./Bladeburner/BlackOperations";
@ -45,7 +46,6 @@ import { KEY } from "../utils/helpers/keyCodes";
import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement"; import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
import { appendLineBreaks } from "../utils/uiHelpers/appendLineBreaks"; import { appendLineBreaks } from "../utils/uiHelpers/appendLineBreaks";
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
import { createElement } from "../utils/uiHelpers/createElement"; import { createElement } from "../utils/uiHelpers/createElement";
import { createPopup } from "../utils/uiHelpers/createPopup"; import { createPopup } from "../utils/uiHelpers/createPopup";
import { removeElement } from "../utils/uiHelpers/removeElement"; import { removeElement } from "../utils/uiHelpers/removeElement";
@ -236,7 +236,7 @@ Bladeburner.prototype.create = function() {
count:getRandomInt(25, 150), countGrowth:getRandomInt(5, 75)/10, count:getRandomInt(25, 150), countGrowth:getRandomInt(5, 75)/10,
weights:{hack:0,str:0.05,def:0.05,dex:0.35,agi:0.35,cha:0.1, int:0.05}, weights:{hack:0,str:0.05,def:0.05,dex:0.35,agi:0.35,cha:0.1, int:0.05},
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.9, int:1}, decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.9, int:1},
isStealth:true isStealth:true,
}); });
this.contracts["Bounty Hunter"] = new Contract({ this.contracts["Bounty Hunter"] = new Contract({
name:"Bounty Hunter", name:"Bounty Hunter",
@ -248,7 +248,7 @@ Bladeburner.prototype.create = function() {
count:getRandomInt(5, 150), countGrowth:getRandomInt(5, 75)/10, count:getRandomInt(5, 150), countGrowth:getRandomInt(5, 75)/10,
weights:{hack:0,str:0.15,def:0.15,dex:0.25,agi:0.25,cha:0.1, int:0.1}, weights:{hack:0,str:0.15,def:0.15,dex:0.25,agi:0.25,cha:0.1, int:0.1},
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9}, decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9},
isKill:true isKill:true,
}); });
this.contracts["Retirement"] = new Contract({ this.contracts["Retirement"] = new Contract({
name:"Retirement", name:"Retirement",
@ -260,7 +260,7 @@ Bladeburner.prototype.create = function() {
count:getRandomInt(5, 150), countGrowth:getRandomInt(5, 75)/10, count:getRandomInt(5, 150), countGrowth:getRandomInt(5, 75)/10,
weights:{hack:0,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0.1, int:0.1}, weights:{hack:0,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0.1, int:0.1},
decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9}, decays:{hack:0,str:0.91,def:0.91,dex:0.91,agi:0.91,cha:0.8, int:0.9},
isKill:true isKill:true,
}); });
this.operations["Investigation"] = new Operation({ this.operations["Investigation"] = new Operation({
@ -275,7 +275,7 @@ Bladeburner.prototype.create = function() {
count:getRandomInt(1, 100), countGrowth:getRandomInt(10, 40)/10, count:getRandomInt(1, 100), countGrowth:getRandomInt(10, 40)/10,
weights:{hack:0.25,str:0.05,def:0.05,dex:0.2,agi:0.1,cha:0.25, int:0.1}, weights:{hack:0.25,str:0.05,def:0.05,dex:0.2,agi:0.1,cha:0.25, int:0.1},
decays:{hack:0.85,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9}, decays:{hack:0.85,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9},
isStealth:true isStealth:true,
}); });
this.operations["Undercover Operation"] = new Operation({ this.operations["Undercover Operation"] = new Operation({
name:"Undercover Operation", name:"Undercover Operation",
@ -288,7 +288,7 @@ Bladeburner.prototype.create = function() {
count:getRandomInt(1, 100), countGrowth:getRandomInt(10, 40)/10, count:getRandomInt(1, 100), countGrowth:getRandomInt(10, 40)/10,
weights:{hack:0.2,str:0.05,def:0.05,dex:0.2,agi:0.2,cha:0.2, int:0.1}, weights:{hack:0.2,str:0.05,def:0.05,dex:0.2,agi:0.2,cha:0.2, int:0.1},
decays:{hack:0.8,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9}, decays:{hack:0.8,str:0.9,def:0.9,dex:0.9,agi:0.9,cha:0.7, int:0.9},
isStealth:true isStealth:true,
}); });
this.operations["Sting Operation"] = new Operation({ this.operations["Sting Operation"] = new Operation({
name:"Sting Operation", name:"Sting Operation",
@ -299,19 +299,19 @@ Bladeburner.prototype.create = function() {
count:getRandomInt(1, 150), countGrowth:getRandomInt(3, 40)/10, count:getRandomInt(1, 150), countGrowth:getRandomInt(3, 40)/10,
weights:{hack:0.25,str:0.05,def:0.05,dex:0.25,agi:0.1,cha:0.2, int:0.1}, weights:{hack:0.25,str:0.05,def:0.05,dex:0.25,agi:0.1,cha:0.2, int:0.1},
decays:{hack:0.8,str:0.85,def:0.85,dex:0.85,agi:0.85,cha:0.7, int:0.9}, decays:{hack:0.8,str:0.85,def:0.85,dex:0.85,agi:0.85,cha:0.7, int:0.9},
isStealth:true isStealth:true,
}); });
this.operations["Raid"] = new Operation({ this.operations["Raid"] = new Operation({
name:"Raid", name:"Raid",
desc:"Lead an assault on a known Synthoid community. Note that " + desc:"Lead an assault on a known Synthoid community. Note that " +
"there must be an existing Synthoid community in your current city " + "there must be an existing Synthoid community in your current city " +
"in order for this Operation to be successful", "in order for this Operation to be successful.",
baseDifficulty:800, difficultyFac:1.045, rewardFac:1.1, reqdRank:3000, baseDifficulty:800, difficultyFac:1.045, rewardFac:1.1, reqdRank:3000,
rankGain:55,rankLoss:2.5,hpLoss:50, rankGain:55,rankLoss:2.5,hpLoss:50,
count:getRandomInt(1, 150), countGrowth:getRandomInt(2, 40)/10, count:getRandomInt(1, 150), countGrowth:getRandomInt(2, 40)/10,
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9}, decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9},
isKill:true isKill:true,
}); });
this.operations["Stealth Retirement Operation"] = new Operation({ this.operations["Stealth Retirement Operation"] = new Operation({
name:"Stealth Retirement Operation", name:"Stealth Retirement Operation",
@ -323,7 +323,7 @@ Bladeburner.prototype.create = function() {
count:getRandomInt(1, 150), countGrowth:getRandomInt(1, 20)/10, count:getRandomInt(1, 150), countGrowth:getRandomInt(1, 20)/10,
weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1}, weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1},
decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9}, decays:{hack:0.7,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.9},
isStealth:true, isKill:true isStealth:true, isKill:true,
}); });
this.operations["Assassination"] = new Operation({ this.operations["Assassination"] = new Operation({
name:"Assassination", name:"Assassination",
@ -335,7 +335,7 @@ Bladeburner.prototype.create = function() {
count:getRandomInt(1, 150), countGrowth:getRandomInt(1, 20)/10, count:getRandomInt(1, 150), countGrowth:getRandomInt(1, 20)/10,
weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1}, weights:{hack:0.1,str:0.1,def:0.1,dex:0.3,agi:0.3,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.8}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.8},
isStealth:true, isKill:true isStealth:true, isKill:true,
}); });
} }
@ -1271,7 +1271,7 @@ Bladeburner.prototype.createContent = function() {
DomElems.consoleInput.focus(); DomElems.consoleInput.focus();
} }
return false; return false;
} },
}); });
DomElems.consoleTable = createElement("table", {class:"bladeburner-console-table"}); DomElems.consoleTable = createElement("table", {class:"bladeburner-console-table"});
DomElems.consoleInputRow = createElement("tr", {class:"bladeburner-console-input-row", id:"bladeburner-console-input-row"}); DomElems.consoleInputRow = createElement("tr", {class:"bladeburner-console-input-row", id:"bladeburner-console-input-row"});
@ -1279,7 +1279,7 @@ Bladeburner.prototype.createContent = function() {
DomElems.consoleInputHeader = createElement("pre", {innerText:"> "}); DomElems.consoleInputHeader = createElement("pre", {innerText:"> "});
DomElems.consoleInput = createElement("input", { DomElems.consoleInput = createElement("input", {
type:"text", class:"bladeburner-console-input", tabIndex:1, type:"text", class:"bladeburner-console-input", tabIndex:1,
onfocus:() => {DomElems.consoleInput.value = DomElems.consoleInput.value} onfocus:() => {DomElems.consoleInput.value = DomElems.consoleInput.value},
}); });
DomElems.consoleInputCell.appendChild(DomElems.consoleInputHeader); DomElems.consoleInputCell.appendChild(DomElems.consoleInputHeader);
@ -1363,7 +1363,7 @@ Bladeburner.prototype.createOverviewContent = function() {
innerText:"Est. Synthoid Population: ", innerText:"Est. Synthoid Population: ",
display:"inline-block", display:"inline-block",
tooltip:"This is your Bladeburner division's estimate of how many Synthoids exist " + tooltip:"This is your Bladeburner division's estimate of how many Synthoids exist " +
"in your current city." "in your current city.",
}); });
DomElems.overviewEstPopHelpTip = createElement("div", { DomElems.overviewEstPopHelpTip = createElement("div", {
@ -1381,7 +1381,7 @@ Bladeburner.prototype.createOverviewContent = function() {
"The Synthoid populations of cities can change due to your " + "The Synthoid populations of cities can change due to your " +
"actions or random events. If random events occur, they will " + "actions or random events. If random events occur, they will " +
"be logged in the Bladeburner Console."); "be logged in the Bladeburner Console.");
} },
}); });
DomElems.overviewEstComms = createElement("p", { DomElems.overviewEstComms = createElement("p", {
@ -1395,14 +1395,14 @@ Bladeburner.prototype.createOverviewContent = function() {
innerText:"City Chaos: ", innerText:"City Chaos: ",
display:"inline-block", display:"inline-block",
tooltip:"The city's chaos level due to tensions and conflicts between humans and Synthoids. " + tooltip:"The city's chaos level due to tensions and conflicts between humans and Synthoids. " +
"Having too high of a chaos level can make contracts and operations harder." "Having too high of a chaos level can make contracts and operations harder.",
}); });
DomElems.overviewBonusTime = createElement("p", { DomElems.overviewBonusTime = createElement("p", {
innerText: "Bonus time: ", innerText: "Bonus time: ",
display: "inline-block", display: "inline-block",
tooltip: "You gain bonus time while offline or when the game is inactive (e.g. when the tab is throttled by browser). " + tooltip: "You gain bonus time while offline or when the game is inactive (e.g. when the tab is throttled by browser). " +
"Bonus time makes the Bladeburner mechanic progress faster, up to 5x the normal speed." "Bonus time makes the Bladeburner mechanic progress faster, up to 5x the normal speed.",
}); });
DomElems.overviewSkillPoints = createElement("p", {display:"block"}); DomElems.overviewSkillPoints = createElement("p", {display:"block"});
@ -1438,7 +1438,7 @@ Bladeburner.prototype.createOverviewContent = function() {
innerText:"Cancel", class:"a-link-button", innerText:"Cancel", class:"a-link-button",
clickListener:() => { clickListener:() => {
removeElementById(popupId); return false; removeElementById(popupId); return false;
} },
})) }))
popupArguments.push(createElement("p", { // Info Text popupArguments.push(createElement("p", { // Info Text
innerText:"Travel to a different city for your Bladeburner " + innerText:"Travel to a different city for your Bladeburner " +
@ -1460,12 +1460,12 @@ Bladeburner.prototype.createOverviewContent = function() {
removeElementById(popupId); removeElementById(popupId);
inst.updateOverviewContent(); inst.updateOverviewContent();
return false; return false;
} },
})); }));
})(this, i); })(this, i);
} }
createPopup(popupId, popupArguments); createPopup(popupId, popupArguments);
} },
})); }));
// Faction button // Faction button
@ -1493,7 +1493,7 @@ Bladeburner.prototype.createOverviewContent = function() {
} }
} }
return false; return false;
} },
})); }));
} }
@ -1526,14 +1526,14 @@ Bladeburner.prototype.createActionAndSkillsContent = function() {
DomElems.currentTab = buttons[i].toLowerCase(); DomElems.currentTab = buttons[i].toLowerCase();
inst.createActionAndSkillsContent(); inst.createActionAndSkillsContent();
return false; return false;
} },
})); }));
}) (buttons, i, this, currTab); }) (buttons, i, this, currTab);
} }
// General info/description for each action // General info/description for each action
DomElems.actionsAndSkillsDesc = createElement("p", { DomElems.actionsAndSkillsDesc = createElement("p", {
display:"block", margin:"4px", padding:"4px" display:"block", margin:"4px", padding:"4px",
}); });
// List for actions/skills // List for actions/skills
@ -1578,7 +1578,7 @@ Bladeburner.prototype.createGeneralActionsContent = function() {
for (var actionName in GeneralActions) { for (var actionName in GeneralActions) {
if (GeneralActions.hasOwnProperty(actionName)) { if (GeneralActions.hasOwnProperty(actionName)) {
DomElems.generalActions[actionName] = createElement("div", { DomElems.generalActions[actionName] = createElement("div", {
class:"bladeburner-action", name:actionName class:"bladeburner-action", name:actionName,
}); });
DomElems.actionsAndSkillsList.appendChild(DomElems.generalActions[actionName]); DomElems.actionsAndSkillsList.appendChild(DomElems.generalActions[actionName]);
} }
@ -1600,7 +1600,7 @@ Bladeburner.prototype.createContractsContent = function() {
for (var contractName in this.contracts) { for (var contractName in this.contracts) {
if (this.contracts.hasOwnProperty(contractName)) { if (this.contracts.hasOwnProperty(contractName)) {
DomElems.contracts[contractName] = createElement("div", { DomElems.contracts[contractName] = createElement("div", {
class:"bladeburner-action", name:contractName class:"bladeburner-action", name:contractName,
}); });
DomElems.actionsAndSkillsList.appendChild(DomElems.contracts[contractName]); DomElems.actionsAndSkillsList.appendChild(DomElems.contracts[contractName]);
} }
@ -1629,7 +1629,7 @@ Bladeburner.prototype.createOperationsContent = function() {
for (var operationName in this.operations) { for (var operationName in this.operations) {
if (this.operations.hasOwnProperty(operationName)) { if (this.operations.hasOwnProperty(operationName)) {
DomElems.operations[operationName] = createElement("div", { DomElems.operations[operationName] = createElement("div", {
class:"bladeburner-action", name:operationName class:"bladeburner-action", name:operationName,
}); });
DomElems.actionsAndSkillsList.appendChild(DomElems.operations[operationName]); DomElems.actionsAndSkillsList.appendChild(DomElems.operations[operationName]);
} }
@ -1667,7 +1667,7 @@ Bladeburner.prototype.createBlackOpsContent = function() {
for (var i = blackops.length-1; i >= 0 ; --i) { for (var i = blackops.length-1; i >= 0 ; --i) {
if (this.blackops[[blackops[i].name]] == null && i !== 0 && this.blackops[[blackops[i-1].name]] == null) {continue;} // If this one nor the next are completed then this isn't unlocked yet. if (this.blackops[[blackops[i].name]] == null && i !== 0 && this.blackops[[blackops[i-1].name]] == null) {continue;} // If this one nor the next are completed then this isn't unlocked yet.
DomElems.blackops[blackops[i].name] = createElement("div", { DomElems.blackops[blackops[i].name] = createElement("div", {
class:"bladeburner-action", name:blackops[i].name class:"bladeburner-action", name:blackops[i].name,
}); });
DomElems.actionsAndSkillsList.appendChild(DomElems.blackops[blackops[i].name]); DomElems.actionsAndSkillsList.appendChild(DomElems.blackops[blackops[i].name]);
} }
@ -1750,7 +1750,7 @@ Bladeburner.prototype.createSkillsContent = function() {
// Skill Points // Skill Points
DomElems.skillPointsDisplay = createElement("p", { DomElems.skillPointsDisplay = createElement("p", {
innerHTML:"<br><strong>Skill Points: " + formatNumber(this.skillPoints, 0) + "</strong>" innerHTML:"<br><strong>Skill Points: " + formatNumber(this.skillPoints, 0) + "</strong>",
}); });
DomElems.actionAndSkillsDiv.appendChild(DomElems.skillPointsDisplay); DomElems.actionAndSkillsDiv.appendChild(DomElems.skillPointsDisplay);
@ -1758,7 +1758,7 @@ Bladeburner.prototype.createSkillsContent = function() {
for (var skillName in Skills) { for (var skillName in Skills) {
if (Skills.hasOwnProperty(skillName)) { if (Skills.hasOwnProperty(skillName)) {
DomElems.skills[skillName] = createElement("div", { DomElems.skills[skillName] = createElement("div", {
class:"bladeburner-action", name:skillName class:"bladeburner-action", name:skillName,
}); });
DomElems.actionsAndSkillsList.appendChild(DomElems.skills[skillName]); DomElems.actionsAndSkillsList.appendChild(DomElems.skills[skillName]);
} }
@ -1902,7 +1902,7 @@ Bladeburner.prototype.updateGeneralActionsUIElement = function(el, action) {
var progress = this.actionTimeCurrent / this.actionTimeToComplete; var progress = this.actionTimeCurrent / this.actionTimeToComplete;
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
display:"block", display:"block",
innerText:createProgressBarText({progress:progress}) innerText:createProgressBarText({progress:progress}),
})); }));
} else { } else {
// Start button // Start button
@ -1915,13 +1915,13 @@ Bladeburner.prototype.updateGeneralActionsUIElement = function(el, action) {
this.startAction(this.action); this.startAction(this.action);
this.updateActionAndSkillsContent(); this.updateActionAndSkillsContent();
return false; return false;
} },
})); }));
} }
appendLineBreaks(el, 2); appendLineBreaks(el, 2);
el.appendChild(createElement("pre", { // Info el.appendChild(createElement("pre", { // Info
innerHTML:action.desc, display:"inline-block" innerHTML:action.desc, display:"inline-block",
})); }));
@ -1937,14 +1937,14 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
formatNumber(this.actionTimeCurrent, 0) + " / " + formatNumber(this.actionTimeCurrent, 0) + " / " +
formatNumber(this.actionTimeToComplete, 0) + ")" formatNumber(this.actionTimeToComplete, 0) + ")"
: action.name, : action.name,
display:"inline-block" display:"inline-block",
})); }));
if (isActive) { // Progress bar if its active if (isActive) { // Progress bar if its active
var progress = this.actionTimeCurrent / this.actionTimeToComplete; var progress = this.actionTimeCurrent / this.actionTimeToComplete;
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
display:"block", display:"block",
innerText:createProgressBarText({progress:progress}) innerText:createProgressBarText({progress:progress}),
})); }));
} else { // Start button } else { // Start button
el.appendChild(createElement("a", { el.appendChild(createElement("a", {
@ -1956,7 +1956,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
this.startAction(this.action); this.startAction(this.action);
this.updateActionAndSkillsContent(); this.updateActionAndSkillsContent();
return false; return false;
} },
})); }));
} }
@ -1967,7 +1967,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
display:"inline-block", display:"inline-block",
innerText:"Level: " + action.level + " / " + action.maxLevel, innerText:"Level: " + action.level + " / " + action.maxLevel,
tooltip:action.getSuccessesNeededForNextLevel(BladeburnerConstants.ContractSuccessesPerLevel) + " successes " + tooltip:action.getSuccessesNeededForNextLevel(BladeburnerConstants.ContractSuccessesPerLevel) + " successes " +
"needed for next level" "needed for next level",
})); }));
el.appendChild(createElement("a", { el.appendChild(createElement("a", {
class: maxLevel ? "a-link-button-inactive" : "a-link-button", innerHTML:"&uarr;", class: maxLevel ? "a-link-button-inactive" : "a-link-button", innerHTML:"&uarr;",
@ -1979,7 +1979,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
if (isActive) {this.startAction(this.action);} // Restart Action if (isActive) {this.startAction(this.action);} // Restart Action
this.updateContractsUIElement(el, action); this.updateContractsUIElement(el, action);
return false; return false;
} },
})); }));
el.appendChild(createElement("a", { el.appendChild(createElement("a", {
class: (action.level <= 1) ? "a-link-button-inactive" : "a-link-button", innerHTML:"&darr;", class: (action.level <= 1) ? "a-link-button-inactive" : "a-link-button", innerHTML:"&darr;",
@ -1991,7 +1991,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
if (isActive) {this.startAction(this.action);} // Restart Action if (isActive) {this.startAction(this.action);} // Restart Action
this.updateContractsUIElement(el, action); this.updateContractsUIElement(el, action);
return false; return false;
} },
})); }));
var actionTime = action.getActionTime(this); var actionTime = action.getActionTime(this);
@ -2011,7 +2011,7 @@ Bladeburner.prototype.updateContractsUIElement = function(el, action) {
var autolevelCheckboxId = "bladeburner-" + action.name + "-autolevel-checkbox"; var autolevelCheckboxId = "bladeburner-" + action.name + "-autolevel-checkbox";
el.appendChild(createElement("label", { el.appendChild(createElement("label", {
for:autolevelCheckboxId, innerText:"Autolevel: ",color:"white", for:autolevelCheckboxId, innerText:"Autolevel: ",color:"white",
tooltip:"Automatically increase contract level when possible" tooltip:"Automatically increase contract level when possible",
})); }));
const checkboxInput = createElement("input", { const checkboxInput = createElement("input", {
@ -2035,14 +2035,14 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
formatNumber(this.actionTimeCurrent, 0) + " / " + formatNumber(this.actionTimeCurrent, 0) + " / " +
formatNumber(this.actionTimeToComplete, 0) + ")" formatNumber(this.actionTimeToComplete, 0) + ")"
: action.name, : action.name,
display:"inline-block" display:"inline-block",
})); }));
if (isActive) { // Progress bar if its active if (isActive) { // Progress bar if its active
var progress = this.actionTimeCurrent / this.actionTimeToComplete; var progress = this.actionTimeCurrent / this.actionTimeToComplete;
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
display:"block", display:"block",
innerText:createProgressBarText({progress:progress}) innerText:createProgressBarText({progress:progress}),
})); }));
} else { // Start button and set Team Size button } else { // Start button and set Team Size button
el.appendChild(createElement("a", { el.appendChild(createElement("a", {
@ -2054,7 +2054,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
this.startAction(this.action); this.startAction(this.action);
this.updateActionAndSkillsContent(); this.updateActionAndSkillsContent();
return false; return false;
} },
})); }));
el.appendChild(createElement("a", { el.appendChild(createElement("a", {
innerText:"Set Team Size (Curr Size: " + formatNumber(action.teamCount, 0) + ")", class:"a-link-button", innerText:"Set Team Size (Curr Size: " + formatNumber(action.teamCount, 0) + ")", class:"a-link-button",
@ -2065,7 +2065,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
innerText:"Enter the amount of team members you would like to take on these " + innerText:"Enter the amount of team members you would like to take on these " +
"operations. If you do not have the specified number of team members, " + "operations. If you do not have the specified number of team members, " +
"then as many as possible will be used. Note that team members may " + "then as many as possible will be used. Note that team members may " +
"be lost during operations." "be lost during operations.",
}); });
var input = createElement("input", { var input = createElement("input", {
@ -2083,17 +2083,17 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
} }
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} },
}); });
var cancelBtn = createElement("a", { var cancelBtn = createElement("a", {
innerText:"Cancel", class:"a-link-button", innerText:"Cancel", class:"a-link-button",
clickListener:() => { clickListener:() => {
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} },
}); });
createPopup(popupId, [txt, input, setBtn, cancelBtn]); createPopup(popupId, [txt, input, setBtn, cancelBtn]);
} },
})); }));
} }
@ -2104,7 +2104,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
display:"inline-block", display:"inline-block",
innerText:"Level: " + action.level + " / " + action.maxLevel, innerText:"Level: " + action.level + " / " + action.maxLevel,
tooltip:action.getSuccessesNeededForNextLevel(BladeburnerConstants.OperationSuccessesPerLevel) + " successes " + tooltip:action.getSuccessesNeededForNextLevel(BladeburnerConstants.OperationSuccessesPerLevel) + " successes " +
"needed for next level" "needed for next level",
})); }));
el.appendChild(createElement("a", { el.appendChild(createElement("a", {
class: maxLevel ? "a-link-button-inactive" : "a-link-button", innerHTML:"&uarr;", class: maxLevel ? "a-link-button-inactive" : "a-link-button", innerHTML:"&uarr;",
@ -2116,7 +2116,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
if (isActive) {this.startAction(this.action);} // Restart Action if (isActive) {this.startAction(this.action);} // Restart Action
this.updateOperationsUIElement(el, action); this.updateOperationsUIElement(el, action);
return false; return false;
} },
})); }));
el.appendChild(createElement("a", { el.appendChild(createElement("a", {
class: (action.level <= 1) ? "a-link-button-inactive" : "a-link-button", innerHTML:"&darr;", class: (action.level <= 1) ? "a-link-button-inactive" : "a-link-button", innerHTML:"&darr;",
@ -2128,11 +2128,10 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
if (isActive) {this.startAction(this.action);} // Restart Action if (isActive) {this.startAction(this.action);} // Restart Action
this.updateOperationsUIElement(el, action); this.updateOperationsUIElement(el, action);
return false; return false;
} },
})); }));
// General Info // General Info
var difficulty = action.getDifficulty();
var actionTime = action.getActionTime(this); var actionTime = action.getActionTime(this);
appendLineBreaks(el, 2); appendLineBreaks(el, 2);
el.appendChild(createElement("pre", { el.appendChild(createElement("pre", {
@ -2150,7 +2149,7 @@ Bladeburner.prototype.updateOperationsUIElement = function(el, action) {
var autolevelCheckboxId = "bladeburner-" + action.name + "-autolevel-checkbox"; var autolevelCheckboxId = "bladeburner-" + action.name + "-autolevel-checkbox";
el.appendChild(createElement("label", { el.appendChild(createElement("label", {
for:autolevelCheckboxId, innerText:"Autolevel: ",color:"white", for:autolevelCheckboxId, innerText:"Autolevel: ",color:"white",
tooltip:"Automatically increase operation level when possible" tooltip:"Automatically increase operation level when possible",
})); }));
const checkboxInput = createElement("input", { const checkboxInput = createElement("input", {
@ -2170,7 +2169,6 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
var isActive = el.classList.contains(ActiveActionCssClass); var isActive = el.classList.contains(ActiveActionCssClass);
var isCompleted = (this.blackops[action.name] != null); var isCompleted = (this.blackops[action.name] != null);
var estimatedSuccessChance = action.getSuccessChance(this, {est:true}); var estimatedSuccessChance = action.getSuccessChance(this, {est:true});
var difficulty = action.getDifficulty();
var actionTime = action.getActionTime(this); var actionTime = action.getActionTime(this);
var hasReqdRank = this.rank >= action.reqdRank; var hasReqdRank = this.rank >= action.reqdRank;
@ -2194,7 +2192,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
var progress = this.actionTimeCurrent / this.actionTimeToComplete; var progress = this.actionTimeCurrent / this.actionTimeToComplete;
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
display:"block", display:"block",
innerText:createProgressBarText({progress:progress}) innerText:createProgressBarText({progress:progress}),
})); }));
} else { } else {
el.appendChild(createElement("a", { // Start button el.appendChild(createElement("a", { // Start button
@ -2206,7 +2204,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
this.startAction(this.action); this.startAction(this.action);
this.updateActionAndSkillsContent(); this.updateActionAndSkillsContent();
return false; return false;
} },
})); }));
el.appendChild(createElement("a", { // Set Team Size Button el.appendChild(createElement("a", { // Set Team Size Button
innerText:"Set Team Size (Curr Size: " + formatNumber(action.teamCount, 0) + ")", class:"a-link-button", innerText:"Set Team Size (Curr Size: " + formatNumber(action.teamCount, 0) + ")", class:"a-link-button",
@ -2217,7 +2215,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
innerText:"Enter the amount of team members you would like to take on this " + innerText:"Enter the amount of team members you would like to take on this " +
"BlackOp. If you do not have the specified number of team members, " + "BlackOp. If you do not have the specified number of team members, " +
"then as many as possible will be used. Note that team members may " + "then as many as possible will be used. Note that team members may " +
"be lost during operations." "be lost during operations.",
}); });
var input = createElement("input", { var input = createElement("input", {
@ -2235,17 +2233,17 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
} }
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} },
}); });
var cancelBtn = createElement("a", { var cancelBtn = createElement("a", {
innerText:"Cancel", class:"a-link-button", innerText:"Cancel", class:"a-link-button",
clickListener:() => { clickListener:() => {
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} },
}); });
createPopup(popupId, [txt, input, setBtn, cancelBtn]); createPopup(popupId, [txt, input, setBtn, cancelBtn]);
} },
})); }));
} }
@ -2257,7 +2255,7 @@ Bladeburner.prototype.updateBlackOpsUIElement = function(el, action) {
})); }));
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
display:"block", color:hasReqdRank ? "white" : "red", display:"block", color:hasReqdRank ? "white" : "red",
innerHTML:"Required Rank: " + formatNumber(action.reqdRank, 0) + "<br>" innerHTML:"Required Rank: " + formatNumber(action.reqdRank, 0) + "<br>",
})); }));
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
display:"inline-block", display:"inline-block",
@ -2297,7 +2295,7 @@ Bladeburner.prototype.updateSkillsUIElement = function(el, skill) {
this.upgradeSkill(skill); this.upgradeSkill(skill);
this.createActionAndSkillsContent(); this.createActionAndSkillsContent();
return false; return false;
} },
})); }));
appendLineBreaks(el, 2); appendLineBreaks(el, 2);
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
@ -2307,7 +2305,7 @@ Bladeburner.prototype.updateSkillsUIElement = function(el, skill) {
if (maxLvl) { if (maxLvl) {
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
color:"red", display:"block", color:"red", display:"block",
innerText:"MAX LEVEL" innerText:"MAX LEVEL",
})); }));
} else { } else {
el.appendChild(createElement("p", { el.appendChild(createElement("p", {
@ -2508,7 +2506,7 @@ Bladeburner.prototype.executeAutomateConsoleCommand = function(args) {
case "gen": case "gen":
if (GeneralActions[val] != null) { if (GeneralActions[val] != null) {
var action = new ActionIdentifier({ var action = new ActionIdentifier({
type:ActionTypes[val], name:val type:ActionTypes[val], name:val,
}); });
if (highLow) { if (highLow) {
this.automateActionHigh = action; this.automateActionHigh = action;
@ -2524,7 +2522,7 @@ Bladeburner.prototype.executeAutomateConsoleCommand = function(args) {
case "contracts": case "contracts":
if (this.contracts[val] != null) { if (this.contracts[val] != null) {
var action = new ActionIdentifier({ var action = new ActionIdentifier({
type:ActionTypes.Contract, name:val type:ActionTypes.Contract, name:val,
}); });
if (highLow) { if (highLow) {
this.automateActionHigh = action; this.automateActionHigh = action;
@ -2542,7 +2540,7 @@ Bladeburner.prototype.executeAutomateConsoleCommand = function(args) {
case "operation": case "operation":
if (this.operations[val] != null) { if (this.operations[val] != null) {
var action = new ActionIdentifier({ var action = new ActionIdentifier({
type:ActionTypes.Operation, name:val type:ActionTypes.Operation, name:val,
}); });
if (highLow) { if (highLow) {
this.automateActionHigh = action; this.automateActionHigh = action;
@ -3210,7 +3208,7 @@ Bladeburner.prototype.setTeamSizeNetscriptFn = function(type, name, size, worker
return -1; return -1;
} }
const sanitizedSize = Math.round(size); let sanitizedSize = Math.round(size);
if (isNaN(sanitizedSize) || sanitizedSize < 0) { if (isNaN(sanitizedSize) || sanitizedSize < 0) {
workerScript.log("bladeburner.setTeamSize", `Invalid size: ${size}`); workerScript.log("bladeburner.setTeamSize", `Invalid size: ${size}`);
return -1; return -1;

@ -3,21 +3,20 @@ import { getRandomInt } from "../../utils/helpers/getRandomInt";
import { addOffset } from "../../utils/helpers/addOffset"; import { addOffset } from "../../utils/helpers/addOffset";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
import { BladeburnerConstants } from "./data/Constants"; import { BladeburnerConstants } from "./data/Constants";
// import { Contract } from "./Contract"; import { IBladeburner } from "./IBladeburner";
// import { Operation } from "./Operation"; import { IAction, ISuccessChanceParams } from "./IAction";
// import { BlackOperation } from "./BlackOperation";
class StatsMultiplier { class StatsMultiplier {
hack: number = 0;
str: number = 0;
def: number = 0;
dex: number = 0;
agi: number = 0;
cha: number = 0;
int: number = 0;
[key: string]: number; [key: string]: number;
};
hack = 0;
str = 0;
def = 0;
dex = 0;
agi = 0;
cha = 0;
int = 0;
}
export interface IActionParams { export interface IActionParams {
name?: string; name?: string;
@ -43,32 +42,32 @@ export interface IActionParams {
teamCount?: number; teamCount?: number;
} }
export class Action { export class Action implements IAction {
name: string = ""; name = "";
desc: string = ""; desc = "";
// Difficulty scales with level. See getDifficulty() method // Difficulty scales with level. See getDifficulty() method
level: number = 1; level = 1;
maxLevel: number = 1; maxLevel = 1;
autoLevel: boolean = true; autoLevel = true;
baseDifficulty: number = 100; baseDifficulty = 100;
difficultyFac: number = 1.01; difficultyFac = 1.01;
// Rank increase/decrease is affected by this exponent // Rank increase/decrease is affected by this exponent
rewardFac: number = 1.02; rewardFac = 1.02;
successes: number = 0; successes = 0;
failures: number = 0; failures = 0;
// All of these scale with level/difficulty // All of these scale with level/difficulty
rankGain: number = 0; rankGain = 0;
rankLoss: number = 0; rankLoss = 0;
hpLoss: number = 0; hpLoss = 0;
hpLost: number = 0; hpLost = 0;
// Action Category. Current categories are stealth and kill // Action Category. Current categories are stealth and kill
isStealth: boolean = false; isStealth = false;
isKill: boolean = false; isKill = false;
/** /**
* Number of this contract remaining, and its growth rate * Number of this contract remaining, and its growth rate
@ -81,7 +80,7 @@ export class Action {
weights: StatsMultiplier = {hack:1/7,str:1/7,def:1/7,dex:1/7,agi:1/7,cha:1/7,int:1/7}; weights: StatsMultiplier = {hack:1/7,str:1/7,def:1/7,dex:1/7,agi:1/7,cha:1/7,int:1/7};
// Diminishing returns of stats (stat ^ decay where 0 <= decay <= 1) // Diminishing returns of stats (stat ^ decay where 0 <= decay <= 1)
decays: StatsMultiplier = { hack: 0.9, str: 0.9, def: 0.9, dex: 0.9, agi: 0.9, cha: 0.9, int: 0.9 }; decays: StatsMultiplier = { hack: 0.9, str: 0.9, def: 0.9, dex: 0.9, agi: 0.9, cha: 0.9, int: 0.9 };
teamCount: number = 0; teamCount = 0;
// Base Class for Contracts, Operations, and BlackOps // Base Class for Contracts, Operations, and BlackOps
constructor(params: IActionParams| null = null) { // | null = null constructor(params: IActionParams| null = null) { // | null = null
@ -138,7 +137,7 @@ export class Action {
* Tests for success. Should be called when an action has completed * Tests for success. Should be called when an action has completed
* @param inst {Bladeburner} - Bladeburner instance * @param inst {Bladeburner} - Bladeburner instance
*/ */
attempt(inst: any): boolean { attempt(inst: IBladeburner): boolean {
return (Math.random() < this.getSuccessChance(inst)); return (Math.random() < this.getSuccessChance(inst));
} }
@ -147,7 +146,7 @@ export class Action {
return 1; return 1;
} }
getActionTime(inst: any): number { getActionTime(inst: IBladeburner): number {
const difficulty = this.getDifficulty(); const difficulty = this.getDifficulty();
let baseTime = difficulty / BladeburnerConstants.DifficultyToTimeFactor; let baseTime = difficulty / BladeburnerConstants.DifficultyToTimeFactor;
const skillFac = inst.skillMultipliers.actionTime; // Always < 1 const skillFac = inst.skillMultipliers.actionTime; // Always < 1
@ -165,15 +164,15 @@ export class Action {
} }
// For actions that have teams. To be implemented by subtypes. // For actions that have teams. To be implemented by subtypes.
getTeamSuccessBonus(inst: any): number { getTeamSuccessBonus(inst: IBladeburner): number {
return 1; return 1;
} }
getActionTypeSkillSuccessBonus(inst: any): number { getActionTypeSkillSuccessBonus(inst: IBladeburner): number {
return 1; return 1;
} }
getChaosCompetencePenalty(inst: any, params: any): number { getChaosCompetencePenalty(inst: IBladeburner, params: ISuccessChanceParams): number {
const city = inst.getCurrentCity(); const city = inst.getCurrentCity();
if (params.est) { if (params.est) {
return Math.pow((city.popEst / BladeburnerConstants.PopulationThreshold), BladeburnerConstants.PopulationExponent); return Math.pow((city.popEst / BladeburnerConstants.PopulationThreshold), BladeburnerConstants.PopulationExponent);
@ -182,7 +181,7 @@ export class Action {
} }
} }
getChaosDifficultyBonus(inst: any, params: any): number { getChaosDifficultyBonus(inst: IBladeburner/*, params: ISuccessChanceParams*/): number {
const city = inst.getCurrentCity(); const city = inst.getCurrentCity();
if (city.chaos > BladeburnerConstants.ChaosThreshold) { if (city.chaos > BladeburnerConstants.ChaosThreshold) {
const diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold); const diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold);
@ -198,14 +197,14 @@ export class Action {
* @params - options: * @params - options:
* est (bool): Get success chance estimate instead of real success chance * est (bool): Get success chance estimate instead of real success chance
*/ */
getSuccessChance(inst: any, params: any={}) { getSuccessChance(inst: IBladeburner, params: ISuccessChanceParams={est: false}): number {
if (inst == null) {throw new Error("Invalid Bladeburner instance passed into Action.getSuccessChance");} if (inst == null) {throw new Error("Invalid Bladeburner instance passed into Action.getSuccessChance");}
let difficulty = this.getDifficulty(); let difficulty = this.getDifficulty();
let competence = 0; let competence = 0;
for (let stat in this.weights) { for (const stat in this.weights) {
if (this.weights.hasOwnProperty(stat)) { if (this.weights.hasOwnProperty(stat)) {
let playerStatLvl = Player.queryStatFromString(stat); const playerStatLvl = Player.queryStatFromString(stat);
let key = "eff" + stat.charAt(0).toUpperCase() + stat.slice(1); const key = "eff" + stat.charAt(0).toUpperCase() + stat.slice(1);
let effMultiplier = inst.skillMultipliers[key]; let effMultiplier = inst.skillMultipliers[key];
if (effMultiplier == null) { if (effMultiplier == null) {
console.error(`Failed to find Bladeburner Skill multiplier for: ${stat}`); console.error(`Failed to find Bladeburner Skill multiplier for: ${stat}`);
@ -220,7 +219,7 @@ export class Action {
competence *= this.getTeamSuccessBonus(inst); competence *= this.getTeamSuccessBonus(inst);
competence *= this.getChaosCompetencePenalty(inst, params); competence *= this.getChaosCompetencePenalty(inst, params);
difficulty *= this.getChaosDifficultyBonus(inst, params); difficulty *= this.getChaosDifficultyBonus(inst);
if(this.name == "Raid" && inst.getCurrentCity().comms <= 0) { if(this.name == "Raid" && inst.getCurrentCity().comms <= 0) {
return 0; return 0;
@ -253,18 +252,14 @@ export class Action {
} }
} }
static fromJSON(value: any): Action {
return Generic_fromJSON(Action, value.data);
}
toJSON(): any { toJSON(): any {
return Generic_toJSON("Action", this); return Generic_toJSON("Action", this);
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Action {
return Generic_fromJSON(Action, value.data);
}
} }
Reviver.constructors.Action = Action; Reviver.constructors.Action = Action;

@ -13,21 +13,22 @@ export class BlackOperation extends Operation {
return 1.5; return 1.5;
} }
getChaosCompetencePenalty(inst: any, params: any): number { getChaosCompetencePenalty(/*inst: IBladeburner, params: ISuccessChanceParams*/): number {
return 1; return 1;
} }
getChaosDifficultyBonus(inst: any, params: any): number { getChaosDifficultyBonus(/*inst: IBladeburner, params: ISuccessChanceParams*/): number {
return 1; return 1;
} }
static fromJSON(value: any): Operation {
return Generic_fromJSON(BlackOperation, value.data);
}
toJSON(): any { toJSON(): any {
return Generic_toJSON("BlackOperation", this); return Generic_toJSON("BlackOperation", this);
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Operation {
return Generic_fromJSON(BlackOperation, value.data);
}
} }
Reviver.constructors.BlackOperation = BlackOperation; Reviver.constructors.BlackOperation = BlackOperation;

@ -16,7 +16,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:50, rankLoss:10, hpLoss:100, rankGain:50, rankLoss:10, hpLoss:100,
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Zero"] = new BlackOperation({ BlackOperations["Operation Zero"] = new BlackOperation({
name:"Operation Zero", name:"Operation Zero",
@ -33,7 +33,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:60, rankLoss:15, hpLoss:50, rankGain:60, rankLoss:15, hpLoss:50,
weights:{hack:0.2,str:0.15,def:0.15,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.2,str:0.15,def:0.15,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isStealth:true isStealth:true,
}); });
BlackOperations["Operation X"] = new BlackOperation({ BlackOperations["Operation X"] = new BlackOperation({
name:"Operation X", name:"Operation X",
@ -52,7 +52,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:75, rankLoss:15, hpLoss:100, rankGain:75, rankLoss:15, hpLoss:100,
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Titan"] = new BlackOperation({ BlackOperations["Operation Titan"] = new BlackOperation({
name:"Operation Titan", name:"Operation Titan",
@ -70,7 +70,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:100, rankLoss:20, hpLoss:100, rankGain:100, rankLoss:20, hpLoss:100,
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Ares"] = new BlackOperation({ BlackOperations["Operation Ares"] = new BlackOperation({
name:"Operation Ares", name:"Operation Ares",
@ -84,7 +84,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:125, rankLoss:20, hpLoss:200, rankGain:125, rankLoss:20, hpLoss:200,
weights:{hack:0,str:0.25,def:0.25,dex:0.25,agi:0.25,cha:0, int:0}, weights:{hack:0,str:0.25,def:0.25,dex:0.25,agi:0.25,cha:0, int:0},
decays:{hack:0,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Archangel"] = new BlackOperation({ BlackOperations["Operation Archangel"] = new BlackOperation({
name:"Operation Archangel", name:"Operation Archangel",
@ -152,7 +152,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:750, rankLoss:60, hpLoss:1000, rankGain:750, rankLoss:60, hpLoss:1000,
weights:{hack:0.05,str:0.2,def:0.2,dex:0.25,agi:0.25,cha:0, int:0.05}, weights:{hack:0.05,str:0.2,def:0.2,dex:0.25,agi:0.25,cha:0, int:0.05},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Deckard"] = new BlackOperation({ BlackOperations["Operation Deckard"] = new BlackOperation({
name:"Operation Deckard", name:"Operation Deckard",
@ -160,7 +160,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
"technology in Operation K, we've discovered that a small group of " + "technology in Operation K, we've discovered that a small group of " +
"MK-VI Synthoids were able to make off with the schematics and design " + "MK-VI Synthoids were able to make off with the schematics and design " +
"of the technology before the Operation. It is almost a certainty that " + "of the technology before the Operation. It is almost a certainty that " +
"these Synthoids are some of the rogue MK-VI ones from the Synthoid Uprising." + "these Synthoids are some of the rogue MK-VI ones from the Synthoid Uprising.<br><br>" +
"The goal of Operation Deckard is to hunt down these Synthoids and retire " + "The goal of Operation Deckard is to hunt down these Synthoids and retire " +
"them. I don't need to tell you how critical this mission is.", "them. I don't need to tell you how critical this mission is.",
baseDifficulty:20e3, reqdRank:40e3, baseDifficulty:20e3, reqdRank:40e3,
@ -202,7 +202,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:2e3, rankLoss:150, hpLoss:1500, rankGain:2e3, rankLoss:150, hpLoss:1500,
weights:{hack:0,str:0.24,def:0.24,dex:0.24,agi:0.24,cha:0, int:0.04}, weights:{hack:0,str:0.24,def:0.24,dex:0.24,agi:0.24,cha:0, int:0.04},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Shoulder of Orion"] = new BlackOperation({ BlackOperations["Operation Shoulder of Orion"] = new BlackOperation({
name:"Operation Shoulder of Orion", name:"Operation Shoulder of Orion",
@ -218,7 +218,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:2.5e3, rankLoss:500, hpLoss:1500, rankGain:2.5e3, rankLoss:500, hpLoss:1500,
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isStealth:true isStealth:true,
}); });
BlackOperations["Operation Hyron"] = new BlackOperation({ BlackOperations["Operation Hyron"] = new BlackOperation({
name:"Operation Hyron", name:"Operation Hyron",
@ -231,7 +231,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
"means that the supercomputer may be able to reason abstractly " + "means that the supercomputer may be able to reason abstractly " +
"and become self-aware.<br><br>" + "and become self-aware.<br><br>" +
"I do not need to remind you why sentient-level AIs pose a serious " + "I do not need to remind you why sentient-level AIs pose a serious " +
"thread to all of mankind.<br><br>" + "threat to all of mankind.<br><br>" +
"The research for this project is being conducted at one of Fulcrum " + "The research for this project is being conducted at one of Fulcrum " +
"Technologies secret facilities in Aevum, codenamed 'Alpha Ranch'. " + "Technologies secret facilities in Aevum, codenamed 'Alpha Ranch'. " +
"Infiltrate the compound, delete and destroy the work, and then find and kill the " + "Infiltrate the compound, delete and destroy the work, and then find and kill the " +
@ -240,7 +240,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:3e3, rankLoss:1e3, hpLoss:500, rankGain:3e3, rankLoss:1e3, hpLoss:500,
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Morpheus"] = new BlackOperation({ BlackOperations["Operation Morpheus"] = new BlackOperation({
name:"Operation Morpheus", name:"Operation Morpheus",
@ -257,7 +257,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:4e3, rankLoss:1e3, hpLoss:100, rankGain:4e3, rankLoss:1e3, hpLoss:100,
weights:{hack:0.05,str:0.15,def:0.15,dex:0.3,agi:0.3,cha:0, int:0.05}, weights:{hack:0.05,str:0.15,def:0.15,dex:0.3,agi:0.3,cha:0, int:0.05},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isStealth:true isStealth:true,
}); });
BlackOperations["Operation Ion Storm"] = new BlackOperation({ BlackOperations["Operation Ion Storm"] = new BlackOperation({
name:"Operation Ion Storm", name:"Operation Ion Storm",
@ -272,7 +272,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:5e3, rankLoss:1e3, hpLoss:5000, rankGain:5e3, rankLoss:1e3, hpLoss:5000,
weights:{hack:0,str:0.24,def:0.24,dex:0.24,agi:0.24,cha:0, int:0.04}, weights:{hack:0,str:0.24,def:0.24,dex:0.24,agi:0.24,cha:0, int:0.04},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Annihilus"] = new BlackOperation({ BlackOperations["Operation Annihilus"] = new BlackOperation({
name:"Operation Annihilus", name:"Operation Annihilus",
@ -286,7 +286,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:7.5e3, rankLoss:1e3, hpLoss:10e3, rankGain:7.5e3, rankLoss:1e3, hpLoss:10e3,
weights:{hack:0,str:0.24,def:0.24,dex:0.24,agi:0.24,cha:0, int:0.04}, weights:{hack:0,str:0.24,def:0.24,dex:0.24,agi:0.24,cha:0, int:0.04},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Ultron"] = new BlackOperation({ BlackOperations["Operation Ultron"] = new BlackOperation({
name:"Operation Ultron", name:"Operation Ultron",
@ -306,7 +306,7 @@ export const BlackOperations: IMap<BlackOperation> = {};
rankGain:10e3, rankLoss:2e3, hpLoss:10e3, rankGain:10e3, rankLoss:2e3, hpLoss:10e3,
weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1}, weights:{hack:0.1,str:0.2,def:0.2,dex:0.2,agi:0.2,cha:0, int:0.1},
decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75}, decays:{hack:0.6,str:0.8,def:0.8,dex:0.8,agi:0.8,cha:0, int:0.75},
isKill:true isKill:true,
}); });
BlackOperations["Operation Centurion"] = new BlackOperation({ BlackOperations["Operation Centurion"] = new BlackOperation({
name:"Operation Centurion", name:"Operation Centurion",

@ -5,13 +5,13 @@ import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviv
import { addOffset } from "../../utils/helpers/addOffset"; import { addOffset } from "../../utils/helpers/addOffset";
export class ChangePopulationByCountParams { export class ChangePopulationByCountParams {
estChange: number = 0; estChange = 0;
estOffset: number = 0; estOffset = 0;
} }
export class ChangePopulationByPercentageParams { export class ChangePopulationByPercentageParams {
nonZero: boolean = false; nonZero = false;
changeEstEqually: boolean = false; changeEstEqually = false;
} }
export class City { export class City {
@ -19,32 +19,32 @@ export class City {
/** /**
* Name of the city. * Name of the city.
*/ */
name: string = ""; name = "";
/** /**
* Population of the city. * Population of the city.
*/ */
pop: number = 0; pop = 0;
/** /**
* Population estimation of the city. * Population estimation of the city.
*/ */
popEst: number = 0; popEst = 0;
/** /**
* Number of communities in the city. * Number of communities in the city.
*/ */
comms: number = 0; comms = 0;
/** /**
* Estimated number of communities in the city. * Estimated number of communities in the city.
*/ */
commsEst: number = 0; commsEst = 0;
/** /**
* Chaos level of the city. * Chaos level of the city.
*/ */
chaos: number = 0; chaos = 0;
constructor(name: string = BladeburnerConstants.CityNames[2]) { constructor(name: string = BladeburnerConstants.CityNames[2]) {
this.name = name; this.name = name;
@ -84,7 +84,7 @@ export class City {
/** /**
* p is the percentage, not the multiplier (e.g. pass in p = 5 for 5%) * p is the percentage, not the multiplier (e.g. pass in p = 5 for 5%)
*/ */
improvePopulationEstimateByPercentage(p: number, skillMult: number=1): void { improvePopulationEstimateByPercentage(p: number, skillMult=1): void {
p = p*skillMult; p = p*skillMult;
if (isNaN(p)) {throw new Error("NaN passed into City.improvePopulationEstimateByPercentage()");} if (isNaN(p)) {throw new Error("NaN passed into City.improvePopulationEstimateByPercentage()");}
if (this.popEst < this.pop) { if (this.popEst < this.pop) {
@ -97,7 +97,7 @@ export class City {
} }
} }
improveCommunityEstimate(n: number=1): void { improveCommunityEstimate(n=1): void {
if (isNaN(n)) {throw new Error("NaN passed into City.improveCommunityEstimate()");} if (isNaN(n)) {throw new Error("NaN passed into City.improveCommunityEstimate()");}
if (this.commsEst < this.comms) { if (this.commsEst < this.comms) {
this.commsEst += n; this.commsEst += n;
@ -154,19 +154,20 @@ export class City {
if (this.chaos < 0) {this.chaos = 0;} if (this.chaos < 0) {this.chaos = 0;}
} }
/**
* Initiatizes a City object from a JSON save state.
*/
static fromJSON(value: any): City {
return Generic_fromJSON(City, value.data);
}
/** /**
* Serialize the current object to a JSON save state. * Serialize the current object to a JSON save state.
*/ */
toJSON(): any { toJSON(): any {
return Generic_toJSON("City", this); return Generic_toJSON("City", this);
} }
/**
* Initiatizes a City object from a JSON save state.
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): City {
return Generic_fromJSON(City, value.data);
}
} }
Reviver.constructors.City = City; Reviver.constructors.City = City;

@ -1,4 +1,4 @@
// import { BladeburnerConstants } from "./data/Constants"; import { IBladeburner } from "./IBladeburner";
import { Action, IActionParams } from "./Action"; import { Action, IActionParams } from "./Action";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
@ -8,17 +8,18 @@ export class Contract extends Action {
super(params); super(params);
} }
getActionTypeSkillSuccessBonus(inst: any): number { getActionTypeSkillSuccessBonus(inst: IBladeburner): number {
return inst.skillMultipliers.successChanceContract; return inst.skillMultipliers.successChanceContract;
} }
static fromJSON(value: any): Contract {
return Generic_fromJSON(Contract, value.data);
}
toJSON(): any { toJSON(): any {
return Generic_toJSON("Contract", this); return Generic_toJSON("Contract", this);
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Contract {
return Generic_fromJSON(Contract, value.data);
}
} }
Reviver.constructors.Contract = Contract; Reviver.constructors.Contract = Contract;

@ -11,7 +11,7 @@ export const GeneralActions: IMap<Action> = {};
name:actionName, name:actionName,
desc:"Improve your abilities at the Bladeburner unit's specialized training " + desc:"Improve your abilities at the Bladeburner unit's specialized training " +
"center. Doing this gives experience for all combat stats and also " + "center. Doing this gives experience for all combat stats and also " +
"increases your max stamina." "increases your max stamina.",
}); });
actionName = "Field Analysis"; actionName = "Field Analysis";
@ -21,7 +21,7 @@ export const GeneralActions: IMap<Action> = {};
"Bladeburner's unit intelligence on Synthoid locations and " + "Bladeburner's unit intelligence on Synthoid locations and " +
"activities. Completing this action will improve the accuracy " + "activities. Completing this action will improve the accuracy " +
"of your Synthoid population estimated in the current city.<br><br>" + "of your Synthoid population estimated in the current city.<br><br>" +
"Does NOT require stamina." "Does NOT require stamina.",
}); });
actionName = "Recruitment"; actionName = "Recruitment";
@ -29,7 +29,7 @@ export const GeneralActions: IMap<Action> = {};
name:actionName, name:actionName,
desc:"Attempt to recruit members for your Bladeburner team. These members " + desc:"Attempt to recruit members for your Bladeburner team. These members " +
"can help you conduct operations.<br><br>" + "can help you conduct operations.<br><br>" +
"Does NOT require stamina." "Does NOT require stamina.",
}); });
actionName = "Diplomacy"; actionName = "Diplomacy";
@ -37,7 +37,7 @@ export const GeneralActions: IMap<Action> = {};
name: actionName, name: actionName,
desc: "Improve diplomatic relations with the Synthoid population. " + desc: "Improve diplomatic relations with the Synthoid population. " +
"Completing this action will reduce the Chaos level in your current city.<br><br>" + "Completing this action will reduce the Chaos level in your current city.<br><br>" +
"Does NOT require stamina." "Does NOT require stamina.",
}); });
actionName = "Hyperbolic Regeneration Chamber"; actionName = "Hyperbolic Regeneration Chamber";

@ -0,0 +1,71 @@
import { IBladeburner } from "./IBladeburner";
export interface IStatsMultiplier {
[key: string]: number;
hack: number;
str: number;
def: number;
dex: number;
agi: number;
cha: number;
int: number;
}
export interface ISuccessChanceParams {
est: boolean;
}
export interface IAction {
name: string;
desc: string;
// Difficulty scales with level. See getDifficulty() method
level: number;
maxLevel: number;
autoLevel: boolean;
baseDifficulty: number;
difficultyFac: number;
// Rank increase/decrease is affected by this exponent
rewardFac: number;
successes: number;
failures: number;
// All of these scale with level/difficulty
rankGain: number;
rankLoss: number;
hpLoss: number;
hpLost: number;
// Action Category. Current categories are stealth and kill
isStealth: boolean;
isKill: boolean;
/**
* Number of this contract remaining, and its growth rate
* Growth rate is an integer and the count will increase by that integer every "cycle"
*/
count: number;
countGrowth: number;
// Weighting of each stat in determining action success rate
weights: IStatsMultiplier;
// Diminishing returns of stats (stat ^ decay where 0 <= decay <= 1)
decays: IStatsMultiplier;
teamCount: number;
getDifficulty(): number;
attempt(inst: IBladeburner): boolean;
getActionTimePenalty(): number;
getActionTime(inst: IBladeburner): number;
getTeamSuccessBonus(inst: IBladeburner): number;
getActionTypeSkillSuccessBonus(inst: IBladeburner): number;
getChaosCompetencePenalty(inst: IBladeburner, params: ISuccessChanceParams): number;
getChaosDifficultyBonus(inst: IBladeburner): number;
getSuccessChance(inst: IBladeburner, params: ISuccessChanceParams): number;
getSuccessesNeededForNextLevel(baseSuccessesPerLevel: number): number;
setMaxLevel(baseSuccessesPerLevel: number): void;
toJSON(): any;
}

@ -0,0 +1,4 @@
export interface IActionIdentifier {
name: string;
type: string;
}

@ -0,0 +1,39 @@
import { IActionIdentifier } from "./IActionIdentifier";
import { City } from "./City";
export interface IBladeburner {
numHosp: number;
moneyLost: number;
rank: number;
maxRank: number;
skillPoints: number;
totalSkillPoints: number;
teamSize: number;
teamLost: number;
storedCycles: number;
randomEventCounter: number;
actionTimeToComplete: number;
actionTimeCurrent: number;
action: IActionIdentifier;
cities: any;
city: string;
skills: any;
skillMultipliers: any;
staminaBonus: number;
maxStamina: number;
stamina: number;
contracts: any;
operations: any;
blackops: any;
logging: any;
automateEnabled: boolean;
automateActionHigh: number;
automateThreshHigh: number;
automateActionLow: number;
automateThreshLow: number;
consoleHistory: string[];
consoleLogs: string[];
getCurrentCity(): City;
calculateStaminaPenalty(): number;
}

@ -1,3 +1,4 @@
import { IBladeburner } from "./IBladeburner";
import { BladeburnerConstants } from "./data/Constants"; import { BladeburnerConstants } from "./data/Constants";
import { Action, IActionParams } from "./Action"; import { Action, IActionParams } from "./Action";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
@ -8,8 +9,8 @@ export interface IOperationParams extends IActionParams {
} }
export class Operation extends Action { export class Operation extends Action {
reqdRank: number = 100; reqdRank = 100;
teamCount: number = 0; teamCount = 0;
constructor(params: IOperationParams | null = null) { constructor(params: IOperationParams | null = null) {
super(params); super(params);
@ -18,38 +19,39 @@ export class Operation extends Action {
} }
// For actions that have teams. To be implemented by subtypes. // For actions that have teams. To be implemented by subtypes.
getTeamSuccessBonus(inst: any): number { getTeamSuccessBonus(inst: IBladeburner): number {
if (this.teamCount && this.teamCount > 0) { if (this.teamCount && this.teamCount > 0) {
this.teamCount = Math.min(this.teamCount, inst.teamSize); this.teamCount = Math.min(this.teamCount, inst.teamSize);
let teamMultiplier = Math.pow(this.teamCount, 0.05); const teamMultiplier = Math.pow(this.teamCount, 0.05);
return teamMultiplier; return teamMultiplier;
} }
return 1; return 1;
} }
getActionTypeSkillSuccessBonus(inst: any): number { getActionTypeSkillSuccessBonus(inst: IBladeburner): number {
return inst.skillMultipliers.successChanceOperation; return inst.skillMultipliers.successChanceOperation;
} }
getChaosDifficultyBonus(inst: any, params: any): number { getChaosDifficultyBonus(inst: IBladeburner/*, params: ISuccessChanceParams*/): number {
const city = inst.getCurrentCity(); const city = inst.getCurrentCity();
if (city.chaos > BladeburnerConstants.ChaosThreshold) { if (city.chaos > BladeburnerConstants.ChaosThreshold) {
let diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold); const diff = 1 + (city.chaos - BladeburnerConstants.ChaosThreshold);
let mult = Math.pow(diff, 0.1); const mult = Math.pow(diff, 0.1);
return mult; return mult;
} }
return 1; return 1;
} }
static fromJSON(value: any): Operation {
return Generic_fromJSON(Operation, value.data);
}
toJSON(): any { toJSON(): any {
return Generic_toJSON("Operation", this); return Generic_toJSON("Operation", this);
} }
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Operation {
return Generic_fromJSON(Operation, value.data);
}
} }
Reviver.constructors.Operation = Operation; Reviver.constructors.Operation = Operation;

@ -33,36 +33,36 @@ export class Skill {
name: string; name: string;
desc: string; desc: string;
// Cost is in Skill Points // Cost is in Skill Points
baseCost: number = 1; baseCost = 1;
// Additive cost increase per level // Additive cost increase per level
costInc: number = 1; costInc = 1;
maxLvl: number = 0; maxLvl = 0;
/** /**
* These benefits are additive. So total multiplier will be level (handled externally) times the * These benefits are additive. So total multiplier will be level (handled externally) times the
* effects below * effects below
*/ */
successChanceAll: number = 0; successChanceAll = 0;
successChanceStealth: number = 0; successChanceStealth = 0;
successChanceKill: number = 0; successChanceKill = 0;
successChanceContract: number = 0; successChanceContract = 0;
successChanceOperation: number = 0; successChanceOperation = 0;
/** /**
* This multiplier affects everything that increases synthoid population/community estimate * This multiplier affects everything that increases synthoid population/community estimate
* e.g. Field analysis, Investigation Op, Undercover Op * e.g. Field analysis, Investigation Op, Undercover Op
*/ */
successChanceEstimate: number = 0; successChanceEstimate = 0;
actionTime: number = 0; actionTime = 0;
effHack: number = 0; effHack = 0;
effStr: number = 0; effStr = 0;
effDef: number = 0; effDef = 0;
effDex: number = 0; effDex = 0;
effAgi: number = 0; effAgi = 0;
effCha: number = 0; effCha = 0;
stamina: number = 0; stamina = 0;
money: number = 0; money = 0;
expGain: number = 0; expGain = 0;
constructor(params: ISkillParams={name:"foo", desc:"foo"}) { constructor(params: ISkillParams={name:"foo", desc:"foo"}) {
if (!params.name) { if (!params.name) {

@ -10,55 +10,55 @@ export const Skills: IMap<Skill> = {};
desc:"Each level of this skill increases your success chance " + desc:"Each level of this skill increases your success chance " +
"for all Contracts, Operations, and BlackOps by 3%", "for all Contracts, Operations, and BlackOps by 3%",
baseCost: 3, costInc: 2.1, baseCost: 3, costInc: 2.1,
successChanceAll:3 successChanceAll:3,
}); });
Skills[SkillNames.Cloak] = new Skill({ Skills[SkillNames.Cloak] = new Skill({
name:SkillNames.Cloak, name:SkillNames.Cloak,
desc:"Each level of this skill increases your " + desc:"Each level of this skill increases your " +
"success chance in stealth-related Contracts, Operations, and BlackOps by 5.5%", "success chance in stealth-related Contracts, Operations, and BlackOps by 5.5%",
baseCost: 2, costInc: 1.1, baseCost: 2, costInc: 1.1,
successChanceStealth:5.5 successChanceStealth:5.5,
}); });
Skills[SkillNames.ShortCircuit] = new Skill({ Skills[SkillNames.ShortCircuit] = new Skill({
name:SkillNames.ShortCircuit, name:SkillNames.ShortCircuit,
desc:"Each level of this skill increases your success chance " + desc:"Each level of this skill increases your success chance " +
"in Contracts, Operations, and BlackOps that involve retirement by 5.5%", "in Contracts, Operations, and BlackOps that involve retirement by 5.5%",
baseCost: 2, costInc: 2.1, baseCost: 2, costInc: 2.1,
successChanceKill:5.5 successChanceKill:5.5,
}); });
Skills[SkillNames.DigitalObserver] = new Skill({ Skills[SkillNames.DigitalObserver] = new Skill({
name:SkillNames.DigitalObserver, name:SkillNames.DigitalObserver,
desc:"Each level of this skill increases your success chance in " + desc:"Each level of this skill increases your success chance in " +
"all Operations and BlackOps by 4%", "all Operations and BlackOps by 4%",
baseCost: 2, costInc: 2.1, baseCost: 2, costInc: 2.1,
successChanceOperation:4 successChanceOperation:4,
}); });
Skills[SkillNames.Tracer] = new Skill({ Skills[SkillNames.Tracer] = new Skill({
name:SkillNames.Tracer, name:SkillNames.Tracer,
desc:"Each level of this skill increases your success chance in " + desc:"Each level of this skill increases your success chance in " +
"all Contracts by 4%", "all Contracts by 4%",
baseCost: 2, costInc: 2.1, baseCost: 2, costInc: 2.1,
successChanceContract:4 successChanceContract:4,
}); });
Skills[SkillNames.Overclock] = new Skill({ Skills[SkillNames.Overclock] = new Skill({
name:SkillNames.Overclock, name:SkillNames.Overclock,
desc:"Each level of this skill decreases the time it takes " + desc:"Each level of this skill decreases the time it takes " +
"to attempt a Contract, Operation, and BlackOp by 1% (Max Level: 90)", "to attempt a Contract, Operation, and BlackOp by 1% (Max Level: 90)",
baseCost: 3, costInc: 1.4, maxLvl: 90, baseCost: 3, costInc: 1.4, maxLvl: 90,
actionTime:1 actionTime:1,
}); });
Skills[SkillNames.Reaper] = new Skill({ Skills[SkillNames.Reaper] = new Skill({
name: SkillNames.Reaper, name: SkillNames.Reaper,
desc: "Each level of this skill increases your effective combat stats for Bladeburner actions by 2%", desc: "Each level of this skill increases your effective combat stats for Bladeburner actions by 2%",
baseCost: 2, costInc: 2.1, baseCost: 2, costInc: 2.1,
effStr: 2, effDef: 2, effDex: 2, effAgi: 2 effStr: 2, effDef: 2, effDex: 2, effAgi: 2,
}); });
Skills[SkillNames.EvasiveSystem] = new Skill({ Skills[SkillNames.EvasiveSystem] = new Skill({
name:SkillNames.EvasiveSystem, name:SkillNames.EvasiveSystem,
desc:"Each level of this skill increases your effective " + desc:"Each level of this skill increases your effective " +
"dexterity and agility for Bladeburner actions by 4%", "dexterity and agility for Bladeburner actions by 4%",
baseCost: 2, costInc: 2.1, baseCost: 2, costInc: 2.1,
effDex: 4, effAgi: 4 effDex: 4, effAgi: 4,
}); });
Skills[SkillNames.Datamancer] = new Skill({ Skills[SkillNames.Datamancer] = new Skill({
name:SkillNames.Datamancer, name:SkillNames.Datamancer,
@ -67,13 +67,13 @@ export const Skills: IMap<Skill> = {};
"This affects all actions that can potentially increase " + "This affects all actions that can potentially increase " +
"the accuracy of your synthoid population/community estimates.", "the accuracy of your synthoid population/community estimates.",
baseCost:3, costInc:1, baseCost:3, costInc:1,
successChanceEstimate:5 successChanceEstimate:5,
}); });
Skills[SkillNames.CybersEdge] = new Skill({ Skills[SkillNames.CybersEdge] = new Skill({
name:SkillNames.CybersEdge, name:SkillNames.CybersEdge,
desc:"Each level of this skill increases your max stamina by 2%", desc:"Each level of this skill increases your max stamina by 2%",
baseCost:1, costInc:3, baseCost:1, costInc:3,
stamina:2 stamina:2,
}); });
Skills[SkillNames.HandsOfMidas] = new Skill({ Skills[SkillNames.HandsOfMidas] = new Skill({
name: SkillNames.HandsOfMidas, name: SkillNames.HandsOfMidas,

@ -1,4 +1,14 @@
export const ConsoleHelpText: {} = { export const ConsoleHelpText: {
helpList: string[];
automate: string[];
clear: string[];
cls: string[];
help: string[];
log: string[];
skill: string[];
start: string[];
stop: string[];
} = {
helpList: [ helpList: [
"Use 'help [command]' to get more information about a particular Bladeburner console command.", "Use 'help [command]' to get more information about a particular Bladeburner console command.",
"", "",
@ -8,7 +18,7 @@ export const ConsoleHelpText: {} = {
" log [en/dis] [type] Enable or disable logging for events and actions", " log [en/dis] [type] Enable or disable logging for events and actions",
" skill [action] [name] Level or display info about your Bladeburner skills", " skill [action] [name] Level or display info about your Bladeburner skills",
" start [type] [name] Start a Bladeburner action/task" , " start [type] [name] Start a Bladeburner action/task" ,
" stop Stops your current Bladeburner action/task" " stop Stops your current Bladeburner action/task",
], ],
automate: [ automate: [
"automate [var] [val] [hi/low]", "automate [var] [val] [hi/low]",
@ -30,17 +40,17 @@ export const ConsoleHelpText: {} = {
"Using the four console commands above will set the automation to perform Tracking contracts " + "Using the four console commands above will set the automation to perform Tracking contracts " +
"if your stamina is 100 or higher, and then switch to Field Analysis if your stamina drops below " + "if your stamina is 100 or higher, and then switch to Field Analysis if your stamina drops below " +
"50. Note that when setting the action, the name of the action is CASE-SENSITIVE. It must " + "50. Note that when setting the action, the name of the action is CASE-SENSITIVE. It must " +
"exactly match whatever the name is in the UI." "exactly match whatever the name is in the UI.",
], ],
clear: [ clear: [
"clear", "clear",
"", "",
"Clears the console" "Clears the console",
], ],
cls: [ cls: [
"cls", "cls",
"", "",
"Clears the console" "Clears the console",
], ],
help: [ help: [
"help [command]", "help [command]",
@ -51,7 +61,7 @@ export const ConsoleHelpText: {} = {
"", "",
" help automate", " help automate",
"", "",
"will display specific information about using the automate console command" "will display specific information about using the automate console command",
], ],
log: [ log: [
"log [en/dis] [type]", "log [en/dis] [type]",
@ -71,7 +81,7 @@ export const ConsoleHelpText: {} = {
"Logging can be universally enabled/disabled using the 'all' keyword:", "Logging can be universally enabled/disabled using the 'all' keyword:",
"", "",
" log dis all", " log dis all",
" log en all" " log en all",
], ],
skill: [ skill: [
"skill [action] [name]", "skill [action] [name]",
@ -91,7 +101,7 @@ export const ConsoleHelpText: {} = {
"", "",
"This console command can also be used to level up skills:", "This console command can also be used to level up skills:",
"", "",
" skill level [skill name]" " skill level [skill name]",
], ],
start: [ start: [
"start [type] [name]", "start [type] [name]",
@ -106,11 +116,11 @@ export const ConsoleHelpText: {} = {
"Examples:", "Examples:",
"", "",
" start contract Tracking", " start contract Tracking",
" start op 'Undercover Operation'" " start op 'Undercover Operation'",
], ],
stop:[ stop:[
"stop", "stop",
"", "",
"Stop your current action and go idle." "Stop your current action and go idle.",
], ],
} }

@ -38,7 +38,7 @@ for (var i = blackops.length-1; i >= 0 ; --i) {
import * as React from "react"; import * as React from "react";
export function BlackOperationsPage(inst: any): React.ReactElement { export function BlackOperationsPage(): React.ReactElement {
// Put Black Operations in sequence of required rank // Put Black Operations in sequence of required rank
const blackops = []; const blackops = [];
for (const name in BlackOperations) { for (const name in BlackOperations) {
@ -55,9 +55,8 @@ export function BlackOperationsPage(inst: any): React.ReactElement {
Black Operations (Black Ops) are special, one-time covert operations. Each Black Op must be unlocked successively by completing the one before it.<br /><br /> Black Operations (Black Ops) are special, one-time covert operations. Each Black Op must be unlocked successively by completing the one before it.<br /><br />
<b>Your ultimate goal to climb through the ranks of Bladeburners is to complete all of the Black Ops.</b><br /><br /> <b>Your ultimate goal to climb through the ranks of Bladeburners is to complete all of the Black Ops.</b><br /><br />
Like normal operations, you may use a team for Black Ops. Failing a black op will incur heavy HP and rank losses.</p> Like normal operations, you may use a team for Black Ops. Failing a black op will incur heavy HP and rank losses.</p>
{blackops.map( op => {blackops.map(() => <div className="bladeburner-action">
<div className="bladeburner-action"> </div>,
</div>
)} )}
</div>) </div>)
} }

@ -41,7 +41,7 @@ export class CoinFlip extends Game<IProps, IState> {
this.updateInvestment = this.updateInvestment.bind(this); this.updateInvestment = this.updateInvestment.bind(this);
} }
updateInvestment(e: React.FormEvent<HTMLInputElement>) { updateInvestment(e: React.FormEvent<HTMLInputElement>): void {
let investment: number = parseInt(e.currentTarget.value); let investment: number = parseInt(e.currentTarget.value);
if (isNaN(investment)) { if (isNaN(investment)) {
investment = minPlay; investment = minPlay;
@ -55,7 +55,7 @@ export class CoinFlip extends Game<IProps, IState> {
this.setState({investment: investment}); this.setState({investment: investment});
} }
play(guess: string) { play(guess: string): void {
if(this.reachedLimit(this.props.p)) return; if(this.reachedLimit(this.props.p)) return;
const v = BadRNG.random(); const v = BadRNG.random();
let letter: string; let letter: string;
@ -80,7 +80,7 @@ export class CoinFlip extends Game<IProps, IState> {
} }
render() { render(): React.ReactNode {
return <> return <>
<pre> <pre>
++<br /> ++<br />
@ -89,7 +89,7 @@ export class CoinFlip extends Game<IProps, IState> {
| | | |<br /> | | | |<br />
++<br /> ++<br />
</pre> </pre>
<span className="text">Play for: </span><input type="number" className='text-input' onChange={this.updateInvestment} value={this.state.investment} /><br /> <span className="text">Play for: </span><input type="number" className="text-input" onChange={this.updateInvestment} value={this.state.investment} /><br />
<StdButton onClick={trusted(() => this.play('H'))} text={"Head!"} disabled={this.state.playLock} /> <StdButton onClick={trusted(() => this.play('H'))} text={"Head!"} disabled={this.state.playLock} />
<StdButton onClick={trusted(() => this.play('T'))} text={"Tail!"} disabled={this.state.playLock} /> <StdButton onClick={trusted(() => this.play('T'))} text={"Tail!"} disabled={this.state.playLock} />
<h1>{this.state.status}</h1> <h1>{this.state.status}</h1>

@ -1,6 +1,6 @@
export interface RNG { export interface RNG {
random(): number random(): number;
} }
/* /*
@ -9,16 +9,16 @@ export interface RNG {
*/ */
class RNG0 implements RNG { class RNG0 implements RNG {
x: number; x: number;
m: number = 1024; m = 1024;
a: number = 341; a = 341;
c: number = 1; c = 1;
constructor() { constructor() {
this.x = 0; this.x = 0;
this.reset(); this.reset();
} }
step() { step(): void {
this.x = (this.a*this.x+this.c) % this.m; this.x = (this.a*this.x+this.c) % this.m;
} }
@ -27,7 +27,7 @@ class RNG0 implements RNG {
return this.x/this.m; return this.x/this.m;
} }
reset() { reset(): void {
this.x = (new Date()).getTime() % this.m; this.x = (new Date()).getTime() % this.m;
} }
} }
@ -39,9 +39,9 @@ export const BadRNG: RNG0 = new RNG0();
* The period is 6e12. * The period is 6e12.
*/ */
export class WHRNG implements RNG { export class WHRNG implements RNG {
s1: number = 0; s1 = 0;
s2: number = 0; s2 = 0;
s3: number = 0; s3 = 0;
constructor(totalPlaytime: number) { constructor(totalPlaytime: number) {
// This one is seeded by the players total play time. // This one is seeded by the players total play time.
@ -51,7 +51,7 @@ export class WHRNG implements RNG {
this.s3 = v; this.s3 = v;
} }
step() { step(): void {
this.s1 = (171 * this.s1) % 30269; this.s1 = (171 * this.s1) % 30269;
this.s2 = (172 * this.s2) % 30307; this.s2 = (172 * this.s2) % 30307;
this.s3 = (170 * this.s3) % 30323; this.s3 = (170 * this.s3) % 30323;

@ -28,10 +28,6 @@ function isRed(n: number): boolean {
21, 23, 25, 27, 30, 32, 34, 36].includes(n); 21, 23, 25, 27, 30, 32, 34, 36].includes(n);
} }
function isBlack(n: number): boolean {
return !isRed(n);
}
type Strategy = { type Strategy = {
match: (n: number) => boolean; match: (n: number) => boolean;
payout: number; payout: number;
@ -102,14 +98,14 @@ const strategies: {
Third2: { Third2: {
match: (n: number): boolean => { match: (n: number): boolean => {
if (n === 0) return false; if (n === 0) return false;
return 13 <= n && n <= 24; return n >= 13 && n <= 24;
}, },
payout: 2, payout: 2,
}, },
Third3: { Third3: {
match: (n: number): boolean => { match: (n: number): boolean => {
if (n === 0) return false; if (n === 0) return false;
return 25 <= n; return n >= 25;
}, },
payout: 2, payout: 2,
}, },
@ -125,7 +121,7 @@ function Single(s: number): Strategy {
} }
export class Roulette extends Game<IProps, IState> { export class Roulette extends Game<IProps, IState> {
interval: number = -1; interval = -1;
rng: WHRNG; rng: WHRNG;
constructor(props: IProps) { constructor(props: IProps) {
@ -140,7 +136,7 @@ export class Roulette extends Game<IProps, IState> {
lock: true, lock: true,
strategy: { strategy: {
payout: 0, payout: 0,
match: (n: number): boolean => { return false }, match: (): boolean => { return false },
}, },
} }
@ -150,21 +146,21 @@ export class Roulette extends Game<IProps, IState> {
} }
componentDidMount() { componentDidMount(): void {
this.interval = setInterval(this.step, 50); this.interval = setInterval(this.step, 50);
} }
step() { step(): void {
if (!this.state.lock) { if (!this.state.lock) {
this.setState({n: Math.floor(Math.random()*37)}); this.setState({n: Math.floor(Math.random()*37)});
} }
} }
componentWillUnmount() { componentWillUnmount(): void {
clearInterval(this.interval); clearInterval(this.interval);
} }
updateInvestment(e: React.FormEvent<HTMLInputElement>) { updateInvestment(e: React.FormEvent<HTMLInputElement>): void {
let investment: number = parseInt(e.currentTarget.value); let investment: number = parseInt(e.currentTarget.value);
if (isNaN(investment)) { if (isNaN(investment)) {
investment = minPlay; investment = minPlay;
@ -178,13 +174,13 @@ export class Roulette extends Game<IProps, IState> {
this.setState({investment: investment}); this.setState({investment: investment});
} }
currentNumber() { currentNumber(): string {
if (this.state.n === 0) return '0'; if (this.state.n === 0) return '0';
const color = isRed(this.state.n) ? 'R' : 'B'; const color = isRed(this.state.n) ? 'R' : 'B';
return `${this.state.n}${color}`; return `${this.state.n}${color}`;
} }
play(s: Strategy) { play(s: Strategy): void {
if(this.reachedLimit(this.props.p)) return; if(this.reachedLimit(this.props.p)) return;
this.setState({ this.setState({
canPlay: false, canPlay: false,
@ -223,10 +219,10 @@ export class Roulette extends Game<IProps, IState> {
} }
render() { render(): React.ReactNode {
return <> return <>
<h1>{this.currentNumber()}</h1> <h1>{this.currentNumber()}</h1>
<input type="number" className='text-input' onChange={this.updateInvestment} placeholder={"Amount to play"} value={this.state.investment} disabled={!this.state.canPlay} /> <input type="number" className="text-input" onChange={this.updateInvestment} placeholder={"Amount to play"} value={this.state.investment} disabled={!this.state.canPlay} />
<h1>{this.state.status}</h1> <h1>{this.state.status}</h1>
<table> <table>
<tbody> <tbody>

@ -20,7 +20,7 @@ type IState = {
} }
// statically shuffled array of symbols. // statically shuffled array of symbols.
let symbols = ["D", "C", "$", "?", "♥", "A", "C", "B", "C", "E", "B", "E", "C", const symbols = ["D", "C", "$", "?", "♥", "A", "C", "B", "C", "E", "B", "E", "C",
"*", "D", "♥", "B", "A", "A", "A", "C", "A", "D", "B", "E", "?", "D", "*", "*", "D", "♥", "B", "A", "A", "A", "C", "A", "D", "B", "E", "?", "D", "*",
"@", "♥", "B", "E", "?"]; "@", "♥", "B", "E", "?"];
@ -63,7 +63,7 @@ const maxPlay = 1e6;
export class SlotMachine extends Game<IProps, IState> { export class SlotMachine extends Game<IProps, IState> {
rng: WHRNG; rng: WHRNG;
interval: number = -1; interval = -1;
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
@ -86,11 +86,11 @@ export class SlotMachine extends Game<IProps, IState> {
this.updateInvestment = this.updateInvestment.bind(this); this.updateInvestment = this.updateInvestment.bind(this);
} }
componentDidMount() { componentDidMount(): void {
this.interval = setInterval(this.step, 50); this.interval = setInterval(this.step, 50);
} }
step() { step(): void {
let stoppedOne = false; let stoppedOne = false;
const index = this.state.index.slice(); const index = this.state.index.slice();
for(const i in index) { for(const i in index) {
@ -106,7 +106,7 @@ export class SlotMachine extends Game<IProps, IState> {
} }
} }
componentWillUnmount() { componentWillUnmount(): void {
clearInterval(this.interval); clearInterval(this.interval);
} }
@ -118,7 +118,7 @@ export class SlotMachine extends Game<IProps, IState> {
]; ];
} }
play() { play(): void {
if(this.reachedLimit(this.props.p)) return; if(this.reachedLimit(this.props.p)) return;
this.setState({status: 'playing'}); this.setState({status: 'playing'});
this.win(this.props.p, -this.state.investment); this.win(this.props.p, -this.state.investment);
@ -127,7 +127,7 @@ export class SlotMachine extends Game<IProps, IState> {
setTimeout(this.lock, this.rng.random()*2000+1000); setTimeout(this.lock, this.rng.random()*2000+1000);
} }
lock() { lock(): void {
this.setState({ this.setState({
locks: [ locks: [
Math.floor(this.rng.random()*symbols.length), Math.floor(this.rng.random()*symbols.length),
@ -139,10 +139,10 @@ export class SlotMachine extends Game<IProps, IState> {
}) })
} }
checkWinnings() { checkWinnings(): void {
const t = this.getTable(); const t = this.getTable();
const getPaylineData = function(payline: number[][]): string[] { const getPaylineData = function(payline: number[][]): string[] {
let data = []; const data = [];
for(const point of payline) { for(const point of payline) {
data.push(t[point[0]][point[1]]); data.push(t[point[0]][point[1]]);
} }
@ -176,14 +176,14 @@ export class SlotMachine extends Game<IProps, IState> {
if(this.reachedLimit(this.props.p)) return; if(this.reachedLimit(this.props.p)) return;
} }
unlock() { unlock(): void {
this.setState({ this.setState({
locks: [-1, -1, -1, -1, -1], locks: [-1, -1, -1, -1, -1],
canPlay: false, canPlay: false,
}) })
} }
updateInvestment(e: React.FormEvent<HTMLInputElement>) { updateInvestment(e: React.FormEvent<HTMLInputElement>): void {
let investment: number = parseInt(e.currentTarget.value); let investment: number = parseInt(e.currentTarget.value);
if (isNaN(investment)) { if (isNaN(investment)) {
investment = minPlay; investment = minPlay;
@ -197,7 +197,7 @@ export class SlotMachine extends Game<IProps, IState> {
this.setState({investment: investment}); this.setState({investment: investment});
} }
render() { render(): React.ReactNode {
const t = this.getTable(); const t = this.getTable();
return <> return <>
<pre> <pre>
@ -209,7 +209,7 @@ export class SlotMachine extends Game<IProps, IState> {
| | {symbols[(this.state.index[0]+1)%symbols.length]} | {symbols[(this.state.index[1]+1)%symbols.length]} | {symbols[(this.state.index[2]+1)%symbols.length]} | {symbols[(this.state.index[3]+1)%symbols.length]} | {symbols[(this.state.index[4]+1)%symbols.length]} | |<br /> | | {symbols[(this.state.index[0]+1)%symbols.length]} | {symbols[(this.state.index[1]+1)%symbols.length]} | {symbols[(this.state.index[2]+1)%symbols.length]} | {symbols[(this.state.index[3]+1)%symbols.length]} | {symbols[(this.state.index[4]+1)%symbols.length]} | |<br />
++<br /> ++<br />
</pre> </pre>
<input type="number" className='text-input' onChange={this.updateInvestment} placeholder={"Amount to play"} value={this.state.investment} disabled={!this.state.canPlay} /> <input type="number" className="text-input" onChange={this.updateInvestment} placeholder={"Amount to play"} value={this.state.investment} disabled={!this.state.canPlay} />
<StdButton onClick={trusted(this.play)} text={"Spin!"} disabled={!this.state.canPlay} /> <StdButton onClick={trusted(this.play)} text={"Spin!"} disabled={!this.state.canPlay} />
<h1>{this.state.status}</h1> <h1>{this.state.status}</h1>
<h2>Pay lines</h2> <h2>Pay lines</h2>

@ -90,7 +90,7 @@ function cinematicTextEnd() {
var mainMenu = document.getElementById("mainmenu-container"); var mainMenu = document.getElementById("mainmenu-container");
container.appendChild(createElement("br")); container.appendChild(createElement("br"));
return new Promise (function(resolve, reject) { return new Promise (function(resolve) {
container.appendChild(createElement("a", { container.appendChild(createElement("a", {
class:"a-link-button", innerText:"Continue...", class:"a-link-button", innerText:"Continue...",
clickListener:()=>{ clickListener:()=>{
@ -99,7 +99,7 @@ function cinematicTextEnd() {
mainMenu.style.visibility = "visible"; mainMenu.style.visibility = "visible";
cinematicTextFlag = false; cinematicTextFlag = false;
resolve(); resolve();
} },
})); }));
}); });
} }

@ -2,7 +2,7 @@ import {
CodingContract, CodingContract,
CodingContractRewardType, CodingContractRewardType,
CodingContractTypes, CodingContractTypes,
ICodingContractReward ICodingContractReward,
} from "./CodingContracts"; } from "./CodingContracts";
import { Factions } from "./Faction/Factions"; import { Factions } from "./Faction/Factions";
import { Player } from "./Player"; import { Player } from "./Player";
@ -15,7 +15,7 @@ import { HacknetServer } from "./Hacknet/HacknetServer";
import { getRandomInt } from "../utils/helpers/getRandomInt"; import { getRandomInt } from "../utils/helpers/getRandomInt";
export function generateRandomContract() { export function generateRandomContract(): void {
// First select a random problem type // First select a random problem type
const problemType = getRandomProblemType(); const problemType = getRandomProblemType();
@ -31,7 +31,7 @@ export function generateRandomContract() {
randServer.addContract(contract); randServer.addContract(contract);
} }
export function generateRandomContractOnHome() { export function generateRandomContractOnHome(): void {
// First select a random problem type // First select a random problem type
const problemType = getRandomProblemType(); const problemType = getRandomProblemType();
@ -53,7 +53,7 @@ export interface IGenerateContractParams {
fn?: string; fn?: string;
} }
export function generateContract(params: IGenerateContractParams) { export function generateContract(params: IGenerateContractParams): void {
// Problem Type // Problem Type
let problemType; let problemType;
const problemTypes = Object.keys(CodingContractTypes); const problemTypes = Object.keys(CodingContractTypes);
@ -88,7 +88,7 @@ export function generateContract(params: IGenerateContractParams) {
fn = getRandomFilename(server, reward); fn = getRandomFilename(server, reward);
} }
let contract = new CodingContract(fn, problemType, reward); const contract = new CodingContract(fn, problemType, reward);
server.addContract(contract); server.addContract(contract);
} }
@ -117,15 +117,15 @@ function sanitizeRewardType(rewardType: CodingContractRewardType): CodingContrac
return type; return type;
} }
function getRandomProblemType() { function getRandomProblemType(): string {
const problemTypes = Object.keys(CodingContractTypes); const problemTypes = Object.keys(CodingContractTypes);
let randIndex = getRandomInt(0, problemTypes.length - 1); const randIndex = getRandomInt(0, problemTypes.length - 1);
return problemTypes[randIndex]; return problemTypes[randIndex];
} }
function getRandomReward(): ICodingContractReward { function getRandomReward(): ICodingContractReward {
let reward: ICodingContractReward = { const reward: ICodingContractReward = {
name: "", name: "",
type: getRandomInt(0, CodingContractRewardType.Money), type: getRandomInt(0, CodingContractRewardType.Money),
}; };
@ -145,8 +145,8 @@ function getRandomReward(): ICodingContractReward {
case CodingContractRewardType.FactionReputation: { case CodingContractRewardType.FactionReputation: {
// Get a random faction that player is a part of. That // Get a random faction that player is a part of. That
// faction must allow hacking contracts // faction must allow hacking contracts
var numFactions = factionsThatAllowHacking.length; const numFactions = factionsThatAllowHacking.length;
var randFaction = factionsThatAllowHacking[getRandomInt(0, numFactions - 1)]; const randFaction = factionsThatAllowHacking[getRandomInt(0, numFactions - 1)];
reward.name = randFaction; reward.name = randFaction;
break; break;
} }

@ -2,7 +2,7 @@ import {
codingContractTypesMetadata, codingContractTypesMetadata,
DescriptionFunc, DescriptionFunc,
GeneratorFunc, GeneratorFunc,
SolverFunc SolverFunc,
} from "./data/codingcontracttypes"; } from "./data/codingcontracttypes";
import { IMap } from "./types"; import { IMap } from "./types";
@ -10,7 +10,7 @@ import { IMap } from "./types";
import { import {
Generic_fromJSON, Generic_fromJSON,
Generic_toJSON, Generic_toJSON,
Reviver Reviver,
} from "../utils/JSONReviver"; } from "../utils/JSONReviver";
import { KEY } from "../utils/helpers/keyCodes"; import { KEY } from "../utils/helpers/keyCodes";
import { createElement } from "../utils/uiHelpers/createElement"; import { createElement } from "../utils/uiHelpers/createElement";
@ -108,12 +108,6 @@ export interface ICodingContractReward {
* The player receives a reward if the problem is solved correctly * The player receives a reward if the problem is solved correctly
*/ */
export class CodingContract { export class CodingContract {
/**
* Initiatizes a CodingContract from a JSON save state.
*/
static fromJSON(value: any): CodingContract {
return Generic_fromJSON(CodingContract, value.data);
}
/* Relevant data for the contract's problem */ /* Relevant data for the contract's problem */
data: any; data: any;
@ -126,13 +120,13 @@ export class CodingContract {
reward: ICodingContractReward | null; reward: ICodingContractReward | null;
/* Number of times the Contract has been attempted */ /* Number of times the Contract has been attempted */
tries: number = 0; tries = 0;
/* String representing the contract's type. Must match type in ContractTypes */ /* String representing the contract's type. Must match type in ContractTypes */
type: string; type: string;
constructor(fn: string = "", constructor(fn = "",
type: string = "Find Largest Prime Factor", type = "Find Largest Prime Factor",
reward: ICodingContractReward | null = null) { reward: ICodingContractReward | null = null) {
this.fn = fn; this.fn = fn;
if (!this.fn.endsWith(".cct")) { if (!this.fn.endsWith(".cct")) {
@ -178,9 +172,9 @@ export class CodingContract {
*/ */
async prompt(): Promise<CodingContractResult> { async prompt(): Promise<CodingContractResult> {
// tslint:disable-next-line // tslint:disable-next-line
return new Promise<CodingContractResult>((resolve: Function, reject: Function) => { return new Promise<CodingContractResult>((resolve) => {
const contractType: CodingContractType = CodingContractTypes[this.type]; const contractType: CodingContractType = CodingContractTypes[this.type];
const popupId: string = `coding-contract-prompt-popup-${this.fn}`; const popupId = `coding-contract-prompt-popup-${this.fn}`;
const title: HTMLElement = createElement("h1", { const title: HTMLElement = createElement("h1", {
innerHTML: this.type, innerHTML: this.type,
}); });
@ -190,10 +184,16 @@ export class CodingContract {
"after which the contract will self-destruct.<br><br>", "after which the contract will self-destruct.<br><br>",
`${contractType.desc(this.data).replace(/\n/g, "<br>")}`].join(" "), `${contractType.desc(this.data).replace(/\n/g, "<br>")}`].join(" "),
}); });
let answerInput: HTMLInputElement;
let solveBtn: HTMLElement; let solveBtn: HTMLElement;
let cancelBtn: HTMLElement; const cancelBtn = createElement("a", {
answerInput = createElement("input", { class: "a-link-button",
clickListener: () => {
resolve(CodingContractResult.Cancelled);
removeElementById(popupId);
},
innerText: "Cancel",
});
const answerInput = createElement("input", {
onkeydown: (e: any) => { onkeydown: (e: any) => {
if (e.keyCode === KEY.ENTER && answerInput.value !== "") { if (e.keyCode === KEY.ENTER && answerInput.value !== "") {
e.preventDefault(); e.preventDefault();
@ -219,14 +219,6 @@ export class CodingContract {
}, },
innerText: "Solve", innerText: "Solve",
}); });
cancelBtn = createElement("a", {
class: "a-link-button",
clickListener: () => {
resolve(CodingContractResult.Cancelled);
removeElementById(popupId);
},
innerText: "Cancel",
});
const lineBreak: HTMLElement = createElement("br"); const lineBreak: HTMLElement = createElement("br");
createPopup(popupId, [title, lineBreak, txt, lineBreak, lineBreak, answerInput, solveBtn, cancelBtn]); createPopup(popupId, [title, lineBreak, txt, lineBreak, lineBreak, answerInput, solveBtn, cancelBtn]);
answerInput.focus(); answerInput.focus();
@ -239,6 +231,14 @@ export class CodingContract {
toJSON(): any { toJSON(): any {
return Generic_toJSON("CodingContract", this); return Generic_toJSON("CodingContract", this);
} }
/**
* Initiatizes a CodingContract from a JSON save state.
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): CodingContract {
return Generic_fromJSON(CodingContract, value.data);
}
} }
Reviver.constructors.CodingContract = CodingContract; Reviver.constructors.CodingContract = CodingContract;

@ -6,7 +6,7 @@ import { Reviver } from "../../utils/JSONReviver";
export let Companies: IMap<Company> = {}; export let Companies: IMap<Company> = {};
function addCompany(params: IConstructorParams) { function addCompany(params: IConstructorParams): void {
if (Companies[params.name] != null) { if (Companies[params.name] != null) {
console.warn(`Duplicate Company Position being defined: ${params.name}`); console.warn(`Duplicate Company Position being defined: ${params.name}`);
} }
@ -15,7 +15,7 @@ function addCompany(params: IConstructorParams) {
// Used to initialize new Company objects for the Companies map // Used to initialize new Company objects for the Companies map
// Called when creating new game or after a prestige/reset // Called when creating new game or after a prestige/reset
export function initCompanies() { export function initCompanies(): void {
// Save Old Company data for 'favor' // Save Old Company data for 'favor'
const oldCompanies = Companies; const oldCompanies = Companies;
@ -40,11 +40,11 @@ export function initCompanies() {
} }
// Used to load Companies map from a save // Used to load Companies map from a save
export function loadCompanies(saveString: string) { 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 // Utility function to check if a string is valid company name
export function companyExists(name: string) { export function companyExists(name: string): boolean {
return Companies.hasOwnProperty(name); return Companies.hasOwnProperty(name);
} }

@ -25,12 +25,6 @@ const DefaultConstructorParams: IConstructorParams = {
} }
export class Company { export class Company {
/**
* Initiatizes a Company from a JSON save state.
*/
static fromJSON(value: any): Company {
return Generic_fromJSON(Company, value.data);
}
/** /**
* Company name * Company name
@ -136,7 +130,7 @@ export class Company {
gainFavor(): void { gainFavor(): void {
if (this.favor == null) { this.favor = 0; } if (this.favor == null) { this.favor = 0; }
if (this.rolloverRep == null) { this.rolloverRep = 0; } if (this.rolloverRep == null) { this.rolloverRep = 0; }
var res = this.getFavorGain(); const res = this.getFavorGain();
if (res.length != 2) { if (res.length != 2) {
console.error("Invalid result from getFavorGain() function"); console.error("Invalid result from getFavorGain() function");
return; return;
@ -170,6 +164,14 @@ export class Company {
toJSON(): any { toJSON(): any {
return Generic_toJSON("Company", this); return Generic_toJSON("Company", this);
} }
/**
* Initiatizes a Company from a JSON save state.
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Company {
return Generic_fromJSON(Company, value.data);
}
} }
Reviver.constructors.Company = Company; Reviver.constructors.Company = Company;

@ -5,7 +5,7 @@ import { IMap } from "../types";
export const CompanyPositions: IMap<CompanyPosition> = {}; export const CompanyPositions: IMap<CompanyPosition> = {};
function addCompanyPosition(params: IConstructorParams) { function addCompanyPosition(params: IConstructorParams): void {
if (CompanyPositions[params.name] != null) { if (CompanyPositions[params.name] != null) {
console.warn(`Duplicate Company Position being defined: ${params.name}`); console.warn(`Duplicate Company Position being defined: ${params.name}`);
} }

@ -5,8 +5,8 @@ import { CompanyPosition } from "./CompanyPosition";
* Returns a string with the given CompanyPosition's stat requirements * Returns a string with the given CompanyPosition's stat requirements
*/ */
export function getJobRequirementText(company: Company, pos: CompanyPosition, tooltiptext: boolean = false): string { export function getJobRequirementText(company: Company, pos: CompanyPosition, tooltiptext = false): string {
let reqText: string = ""; let reqText = "";
const offset: number = company.jobStatReqOffset; const offset: number = company.jobStatReqOffset;
const reqHacking: number = pos.requiredHacking > 0 ? pos.requiredHacking+offset : 0; const reqHacking: number = pos.requiredHacking > 0 ? pos.requiredHacking+offset : 0;
const reqStrength: number = pos.requiredStrength > 0 ? pos.requiredStrength+offset : 0; const reqStrength: number = pos.requiredStrength > 0 ? pos.requiredStrength+offset : 0;

@ -95,7 +95,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 3, expMultiplier: 3,
salaryMultiplier: 3, salaryMultiplier: 3,
@ -107,7 +107,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 3, expMultiplier: 3,
salaryMultiplier: 3, salaryMultiplier: 3,
@ -119,7 +119,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 2.6, expMultiplier: 2.6,
salaryMultiplier: 2.6, salaryMultiplier: 2.6,
@ -131,7 +131,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 2.75, expMultiplier: 2.75,
salaryMultiplier: 2.75, salaryMultiplier: 2.75,
@ -143,7 +143,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 2.75, expMultiplier: 2.75,
salaryMultiplier: 2.75, salaryMultiplier: 2.75,
@ -155,7 +155,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 2.25, expMultiplier: 2.25,
salaryMultiplier: 2.25, salaryMultiplier: 2.25,
@ -167,7 +167,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 2.25, expMultiplier: 2.25,
salaryMultiplier: 2.25, salaryMultiplier: 2.25,
@ -179,7 +179,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 2.5, expMultiplier: 2.5,
salaryMultiplier: 2.5, salaryMultiplier: 2.5,
@ -191,7 +191,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 2.2, expMultiplier: 2.2,
salaryMultiplier: 2.2, salaryMultiplier: 2.2,
@ -202,7 +202,7 @@ export const companiesMetadata: IConstructorParams[] = [
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions AllBusinessPositions,
), ),
expMultiplier: 2, expMultiplier: 2,
salaryMultiplier: 2, salaryMultiplier: 2,
@ -214,7 +214,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllSoftwareConsultantPositions, AllSoftwareConsultantPositions,
AllBusinessPositions AllBusinessPositions,
), ),
expMultiplier: 1.8, expMultiplier: 1.8,
salaryMultiplier: 1.8, salaryMultiplier: 1.8,
@ -226,7 +226,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
CEOOnly, CEOOnly,
AllTechnologyPositions, AllTechnologyPositions,
AllSoftwareConsultantPositions AllSoftwareConsultantPositions,
), ),
expMultiplier: 1.75, expMultiplier: 1.75,
salaryMultiplier: 1.75, salaryMultiplier: 1.75,
@ -238,7 +238,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
CEOOnly, CEOOnly,
AllTechnologyPositions, AllTechnologyPositions,
AllSoftwareConsultantPositions AllSoftwareConsultantPositions,
), ),
expMultiplier: 1.8, expMultiplier: 1.8,
salaryMultiplier: 1.8, salaryMultiplier: 1.8,
@ -250,7 +250,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSoftwareConsultantPositions AllSoftwareConsultantPositions,
), ),
expMultiplier: 1.8, expMultiplier: 1.8,
salaryMultiplier: 1.8, salaryMultiplier: 1.8,
@ -262,7 +262,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSoftwareConsultantPositions AllSoftwareConsultantPositions,
), ),
expMultiplier: 1.9, expMultiplier: 1.9,
salaryMultiplier: 1.9, salaryMultiplier: 1.9,
@ -274,7 +274,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSoftwareConsultantPositions AllSoftwareConsultantPositions,
), ),
expMultiplier: 2, expMultiplier: 2,
salaryMultiplier: 2, salaryMultiplier: 2,
@ -286,7 +286,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSoftwareConsultantPositions AllSoftwareConsultantPositions,
), ),
expMultiplier: 1.9, expMultiplier: 1.9,
salaryMultiplier: 1.9, salaryMultiplier: 1.9,
@ -299,7 +299,7 @@ export const companiesMetadata: IConstructorParams[] = [
CEOOnly, CEOOnly,
OperationsManagerOnly, OperationsManagerOnly,
AllTechnologyPositions, AllTechnologyPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 1.7, expMultiplier: 1.7,
salaryMultiplier: 1.7, salaryMultiplier: 1.7,
@ -351,7 +351,7 @@ export const companiesMetadata: IConstructorParams[] = [
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSoftwareConsultantPositions, AllSoftwareConsultantPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 1.8, expMultiplier: 1.8,
salaryMultiplier: 1.8, salaryMultiplier: 1.8,
@ -364,7 +364,7 @@ export const companiesMetadata: IConstructorParams[] = [
AllTechnologyPositions, AllTechnologyPositions,
AllBusinessPositions, AllBusinessPositions,
AllSoftwareConsultantPositions, AllSoftwareConsultantPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 1.75, expMultiplier: 1.75,
salaryMultiplier: 1.75, salaryMultiplier: 1.75,
@ -379,7 +379,7 @@ export const companiesMetadata: IConstructorParams[] = [
SecurityEngineerPositions, SecurityEngineerPositions,
AllITPositions, AllITPositions,
AllSecurityPositions, AllSecurityPositions,
AllAgentPositions AllAgentPositions,
), ),
expMultiplier: 2, expMultiplier: 2,
salaryMultiplier: 2, salaryMultiplier: 2,
@ -394,7 +394,7 @@ export const companiesMetadata: IConstructorParams[] = [
SecurityEngineerPositions, SecurityEngineerPositions,
AllITPositions, AllITPositions,
AllSecurityPositions, AllSecurityPositions,
AllAgentPositions AllAgentPositions,
), ),
expMultiplier: 2, expMultiplier: 2,
salaryMultiplier: 2, salaryMultiplier: 2,
@ -409,7 +409,7 @@ export const companiesMetadata: IConstructorParams[] = [
AllITPositions, AllITPositions,
AllSecurityPositions, AllSecurityPositions,
AllAgentPositions, AllAgentPositions,
AllSoftwareConsultantPositions AllSoftwareConsultantPositions,
), ),
expMultiplier: 1.5, expMultiplier: 1.5,
salaryMultiplier: 1.5, salaryMultiplier: 1.5,
@ -422,7 +422,7 @@ export const companiesMetadata: IConstructorParams[] = [
AllTechnologyPositions, AllTechnologyPositions,
AllSoftwareConsultantPositions, AllSoftwareConsultantPositions,
AllBusinessPositions, AllBusinessPositions,
AllSecurityPositions AllSecurityPositions,
), ),
expMultiplier: 1.4, expMultiplier: 1.4,
salaryMultiplier: 1.4, salaryMultiplier: 1.4,
@ -433,7 +433,7 @@ export const companiesMetadata: IConstructorParams[] = [
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
SoftwarePositionsUpToLeadDeveloper, SoftwarePositionsUpToLeadDeveloper,
BusinessPositionsUpToOperationsManager BusinessPositionsUpToOperationsManager,
), ),
expMultiplier: 1.3, expMultiplier: 1.3,
salaryMultiplier: 1.3, salaryMultiplier: 1.3,
@ -445,7 +445,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
SoftwarePositionsUpToLeadDeveloper, SoftwarePositionsUpToLeadDeveloper,
BusinessPositionsUpToOperationsManager, BusinessPositionsUpToOperationsManager,
AllSoftwareConsultantPositions AllSoftwareConsultantPositions,
), ),
expMultiplier: 1.5, expMultiplier: 1.5,
salaryMultiplier: 1.5, salaryMultiplier: 1.5,
@ -456,7 +456,7 @@ export const companiesMetadata: IConstructorParams[] = [
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllSecurityPositions, AllSecurityPositions,
SoftwarePositionsUpToLeadDeveloper SoftwarePositionsUpToLeadDeveloper,
), ),
expMultiplier: 1.3, expMultiplier: 1.3,
salaryMultiplier: 1.3, salaryMultiplier: 1.3,
@ -466,7 +466,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.VolhavenSysCoreSecurities, name: LocationName.VolhavenSysCoreSecurities,
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions AllTechnologyPositions,
), ),
expMultiplier: 1.3, expMultiplier: 1.3,
salaryMultiplier: 1.3, salaryMultiplier: 1.3,
@ -476,7 +476,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.VolhavenCompuTek, name: LocationName.VolhavenCompuTek,
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions AllTechnologyPositions,
), ),
expMultiplier: 1.2, expMultiplier: 1.2,
salaryMultiplier: 1.2, salaryMultiplier: 1.2,
@ -486,7 +486,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.AevumNetLinkTechnologies, name: LocationName.AevumNetLinkTechnologies,
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllTechnologyPositions AllTechnologyPositions,
), ),
expMultiplier: 1.2, expMultiplier: 1.2,
salaryMultiplier: 1.2, salaryMultiplier: 1.2,
@ -509,7 +509,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.Sector12FoodNStuff, name: LocationName.Sector12FoodNStuff,
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
EmployeeOnly, PartTimeEmployeeOnly EmployeeOnly, PartTimeEmployeeOnly,
), ),
expMultiplier: 1, expMultiplier: 1,
salaryMultiplier: 1, salaryMultiplier: 1,
@ -519,7 +519,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.Sector12JoesGuns, name: LocationName.Sector12JoesGuns,
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
EmployeeOnly, PartTimeEmployeeOnly EmployeeOnly, PartTimeEmployeeOnly,
), ),
expMultiplier: 1, expMultiplier: 1,
salaryMultiplier: 1, salaryMultiplier: 1,
@ -531,7 +531,7 @@ export const companiesMetadata: IConstructorParams[] = [
companyPositions: Object.assign({}, companyPositions: Object.assign({},
AllSoftwarePositions, AllSoftwarePositions,
AllSoftwareConsultantPositions, AllSoftwareConsultantPositions,
AllITPositions AllITPositions,
), ),
expMultiplier: 1.1, expMultiplier: 1.1,
salaryMultiplier: 1.1, salaryMultiplier: 1.1,
@ -541,7 +541,7 @@ export const companiesMetadata: IConstructorParams[] = [
name: LocationName.NewTokyoNoodleBar, name: LocationName.NewTokyoNoodleBar,
info: "", info: "",
companyPositions: Object.assign({}, companyPositions: Object.assign({},
WaiterOnly, PartTimeWaiterOnly WaiterOnly, PartTimeWaiterOnly,
), ),
expMultiplier: 1, expMultiplier: 1,
salaryMultiplier: 1, salaryMultiplier: 1,

@ -8,23 +8,23 @@ export const SoftwareCompanyPositions: string[] = [
"Head of Software", "Head of Software",
"Head of Engineering", "Head of Engineering",
"Vice President of Technology", "Vice President of Technology",
"Chief Technology Officer" "Chief Technology Officer",
]; ];
export const ITCompanyPositions: string[] = [ export const ITCompanyPositions: string[] = [
"IT Intern", "IT Intern",
"IT Analyst", "IT Analyst",
"IT Manager", "IT Manager",
"Systems Administrator" "Systems Administrator",
]; ];
export const SecurityEngineerCompanyPositions: string[] = [ export const SecurityEngineerCompanyPositions: string[] = [
"Security Engineer" "Security Engineer",
]; ];
export const NetworkEngineerCompanyPositions: string[] = [ export const NetworkEngineerCompanyPositions: string[] = [
"Network Engineer", "Network Engineer",
"Network Administrator" "Network Administrator",
]; ];
export const BusinessCompanyPositions: string[] = [ export const BusinessCompanyPositions: string[] = [
@ -33,7 +33,7 @@ export const BusinessCompanyPositions: string[] = [
"Business Manager", "Business Manager",
"Operations Manager", "Operations Manager",
"Chief Financial Officer", "Chief Financial Officer",
"Chief Executive Officer" "Chief Executive Officer",
]; ];
export const SecurityCompanyPositions: string[] = [ export const SecurityCompanyPositions: string[] = [
@ -42,31 +42,31 @@ export const SecurityCompanyPositions: string[] = [
"Security Guard", "Security Guard",
"Security Officer", "Security Officer",
"Security Supervisor", "Security Supervisor",
"Head of Security" "Head of Security",
]; ];
export const AgentCompanyPositions: string[] = [ export const AgentCompanyPositions: string[] = [
"Field Agent", "Field Agent",
"Secret Agent", "Secret Agent",
"Special Operative" "Special Operative",
]; ];
export const MiscCompanyPositions: string[] = [ export const MiscCompanyPositions: string[] = [
"Waiter", "Waiter",
"Employee" "Employee",
]; ];
export const SoftwareConsultantCompanyPositions: string[] = [ export const SoftwareConsultantCompanyPositions: string[] = [
"Software Consultant", "Software Consultant",
"Senior Software Consultant" "Senior Software Consultant",
]; ];
export const BusinessConsultantCompanyPositions: string[] = [ export const BusinessConsultantCompanyPositions: string[] = [
"Business Consultant", "Business Consultant",
"Senior Business Consultant" "Senior Business Consultant",
]; ];
export const PartTimeCompanyPositions: string[] = [ export const PartTimeCompanyPositions: string[] = [
"Part-time Waiter", "Part-time Waiter",
"Part-time Employee" "Part-time Employee",
]; ];

@ -5,7 +5,7 @@
*/ */
import { IMap } from "./types"; import { IMap } from "./types";
export let CONSTANTS: IMap<any> = { export const CONSTANTS: IMap<any> = {
Version: "0.51.6", Version: "0.51.6",
/** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience /** Max level for any skill, assuming no multipliers. Determined by max numerical value in javascript for experience
@ -268,5 +268,5 @@ export let CONSTANTS: IMap<any> = {
* so many documentation and typos fixes (@Pimgd) * so many documentation and typos fixes (@Pimgd)
* A corruption visual effect has been added to location with servers that * A corruption visual effect has been added to location with servers that
have backdoor installed. (@dewint) have backdoor installed. (@dewint)
` `,
} }

@ -5,7 +5,6 @@ import { CorporationUpgrades } from "./data/Corporation
import { EmployeePositions } from "./EmployeePositions"; import { EmployeePositions } from "./EmployeePositions";
import { Industries, import { Industries,
IndustryStartingCosts, IndustryStartingCosts,
IndustryDescriptions,
IndustryResearchTrees } from "./IndustryData"; IndustryResearchTrees } from "./IndustryData";
import { IndustryUpgrades } from "./IndustryUpgrades"; import { IndustryUpgrades } from "./IndustryUpgrades";
import { Material } from "./Material"; import { Material } from "./Material";
@ -15,11 +14,8 @@ import { ResearchMap } from "./ResearchMap";
import { Warehouse } from "./Warehouse"; import { Warehouse } from "./Warehouse";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { CONSTANTS } from "../Constants";
import { Factions } from "../Faction/Factions";
import { showLiterature } from "../Literature/LiteratureHelpers"; import { showLiterature } from "../Literature/LiteratureHelpers";
import { LiteratureNames } from "../Literature/data/LiteratureNames"; import { LiteratureNames } from "../Literature/data/LiteratureNames";
import { createCityMap } from "../Locations/Cities";
import { CityName } from "../Locations/data/CityNames"; import { CityName } from "../Locations/data/CityNames";
import { Player } from "../Player"; import { Player } from "../Player";
@ -29,7 +25,6 @@ import { Page, routing } from "../ui/navigationTr
import { calculateEffectWithFactors } from "../utils/calculateEffectWithFactors"; import { calculateEffectWithFactors } from "../utils/calculateEffectWithFactors";
import { dialogBoxCreate } from "../../utils/DialogBox"; import { dialogBoxCreate } from "../../utils/DialogBox";
import { clearSelector } from "../../utils/uiHelpers/clearSelector";
import { Reviver, import { Reviver,
Generic_toJSON, Generic_toJSON,
Generic_fromJSON } from "../../utils/JSONReviver"; Generic_fromJSON } from "../../utils/JSONReviver";
@ -99,7 +94,6 @@ export const BaseMaxProducts = 3; // Initial value for maximum
let researchTreeBoxOpened = false; let researchTreeBoxOpened = false;
let researchTreeBox = null; let researchTreeBox = null;
$(document).mousedown(function(event) { $(document).mousedown(function(event) {
const boxId = "corporation-research-popup-box";
const contentId = "corporation-research-popup-box-content"; const contentId = "corporation-research-popup-box-content";
if (researchTreeBoxOpened) { if (researchTreeBoxOpened) {
if ( $(event.target).closest("#" + contentId).get(0) == null ) { if ( $(event.target).closest("#" + contentId).get(0) == null ) {
@ -111,7 +105,6 @@ $(document).mousedown(function(event) {
} }
}); });
var empManualAssignmentModeActive = false;
function Industry(params={}) { function Industry(params={}) {
this.offices = { //Maps locations to offices. 0 if no office at that location this.offices = { //Maps locations to offices. 0 if no office at that location
[CityName.Aevum]: 0, [CityName.Aevum]: 0,
@ -122,7 +115,7 @@ function Industry(params={}) {
}), }),
[CityName.NewTokyo]: 0, [CityName.NewTokyo]: 0,
[CityName.Ishima]: 0, [CityName.Ishima]: 0,
[CityName.Volhaven]: 0 [CityName.Volhaven]: 0,
}; };
this.name = params.name ? params.name : 0; this.name = params.name ? params.name : 0;
@ -183,7 +176,7 @@ function Industry(params={}) {
}), }),
[CityName.NewTokyo]: 0, [CityName.NewTokyo]: 0,
[CityName.Ishima]: 0, [CityName.Ishima]: 0,
[CityName.Volhaven]: 0 [CityName.Volhaven]: 0,
}; };
this.init(); this.init();
@ -378,7 +371,7 @@ Industry.prototype.init = function() {
"Metal": 5, "Metal": 5,
"Energy": 5, "Energy": 5,
"Water": 2, "Water": 2,
"Hardware": 4 "Hardware": 4,
} }
this.prodMats = ["RealEstate"]; this.prodMats = ["RealEstate"];
this.makesProducts = true; this.makesProducts = true;
@ -441,8 +434,7 @@ Industry.prototype.calculateProductionFactors = function() {
continue; continue;
} }
var materials = warehouse.materials, var materials = warehouse.materials;
office = this.offices[city];
var cityMult = Math.pow(0.002 * materials.RealEstate.qty+1, this.reFac) * var cityMult = Math.pow(0.002 * materials.RealEstate.qty+1, this.reFac) *
Math.pow(0.002 * materials.Hardware.qty+1, this.hwFac) * Math.pow(0.002 * materials.Hardware.qty+1, this.hwFac) *
@ -535,7 +527,7 @@ Industry.prototype.process = function(marketCycles=1, state, company) {
} }
// Process change in demand and competition for this industry's materials // Process change in demand and competition for this industry's materials
Industry.prototype.processMaterialMarket = function(marketCycles=1) { Industry.prototype.processMaterialMarket = function() {
//References to prodMats and reqMats //References to prodMats and reqMats
var reqMats = this.reqMats, prodMats = this.prodMats; var reqMats = this.reqMats, prodMats = this.prodMats;
@ -589,7 +581,7 @@ Industry.prototype.processProductMarket = function(marketCycles=1) {
//Process production, purchase, and import/export of materials //Process production, purchase, and import/export of materials
Industry.prototype.processMaterials = function(marketCycles=1, company) { Industry.prototype.processMaterials = function(marketCycles=1, company) {
var revenue = 0, expenses = 0, industry = this; var revenue = 0, expenses = 0;
this.calculateProductionFactors(); this.calculateProductionFactors();
//At the start of the export state, set the imports of everything to 0 //At the start of the export state, set the imports of everything to 0
@ -642,7 +634,7 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
mat.qty += buyAmt; mat.qty += buyAmt;
expenses += (buyAmt * mat.bCost); expenses += (buyAmt * mat.bCost);
} }
})(matName, industry); })(matName, this);
this.updateWarehouseSizeUsed(warehouse); this.updateWarehouseSizeUsed(warehouse);
} }
} //End process purchase of materials } //End process purchase of materials
@ -1003,7 +995,7 @@ Industry.prototype.processProduct = function(marketCycles=1, product, corporatio
if (warehouse instanceof Warehouse) { if (warehouse instanceof Warehouse) {
switch(this.state) { switch(this.state) {
case "PRODUCTION": case "PRODUCTION": {
//Calculate the maximum production of this material based //Calculate the maximum production of this material based
//on the office's productivity //on the office's productivity
var maxProd = this.getOfficeProductivity(office, {forProduct:true}) var maxProd = this.getOfficeProductivity(office, {forProduct:true})
@ -1065,8 +1057,8 @@ Industry.prototype.processProduct = function(marketCycles=1, product, corporatio
//Keep track of production Per second //Keep track of production Per second
product.data[city][1] = prod * producableFrac / (SecsPerMarketCycle * marketCycles); product.data[city][1] = prod * producableFrac / (SecsPerMarketCycle * marketCycles);
break; break;
}
case "SALE": case "SALE": {
//Process sale of Products //Process sale of Products
product.pCost = 0; //Estimated production cost product.pCost = 0; //Estimated production cost
for (var reqMatName in product.reqMats) { for (var reqMatName in product.reqMats) {
@ -1174,7 +1166,7 @@ Industry.prototype.processProduct = function(marketCycles=1, product, corporatio
product.data[city][2] = 0; //data[2] is sell property product.data[city][2] = 0; //data[2] is sell property
} }
break; break;
}
case "START": case "START":
case "PURCHASE": case "PURCHASE":
case "EXPORT": case "EXPORT":
@ -1199,10 +1191,9 @@ Industry.prototype.discontinueProduct = function(product) {
} }
Industry.prototype.upgrade = function(upgrade, refs) { Industry.prototype.upgrade = function(upgrade, refs) {
var corporation = refs.corporation, division = refs.division, var corporation = refs.corporation;
office = refs.office; var office = refs.office;
var upgN = upgrade[0], basePrice = upgrade[1], priceMult = upgrade[2], var upgN = upgrade[0];
upgradeBenefit = upgrade[3];
while (this.upgrades.length <= upgN) {this.upgrades.push(0);} while (this.upgrades.length <= upgN) {this.upgrades.push(0);}
++this.upgrades[upgN]; ++this.upgrades[upgN];
@ -1374,9 +1365,6 @@ Industry.prototype.createResearchBox = function() {
}, },
} }
// Construct the tree with Treant
const treantTree = new Treant(markup);
// Add Event Listeners for all Nodes // Add Event Listeners for all Nodes
const allResearch = researchTree.getAllNodes(); const allResearch = researchTree.getAllNodes();
for (let i = 0; i < allResearch.length; ++i) { for (let i = 0; i < allResearch.length; ++i) {
@ -1620,7 +1608,7 @@ var OfficeSpaceTiers = {
Basic: "Basic", Basic: "Basic",
Enhanced: "Enhanced", Enhanced: "Enhanced",
Luxurious: "Luxurious", Luxurious: "Luxurious",
Extravagant: "Extravagant" Extravagant: "Extravagant",
} }
function OfficeSpace(params={}) { function OfficeSpace(params={}) {
@ -1658,7 +1646,7 @@ OfficeSpace.prototype.atCapacity = function() {
} }
OfficeSpace.prototype.process = function(marketCycles=1, parentRefs) { OfficeSpace.prototype.process = function(marketCycles=1, parentRefs) {
var corporation = parentRefs.corporation, industry = parentRefs.industry; var industry = parentRefs.industry;
// HRBuddy AutoRecruitment and training // HRBuddy AutoRecruitment and training
if (industry.hasResearch("HRBuddy-Recruitment") && !this.atCapacity()) { if (industry.hasResearch("HRBuddy-Recruitment") && !this.atCapacity()) {
@ -1741,7 +1729,6 @@ OfficeSpace.prototype.calculateEmployeeProductivity = function(parentRefs) {
//Takes care of UI as well //Takes care of UI as well
OfficeSpace.prototype.findEmployees = function(parentRefs) { OfficeSpace.prototype.findEmployees = function(parentRefs) {
var company = parentRefs.corporation, division = parentRefs.industry;
if (this.atCapacity()) { return; } if (this.atCapacity()) { return; }
if (document.getElementById("cmpy-mgmt-hire-employee-popup") != null) {return;} if (document.getElementById("cmpy-mgmt-hire-employee-popup") != null) {return;}
@ -1800,7 +1787,7 @@ OfficeSpace.prototype.findEmployees = function(parentRefs) {
office.hireEmployee(employee, parentRefs); office.hireEmployee(employee, parentRefs);
removeElementById("cmpy-mgmt-hire-employee-popup"); removeElementById("cmpy-mgmt-hire-employee-popup");
return false; return false;
} },
}); });
return div; return div;
}; };
@ -1812,7 +1799,7 @@ OfficeSpace.prototype.findEmployees = function(parentRefs) {
clickListener:() => { clickListener:() => {
removeElementById("cmpy-mgmt-hire-employee-popup"); removeElementById("cmpy-mgmt-hire-employee-popup");
return false; return false;
} },
}); });
var elems = [text, var elems = [text,
@ -1825,7 +1812,7 @@ OfficeSpace.prototype.findEmployees = function(parentRefs) {
} }
OfficeSpace.prototype.hireEmployee = function(employee, parentRefs) { OfficeSpace.prototype.hireEmployee = function(employee, parentRefs) {
var company = parentRefs.corporation, division = parentRefs.industry; var company = parentRefs.corporation;
var yesBtn = yesNoTxtInpBoxGetYesButton(), var yesBtn = yesNoTxtInpBoxGetYesButton(),
noBtn = yesNoTxtInpBoxGetNoButton(); noBtn = yesNoTxtInpBoxGetNoButton();
yesBtn.innerHTML = "Hire"; yesBtn.innerHTML = "Hire";
@ -1958,15 +1945,14 @@ Corporation.prototype.storeCycles = function(numCycles=1) {
} }
Corporation.prototype.process = function() { Corporation.prototype.process = function() {
var corp = this;
if (this.storedCycles >= CyclesPerIndustryStateCycle) { if (this.storedCycles >= CyclesPerIndustryStateCycle) {
const state = this.getState(); const state = this.getState();
const marketCycles = 1; const marketCycles = 1;
const gameCycles = (marketCycles * CyclesPerIndustryStateCycle); const gameCycles = (marketCycles * CyclesPerIndustryStateCycle);
this.storedCycles -= gameCycles; this.storedCycles -= gameCycles;
this.divisions.forEach(function(ind) { this.divisions.forEach((ind) => {
ind.process(marketCycles, state, corp); ind.process(marketCycles, state, this);
}); });
// Process cooldowns // Process cooldowns
@ -2111,7 +2097,7 @@ Corporation.prototype.goPublic = function() {
onkeyup:(e) => { onkeyup:(e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {yesBtn.click();} if (e.keyCode === KEY.ENTER) {yesBtn.click();}
} },
}); });
var br = createElement("br", {}); var br = createElement("br", {});
yesBtn = createElement("a", { yesBtn = createElement("a", {
@ -2138,7 +2124,7 @@ Corporation.prototype.goPublic = function() {
dialogBoxCreate(`You took your ${this.name} public and earned ` + dialogBoxCreate(`You took your ${this.name} public and earned ` +
`${numeralWrapper.formatMoney(numShares * initialSharePrice)} in your IPO`); `${numeralWrapper.formatMoney(numShares * initialSharePrice)} in your IPO`);
return false; return false;
} },
}); });
var noBtn = createElement("a", { var noBtn = createElement("a", {
class:"a-link-button", class:"a-link-button",
@ -2146,7 +2132,7 @@ Corporation.prototype.goPublic = function() {
clickListener:() => { clickListener:() => {
removeElementById(goPublicPopupId); removeElementById(goPublicPopupId);
return false; return false;
} },
}); });
createPopup(goPublicPopupId, [txt, br, input, yesBtn, noBtn]); createPopup(goPublicPopupId, [txt, br, input, yesBtn, noBtn]);
} }
@ -2208,7 +2194,6 @@ Corporation.prototype.calculateShareSale = function(numShares) {
Corporation.prototype.convertCooldownToString = function(cd) { Corporation.prototype.convertCooldownToString = function(cd) {
// The cooldown value is based on game cycles. Convert to a simple string // The cooldown value is based on game cycles. Convert to a simple string
const CyclesPerSecond = 1000 / CONSTANTS.MilliPerCycle;
const seconds = cd / 5; const seconds = cd / 5;
const SecondsPerMinute = 60; const SecondsPerMinute = 60;
@ -2351,7 +2336,7 @@ Corporation.prototype.createUI = function() {
companyManagementDiv = createElement("div", { companyManagementDiv = createElement("div", {
id:"cmpy-mgmt-container", id:"cmpy-mgmt-container",
position:"fixed", position:"fixed",
class:"generic-menupage-container" class:"generic-menupage-container",
}); });
document.getElementById("entire-game-container").appendChild(companyManagementDiv); document.getElementById("entire-game-container").appendChild(companyManagementDiv);

@ -6,16 +6,10 @@ import { Generic_fromJSON,
export const AllCorporationStates: string[] = ["START", "PURCHASE", "PRODUCTION", "SALE", "EXPORT"]; export const AllCorporationStates: string[] = ["START", "PURCHASE", "PRODUCTION", "SALE", "EXPORT"];
export class CorporationState { export class CorporationState {
// Initiatizes a CorporationState object from a JSON save state.
static fromJSON(value: any): CorporationState {
return Generic_fromJSON(CorporationState, value.data);
}
// Number representing what state the Corporation is in. The number // Number representing what state the Corporation is in. The number
// is an index for the array that holds all Corporation States // is an index for the array that holds all Corporation States
state: number = 0; state = 0;
constructor() {}
// Get the name of the current state // Get the name of the current state
// NOTE: This does NOT return the number stored in the 'state' property, // NOTE: This does NOT return the number stored in the 'state' property,
@ -40,6 +34,12 @@ export class CorporationState {
toJSON(): any { toJSON(): any {
return Generic_toJSON("CorporationState", this); return Generic_toJSON("CorporationState", this);
} }
// Initiatizes a CorporationState object from a JSON save state.
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): CorporationState {
return Generic_fromJSON(CorporationState, value.data);
}
} }
Reviver.constructors.CorporationState = CorporationState; Reviver.constructors.CorporationState = CorporationState;

@ -4,8 +4,6 @@ import { getBaseResearchTreeCopy,
import { numeralWrapper } from "../ui/numeralFormat"; import { numeralWrapper } from "../ui/numeralFormat";
import { Reviver } from "../../utils/JSONReviver";
interface IIndustryMap<T> { interface IIndustryMap<T> {
Energy: T; Energy: T;
Utilities: T; Utilities: T;
@ -107,7 +105,7 @@ export const IndustryDescriptions: IIndustryMap<string> = {
// Map of available Research for each Industry. This data is held in a // Map of available Research for each Industry. This data is held in a
// ResearchTree object // ResearchTree object
export let IndustryResearchTrees: IIndustryMap<ResearchTree> = { export const IndustryResearchTrees: IIndustryMap<ResearchTree> = {
Energy: getBaseResearchTreeCopy(), Energy: getBaseResearchTreeCopy(),
Utilities: getBaseResearchTreeCopy(), Utilities: getBaseResearchTreeCopy(),
Agriculture: getBaseResearchTreeCopy(), Agriculture: getBaseResearchTreeCopy(),
@ -124,7 +122,7 @@ export let IndustryResearchTrees: IIndustryMap<ResearchTree> = {
RealEstate: getProductIndustryResearchTreeCopy(), RealEstate: getProductIndustryResearchTreeCopy(),
} }
export function resetIndustryResearchTrees() { export function resetIndustryResearchTrees(): void {
IndustryResearchTrees.Energy = getBaseResearchTreeCopy(); IndustryResearchTrees.Energy = getBaseResearchTreeCopy();
IndustryResearchTrees.Utilities = getBaseResearchTreeCopy(); IndustryResearchTrees.Utilities = getBaseResearchTreeCopy();
IndustryResearchTrees.Agriculture = getBaseResearchTreeCopy(); IndustryResearchTrees.Agriculture = getBaseResearchTreeCopy();

@ -11,5 +11,5 @@ export const IndustryUpgrades: IMap<any[]> = {
"this upgrade grants your company a static increase of 3 and 1 to its awareness and " + "this upgrade grants your company a static increase of 3 and 1 to its awareness and " +
"popularity, respectively. It will then increase your company's awareness by 1%, and its popularity " + "popularity, respectively. It will then increase your company's awareness by 1%, and its popularity " +
"by a random percentage between 1% and 3%. These effects are increased by other upgrades " + "by a random percentage between 1% and 3%. These effects are increased by other upgrades " +
"that increase the power of your advertising."] "that increase the power of your advertising."],
} }

@ -7,56 +7,52 @@ interface IConstructorParams {
} }
export class Material { export class Material {
// Initiatizes a Material object from a JSON save state.
static fromJSON(value: any): Material {
return Generic_fromJSON(Material, value.data);
}
// Name of material // Name of material
name: string = "InitName"; name = "InitName";
// Amount of material owned // Amount of material owned
qty: number = 0; qty = 0;
// Material's "quality". Unbounded // Material's "quality". Unbounded
qlt: number = 0; qlt = 0;
// How much demand the Material has in the market, and the range of possible // How much demand the Material has in the market, and the range of possible
// values for this "demand" // values for this "demand"
dmd: number = 0; dmd = 0;
dmdR: number[] = [0, 0]; dmdR: number[] = [0, 0];
// How much competition there is for this Material in the market, and the range // How much competition there is for this Material in the market, and the range
// of possible values for this "competition" // of possible values for this "competition"
cmp: number = 0; cmp = 0;
cmpR: number[] = [0, 0]; cmpR: number[] = [0, 0];
// Maximum volatility of this Materials stats // Maximum volatility of this Materials stats
mv: number = 0; mv = 0;
// Markup. Determines how high of a price you can charge on the material // Markup. Determines how high of a price you can charge on the material
// compared to the market price without suffering loss in # of sales // compared to the market price without suffering loss in # of sales
// Quality is divided by this to determine markup limits // Quality is divided by this to determine markup limits
// e,g, If mku is 10 and quality is 100 then you can markup prices by 100/10 = 10 // e,g, If mku is 10 and quality is 100 then you can markup prices by 100/10 = 10
mku: number = 0; mku = 0;
// How much of this material is being bought, sold, imported and produced every second // How much of this material is being bought, sold, imported and produced every second
buy: number = 0; buy = 0;
sll: number = 0; sll = 0;
prd: number = 0; prd = 0;
imp: number = 0; imp = 0;
// Exports of this material to another warehouse/industry // Exports of this material to another warehouse/industry
exp: any[] = []; exp: any[] = [];
// Total amount of this material exported in the last cycle // Total amount of this material exported in the last cycle
totalExp: number = 0; totalExp = 0;
// Cost / sec to buy this material. AKA Market Price // Cost / sec to buy this material. AKA Market Price
bCost: number = 0; bCost = 0;
// Cost / sec to sell this material // Cost / sec to sell this material
sCost: number = 0; sCost = 0;
// Flags to keep track of whether production and/or sale of this material is limited // Flags to keep track of whether production and/or sale of this material is limited
// [Whether production/sale is limited, limit amount] // [Whether production/sale is limited, limit amount]
@ -64,9 +60,9 @@ export class Material {
sllman: any[] = [false, 0]; // Sale sllman: any[] = [false, 0]; // Sale
// Flags that signal whether automatic sale pricing through Market TA is enabled // Flags that signal whether automatic sale pricing through Market TA is enabled
marketTa1: boolean = false; marketTa1 = false;
marketTa2: boolean = false; marketTa2 = false;
marketTa2Price: number = 0; marketTa2Price = 0;
constructor(params: IConstructorParams = {}) { constructor(params: IConstructorParams = {}) {
if (params.name) { this.name = params.name; } if (params.name) { this.name = params.name; }
@ -166,7 +162,7 @@ export class Material {
const compChange: number = 1 + compVolatility; const compChange: number = 1 + compVolatility;
if (Math.random() < 0.5) { if (Math.random() < 0.5) {
this.cmp *= compChange; this.cmp *= compChange;
if (this.cmp > this.cmpR[1]) {this.cmp = this.cmpR[1]}; if (this.cmp > this.cmpR[1]) {this.cmp = this.cmpR[1]}
this.bCost *= (1 / priceChange); // Competition increases, so price goes down this.bCost *= (1 / priceChange); // Competition increases, so price goes down
} else { } else {
this.cmp *= (1 / compChange); this.cmp *= (1 / compChange);
@ -192,6 +188,12 @@ export class Material {
toJSON(): any { toJSON(): any {
return Generic_toJSON("Material", this); return Generic_toJSON("Material", this);
} }
// Initiatizes a Material object from a JSON save state.
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Material {
return Generic_fromJSON(Material, value.data);
}
} }
Reviver.constructors.Material = Material; Reviver.constructors.Material = Material;

@ -42,49 +42,45 @@ interface IIndustry {
export class Product { export class Product {
// Initiatizes a Product object from a JSON save state.
static fromJSON(value: any): Product {
return Generic_fromJSON(Product, value.data);
}
// Product name // Product name
name: string = ""; name = "";
// The demand for this Product in the market. Gradually decreases // The demand for this Product in the market. Gradually decreases
dmd: number = 0; dmd = 0;
// How much competition there is in the market for this Product // How much competition there is in the market for this Product
cmp: number = 0; cmp = 0;
// Markup. Affects how high of a price you can charge for this Product // Markup. Affects how high of a price you can charge for this Product
// without suffering a loss in the # of sales // without suffering a loss in the # of sales
mku: number = 0; mku = 0;
// Production cost - estimation of how much money it costs to make this Product // Production cost - estimation of how much money it costs to make this Product
pCost: number = 0; pCost = 0;
// Sell cost // Sell cost
sCost: number = 0; sCost = 0;
// Variables for handling the creation process of this Product // Variables for handling the creation process of this Product
fin: boolean = false; // Whether this Product has finished being created fin = false; // Whether this Product has finished being created
prog: number = 0; // Creation progress - A number betwee 0-100 representing percentage prog = 0; // Creation progress - A number betwee 0-100 representing percentage
createCity: string = ""; // City in which the product is/was being created createCity = ""; // City in which the product is/was being created
designCost: number = 0; // How much money was invested into designing this Product designCost = 0; // How much money was invested into designing this Product
advCost: number = 0; // How much money was invested into advertising this Product advCost = 0; // How much money was invested into advertising this Product
// Aggregate score for this Product's 'rating' // Aggregate score for this Product's 'rating'
// This is based on the stats/properties below. The weighting of the // This is based on the stats/properties below. The weighting of the
// stats/properties below differs between different industries // stats/properties below differs between different industries
rat: number = 0; rat = 0;
// Stats/properties of this Product // Stats/properties of this Product
qlt: number = 0; qlt = 0;
per: number = 0; per = 0;
dur: number = 0; dur = 0;
rel: number = 0; rel = 0;
aes: number = 0; aes = 0;
fea: number = 0; fea = 0;
// Data refers to the production, sale, and quantity of the products // Data refers to the production, sale, and quantity of the products
// These values are specific to a city // These values are specific to a city
@ -93,11 +89,11 @@ export class Product {
// Location of this Product // Location of this Product
// Only applies for location-based products like restaurants/hospitals // Only applies for location-based products like restaurants/hospitals
loc: string = ""; loc = "";
// How much space 1 unit of the Product takes (in the warehouse) // How much space 1 unit of the Product takes (in the warehouse)
// Not applicable for all Products // Not applicable for all Products
siz: number = 0; siz = 0;
// Material requirements. An object that maps the name of a material to how much it requires // Material requirements. An object that maps the name of a material to how much it requires
// to make 1 unit of the product. // to make 1 unit of the product.
@ -110,8 +106,8 @@ export class Product {
sllman: IMap<any[]> = createCityMap<any[]>([false, 0]); sllman: IMap<any[]> = createCityMap<any[]>([false, 0]);
// Flags that signal whether automatic sale pricing through Market TA is enabled // Flags that signal whether automatic sale pricing through Market TA is enabled
marketTa1: boolean = false; marketTa1 = false;
marketTa2: boolean = false; marketTa2 = false;
marketTa2Price: IMap<number> = createCityMap<number>(0); marketTa2Price: IMap<number> = createCityMap<number>(0);
constructor(params: IConstructorParams={}) { constructor(params: IConstructorParams={}) {
@ -135,7 +131,7 @@ export class Product {
// empWorkMult is a multiplier that increases progress rate based on // empWorkMult is a multiplier that increases progress rate based on
// productivity of employees // productivity of employees
createProduct(marketCycles: number=1, empWorkMult: number=1): void { createProduct(marketCycles=1, empWorkMult=1): void {
if (this.fin) { return; } if (this.fin) { return; }
this.prog += (marketCycles * .01 * empWorkMult); this.prog += (marketCycles * .01 * empWorkMult);
} }
@ -145,18 +141,18 @@ export class Product {
this.fin = true; this.fin = true;
//Calculate properties //Calculate properties
var progrMult = this.prog / 100; const progrMult = this.prog / 100;
const engrRatio = employeeProd[EmployeePositions.Engineer] / employeeProd["total"]; const engrRatio = employeeProd[EmployeePositions.Engineer] / employeeProd["total"];
const mgmtRatio = employeeProd[EmployeePositions.Management] / employeeProd["total"]; const mgmtRatio = employeeProd[EmployeePositions.Management] / employeeProd["total"];
const rndRatio = employeeProd[EmployeePositions.RandD] / employeeProd["total"]; const rndRatio = employeeProd[EmployeePositions.RandD] / employeeProd["total"];
const opsRatio = employeeProd[EmployeePositions.Operations] / employeeProd["total"]; const opsRatio = employeeProd[EmployeePositions.Operations] / employeeProd["total"];
const busRatio = employeeProd[EmployeePositions.Business] / employeeProd["total"]; const busRatio = employeeProd[EmployeePositions.Business] / employeeProd["total"];
var designMult = 1 + (Math.pow(this.designCost, 0.1) / 100); const designMult = 1 + (Math.pow(this.designCost, 0.1) / 100);
var balanceMult = (1.2 * engrRatio) + (0.9 * mgmtRatio) + (1.3 * rndRatio) + const balanceMult = (1.2 * engrRatio) + (0.9 * mgmtRatio) + (1.3 * rndRatio) +
(1.5 * opsRatio) + (busRatio); (1.5 * opsRatio) + (busRatio);
var sciMult = 1 + (Math.pow(industry.sciResearch.qty, industry.sciFac) / 800); const sciMult = 1 + (Math.pow(industry.sciResearch.qty, industry.sciFac) / 800);
var totalMult = progrMult * balanceMult * designMult * sciMult; const totalMult = progrMult * balanceMult * designMult * sciMult;
this.qlt = totalMult * ((0.10 * employeeProd[EmployeePositions.Engineer]) + this.qlt = totalMult * ((0.10 * employeeProd[EmployeePositions.Engineer]) +
(0.05 * employeeProd[EmployeePositions.Management]) + (0.05 * employeeProd[EmployeePositions.Management]) +
@ -189,14 +185,14 @@ export class Product {
(0.05 * employeeProd[EmployeePositions.Operations]) + (0.05 * employeeProd[EmployeePositions.Operations]) +
(0.05 * employeeProd[EmployeePositions.Business])); (0.05 * employeeProd[EmployeePositions.Business]));
this.calculateRating(industry); this.calculateRating(industry);
var advMult = 1 + (Math.pow(this.advCost, 0.1) / 100); const advMult = 1 + (Math.pow(this.advCost, 0.1) / 100);
this.mku = 100 / (advMult * Math.pow((this.qlt + 0.001), 0.65) * (busRatio + mgmtRatio)); this.mku = 100 / (advMult * Math.pow((this.qlt + 0.001), 0.65) * (busRatio + mgmtRatio));
this.dmd = industry.awareness === 0 ? 20 : Math.min(100, advMult * (100 * (industry.popularity / industry.awareness))); this.dmd = industry.awareness === 0 ? 20 : Math.min(100, advMult * (100 * (industry.popularity / industry.awareness)));
this.cmp = getRandomInt(0, 70); this.cmp = getRandomInt(0, 70);
//Calculate the product's required materials //Calculate the product's required materials
//For now, just set it to be the same as the requirements to make materials //For now, just set it to be the same as the requirements to make materials
for (var matName in industry.reqMats) { for (const matName in industry.reqMats) {
if (industry.reqMats.hasOwnProperty(matName)) { if (industry.reqMats.hasOwnProperty(matName)) {
this.reqMats[matName] = industry.reqMats[matName]; this.reqMats[matName] = industry.reqMats[matName];
} }
@ -205,7 +201,7 @@ export class Product {
//Calculate the product's size //Calculate the product's size
//For now, just set it to be the same size as the requirements to make materials //For now, just set it to be the same size as the requirements to make materials
this.siz = 0; this.siz = 0;
for (var matName in industry.reqMats) { for (const matName in industry.reqMats) {
this.siz += MaterialSizes[matName] * industry.reqMats[matName]; this.siz += MaterialSizes[matName] * industry.reqMats[matName];
} }
@ -240,6 +236,12 @@ export class Product {
toJSON(): any { toJSON(): any {
return Generic_toJSON("Product", this); return Generic_toJSON("Product", this);
} }
// Initiatizes a Product object from a JSON save state.
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Product {
return Generic_fromJSON(Product, value.data);
}
} }
Reviver.constructors.Product = Product; Reviver.constructors.Product = Product;

@ -10,7 +10,7 @@ export interface IProductRatingWeight {
Reliability?: number; Reliability?: number;
} }
export const ProductRatingWeights: IMap<object> = { export const ProductRatingWeights: IMap<any> = {
[Industries.Food]: { [Industries.Food]: {
Quality: 0.7, Quality: 0.7,
Durability: 0.1, Durability: 0.1,
@ -73,5 +73,5 @@ export const ProductRatingWeights: IMap<object> = {
Reliability: 0.1, Reliability: 0.1,
Aesthetics: 0.35, Aesthetics: 0.35,
Features: 0.1, Features: 0.1,
} },
} }

@ -16,25 +16,25 @@ export interface IConstructorParams {
export class Research { export class Research {
// Name of research. This will be used to identify researches in the Research Tree // Name of research. This will be used to identify researches in the Research Tree
name: string = ""; name = "";
// How much scientific research it costs to unlock this // How much scientific research it costs to unlock this
cost: number = 0; cost = 0;
// Description of what the Research does // Description of what the Research does
desc: string = ""; desc = "";
// All possible generic upgrades for the company, in the form of multipliers // All possible generic upgrades for the company, in the form of multipliers
advertisingMult: number = 1; advertisingMult = 1;
employeeChaMult: number = 1; employeeChaMult = 1;
employeeCreMult: number = 1; employeeCreMult = 1;
employeeEffMult: number = 1; employeeEffMult = 1;
employeeIntMult: number = 1; employeeIntMult = 1;
productionMult: number = 1; productionMult = 1;
productProductionMult: number = 1; productProductionMult = 1;
salesMult: number = 1; salesMult = 1;
sciResearchMult: number = 1; sciResearchMult = 1;
storageMult: number = 1; storageMult = 1;
constructor(p: IConstructorParams={name: "", cost: 0, desc: ""}) { constructor(p: IConstructorParams={name: "", cost: 0, desc: ""}) {
this.name = p.name; this.name = p.name;

@ -5,9 +5,9 @@ import { Research,
import { researchMetadata } from "./data/ResearchMetadata"; import { researchMetadata } from "./data/ResearchMetadata";
import { IMap } from "../types"; import { IMap } from "../types";
export let ResearchMap: IMap<Research> = {}; export const ResearchMap: IMap<Research> = {};
function addResearch(p: IConstructorParams) { function addResearch(p: IConstructorParams): void {
if (ResearchMap[p.name] != null) { if (ResearchMap[p.name] != null) {
console.warn(`Duplicate Research being defined: ${p.name}`); console.warn(`Duplicate Research being defined: ${p.name}`);
} }

@ -26,10 +26,10 @@ export class Node {
// How much Scientific Research is needed for this // How much Scientific Research is needed for this
// Necessary to show it on the UI // Necessary to show it on the UI
cost: number = 0; cost = 0;
// Whether or not this Research has been unlocked // Whether or not this Research has been unlocked
researched: boolean = false; researched = false;
// Parent node in the tree // Parent node in the tree
// The parent node defines the prerequisite Research (there can only be one) // The parent node defines the prerequisite Research (there can only be one)
@ -37,7 +37,7 @@ export class Node {
parent: Node | null = null; parent: Node | null = null;
// Name of the Research held in this Node // Name of the Research held in this Node
text: string = ""; text = "";
constructor(p: IConstructorParams = {cost: 0, text: ""}) { constructor(p: IConstructorParams = {cost: 0, text: ""}) {
if (ResearchMap[p.text] == null) { if (ResearchMap[p.text] == null) {
@ -56,21 +56,21 @@ export class Node {
} }
} }
addChild(n: Node) { addChild(n: Node): void {
this.children.push(n); this.children.push(n);
n.parent = this; n.parent = this;
} }
// Return an object that describes a TreantJS-compatible markup/config for this Node // Return an object that describes a TreantJS-compatible markup/config for this Node
// See: http://fperucic.github.io/treant-js/ // See: http://fperucic.github.io/treant-js/
createTreantMarkup(): object { createTreantMarkup(): any {
const childrenArray = []; const childrenArray = [];
for (let i = 0; i < this.children.length; ++i) { for (let i = 0; i < this.children.length; ++i) {
childrenArray.push(this.children[i].createTreantMarkup()); childrenArray.push(this.children[i].createTreantMarkup());
} }
// Determine what css class this Node should have in the diagram // Determine what css class this Node should have in the diagram
let htmlClass: string = ""; let htmlClass = "";
if (this.researched) { if (this.researched) {
htmlClass = "researched"; htmlClass = "researched";
} else if (this.parent && this.parent.researched === false) { } else if (this.parent && this.parent.researched === false) {
@ -109,7 +109,7 @@ export class Node {
return null; return null;
} }
setParent(n: Node) { setParent(n: Node): void {
this.parent = n; this.parent = n;
} }
} }
@ -124,11 +124,9 @@ export class ResearchTree {
// Root Node // Root Node
root: Node | null = null; root: Node | null = null;
constructor() {}
// Return an object that contains a Tree markup for TreantJS (using the JSON approach) // Return an object that contains a Tree markup for TreantJS (using the JSON approach)
// See: http://fperucic.github.io/treant-js/ // See: http://fperucic.github.io/treant-js/
createTreantMarkup(): object { createTreantMarkup(): any {
if (this.root == null) { return {}; } if (this.root == null) { return {}; }
const treeMarkup = this.root.createTreantMarkup(); const treeMarkup = this.root.createTreantMarkup();
@ -205,7 +203,7 @@ export class ResearchTree {
// Helper function for all the multiplier getter fns // Helper function for all the multiplier getter fns
getMultiplierHelper(propName: string): number { getMultiplierHelper(propName: string): number {
let res: number = 1; let res = 1;
if (this.root == null) { return res; } if (this.root == null) { return res; }
const queue: Node[] = []; const queue: Node[] = [];

@ -19,17 +19,13 @@ interface IConstructorParams {
} }
export class Warehouse { export class Warehouse {
// Initiatizes a Warehouse object from a JSON save state.
static fromJSON(value: any): Warehouse {
return Generic_fromJSON(Warehouse, value.data);
}
// Text that describes how the space in this Warehouse is being used // Text that describes how the space in this Warehouse is being used
// Used to create a tooltip in the UI // Used to create a tooltip in the UI
breakdown: string = ""; breakdown = "";
// Warehouse's level, which affects its maximum size // Warehouse's level, which affects its maximum size
level: number = 1; level = 1;
// City that this Warehouse is in // City that this Warehouse is in
loc: string; loc: string;
@ -41,19 +37,19 @@ export class Warehouse {
size: number; size: number;
// Amount of space currently used by warehouse // Amount of space currently used by warehouse
sizeUsed: number = 0; sizeUsed = 0;
// Whether Smart Supply is enabled for this Industry (the Industry that this Warehouse is for) // Whether Smart Supply is enabled for this Industry (the Industry that this Warehouse is for)
smartSupplyEnabled: boolean = false; smartSupplyEnabled = false;
// Flag that indicates whether Smart Supply accounts for imports when calculating // Flag that indicates whether Smart Supply accounts for imports when calculating
// the amount fo purchase // the amount fo purchase
smartSupplyConsiderExports: boolean = false; smartSupplyConsiderExports = false;
// Stores the amount of product to be produced. Used for Smart Supply unlock. // Stores the amount of product to be produced. Used for Smart Supply unlock.
// The production tracked by smart supply is always based on the previous cycle, // The production tracked by smart supply is always based on the previous cycle,
// so it will always trail the "true" production by 1 cycle // so it will always trail the "true" production by 1 cycle
smartSupplyStore: number = 0; smartSupplyStore = 0;
constructor(params: IConstructorParams = {}) { constructor(params: IConstructorParams = {}) {
this.loc = params.loc ? params.loc : ""; this.loc = params.loc ? params.loc : "";
@ -70,7 +66,7 @@ export class Warehouse {
Drugs: new Material({name: "Drugs"}), Drugs: new Material({name: "Drugs"}),
Robots: new Material({name: "Robots"}), Robots: new Material({name: "Robots"}),
AICores: new Material({name: "AI Cores"}), AICores: new Material({name: "AI Cores"}),
RealEstate: new Material({name: "Real Estate"}) RealEstate: new Material({name: "Real Estate"}),
} }
if (params.corp && params.industry) { if (params.corp && params.industry) {
@ -79,11 +75,11 @@ export class Warehouse {
} }
// Re-calculate how much space is being used by this Warehouse // Re-calculate how much space is being used by this Warehouse
updateMaterialSizeUsed() { updateMaterialSizeUsed(): void {
this.sizeUsed = 0; this.sizeUsed = 0;
this.breakdown = ""; this.breakdown = "";
for (const matName in this.materials) { for (const matName in this.materials) {
var mat = this.materials[matName]; const mat = this.materials[matName];
if (MaterialSizes.hasOwnProperty(matName)) { if (MaterialSizes.hasOwnProperty(matName)) {
this.sizeUsed += (mat.qty * MaterialSizes[matName]); this.sizeUsed += (mat.qty * MaterialSizes[matName]);
if (mat.qty > 0) { if (mat.qty > 0) {
@ -96,7 +92,7 @@ export class Warehouse {
} }
} }
updateSize(corporation: IParent, industry: IParent) { updateSize(corporation: IParent, industry: IParent): void {
try { try {
this.size = (this.level * 100) this.size = (this.level * 100)
* corporation.getStorageMultiplier() * corporation.getStorageMultiplier()
@ -110,6 +106,12 @@ export class Warehouse {
toJSON(): any { toJSON(): any {
return Generic_toJSON("Warehouse", this); return Generic_toJSON("Warehouse", this);
} }
// Initiatizes a Warehouse object from a JSON save state.
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Warehouse {
return Generic_fromJSON(Warehouse, value.data);
}
} }
Reviver.constructors.Warehouse = Warehouse; Reviver.constructors.Warehouse = Warehouse;

@ -82,7 +82,7 @@ export const researchMetadata: IConstructorParams[] = [
cost: 15e3, cost: 15e3,
desc: "Use automated software to handle the hiring of employees. With this " + desc: "Use automated software to handle the hiring of employees. With this " +
"research, each office will automatically hire one employee per " + "research, each office will automatically hire one employee per " +
"market cycle if there is available space." "market cycle if there is available space.",
}, },
{ {
@ -90,7 +90,7 @@ export const researchMetadata: IConstructorParams[] = [
cost: 20e3, cost: 20e3,
desc: "Use automated software to handle the training of employees. With this " + desc: "Use automated software to handle the training of employees. With this " +
"research, each employee hired with HRBuddy-Recruitment will automatically " + "research, each employee hired with HRBuddy-Recruitment will automatically " +
"be assigned to 'Training', rather than being unassigned." "be assigned to 'Training', rather than being unassigned.",
}, },
{ {
name: "JoyWire", name: "JoyWire",

@ -17,6 +17,4 @@ export class BaseReactComponent extends Component {
routing() { routing() {
return this.props.routing; return this.props.routing;
} }
render() {}
} }

@ -16,7 +16,7 @@ import { Corporation,
import { Industries, import { Industries,
IndustryStartingCosts, IndustryStartingCosts,
IndustryDescriptions, IndustryDescriptions,
IndustryResearchTrees } from "../IndustryData"; } from "../IndustryData";
import { MaterialSizes } from "../MaterialSizes"; import { MaterialSizes } from "../MaterialSizes";
@ -61,13 +61,13 @@ export class CorporationEventHandler {
createBribeFactionsPopup() { createBribeFactionsPopup() {
const popupId = "cmpy-mgmt-bribe-factions-popup"; const popupId = "cmpy-mgmt-bribe-factions-popup";
const txt = createElement("p", { const txt = createElement("p", {
innerText:"You can use Corporation funds or stock shares to bribe Faction Leaders in exchange for faction reputation" innerText:"You can use Corporation funds or stock shares to bribe Faction Leaders in exchange for faction reputation",
}); });
const factionSelector = createElement("select", { margin:"3px" }); const factionSelector = createElement("select", { margin:"3px" });
for (let i = 0; i < Player.factions.length; ++i) { for (let i = 0; i < Player.factions.length; ++i) {
const facName = Player.factions[i]; const facName = Player.factions[i];
factionSelector.add(createElement("option", { factionSelector.add(createElement("option", {
text: facName, value: facName text: facName, value: facName,
})); }));
} }
var repGainText = createElement("p"); var repGainText = createElement("p");
@ -93,7 +93,7 @@ export class CorporationEventHandler {
factionSelector.options[factionSelector.selectedIndex].value + factionSelector.options[factionSelector.selectedIndex].value +
" with this bribe"; " with this bribe";
} }
} },
}); });
stockSharesInput = createElement("input", { stockSharesInput = createElement("input", {
type:"number", placeholder:"Stock Shares", margin: "5px", type:"number", placeholder:"Stock Shares", margin: "5px",
@ -115,7 +115,7 @@ export class CorporationEventHandler {
factionSelector.options[factionSelector.selectedIndex].value + factionSelector.options[factionSelector.selectedIndex].value +
" with this bribe"; " with this bribe";
} }
} },
}); });
var confirmButton = createElement("button", { var confirmButton = createElement("button", {
class:"a-link-button", innerText:"Bribe", display:"inline-block", class:"a-link-button", innerText:"Bribe", display:"inline-block",
@ -145,7 +145,7 @@ export class CorporationEventHandler {
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} }
} },
}); });
const cancelButton = createPopupCloseButton(popupId, { const cancelButton = createPopupCloseButton(popupId, {
class: "std-button", class: "std-button",
@ -187,7 +187,7 @@ export class CorporationEventHandler {
costIndicator.innerText = "Purchase " + numShares + " shares for a total of " + costIndicator.innerText = "Purchase " + numShares + " shares for a total of " +
numeralWrapper.format(numShares * buybackPrice, '$0.000a'); numeralWrapper.format(numShares * buybackPrice, '$0.000a');
} }
} },
}); });
var confirmBtn = createElement("button", { var confirmBtn = createElement("button", {
class:"a-link-button", innerText:"Buy shares", display:"inline-block", class:"a-link-button", innerText:"Buy shares", display:"inline-block",
@ -221,7 +221,7 @@ export class CorporationEventHandler {
} }
return false; return false;
} },
}); });
var cancelBtn = createPopupCloseButton(popupId, { var cancelBtn = createPopupCloseButton(popupId, {
class: "std-button", class: "std-button",
@ -249,7 +249,7 @@ export class CorporationEventHandler {
removeElementById(popupId); removeElementById(popupId);
this.rerender(); this.rerender();
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" }); const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" });
@ -264,7 +264,7 @@ export class CorporationEventHandler {
const exportTxt = createElement("p", { const exportTxt = createElement("p", {
innerText:"Select the industry and city to export this material to, as well as " + innerText:"Select the industry and city to export this material to, as well as " +
"how much of this material to export per second. You can set the export " + "how much of this material to export per second. You can set the export " +
"amount to 'MAX' to export all of the materials in this warehouse." "amount to 'MAX' to export all of the materials in this warehouse.",
}); });
//Select industry and city to export to //Select industry and city to export to
@ -286,7 +286,7 @@ export class CorporationEventHandler {
return; return;
} }
} }
} },
}); });
for (let i = 0; i < corp.divisions.length; ++i) { for (let i = 0; i < corp.divisions.length; ++i) {
@ -299,7 +299,7 @@ export class CorporationEventHandler {
//Select amount to export //Select amount to export
const exportAmount = createElement("input", { const exportAmount = createElement("input", {
class: "text-input", class: "text-input",
placeholder:"Export amount / s" placeholder:"Export amount / s",
}); });
const exportBtn = createElement("button", { const exportBtn = createElement("button", {
@ -328,14 +328,14 @@ export class CorporationEventHandler {
mat.exp.push(exportObj); mat.exp.push(exportObj);
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" }); const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" });
const currExportsText = createElement("p", { const currExportsText = createElement("p", {
innerText:"Below is a list of all current exports of this material from this warehouse. " + innerText:"Below is a list of all current exports of this material from this warehouse. " +
"Clicking on one of the exports below will REMOVE that export." "Clicking on one of the exports below will REMOVE that export.",
}); });
const currExports = []; const currExports = [];
for (var i = 0; i < mat.exp.length; ++i) { for (var i = 0; i < mat.exp.length; ++i) {
@ -349,7 +349,7 @@ export class CorporationEventHandler {
mat.exp.splice(i, 1); //Remove export object mat.exp.splice(i, 1); //Remove export object
removeElementById(popupId); removeElementById(popupId);
createExportMaterialPopup(mat); createExportMaterialPopup(mat);
} },
})); }));
})(i, mat, currExports); })(i, mat, currExports);
} }
@ -385,7 +385,7 @@ export class CorporationEventHandler {
onkeyup: (e) => { onkeyup: (e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {allocateBtn.click();} if (e.keyCode === KEY.ENTER) {allocateBtn.click();}
} },
}); });
allocateBtn = createElement("button", { allocateBtn = createElement("button", {
@ -404,7 +404,7 @@ export class CorporationEventHandler {
this.rerender(); this.rerender();
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { const cancelBtn = createPopupCloseButton(popupId, {
@ -478,7 +478,7 @@ export class CorporationEventHandler {
} else { } else {
updateDynamicText(this.corp); updateDynamicText(this.corp);
} }
} },
}); });
issueBtn = createElement("button", { issueBtn = createElement("button", {
@ -523,7 +523,7 @@ export class CorporationEventHandler {
this.rerender(); this.rerender();
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { const cancelBtn = createPopupCloseButton(popupId, {
@ -541,7 +541,7 @@ export class CorporationEventHandler {
const popupId = "cmpy-mgmt-limit-product-production-popup"; const popupId = "cmpy-mgmt-limit-product-production-popup";
const txt = createElement("p", { const txt = createElement("p", {
innerText:"Enter a limit to the amount of this product you would " + innerText:"Enter a limit to the amount of this product you would " +
"like to product per second. Leave the box empty to set no limit." "like to product per second. Leave the box empty to set no limit.",
}); });
let confirmBtn; let confirmBtn;
const input = createElement("input", { const input = createElement("input", {
@ -551,7 +551,7 @@ export class CorporationEventHandler {
onkeyup: (e) => { onkeyup: (e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) { confirmBtn.click(); } if (e.keyCode === KEY.ENTER) { confirmBtn.click(); }
} },
}); });
confirmBtn = createElement("button", { confirmBtn = createElement("button", {
class: "std-button", class: "std-button",
@ -578,7 +578,7 @@ export class CorporationEventHandler {
removeElementById(popupId); removeElementById(popupId);
this.rerender(); this.rerender();
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" }); const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" });
cancelBtn.style.margin = "6px"; cancelBtn.style.margin = "6px";
@ -600,7 +600,7 @@ export class CorporationEventHandler {
if (division.offices[cityName] instanceof OfficeSpace) { if (division.offices[cityName] instanceof OfficeSpace) {
designCity.add(createElement("option", { designCity.add(createElement("option", {
value: cityName, value: cityName,
text: cityName text: cityName,
})); }));
} }
} }
@ -630,7 +630,7 @@ export class CorporationEventHandler {
onkeyup: (e) => { onkeyup: (e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) { confirmBtn.click(); } if (e.keyCode === KEY.ENTER) { confirmBtn.click(); }
} },
}); });
confirmBtn = createElement("button", { confirmBtn = createElement("button", {
class: "std-button", class: "std-button",
@ -665,7 +665,7 @@ export class CorporationEventHandler {
} }
this.rerender(); this.rerender();
return false; return false;
} },
}) })
const cancelBtn = createPopupCloseButton(popupId, { const cancelBtn = createPopupCloseButton(popupId, {
class: "std-button", class: "std-button",
@ -679,8 +679,6 @@ export class CorporationEventHandler {
// 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
createMaterialMarketTaPopup(mat, industry) { createMaterialMarketTaPopup(mat, industry) {
const corp = this.corp;
const popupId = "cmpy-mgmt-marketta-popup"; const popupId = "cmpy-mgmt-marketta-popup";
const markupLimit = mat.getMarkupLimit(); const markupLimit = mat.getMarkupLimit();
const ta1 = createElement("p", { const ta1 = createElement("p", {
@ -699,7 +697,7 @@ export class CorporationEventHandler {
for: useTa1AutoSaleId, for: useTa1AutoSaleId,
innerText: "Use Market-TA.I for Auto-Sale Price", innerText: "Use Market-TA.I for Auto-Sale Price",
tooltip: "If this is enabled, then this Material will automatically " + tooltip: "If this is enabled, then this Material will automatically " +
"be sold at the price identified by Market-TA.I (i.e. the price shown above)" "be sold at the price identified by Market-TA.I (i.e. the price shown above)",
}) })
const useTa1AutoSaleCheckbox = createElement("input", { const useTa1AutoSaleCheckbox = createElement("input", {
checked: mat.marketTa1, checked: mat.marketTa1,
@ -708,7 +706,7 @@ export class CorporationEventHandler {
type: "checkbox", type: "checkbox",
changeListener: (e) => { changeListener: (e) => {
mat.marketTa1 = e.target.checked; mat.marketTa1 = e.target.checked;
} },
}); });
useTa1AutoSaleDiv.appendChild(useTa1AutoSaleLabel); useTa1AutoSaleDiv.appendChild(useTa1AutoSaleLabel);
useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox); useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox);
@ -766,7 +764,7 @@ export class CorporationEventHandler {
tooltip: "If this is enabled, then this Material will automatically " + tooltip: "If this is enabled, then this Material will automatically " +
"be sold at the optimal price such that the amount sold matches the " + "be sold at the optimal price such that the amount sold matches the " +
"amount produced. (i.e. the highest possible price, while still ensuring " + "amount produced. (i.e. the highest possible price, while still ensuring " +
" that all produced materials will be sold)" " that all produced materials will be sold)",
}) })
const useTa2AutoSaleCheckbox = createElement("input", { const useTa2AutoSaleCheckbox = createElement("input", {
checked: mat.marketTa2, checked: mat.marketTa2,
@ -775,14 +773,14 @@ export class CorporationEventHandler {
type: "checkbox", type: "checkbox",
changeListener: (e) => { changeListener: (e) => {
mat.marketTa2 = e.target.checked; mat.marketTa2 = e.target.checked;
} },
}); });
useTa2AutoSaleDiv.appendChild(useTa2AutoSaleLabel); useTa2AutoSaleDiv.appendChild(useTa2AutoSaleLabel);
useTa2AutoSaleDiv.appendChild(useTa2AutoSaleCheckbox); useTa2AutoSaleDiv.appendChild(useTa2AutoSaleCheckbox);
const ta2OverridesTa1 = createElement("p", { const ta2OverridesTa1 = createElement("p", {
innerText: "Note that Market-TA.II overrides Market-TA.I. This means that if " + innerText: "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" "both are enabled, then Market-TA.II will take effect, not Market-TA.I",
}); });
createPopup(popupId, [ta1, useTa1AutoSaleDiv, ta2Text, ta2Input, useTa2AutoSaleDiv, ta2OverridesTa1, closeBtn]); createPopup(popupId, [ta1, useTa1AutoSaleDiv, ta2Text, ta2Input, useTa2AutoSaleDiv, ta2OverridesTa1, closeBtn]);
@ -805,7 +803,7 @@ export class CorporationEventHandler {
if (!(division.offices[cityName] instanceof OfficeSpace)) { if (!(division.offices[cityName] instanceof OfficeSpace)) {
citySelector.add(createElement("option", { citySelector.add(createElement("option", {
text: cityName, text: cityName,
value: cityName value: cityName,
})); }));
} }
} }
@ -832,7 +830,7 @@ export class CorporationEventHandler {
removeElementById(popupId); removeElementById(popupId);
this.rerender(); this.rerender();
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { const cancelBtn = createPopupCloseButton(popupId, {
class: "std-button", class: "std-button",
@ -852,7 +850,7 @@ export class CorporationEventHandler {
innerHTML: "Create a new division to expand into a new industry:", innerHTML: "Create a new division to expand into a new industry:",
}); });
var selector = createElement("select", { var selector = createElement("select", {
class:"dropdown" class:"dropdown",
}); });
var industryDescription = createElement("p", {}); var industryDescription = createElement("p", {});
var yesBtn; var yesBtn;
@ -866,11 +864,11 @@ export class CorporationEventHandler {
onkeyup:(e)=>{ onkeyup:(e)=>{
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {yesBtn.click();} if (e.keyCode === KEY.ENTER) {yesBtn.click();}
} },
}); });
var nameLabel = createElement("label", { var nameLabel = createElement("label", {
for:"cmpy-mgmt-expand-industry-name-input", for:"cmpy-mgmt-expand-industry-name-input",
innerText:"Division name: " innerText:"Division name: ",
}); });
yesBtn = createElement("span", { yesBtn = createElement("span", {
class:"popup-box-button", class:"popup-box-button",
@ -905,7 +903,7 @@ export class CorporationEventHandler {
this.rerender(); this.rerender();
} }
return false; return false;
} },
}); });
const noBtn = createPopupCloseButton(popupId, { const noBtn = createPopupCloseButton(popupId, {
@ -923,7 +921,7 @@ export class CorporationEventHandler {
// Have Agriculture be first as recommended option // Have Agriculture be first as recommended option
if (!ownedIndustries["Agriculture"]) { if (!ownedIndustries["Agriculture"]) {
selector.add(createElement("option", { selector.add(createElement("option", {
text:Industries["Agriculture"], value:"Agriculture" text:Industries["Agriculture"], value:"Agriculture",
})); }));
} }
@ -964,8 +962,6 @@ export class CorporationEventHandler {
// 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
createProductMarketTaPopup(product, industry) { createProductMarketTaPopup(product, industry) {
const corp = this.corp;
const popupId = "cmpy-mgmt-marketta-popup"; const popupId = "cmpy-mgmt-marketta-popup";
const markupLimit = product.rat / product.mku; const markupLimit = product.rat / product.mku;
const ta1 = createElement("p", { const ta1 = createElement("p", {
@ -984,7 +980,7 @@ export class CorporationEventHandler {
for: useTa1AutoSaleId, for: useTa1AutoSaleId,
innerText: "Use Market-TA.I for Auto-Sale Price", innerText: "Use Market-TA.I for Auto-Sale Price",
tooltip: "If this is enabled, then this Product will automatically " + tooltip: "If this is enabled, then this Product will automatically " +
"be sold at the price identified by Market-TA.I (i.e. the price shown above)" "be sold at the price identified by Market-TA.I (i.e. the price shown above)",
}) })
const useTa1AutoSaleCheckbox = createElement("input", { const useTa1AutoSaleCheckbox = createElement("input", {
checked: product.marketTa1, checked: product.marketTa1,
@ -993,7 +989,7 @@ export class CorporationEventHandler {
type: "checkbox", type: "checkbox",
changeListener: (e) => { changeListener: (e) => {
product.marketTa1 = e.target.checked; product.marketTa1 = e.target.checked;
} },
}); });
useTa1AutoSaleDiv.appendChild(useTa1AutoSaleLabel); useTa1AutoSaleDiv.appendChild(useTa1AutoSaleLabel);
useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox); useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox);
@ -1043,7 +1039,7 @@ export class CorporationEventHandler {
tooltip: "If this is enabled, then this Product will automatically " + tooltip: "If this is enabled, then this Product will automatically " +
"be sold at the optimal price such that the amount sold matches the " + "be sold at the optimal price such that the amount sold matches the " +
"amount produced. (i.e. the highest possible price, while still ensuring " + "amount produced. (i.e. the highest possible price, while still ensuring " +
" that all produced materials will be sold)" " that all produced materials will be sold)",
}) })
const useTa2AutoSaleCheckbox = createElement("input", { const useTa2AutoSaleCheckbox = createElement("input", {
checked: product.marketTa2, checked: product.marketTa2,
@ -1052,14 +1048,14 @@ export class CorporationEventHandler {
type: "checkbox", type: "checkbox",
changeListener: (e) => { changeListener: (e) => {
product.marketTa2 = e.target.checked; product.marketTa2 = e.target.checked;
} },
}); });
useTa2AutoSaleDiv.appendChild(useTa2AutoSaleLabel); useTa2AutoSaleDiv.appendChild(useTa2AutoSaleLabel);
useTa2AutoSaleDiv.appendChild(useTa2AutoSaleCheckbox); useTa2AutoSaleDiv.appendChild(useTa2AutoSaleCheckbox);
const ta2OverridesTa1 = createElement("p", { const ta2OverridesTa1 = createElement("p", {
innerText: "Note that Market-TA.II overrides Market-TA.I. This means that if " + innerText: "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" "both are enabled, then Market-TA.II will take effect, not Market-TA.I",
}); });
createPopup(popupId, [ta1, useTa1AutoSaleDiv, ta2Text, ta2Input, useTa2AutoSaleDiv, ta2OverridesTa1, closeBtn]); createPopup(popupId, [ta1, useTa1AutoSaleDiv, ta2Text, ta2Input, useTa2AutoSaleDiv, ta2OverridesTa1, closeBtn]);
@ -1076,7 +1072,7 @@ export class CorporationEventHandler {
const purchasePopupId = "cmpy-mgmt-material-purchase-popup"; const purchasePopupId = "cmpy-mgmt-material-purchase-popup";
const txt = createElement("p", { const txt = createElement("p", {
innerHTML: "Enter the amount of " + mat.name + " you would like " + innerHTML: "Enter the amount of " + mat.name + " you would like " +
"to purchase per second. This material's cost changes constantly" "to purchase per second. This material's cost changes constantly",
}); });
let confirmBtn; let confirmBtn;
let input = createElement("input", { let input = createElement("input", {
@ -1087,7 +1083,7 @@ export class CorporationEventHandler {
onkeyup: (e) => { onkeyup: (e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();} if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
} },
}); });
confirmBtn = createElement("button", { confirmBtn = createElement("button", {
innerText: "Confirm", class: "std-button", innerText: "Confirm", class: "std-button",
@ -1101,7 +1097,7 @@ export class CorporationEventHandler {
this.rerender(); this.rerender();
return false; return false;
} }
} },
}); });
const clearButton = createElement("button", { const clearButton = createElement("button", {
innerText: "Clear Purchase", class: "std-button", innerText: "Clear Purchase", class: "std-button",
@ -1110,7 +1106,7 @@ export class CorporationEventHandler {
removeElementById(purchasePopupId); removeElementById(purchasePopupId);
this.rerender(); this.rerender();
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(purchasePopupId, { const cancelBtn = createPopupCloseButton(purchasePopupId, {
class: "std-button", class: "std-button",
@ -1153,7 +1149,7 @@ export class CorporationEventHandler {
e.preventDefault(); e.preventDefault();
updateBulkPurchaseText(e.target.value); updateBulkPurchaseText(e.target.value);
if (e.keyCode === KEY.ENTER) {bulkPurchaseConfirmBtn.click();} if (e.keyCode === KEY.ENTER) {bulkPurchaseConfirmBtn.click();}
} },
}); });
bulkPurchaseConfirmBtn = createElement("button", { bulkPurchaseConfirmBtn = createElement("button", {
@ -1184,7 +1180,7 @@ export class CorporationEventHandler {
removeElementById(purchasePopupId); removeElementById(purchasePopupId);
return false; return false;
} }
} },
}) })
elems.push(bulkPurchaseInfo); elems.push(bulkPurchaseInfo);
@ -1224,7 +1220,7 @@ export class CorporationEventHandler {
onkeyup: (e) => { onkeyup: (e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();} if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
} },
}); });
let inputButtonInitValue = mat.sCost ? mat.sCost : null; let inputButtonInitValue = mat.sCost ? mat.sCost : null;
@ -1241,7 +1237,7 @@ export class CorporationEventHandler {
onkeyup: (e) => { onkeyup: (e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();} if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
} },
}); });
confirmBtn = createElement("button", { confirmBtn = createElement("button", {
class: "std-button", class: "std-button",
@ -1307,7 +1303,7 @@ export class CorporationEventHandler {
removeElementById(sellPopupId); removeElementById(sellPopupId);
this.rerender(); this.rerender();
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(sellPopupId, { const cancelBtn = createPopupCloseButton(sellPopupId, {
class: "std-button", class: "std-button",
@ -1347,7 +1343,7 @@ export class CorporationEventHandler {
onkeyup: (e) => { onkeyup: (e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();} if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
} },
}); });
let inputButtonInitValue = product.sCost ? product.sCost : null; let inputButtonInitValue = product.sCost ? product.sCost : null;
@ -1365,7 +1361,7 @@ export class CorporationEventHandler {
onkeyup: (e) => { onkeyup: (e) => {
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();} if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
} },
}); });
const checkboxDiv = createElement("div", { const checkboxDiv = createElement("div", {
border: "1px solid white", border: "1px solid white",
@ -1478,7 +1474,7 @@ export class CorporationEventHandler {
removeElementById(popupId); removeElementById(popupId);
this.rerender(); this.rerender();
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { class: "std-button" }); const cancelBtn = createPopupCloseButton(popupId, { class: "std-button" });
@ -1515,12 +1511,10 @@ export class CorporationEventHandler {
} else { } else {
const stockSaleResults = this.corp.calculateShareSale(numShares); const stockSaleResults = this.corp.calculateShareSale(numShares);
const profit = stockSaleResults[0]; const profit = stockSaleResults[0];
const newSharePrice = stockSaleResults[1];
const newSharesUntilUpdate = stockSaleResults[2];
profitIndicator.innerText = "Sell " + numShares + " shares for a total of " + profitIndicator.innerText = "Sell " + numShares + " shares for a total of " +
numeralWrapper.format(profit, '$0.000a'); numeralWrapper.format(profit, '$0.000a');
} }
} },
}); });
const confirmBtn = createElement("button", { const confirmBtn = createElement("button", {
class:"a-link-button", innerText:"Sell shares", display:"inline-block", class:"a-link-button", innerText:"Sell shares", display:"inline-block",
@ -1562,7 +1556,7 @@ export class CorporationEventHandler {
return false; return false;
} }
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { const cancelBtn = createPopupCloseButton(popupId, {
class: "std-button", class: "std-button",
@ -1579,10 +1573,10 @@ export class CorporationEventHandler {
const popupId = "cmpy-mgmt-throw-office-party-popup"; const popupId = "cmpy-mgmt-throw-office-party-popup";
const txt = createElement("p", { const txt = createElement("p", {
innerText:"Enter the amount of money you would like to spend PER EMPLOYEE " + innerText:"Enter the amount of money you would like to spend PER EMPLOYEE " +
"on this office party" "on this office party",
}); });
const totalCostTxt = createElement("p", { const totalCostTxt = createElement("p", {
innerText:"Throwing this party will cost a total of $0" innerText:"Throwing this party will cost a total of $0",
}); });
let confirmBtn; let confirmBtn;
const input = createElement("input", { const input = createElement("input", {
@ -1598,7 +1592,7 @@ export class CorporationEventHandler {
onkeyup:(e)=>{ onkeyup:(e)=>{
e.preventDefault(); e.preventDefault();
if (e.keyCode === KEY.ENTER) {confirmBtn.click();} if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
} },
}); });
confirmBtn = createElement("button", { confirmBtn = createElement("button", {
class: "std-button", class: "std-button",
@ -1622,7 +1616,7 @@ export class CorporationEventHandler {
} }
} }
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { class: "std-button", innerText: "Cancel" }); const cancelBtn = createPopupCloseButton(popupId, { class: "std-button", innerText: "Cancel" });
@ -1661,7 +1655,7 @@ export class CorporationEventHandler {
const upgradeCostMax = OfficeInitialCost * mult; const upgradeCostMax = OfficeInitialCost * mult;
const text = createElement("p", { const text = createElement("p", {
innerText:"Increase the size of your office space to fit additional employees!" innerText:"Increase the size of your office space to fit additional employees!",
}); });
const text2 = createElement("p", { innerText: "Upgrade size: " }); const text2 = createElement("p", { innerText: "Upgrade size: " });
@ -1680,7 +1674,7 @@ export class CorporationEventHandler {
} }
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} },
}); });
const confirmBtn15 = createElement("button", { const confirmBtn15 = createElement("button", {
class: this.corp.funds.lt(upgradeCost15) ? "a-link-button-inactive" : "a-link-button", class: this.corp.funds.lt(upgradeCost15) ? "a-link-button-inactive" : "a-link-button",
@ -1697,7 +1691,7 @@ export class CorporationEventHandler {
} }
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} },
}); });
const confirmBtnMax = createElement("button", { const confirmBtnMax = createElement("button", {
class:this.corp.funds.lt(upgradeCostMax) ? "a-link-button-inactive" : "a-link-button", class:this.corp.funds.lt(upgradeCostMax) ? "a-link-button-inactive" : "a-link-button",
@ -1714,7 +1708,7 @@ export class CorporationEventHandler {
} }
removeElementById(popupId); removeElementById(popupId);
return false; return false;
} },
}); });
const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" }); const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" });
cancelBtn.style.margin = "4px"; cancelBtn.style.margin = "4px";

@ -4,8 +4,6 @@
import React from "react"; import React from "react";
import { BaseReactComponent } from "./BaseReactComponent"; import { BaseReactComponent } from "./BaseReactComponent";
import { overviewPage } from "./Routing";
function HeaderTab(props) { function HeaderTab(props) {
let className = "cmpy-mgmt-header-tab"; let className = "cmpy-mgmt-header-tab";
if (props.current) { if (props.current) {
@ -71,7 +69,7 @@ export class HeaderTabs extends BaseReactComponent {
{ {
this.renderTab({ this.renderTab({
onClick: this.eventHandler().createNewIndustryPopup.bind(this.eventHandler()), onClick: this.eventHandler().createNewIndustryPopup.bind(this.eventHandler()),
text: "Expand into new Industry" text: "Expand into new Industry",
}) })
} }
</div> </div>

@ -62,7 +62,6 @@ export class IndustryOffice extends BaseReactComponent {
// Calculate how many NEW emplyoees we need to account for // Calculate how many NEW emplyoees we need to account for
const currentNumEmployees = office.employees.length; const currentNumEmployees = office.employees.length;
const newEmployees = currentNumEmployees - this.state.numEmployees;
// Record the number of employees in each position, for NEW employees only // Record the number of employees in each position, for NEW employees only
for (let i = this.state.numEmployees; i < office.employees.length; ++i) { for (let i = this.state.numEmployees; i < office.employees.length; ++i) {

@ -12,7 +12,6 @@ import { createProgressBarText } from "../../../utils/helpers/createProgressB
export class IndustryOverview extends BaseReactComponent { export class IndustryOverview extends BaseReactComponent {
renderMakeProductButton() { renderMakeProductButton() {
const corp = this.corp();
const division = this.routing().currentDivision; // Validated inside render() const division = this.routing().currentDivision; // Validated inside render()
var createProductButtonText, createProductPopupText; var createProductButtonText, createProductPopupText;
@ -97,7 +96,6 @@ export class IndustryOverview extends BaseReactComponent {
const popularity = `Popularity: ${numeralWrapper.format(division.popularity, "0.000")}`; const popularity = `Popularity: ${numeralWrapper.format(division.popularity, "0.000")}`;
let advertisingInfo = false; let advertisingInfo = false;
let advertisingTooltip;
const advertisingFactors = division.getAdvertisingFactors(); const advertisingFactors = division.getAdvertisingFactors();
const awarenessFac = advertisingFactors[1]; const awarenessFac = advertisingFactors[1];
const popularityFac = advertisingFactors[2]; const popularityFac = advertisingFactors[2];

@ -19,7 +19,6 @@ import { isString } from "../../../utils/helpers/isString";
function ProductComponent(props) { function ProductComponent(props) {
const corp = props.corp; const corp = props.corp;
const division = props.division; const division = props.division;
const warehouse = props.warehouse;
const city = props.city; const city = props.city;
const product = props.product; const product = props.product;
const eventHandler = props.eventHandler; const eventHandler = props.eventHandler;
@ -203,15 +202,6 @@ function MaterialComponent(props) {
// Total gain or loss of this material (per second) // Total gain or loss of this material (per second)
const totalGain = mat.buy + mat.prd + mat.imp - mat.sll - mat.totalExp; const totalGain = mat.buy + mat.prd + mat.imp - mat.sll - mat.totalExp;
// Competition and demand info, if they're unlocked
let cmpAndDmdText = "";
if (corp.unlockUpgrades[2] === 1) {
cmpAndDmdText += "<br>Demand: " + numeralWrapper.format(mat.dmd, nf);
}
if (corp.unlockUpgrades[3] === 1) {
cmpAndDmdText += "<br>Competition: " + numeralWrapper.format(mat.cmp, nf);
}
// Flag that determines whether this industry is "new" and the current material should be // Flag that determines whether this industry is "new" and the current material should be
// marked with flashing-red lights // marked with flashing-red lights
const tutorial = division.newInd && Object.keys(division.reqMats).includes(mat.name) && const tutorial = division.newInd && Object.keys(division.reqMats).includes(mat.name) &&
@ -511,7 +501,6 @@ export class IndustryWarehouse extends BaseReactComponent {
} }
render() { render() {
const corp = this.corp();
const division = this.routing().currentDivision; const division = this.routing().currentDivision;
if (division == null) { if (division == null) {
throw new Error(`Routing does not hold reference to the current Industry`); throw new Error(`Routing does not hold reference to the current Industry`);

@ -7,7 +7,6 @@ import { BaseReactComponent } from "./BaseReactComponent";
import { CityTabs } from "./CityTabs"; import { CityTabs } from "./CityTabs";
import { Industry } from "./Industry"; import { Industry } from "./Industry";
import { Overview } from "./Overview"; import { Overview } from "./Overview";
import { overviewPage } from "./Routing";
import { OfficeSpace } from "../Corporation"; import { OfficeSpace } from "../Corporation";

@ -158,7 +158,7 @@ export class Overview extends BaseReactComponent {
onClick: findInvestorsOnClick, onClick: findInvestorsOnClick,
style: "inline-block", style: "inline-block",
text: "Find Investors", text: "Find Investors",
tooltip: findInvestorsTooltip tooltip: findInvestorsTooltip,
}); });
const goPublicBtn = this.createButton({ const goPublicBtn = this.createButton({
class: "std-button", class: "std-button",
@ -167,7 +167,7 @@ export class Overview extends BaseReactComponent {
text: "Go Public", text: "Go Public",
tooltip: "Become a publicly traded and owned entity. Going public " + tooltip: "Become a publicly traded and owned entity. Going public " +
"involves issuing shares for an IPO. Once you are a public " + "involves issuing shares for an IPO. Once you are a public " +
"company, your shares will be traded on the stock market." "company, your shares will be traded on the stock market.",
}); });
return ( return (

@ -1,15 +1,27 @@
import { IMap } from "../../types"; import { IMap } from "../../types";
export const overviewPage: string = "Overview"; export const overviewPage = "Overview";
// Interfaces for whatever's required to sanitize routing with Corporation Data // Interfaces for whatever's required to sanitize routing with Corporation Data
interface IOfficeSpace { interface IOfficeSpace {
loc: string;
cost: number;
size: number;
comf: number;
beau: number;
tier: any;
minEne: number;
maxEne: number;
minHap: number;
maxHap: number;
maxMor: number;
employees: any;
employeeProd: any;
} }
interface IDivision { interface IDivision {
name: string; name: string;
offices: IMap<IOfficeSpace> offices: IMap<IOfficeSpace>;
} }
interface ICorporation { interface ICorporation {
@ -76,7 +88,7 @@ export class CorporationRouting {
for (let i = 0; i < this.corp.divisions.length; ++i) { for (let i = 0; i < this.corp.divisions.length; ++i) {
if (this.corp.divisions[i].name === page) { if (this.corp.divisions[i].name === page) {
this.currentDivision = this.corp.divisions[i]; this.currentDivision = this.corp.divisions[i];
}; }
} }
// 'currentDivision' should not be null, since the routing is either on // 'currentDivision' should not be null, since the routing is either on

@ -22,49 +22,49 @@ export interface IConstructorParams {
export class Crime { export class Crime {
// Number representing the difficulty of the crime. Used for success chance calculations // Number representing the difficulty of the crime. Used for success chance calculations
difficulty: number = 0; difficulty = 0;
// Amount of karma lost for SUCCESSFULLY committing this crime // Amount of karma lost for SUCCESSFULLY committing this crime
karma: number = 0; karma = 0;
// How many people die as a result of this crime // How many people die as a result of this crime
kills: number = 0; kills = 0;
// How much money is given by the // How much money is given by the
money: number = 0; money = 0;
// Name of crime // Name of crime
name: string = ""; name = "";
// Milliseconds it takes to attempt the crime // Milliseconds it takes to attempt the crime
time: number = 0; time = 0;
// Corresponding type in CONSTANTS. Contains a description for the crime activity // Corresponding type in CONSTANTS. Contains a description for the crime activity
type: string = ""; type = "";
// Weighting factors that determine how stats affect the success rate of this crime // Weighting factors that determine how stats affect the success rate of this crime
hacking_success_weight: number = 0; hacking_success_weight = 0;
strength_success_weight: number = 0; strength_success_weight = 0;
defense_success_weight: number = 0; defense_success_weight = 0;
dexterity_success_weight: number = 0; dexterity_success_weight = 0;
agility_success_weight: number = 0; agility_success_weight = 0;
charisma_success_weight: number = 0; charisma_success_weight = 0;
// How much stat experience is granted by this crime // How much stat experience is granted by this crime
hacking_exp: number = 0; hacking_exp = 0;
strength_exp: number = 0; strength_exp = 0;
defense_exp: number = 0; defense_exp = 0;
dexterity_exp: number = 0; dexterity_exp = 0;
agility_exp: number = 0; agility_exp = 0;
charisma_exp: number = 0; charisma_exp = 0;
intelligence_exp: number = 0; intelligence_exp = 0;
constructor(name: string = "", constructor(name = "",
type: string = "", type = "",
time: number = 0, time = 0,
money: number = 0, money = 0,
difficulty: number = 0, difficulty = 0,
karma: number = 0, karma = 0,
params: IConstructorParams={}) { params: IConstructorParams={}) {
this.name = name; this.name = name;
this.type = type; this.type = type;
@ -91,7 +91,7 @@ export class Crime {
this.kills = params.kills ? params.kills : 0; this.kills = params.kills ? params.kills : 0;
} }
commit(p: IPlayer, div: number=1, singParams: any=null): number { commit(p: IPlayer, div=1, singParams: any=null): number {
if (div <= 0) { div = 1; } if (div <= 0) { div = 1; }
p.startCrime( p.startCrime(
this.type, this.type,
@ -103,7 +103,7 @@ export class Crime {
this.charisma_exp/div, this.charisma_exp/div,
this.money/div, this.money/div,
this.time, this.time,
singParams singParams,
); );
return this.time; return this.time;

@ -1,13 +1,14 @@
import { Crimes } from "./Crimes"; import { Crimes } from "./Crimes";
import { Crime } from "./Crime";
import { IPlayer } from "../PersonObjects/IPlayer"; import { IPlayer } from "../PersonObjects/IPlayer";
import { dialogBoxCreate } from "../../utils/DialogBox"; import { dialogBoxCreate } from "../../utils/DialogBox";
export function determineCrimeSuccess(p: IPlayer, type: string) { export function determineCrimeSuccess(p: IPlayer, type: string): boolean {
let chance: number = 0; let chance = 0;
let found: boolean = false; let found = false;
for (const i in Crimes) { for (const i in Crimes) {
let crime = Crimes[i]; const crime = Crimes[i];
if (crime.type == type) { if (crime.type == type) {
chance = crime.successRate(p); chance = crime.successRate(p);
found = true; found = true;
@ -17,7 +18,7 @@ export function determineCrimeSuccess(p: IPlayer, type: string) {
if (!found) { if (!found) {
dialogBoxCreate(`ERR: Unrecognized crime type: ${type} This is probably a bug please contact the developer`, false); dialogBoxCreate(`ERR: Unrecognized crime type: ${type} This is probably a bug please contact the developer`, false);
return; return false;
} }
if (Math.random() <= chance) { if (Math.random() <= chance) {
@ -29,7 +30,7 @@ export function determineCrimeSuccess(p: IPlayer, type: string) {
} }
} }
export function findCrime(roughName: string) { export function findCrime(roughName: string): Crime | null {
if (roughName.includes("shoplift")) { if (roughName.includes("shoplift")) {
return Crimes.Shoplift; return Crimes.Shoplift;
} else if (roughName.includes("rob") && roughName.includes("store")) { } else if (roughName.includes("rob") && roughName.includes("store")) {

@ -22,7 +22,7 @@ export interface IPerson {
crime_success_mult: number; crime_success_mult: number;
} }
export function calculateCrimeSuccessChance(crime: ICrime, person: IPerson) { export function calculateCrimeSuccessChance(crime: ICrime, person: IPerson): number {
let chance: number = (crime.hacking_success_weight * person.hacking_skill + let chance: number = (crime.hacking_success_weight * person.hacking_skill +
crime.strength_success_weight * person.strength + crime.strength_success_weight * person.strength +
crime.defense_success_weight * person.defense + crime.defense_success_weight * person.defense +

@ -7,8 +7,6 @@ import { post, postElement } from "../ui/postToTerminal";
import { Money } from "../ui/React/Money"; import { Money } from "../ui/React/Money";
import { isValidIPAddress } from "../../utils/helpers/isValidIPAddress"; import { isValidIPAddress } from "../../utils/helpers/isValidIPAddress";
import { formatNumber } from "../../utils/StringHelperFunctions";
import { numeralWrapper } from "../ui/numeralFormat";
//Posts a "help" message if connected to DarkWeb //Posts a "help" message if connected to DarkWeb
export function checkIfConnectedToDarkweb(): void { export function checkIfConnectedToDarkweb(): void {
@ -29,27 +27,28 @@ export function checkIfConnectedToDarkweb(): void {
export function executeDarkwebTerminalCommand(commandArray: string[]): void { export function executeDarkwebTerminalCommand(commandArray: string[]): void {
if (commandArray.length == 0) {return;} if (commandArray.length == 0) {return;}
switch (commandArray[0]) { switch (commandArray[0]) {
case "buy": case "buy": {
if (commandArray.length != 2) { if (commandArray.length != 2) {
post("Incorrect number of arguments. Usage: "); post("Incorrect number of arguments. Usage: ");
post("buy -l"); post("buy -l");
post("buy [item name]"); post("buy [item name]");
return; return;
} }
var arg = commandArray[1]; const arg = commandArray[1];
if (arg == "-l") { if (arg == "-l") {
listAllDarkwebItems(); listAllDarkwebItems();
} else { } else {
buyDarkwebItem(arg); buyDarkwebItem(arg);
} }
break; break;
}
default: default:
post("Command not found"); post("Command not found");
break; break;
} }
} }
function listAllDarkwebItems() { function listAllDarkwebItems(): void {
for(const key in DarkWebItems) { for(const key in DarkWebItems) {
const item = DarkWebItems[key]; const item = DarkWebItems[key];
postElement(<>{item.program} - {Money(item.price)} - {item.description}</>); postElement(<>{item.program} - {Money(item.price)} - {item.description}</>);

@ -1,5 +1,3 @@
import { numeralWrapper } from "../ui/numeralFormat";
export class DarkWebItem { export class DarkWebItem {
program: string; program: string;
price: number; price: number;

@ -3,10 +3,9 @@ import { CodingContractTypes } from "./CodingContracts";
import { import {
generateContract, generateContract,
generateRandomContract, generateRandomContract,
generateRandomContractOnHome generateRandomContractOnHome,
} from "./CodingContractGenerator"; } from "./CodingContractGenerator";
import { Companies } from "./Company/Companies"; import { Companies } from "./Company/Companies";
import { Company } from "./Company/Company";
import { Programs } from "./Programs/Programs"; import { Programs } from "./Programs/Programs";
import { Factions } from "./Faction/Factions"; import { Factions } from "./Faction/Factions";
import { Player } from "./Player"; import { Player } from "./Player";
@ -14,17 +13,11 @@ import { PlayerOwnedSourceFile } from "./SourceFile/PlayerOwnedSourceFile";
import { AllServers } from "./Server/AllServers"; import { AllServers } from "./Server/AllServers";
import { GetServerByHostname } from "./Server/ServerHelpers"; import { GetServerByHostname } from "./Server/ServerHelpers";
import { hackWorldDaemon } from "./RedPill"; import { hackWorldDaemon } from "./RedPill";
import { StockMarket, SymbolToStockMap } from "./StockMarket/StockMarket"; import { StockMarket } from "./StockMarket/StockMarket";
import { Stock } from "./StockMarket/Stock"; import { Stock } from "./StockMarket/Stock";
import { Terminal } from "./Terminal";
import { numeralWrapper } from "./ui/numeralFormat";
import { dialogBoxCreate } from "../utils/DialogBox"; import { dialogBoxCreate } from "../utils/DialogBox";
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
import { createElement } from "../utils/uiHelpers/createElement"; import { createElement } from "../utils/uiHelpers/createElement";
import { createOptionElement } from "../utils/uiHelpers/createOptionElement";
import { getSelectText } from "../utils/uiHelpers/getSelectData";
import { removeElementById } from "../utils/uiHelpers/removeElementById"; import { removeElementById } from "../utils/uiHelpers/removeElementById";
import { Money } from "./ui/React/Money"; import { Money } from "./ui/React/Money";
@ -47,12 +40,13 @@ class ValueAdjusterComponent extends Component {
this.state = { value: '' }; this.state = { value: '' };
this.setValue = this.setValue.bind(this); this.setValue = this.setValue.bind(this);
} }
setValue(event) { setValue(event) {
this.setState({ value: parseFloat(event.target.value) }); this.setState({ value: parseFloat(event.target.value) });
} }
render() { render() {
const { title, add, subtract, reset } = this.props; const { title, add, subtract, reset } = this.props;
const { value } = this.state;
return ( return (
<> <>
<button className="std-button add-exp-button" onClick={() => add(this.state.value)}>+</button> <button className="std-button add-exp-button" onClick={() => add(this.state.value)}>+</button>
@ -141,6 +135,10 @@ class DevMenuComponent extends Component {
Player.getHomeComputer().maxRam *= 2; Player.getHomeComputer().maxRam *= 2;
} }
quickB1tFlum3() {
hackWorldDaemon(Player.bitNodeN, true, true);
}
b1tflum3() { b1tflum3() {
hackWorldDaemon(Player.bitNodeN, true); hackWorldDaemon(Player.bitNodeN, true);
} }
@ -279,9 +277,8 @@ class DevMenuComponent extends Component {
} }
modifyFactionRep(modifier) { modifyFactionRep(modifier) {
const component = this; return (reputation) => {
return function(reputation) { const fac = Factions[this.state.faction];
const fac = Factions[component.state.faction];
if (fac != null && !isNaN(reputation)) { if (fac != null && !isNaN(reputation)) {
fac.playerReputation += reputation*modifier; fac.playerReputation += reputation*modifier;
} }
@ -296,9 +293,8 @@ class DevMenuComponent extends Component {
} }
modifyFactionFavor(modifier) { modifyFactionFavor(modifier) {
const component = this; return (favor) => {
return function(favor) { const fac = Factions[this.state.faction];
const fac = Factions[component.state.faction];
if (fac != null && !isNaN(favor)) { if (fac != null && !isNaN(favor)) {
fac.favor += favor*modifier; fac.favor += favor*modifier;
} }
@ -368,10 +364,9 @@ class DevMenuComponent extends Component {
} }
setAllSF(sfLvl) { setAllSF(sfLvl) {
const component = this; return () => {
return function(){
for (let i = 0; i < validSFN.length; i++) { for (let i = 0; i < validSFN.length; i++) {
component.setSF(validSFN[i], sfLvl)(); this.setSF(validSFN[i], sfLvl)();
} }
} }
} }
@ -441,9 +436,8 @@ class DevMenuComponent extends Component {
} }
modifyCompanyRep(modifier) { modifyCompanyRep(modifier) {
const component = this; return (reputation) => {
return function(reputation) { const company = Companies[this.state.company];
const company = Companies[component.state.company];
if (company != null && !isNaN(reputation)) { if (company != null && !isNaN(reputation)) {
company.playerReputation += reputation*modifier; company.playerReputation += reputation*modifier;
} }
@ -456,9 +450,8 @@ class DevMenuComponent extends Component {
} }
modifyCompanyFavor(modifier) { modifyCompanyFavor(modifier) {
const component = this; return (favor) => {
return function(favor) { const company = Companies[this.state.company];
const company = Companies[component.state.company];
if (company != null && !isNaN(favor)) { if (company != null && !isNaN(favor)) {
company.favor += favor*modifier; company.favor += favor*modifier;
} }
@ -496,7 +489,7 @@ class DevMenuComponent extends Component {
modifyBladeburnerRank(modify) { modifyBladeburnerRank(modify) {
return function(rank) { return function(rank) {
if (!!Player.bladeburner) { if (Player.bladeburner) {
Player.bladeburner.changeRank(rank*modify); Player.bladeburner.changeRank(rank*modify);
} }
} }
@ -508,67 +501,67 @@ class DevMenuComponent extends Component {
} }
addTonsBladeburnerRank() { addTonsBladeburnerRank() {
if (!!Player.bladeburner) { if (Player.bladeburner) {
Player.bladeburner.changeRank(tonsP); Player.bladeburner.changeRank(tonsP);
} }
} }
modifyBladeburnerCycles(modify) { modifyBladeburnerCycles(modify) {
return function(cycles) { return function(cycles) {
if (!!Player.bladeburner) { if (Player.bladeburner) {
Player.bladeburner.storedCycles += cycles*modify; Player.bladeburner.storedCycles += cycles*modify;
} }
} }
} }
resetBladeburnerCycles() { resetBladeburnerCycles() {
if (!!Player.bladeburner) { if (Player.bladeburner) {
Player.bladeburner.storedCycles = 0; Player.bladeburner.storedCycles = 0;
} }
} }
addTonsBladeburnerCycles() { addTonsBladeburnerCycles() {
if (!!Player.bladeburner) { if (Player.bladeburner) {
Player.bladeburner.storedCycles += tonsP; Player.bladeburner.storedCycles += tonsP;
} }
} }
addTonsGangCycles() { addTonsGangCycles() {
if (!!Player.gang) { if (Player.gang) {
Player.gang.storedCycles = tonsP; Player.gang.storedCycles = tonsP;
} }
} }
modifyGangCycles(modify) { modifyGangCycles(modify) {
return function(cycles) { return function(cycles) {
if (!!Player.gang) { if (Player.gang) {
Player.gang.storedCycles += cycles*modify; Player.gang.storedCycles += cycles*modify;
} }
} }
} }
resetGangCycles() { resetGangCycles() {
if (!!Player.gang) { if (Player.gang) {
Player.gang.storedCycles = 0; Player.gang.storedCycles = 0;
} }
} }
addTonsCorporationCycles() { addTonsCorporationCycles() {
if (!!Player.corporation) { if (Player.corporation) {
Player.corporation.storedCycles = tonsP; Player.corporation.storedCycles = tonsP;
} }
} }
modifyCorporationCycles(modify) { modifyCorporationCycles(modify) {
return function(cycles) { return function(cycles) {
if (!!Player.corporation) { if (Player.corporation) {
Player.corporation.storedCycles += cycles*modify; Player.corporation.storedCycles += cycles*modify;
} }
} }
} }
resetCorporationCycles() { resetCorporationCycles() {
if (!!Player.corporation) { if (Player.corporation) {
Player.corporation.storedCycles = 0; Player.corporation.storedCycles = 0;
} }
} }
@ -580,10 +573,10 @@ class DevMenuComponent extends Component {
}); });
} }
processStocks(cb) { processStocks(sub) {
const inputSymbols = document.getElementById('dev-stock-symbol').value.toString().replace(/\s/g, ''); const inputSymbols = document.getElementById('dev-stock-symbol').value.toString().replace(/\s/g, '');
let match = function(symbol) { return true; } let match = function() { return true; }
if (inputSymbols !== '' && inputSymbols !== 'all') { if (inputSymbols !== '' && inputSymbols !== 'all') {
match = function(symbol) { match = function(symbol) {
@ -595,7 +588,7 @@ class DevMenuComponent extends Component {
if (StockMarket.hasOwnProperty(name)) { if (StockMarket.hasOwnProperty(name)) {
const stock = StockMarket[name]; const stock = StockMarket[name];
if (stock instanceof Stock && match(stock.symbol)) { if (stock instanceof Stock && match(stock.symbol)) {
cb(stock); sub(stock);
} }
} }
} }
@ -636,13 +629,13 @@ class DevMenuComponent extends Component {
} }
} }
sleeveMaxAllSync() { sleeveSyncMaxAll() {
for (let i = 0; i < Player.sleeves.length; ++i) { for (let i = 0; i < Player.sleeves.length; ++i) {
Player.sleeves[i].sync = 100; Player.sleeves[i].sync = 100;
} }
} }
sleeveClearAllSync() { sleeveSyncClearAll() {
for (let i = 0; i < Player.sleeves.length; ++i) { for (let i = 0; i < Player.sleeves.length; ++i) {
Player.sleeves[i].sync = 0; Player.sleeves[i].sync = 0;
} }
@ -674,7 +667,7 @@ class DevMenuComponent extends Component {
<button className="std-button touch-sides" onClick={this.setSF(i, 2)}>2</button> <button className="std-button touch-sides" onClick={this.setSF(i, 2)}>2</button>
<button className="std-button touch-left" onClick={this.setSF(i, 3)}>3</button> <button className="std-button touch-left" onClick={this.setSF(i, 3)}>3</button>
</td> </td>
</tr> </tr>,
)); ));
@ -716,7 +709,8 @@ class DevMenuComponent extends Component {
<button className="std-button" onClick={this.upgradeRam}>Upgrade Home Computer's RAM</button> <button className="std-button" onClick={this.upgradeRam}>Upgrade Home Computer's RAM</button>
</div> </div>
<div className="row"> <div className="row">
<button className="std-button" onClick={this.b1tflum3}>Run bit_flum3.exe</button> <button className="std-button" onClick={this.quickB1tFlum3}>Quick b1t_flum3.exe</button>
<button className="std-button" onClick={this.b1tflum3}>Run b1t_flum3.exe</button>
<button className="std-button" onClick={this.hackW0r1dD43m0n}>Hack w0rld_d34m0n</button> <button className="std-button" onClick={this.hackW0r1dD43m0n}>Hack w0rld_d34m0n</button>
</div> </div>
<div className="row"> <div className="row">
@ -1210,8 +1204,8 @@ class DevMenuComponent extends Component {
</tr> </tr>
<tr> <tr>
<td><span className="text">Sync:</span></td> <td><span className="text">Sync:</span></td>
<td><button className="std-button" onClick={this.sleeveMaxAllSync}>Max all</button></td> <td><button className="std-button" onClick={this.sleeveSyncMaxAll}>Max all</button></td>
<td><button className="std-button" onClick={this.sleeveClearAllSync}>Clear all</button></td> <td><button className="std-button" onClick={this.sleeveSyncClearAll}>Clear all</button></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

@ -1,11 +1,11 @@
import { Player } from "../Player"; import { Player } from "../Player";
export function applyExploit() { export function applyExploit(): void {
if (Player.exploits && Player.exploits.length === 0) { if (Player.exploits && Player.exploits.length === 0) {
return; return;
} }
const inc = Math.pow(1.0001, Player.exploits.length); const inc = Math.pow(1.001, Player.exploits.length);
const dec = Math.pow(0.9999, Player.exploits.length); const dec = Math.pow(0.999, Player.exploits.length);
Player.hacking_chance_mult *= inc; Player.hacking_chance_mult *= inc;
Player.hacking_speed_mult *= inc; Player.hacking_speed_mult *= inc;

@ -2,7 +2,7 @@ import { Player } from "../Player";
import { Exploit } from "./Exploit"; import { Exploit } from "./Exploit";
(function() { (function() {
function clickTheUnclickable(event: MouseEvent) { function clickTheUnclickable(event: MouseEvent): void {
if(!event.target || !(event.target instanceof Element)) return; if(!event.target || !(event.target instanceof Element)) return;
const display = window.getComputedStyle(event.target as Element).display; const display = window.getComputedStyle(event.target as Element).display;
if(display === 'none' && event.isTrusted) if(display === 'none' && event.isTrusted)
@ -10,7 +10,7 @@ import { Exploit } from "./Exploit";
} }
function targetElement() { function targetElement(): void {
const elem = document.getElementById('unclickable'); const elem = document.getElementById('unclickable');
if(elem == null) { if(elem == null) {
console.error('Could not find the unclickable elem for the related exploit.'); console.error('Could not find the unclickable elem for the related exploit.');

@ -4,18 +4,12 @@ import { FactionInfo,
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
export class Faction { export class Faction {
/**
* Initiatizes a Faction object from a JSON save state.
*/
static fromJSON(value: any): Faction {
return Generic_fromJSON(Faction, value.data);
}
/** /**
* Flag signalling whether the player has already received an invitation * Flag signalling whether the player has already received an invitation
* to this faction * to this faction
*/ */
alreadyInvited: boolean = false; alreadyInvited = false;
/** /**
* Holds names of all augmentations that this Faction offers * Holds names of all augmentations that this Faction offers
@ -25,35 +19,35 @@ export class Faction {
/** /**
* Amount of favor the player has with this faction. * Amount of favor the player has with this faction.
*/ */
favor: number = 0; favor = 0;
/** /**
* Flag signalling whether player has been banned from this faction * Flag signalling whether player has been banned from this faction
*/ */
isBanned: boolean = false; isBanned = false;
/** /**
* Flag signalling whether player is a member of this faction * Flag signalling whether player is a member of this faction
*/ */
isMember: boolean = false; isMember = false;
/** /**
* Name of faction * Name of faction
*/ */
name: string = ""; name = "";
/** /**
* Amount of reputation player has with this faction * Amount of reputation player has with this faction
*/ */
playerReputation: number = 0; playerReputation = 0;
/** /**
* Reputation from the last "prestige" that was not converted to favor. * Reputation from the last "prestige" that was not converted to favor.
* This reputation rolls over and is used for the next favor calculation * This reputation rolls over and is used for the next favor calculation
*/ */
rolloverRep: number = 0; rolloverRep = 0;
constructor(name: string="") { constructor(name="") {
this.name = name; this.name = name;
} }
@ -82,7 +76,7 @@ export class Faction {
getFavorGain(): number[] { getFavorGain(): number[] {
if (this.favor == null) { this.favor = 0; } if (this.favor == null) { this.favor = 0; }
if (this.rolloverRep == null) { this.rolloverRep = 0; } if (this.rolloverRep == null) { this.rolloverRep = 0; }
var favorGain = 0, rep = this.playerReputation + this.rolloverRep; let favorGain = 0, rep = this.playerReputation + this.rolloverRep;
let reqdRep = CONSTANTS.FactionReputationToFavorBase * let reqdRep = CONSTANTS.FactionReputationToFavorBase *
Math.pow(CONSTANTS.FactionReputationToFavorMult, this.favor); Math.pow(CONSTANTS.FactionReputationToFavorMult, this.favor);
while(rep > 0) { while(rep > 0) {
@ -103,6 +97,14 @@ export class Faction {
toJSON(): any { toJSON(): any {
return Generic_toJSON("Faction", this); return Generic_toJSON("Faction", this);
} }
/**
* Initiatizes a Faction object from a JSON save state.
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): Faction {
return Generic_fromJSON(Faction, value.data);
}
} }
Reviver.constructors.Faction = Faction; Reviver.constructors.Faction = Faction;

@ -24,19 +24,12 @@ import {
import { Page, routing } from "../ui/navigationTracking"; import { Page, routing } from "../ui/navigationTracking";
import { dialogBoxCreate } from "../../utils/DialogBox"; import { dialogBoxCreate } from "../../utils/DialogBox";
import { factionInvitationBoxCreate } from "../../utils/FactionInvitationBox"; import { factionInvitationBoxCreate } from "../../utils/FactionInvitationBox";
import {
Reviver,
Generic_toJSON,
Generic_fromJSON
} from "../../utils/JSONReviver";
import { formatNumber } from "../../utils/StringHelperFunctions";
import { numeralWrapper } from "../ui/numeralFormat";
import { Money } from "../ui/React/Money"; import { Money } from "../ui/React/Money";
import { import {
yesNoBoxCreate, yesNoBoxCreate,
yesNoBoxGetYesButton, yesNoBoxGetYesButton,
yesNoBoxGetNoButton, yesNoBoxGetNoButton,
yesNoBoxClose yesNoBoxClose,
} from "../../utils/YesNoBox"; } from "../../utils/YesNoBox";
export function inviteToFaction(faction) { export function inviteToFaction(faction) {
@ -90,7 +83,7 @@ export function displayFactionContent(factionName, initiallyOnAugmentationsPage=
p={Player} p={Player}
startHackingMissionFn={startHackingMission} startHackingMissionFn={startHackingMission}
/>, />,
Engine.Display.factionContent Engine.Display.factionContent,
) )
} }

@ -16,7 +16,7 @@ export function loadFactions(saveString: string): void {
Factions = JSON.parse(saveString, Reviver); Factions = JSON.parse(saveString, Reviver);
} }
export function AddToFactions(faction: Faction) { export function AddToFactions(faction: Faction): void {
const name: string = faction.name; const name: string = faction.name;
Factions[name] = faction; Factions[name] = faction;
} }
@ -25,7 +25,7 @@ export function factionExists(name: string): boolean {
return Factions.hasOwnProperty(name); return Factions.hasOwnProperty(name);
} }
export function initFactions(bitNode: number=1) { export function initFactions(): void {
for (const name in FactionInfos) { for (const name in FactionInfos) {
resetFaction(new Faction(name)); resetFaction(new Faction(name));
} }
@ -34,7 +34,7 @@ export function initFactions(bitNode: number=1) {
//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
export function resetFaction(newFactionObject: Faction) { 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()");
} }

@ -77,7 +77,7 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
getAugsSortedByCost(): string[] { getAugsSortedByCost(): string[] {
const augs = this.getAugs(); const augs = this.getAugs();
augs.sort((augName1, augName2)=>{ augs.sort((augName1, augName2)=>{
var aug1 = Augmentations[augName1], aug2 = Augmentations[augName2]; const aug1 = Augmentations[augName1], aug2 = Augmentations[augName2];
if (aug1 == null || aug2 == null) { if (aug1 == null || aug2 == null) {
throw new Error("Invalid Augmentation Names"); throw new Error("Invalid Augmentation Names");
} }
@ -91,7 +91,7 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
getAugsSortedByReputation(): string[] { getAugsSortedByReputation(): string[] {
const augs = this.getAugs(); const augs = this.getAugs();
augs.sort((augName1, augName2)=>{ augs.sort((augName1, augName2)=>{
var aug1 = Augmentations[augName1], aug2 = Augmentations[augName2]; const aug1 = Augmentations[augName1], aug2 = Augmentations[augName2];
if (aug1 == null || aug2 == null) { if (aug1 == null || aug2 == null) {
throw new Error("Invalid Augmentation Names"); throw new Error("Invalid Augmentation Names");
} }
@ -118,23 +118,21 @@ export class AugmentationsPage extends React.Component<IProps, IState> {
}); });
} }
render() { render(): React.ReactNode {
const augs = this.getAugsSorted(); const augs = this.getAugsSorted();
const purchasable = augs.filter((aug: string) => const purchasable = augs.filter((aug: string) => aug === AugmentationNames.NeuroFluxGovernor ||
aug === AugmentationNames.NeuroFluxGovernor ||
(!this.props.p.augmentations.some(a => a.name === aug) && (!this.props.p.augmentations.some(a => a.name === aug) &&
!this.props.p.queuedAugmentations.some(a => a.name === aug)) !this.props.p.queuedAugmentations.some(a => a.name === aug)),
) )
const parent = this; const purchaseableAugmentation = (aug: string): React.ReactNode => {
function purchaseableAugmentation(aug: string) {
return ( return (
<PurchaseableAugmentation <PurchaseableAugmentation
augName={aug} augName={aug}
faction={parent.props.faction} faction={this.props.faction}
key={aug} key={aug}
p={parent.props.p} p={this.props.p}
rerender={parent.rerender} rerender={this.rerender}
/> />
) )
} }

@ -7,7 +7,6 @@ import { CONSTANTS } from "../../Constants";
import { Faction } from "../../Faction/Faction"; import { Faction } from "../../Faction/Faction";
import { IPlayer } from "../../PersonObjects/IPlayer"; import { IPlayer } from "../../PersonObjects/IPlayer";
import { numeralWrapper } from "../../ui/numeralFormat";
import { Money } from "../../ui/React/Money"; import { Money } from "../../ui/React/Money";
import { Reputation } from "../../ui/React/Reputation"; import { Reputation } from "../../ui/React/Reputation";
@ -17,6 +16,8 @@ import { dialogBoxCreate } from "../../../utils/DialogBox";
type IProps = { type IProps = {
faction: Faction; faction: Faction;
disabled: boolean;
favorToDonate: number;
p: IPlayer; p: IPlayer;
rerender: () => void; rerender: () => void;
} }
@ -32,14 +33,15 @@ const inputStyleMarkup = {
export class DonateOption extends React.Component<IProps, IState> { export class DonateOption extends React.Component<IProps, IState> {
// Style markup for block elements. Stored as property // Style markup for block elements. Stored as property
blockStyle: object = { display: "block" }; blockStyle: any = { display: "block" };
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
this.state = { this.state = {
donateAmt: 0, donateAmt: 0,
status: <></>, status: props.disabled ? <>Unlocked at {props.favorToDonate} favor with {props.faction.name}</> : <></>,
} }
this.calculateRepGain = this.calculateRepGain.bind(this); this.calculateRepGain = this.calculateRepGain.bind(this);
@ -87,14 +89,21 @@ export class DonateOption extends React.Component<IProps, IState> {
} }
} }
render() { render(): React.ReactNode {
return ( return (
<div className={"faction-work-div"}> <div className={"faction-work-div"}>
<div className={"faction-work-div-wrapper"}> <div className={"faction-work-div-wrapper"}>
<input className='text-input' onChange={this.handleChange} placeholder={"Donation amount"} style={inputStyleMarkup} /> <input
className="text-input"
onChange={this.handleChange}
placeholder={"Donation amount"}
style={inputStyleMarkup}
disabled={this.props.disabled}
/>
<StdButton <StdButton
onClick={this.donate} onClick={this.donate}
text={"Donate Money"} text={"Donate Money"}
disabled={this.props.disabled}
/> />
<p style={this.blockStyle}>{this.state.status}</p> <p style={this.blockStyle}>{this.state.status}</p>
</div> </div>

@ -6,7 +6,6 @@ import * as React from "react";
import { Faction } from "../../Faction/Faction"; import { Faction } from "../../Faction/Faction";
import { FactionInfo } from "../../Faction/FactionInfo"; import { FactionInfo } from "../../Faction/FactionInfo";
import { numeralWrapper } from "../../ui/numeralFormat";
import { AutoupdatingParagraph } from "../../ui/React/AutoupdatingParagraph"; import { AutoupdatingParagraph } from "../../ui/React/AutoupdatingParagraph";
import { ParagraphWithTooltip } from "../../ui/React/ParagraphWithTooltip"; import { ParagraphWithTooltip } from "../../ui/React/ParagraphWithTooltip";
@ -48,7 +47,7 @@ export class Info extends React.Component<IProps, any> {
return <>Reputation: {Reputation(this.props.faction.playerReputation)}</> return <>Reputation: {Reputation(this.props.faction.playerReputation)}</>
} }
render() { render(): React.ReactNode {
const favorTooltip = "Faction favor increases the rate at which you earn reputation for " + const favorTooltip = "Faction favor increases the rate at which you earn reputation for " +
"this faction by 1% per favor. Faction favor is gained whenever you " + "this faction by 1% per favor. Faction favor is gained whenever you " +
"reset after installing an Augmentation. The amount of " + "reset after installing an Augmentation. The amount of " +

@ -14,7 +14,7 @@ type IProps = {
} }
export class Option extends React.Component<IProps, any> { export class Option extends React.Component<IProps, any> {
render() { render(): React.ReactNode {
return ( return (
<div className={"faction-work-div"}> <div className={"faction-work-div"}>
<div className={"faction-work-div-wrapper"}> <div className={"faction-work-div-wrapper"}>

@ -17,7 +17,6 @@ import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Faction } from "../../Faction/Faction"; import { Faction } from "../../Faction/Faction";
import { IPlayer } from "../../PersonObjects/IPlayer"; import { IPlayer } from "../../PersonObjects/IPlayer";
import { Settings } from "../../Settings/Settings"; import { Settings } from "../../Settings/Settings";
import { numeralWrapper } from "../../ui/numeralFormat";
import { Money } from "../../ui/React/Money"; import { Money } from "../../ui/React/Money";
import { Reputation } from "../../ui/React/Reputation"; import { Reputation } from "../../ui/React/Reputation";
import { IMap } from "../../types"; import { IMap } from "../../types";
@ -42,35 +41,37 @@ const inlineStyleMarkup = {
} }
export class PurchaseableAugmentation extends React.Component<IProps, any> { export class PurchaseableAugmentation extends React.Component<IProps, any> {
aug: Augmentation | null; aug: Augmentation;
constructor(props: IProps) { constructor(props: IProps) {
super(props); super(props);
this.aug = Augmentations[this.props.augName]; const aug = Augmentations[this.props.augName];
if(aug == null) throw new Error(`aug ${this.props.augName} does not exists`);
this.aug = aug;
this.handleClick = this.handleClick.bind(this); this.handleClick = this.handleClick.bind(this);
} }
getMoneyCost(): number { getMoneyCost(): number {
return this.aug!.baseCost * this.props.faction.getInfo().augmentationPriceMult; return this.aug.baseCost * this.props.faction.getInfo().augmentationPriceMult;
} }
getRepCost(): number { getRepCost(): number {
return this.aug!.baseRepRequirement * this.props.faction.getInfo().augmentationRepRequirementMult; return this.aug.baseRepRequirement * this.props.faction.getInfo().augmentationRepRequirementMult;
} }
handleClick() { handleClick(): void {
if (!Settings.SuppressBuyAugmentationConfirmation) { if (!Settings.SuppressBuyAugmentationConfirmation) {
purchaseAugmentationBoxCreate(this.aug!, this.props.faction); purchaseAugmentationBoxCreate(this.aug, this.props.faction);
} else { } else {
purchaseAugmentation(this.aug!, this.props.faction); purchaseAugmentation(this.aug, this.props.faction);
} }
} }
// Whether the player has the prerequisite Augmentations // Whether the player has the prerequisite Augmentations
hasPrereqs(): boolean { hasPrereqs(): boolean {
return hasAugmentationPrereqs(this.aug!); return hasAugmentationPrereqs(this.aug);
} }
// Whether the player has enough rep for this Augmentation // Whether the player has enough rep for this Augmentation
@ -98,7 +99,7 @@ export class PurchaseableAugmentation extends React.Component<IProps, any> {
return owned; return owned;
} }
render() { render(): React.ReactNode {
if (this.aug == null) { if (this.aug == null) {
console.error(`Invalid Augmentation when trying to create PurchaseableAugmentation display element: ${this.props.augName}`); console.error(`Invalid Augmentation when trying to create PurchaseableAugmentation display element: ${this.props.augName}`);
return null; return null;
@ -108,9 +109,9 @@ export class PurchaseableAugmentation extends React.Component<IProps, any> {
const repCost = this.getRepCost(); const repCost = this.getRepCost();
// Determine UI properties // Determine UI properties
let disabled: boolean = false; let disabled = false;
let status: JSX.Element = <></>; let status: JSX.Element = <></>;
let color: string = ""; let color = "";
if (!this.hasPrereqs()) { if (!this.hasPrereqs()) {
disabled = true; disabled = true;
status = <>LOCKED (Requires {this.aug.prereqs.map(aug => AugFormat(aug))} as prerequisite)</>; status = <>LOCKED (Requires {this.aug.prereqs.map(aug => AugFormat(aug))} as prerequisite)</>;

@ -69,7 +69,7 @@ const GangNames = [
"The Dark Army", "The Dark Army",
"Speakers for the Dead", "Speakers for the Dead",
"NiteSec", "NiteSec",
"The Black Hand" "The Black Hand",
]; ];
export class FactionRoot extends React.Component<IProps, IState> { export class FactionRoot extends React.Component<IProps, IState> {
@ -92,7 +92,7 @@ export class FactionRoot extends React.Component<IProps, IState> {
this.startSecurityWork = this.startSecurityWork.bind(this); this.startSecurityWork = this.startSecurityWork.bind(this);
} }
manageGang() { manageGang(): void {
// If player already has a gang, just go to the gang UI // If player already has a gang, just go to the gang UI
if (this.props.p.inGang()) { if (this.props.p.inGang()) {
return this.props.engine.loadGangContent(); return this.props.engine.loadGangContent();
@ -146,7 +146,7 @@ export class FactionRoot extends React.Component<IProps, IState> {
"create a Gang with, and each of these Factions have all Augmentations available."); "create a Gang with, and each of these Factions have all Augmentations available.");
} }
rerender() { rerender(): void {
this.setState((prevState) => { this.setState((prevState) => {
return { return {
rerenderFlag: !prevState.rerenderFlag, rerenderFlag: !prevState.rerenderFlag,
@ -155,42 +155,42 @@ export class FactionRoot extends React.Component<IProps, IState> {
} }
// Route to the main faction page // Route to the main faction page
routeToMain() { routeToMain(): void {
this.setState({ purchasingAugs: false }); this.setState({ purchasingAugs: false });
} }
// Route to the purchase augmentation UI for this faction // Route to the purchase augmentation UI for this faction
routeToPurchaseAugs() { routeToPurchaseAugs(): void {
this.setState({ purchasingAugs: true }); this.setState({ purchasingAugs: true });
} }
sleevePurchases() { sleevePurchases(): void {
createSleevePurchasesFromCovenantPopup(this.props.p); createSleevePurchasesFromCovenantPopup(this.props.p);
} }
startFieldWork() { startFieldWork(): void {
this.props.p.startFactionFieldWork(this.props.faction); this.props.p.startFactionFieldWork(this.props.faction);
} }
startHackingContracts() { startHackingContracts(): void {
this.props.p.startFactionHackWork(this.props.faction); this.props.p.startFactionHackWork(this.props.faction);
} }
startHackingMission() { startHackingMission(): void {
const fac = this.props.faction; const fac = this.props.faction;
this.props.engine.loadMissionContent(); this.props.engine.loadMissionContent();
this.props.startHackingMissionFn(fac); this.props.startHackingMissionFn(fac);
} }
startSecurityWork() { startSecurityWork(): void {
this.props.p.startFactionSecurityWork(this.props.faction); this.props.p.startFactionSecurityWork(this.props.faction);
} }
render() { render(): React.ReactNode {
return this.state.purchasingAugs ? this.renderAugmentationsPage() : this.renderMainPage(); return this.state.purchasingAugs ? this.renderAugmentationsPage() : this.renderMainPage();
} }
renderMainPage() { renderMainPage(): React.ReactNode {
const p = this.props.p; const p = this.props.p;
const faction = this.props.faction; const faction = this.props.faction;
const factionInfo = faction.getInfo(); const factionInfo = faction.getInfo();
@ -264,11 +264,13 @@ export class FactionRoot extends React.Component<IProps, IState> {
/> />
} }
{ {
(!isPlayersGang && canDonate) && !isPlayersGang &&
<DonateOption <DonateOption
faction={this.props.faction} faction={this.props.faction}
p={this.props.p} p={this.props.p}
rerender={this.rerender} rerender={this.rerender}
favorToDonate={favorToDonate}
disabled={!canDonate}
/> />
} }
<Option <Option
@ -288,7 +290,7 @@ export class FactionRoot extends React.Component<IProps, IState> {
) )
} }
renderAugmentationsPage() { renderAugmentationsPage(): React.ReactNode {
return ( return (
<div> <div>
<AugmentationsPage <AugmentationsPage

@ -19,9 +19,12 @@ import { dialogBoxCreate } from "../utils/DialogBox";
import { import {
Reviver, Reviver,
Generic_toJSON, Generic_toJSON,
Generic_fromJSON Generic_fromJSON,
} from "../utils/JSONReviver"; } from "../utils/JSONReviver";
import { formatNumber } from "../utils/StringHelperFunctions"; import {
formatNumber,
convertTimeMsToTimeElapsedString,
} from "../utils/StringHelperFunctions";
import { exceptionAlert } from "../utils/helpers/exceptionAlert"; import { exceptionAlert } from "../utils/helpers/exceptionAlert";
import { getRandomInt } from "../utils/helpers/getRandomInt"; import { getRandomInt } from "../utils/helpers/getRandomInt";
@ -33,7 +36,6 @@ import { createPopup } from "../utils/uiHelpers/createPopup";
import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement"; import { removeChildrenFromElement } from "../utils/uiHelpers/removeChildrenFromElement";
import { removeElement } from "../utils/uiHelpers/removeElement"; import { removeElement } from "../utils/uiHelpers/removeElement";
import { removeElementById } from "../utils/uiHelpers/removeElementById"; import { removeElementById } from "../utils/uiHelpers/removeElementById";
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
import { StatsTable } from "./ui/React/StatsTable"; import { StatsTable } from "./ui/React/StatsTable";
import { Money } from "./ui/React/Money"; import { Money } from "./ui/React/Money";
@ -47,7 +49,6 @@ import { renderToStaticMarkup } from "react-dom/server"
// Constants // Constants
const GangRespectToReputationRatio = 5; // Respect is divided by this to get rep gain const GangRespectToReputationRatio = 5; // Respect is divided by this to get rep gain
const MaximumGangMembers = 30; const MaximumGangMembers = 30;
const GangRecruitCostMultiplier = 2;
const CyclesPerTerritoryAndPowerUpdate = 100; const CyclesPerTerritoryAndPowerUpdate = 100;
const AscensionMultiplierRatio = 15 / 100; // Portion of upgrade multiplier that is kept after ascending const AscensionMultiplierRatio = 15 / 100; // Portion of upgrade multiplier that is kept after ascending
@ -69,7 +70,6 @@ $(document).keydown(function(event) {
// Delete upgrade box when clicking outside // Delete upgrade box when clicking outside
$(document).mousedown(function(event) { $(document).mousedown(function(event) {
var boxId = "gang-member-upgrade-popup-box";
var contentId = "gang-member-upgrade-popup-box-content"; var contentId = "gang-member-upgrade-popup-box-content";
if (UIElems.gangMemberUpgradeBoxOpened) { if (UIElems.gangMemberUpgradeBoxOpened) {
if ( $(event.target).closest("#" + contentId).get(0) == null ) { if ( $(event.target).closest("#" + contentId).get(0) == null ) {
@ -90,7 +90,7 @@ const GangNames = [
"The Dark Army", "The Dark Army",
"Speakers for the Dead", "Speakers for the Dead",
"NiteSec", "NiteSec",
"The Black Hand" "The Black Hand",
]; ];
export let AllGangs = { export let AllGangs = {
@ -461,8 +461,6 @@ Gang.prototype.clash = function(won=false) {
} }
Gang.prototype.killMember = function(memberObj) { Gang.prototype.killMember = function(memberObj) {
const gangName = this.facName;
// Player loses a percentage of total respect, plus whatever respect that member has earned // Player loses a percentage of total respect, plus whatever respect that member has earned
const totalRespect = this.respect; const totalRespect = this.respect;
const lostRespect = (0.05 * totalRespect) + memberObj.earnedRespect; const lostRespect = (0.05 * totalRespect) + memberObj.earnedRespect;
@ -1055,14 +1053,14 @@ Gang.prototype.createGangMemberUpgradeBox = function(player, initialFilter="") {
onkeyup:() => { onkeyup:() => {
var filterValue = UIElems.gangMemberUpgradeBoxFilter.value.toString(); var filterValue = UIElems.gangMemberUpgradeBoxFilter.value.toString();
this.createGangMemberUpgradeBox(player, filterValue); this.createGangMemberUpgradeBox(player, filterValue);
} },
}); });
UIElems.gangMemberUpgradeBoxDiscount = createElement("p", { UIElems.gangMemberUpgradeBoxDiscount = createElement("p", {
innerText: "Discount: -" + numeralWrapper.formatPercentage(1 - 1 / this.getDiscount()), innerText: "Discount: -" + numeralWrapper.formatPercentage(1 - 1 / this.getDiscount()),
marginLeft: "6px", marginLeft: "6px",
tooltip: "You get a discount on equipment and upgrades based on your gang's " + tooltip: "You get a discount on equipment and upgrades based on your gang's " +
"respect and power. More respect and power leads to more discounts." "respect and power. More respect and power leads to more discounts.",
}); });
UIElems.gangMemberUpgradeBoxElements = [UIElems.gangMemberUpgradeBoxFilter, UIElems.gangMemberUpgradeBoxDiscount]; UIElems.gangMemberUpgradeBoxElements = [UIElems.gangMemberUpgradeBoxFilter, UIElems.gangMemberUpgradeBoxDiscount];
@ -1087,7 +1085,7 @@ GangMember.prototype.createGangMemberUpgradePanel = function(gangObj, player) {
}); });
var header = createElement("h1", { var header = createElement("h1", {
innerText: this.name + " (" + this.task + ")" innerText: this.name + " (" + this.task + ")",
}); });
container.appendChild(header); container.appendChild(header);
@ -1192,7 +1190,7 @@ GangMember.prototype.createGangMemberUpgradePanel = function(gangObj, player) {
clickListener:() => { clickListener:() => {
memberObj.buyUpgrade(upg, player, gangObj); memberObj.buyUpgrade(upg, player, gangObj);
return false; return false;
} },
} }
// For the last two divs, tooltip should be on the left // For the last two divs, tooltip should be on the left
@ -1266,10 +1264,7 @@ Gang.prototype.displayGangContent = function(player) {
}); });
// Get variables // Get variables
var facName = this.facName, var facName = this.facName;
members = this.members,
wanted = this.wanted,
respect = this.respect;
// Back button // Back button
UIElems.gangContainer.appendChild(createElement("a", { UIElems.gangContainer.appendChild(createElement("a", {
@ -1278,7 +1273,7 @@ Gang.prototype.displayGangContent = function(player) {
Engine.loadFactionContent(); Engine.loadFactionContent();
displayFactionContent(facName); displayFactionContent(facName);
return false; return false;
} },
})); }));
// Buttons to switch between panels // Buttons to switch between panels
@ -1294,7 +1289,7 @@ Gang.prototype.displayGangContent = function(player) {
UIElems.territoryButton.classList.toggle("a-link-button"); UIElems.territoryButton.classList.toggle("a-link-button");
this.updateGangContent(); this.updateGangContent();
return false; return false;
} },
}) })
UIElems.territoryButton = createElement("a", { UIElems.territoryButton = createElement("a", {
id:"gang-territory-subpage-button", class:"a-link-button", id:"gang-territory-subpage-button", class:"a-link-button",
@ -1308,7 +1303,7 @@ Gang.prototype.displayGangContent = function(player) {
UIElems.territoryButton.classList.toggle("a-link-button"); UIElems.territoryButton.classList.toggle("a-link-button");
this.updateGangContent(); this.updateGangContent();
return false; return false;
} },
}); });
UIElems.gangContainer.appendChild(UIElems.managementButton); UIElems.gangContainer.appendChild(UIElems.managementButton);
UIElems.gangContainer.appendChild(UIElems.territoryButton); UIElems.gangContainer.appendChild(UIElems.territoryButton);
@ -1338,7 +1333,7 @@ Gang.prototype.displayGangContent = function(player) {
"Installing Augmentations does NOT reset your progress with your Gang. " + "Installing Augmentations does NOT reset your progress with your Gang. " +
"Furthermore, after installing Augmentations, you will " + "Furthermore, after installing Augmentations, you will " +
"automatically be a member of whatever Faction you created your gang with.<br><br>" + "automatically be a member of whatever Faction you created your gang with.<br><br>" +
"You can also manage your gang programmatically through Netscript using the Gang API" "You can also manage your gang programmatically through Netscript using the Gang API",
}); });
UIElems.gangManagementSubpage.appendChild(UIElems.gangDesc); UIElems.gangManagementSubpage.appendChild(UIElems.gangDesc);
@ -1399,7 +1394,7 @@ Gang.prototype.displayGangContent = function(player) {
}); });
createPopup(popupId, [txt, br, nameInput, yesBtn, noBtn]); createPopup(popupId, [txt, br, nameInput, yesBtn, noBtn]);
nameInput.focus(); nameInput.focus();
} },
}); });
UIElems.gangManagementSubpage.appendChild(UIElems.gangRecruitMemberButton); UIElems.gangManagementSubpage.appendChild(UIElems.gangRecruitMemberButton);
@ -1425,7 +1420,7 @@ Gang.prototype.displayGangContent = function(player) {
} }
} }
return false; return false;
} },
}); });
UIElems.gangCollapseAllButton = createElement("a", { UIElems.gangCollapseAllButton = createElement("a", {
class:"a-link-button", display:"inline-block", class:"a-link-button", display:"inline-block",
@ -1439,21 +1434,21 @@ Gang.prototype.displayGangContent = function(player) {
} }
} }
return false; return false;
} },
}); });
UIElems.gangMemberFilter = createElement("input", { UIElems.gangMemberFilter = createElement("input", {
type:"text", placeholder:"Filter gang members", margin:"5px", padding:"5px", type:"text", placeholder:"Filter gang members", margin:"5px", padding:"5px",
class:"text-input", class:"text-input",
onkeyup:() => { onkeyup:() => {
this.displayGangMemberList(); this.displayGangMemberList();
} },
}); });
UIElems.gangManageEquipmentButton = createElement("a", { UIElems.gangManageEquipmentButton = createElement("a", {
class:"a-link-button", display:"inline-block", class:"a-link-button", display:"inline-block",
innerHTML:"Manage Equipment", innerHTML:"Manage Equipment",
clickListener: () => { clickListener: () => {
this.createGangMemberUpgradeBox(player); this.createGangMemberUpgradeBox(player);
} },
}); });
UIElems.gangManagementSubpage.appendChild(UIElems.gangExpandAllButton); UIElems.gangManagementSubpage.appendChild(UIElems.gangExpandAllButton);
UIElems.gangManagementSubpage.appendChild(UIElems.gangCollapseAllButton); UIElems.gangManagementSubpage.appendChild(UIElems.gangCollapseAllButton);
@ -1467,7 +1462,7 @@ Gang.prototype.displayGangContent = function(player) {
// Subpage for seeing gang territory information // Subpage for seeing gang territory information
UIElems.gangTerritorySubpage = createElement("div", { UIElems.gangTerritorySubpage = createElement("div", {
id:"gang-territory-subpage", display:"none" id:"gang-territory-subpage", display:"none",
}); });
// Info text for territory page // Info text for territory page
@ -1485,7 +1480,7 @@ Gang.prototype.displayGangContent = function(player) {
"NOTE: Gang members assigned to 'Territory Warfare' can be killed during clashes. This can happen regardless of whether you win " + "NOTE: Gang members assigned to 'Territory Warfare' can be killed during clashes. This can happen regardless of whether you win " +
"or lose the clash. A gang member being killed results in both respect and power loss for your gang.<br><br>" + "or lose the clash. A gang member being killed results in both respect and power loss for your gang.<br><br>" +
"The amount of territory you have affects all aspects of your Gang members' production, including " + "The amount of territory you have affects all aspects of your Gang members' production, including " +
"money, respect, and wanted level. It is very beneficial to have high territory control.<br><br>" "money, respect, and wanted level. It is very beneficial to have high territory control.<br><br>",
}); });
UIElems.gangTerritorySubpage.appendChild(UIElems.gangTerritoryDescText); UIElems.gangTerritorySubpage.appendChild(UIElems.gangTerritoryDescText);
@ -1654,7 +1649,7 @@ Gang.prototype.updateGangContent = function() {
tooltip: "Represents the amount of respect your gang has from other gangs and criminal " + tooltip: "Represents the amount of respect your gang has from other gangs and criminal " +
"organizations. Your respect affects the amount of money " + "organizations. Your respect affects the amount of money " +
"your gang members will earn, and also determines how much " + "your gang members will earn, and also determines how much " +
"reputation you are earning with your gang's corresponding Faction." "reputation you are earning with your gang's corresponding Faction.",
})); }));
UIElems.gangInfo.appendChild(createElement("br")); UIElems.gangInfo.appendChild(createElement("br"));
@ -1664,7 +1659,7 @@ Gang.prototype.updateGangContent = function() {
" (" + numeralWrapper.formatWanted(5*this.wantedGainRate) + " / sec)", " (" + numeralWrapper.formatWanted(5*this.wantedGainRate) + " / sec)",
tooltip: "Represents how much the gang is wanted by law enforcement. The higher " + tooltip: "Represents how much the gang is wanted by law enforcement. The higher " +
"your gang's wanted level, the harder it will be for your gang members " + "your gang's wanted level, the harder it will be for your gang members " +
"to make money and earn respect. Note that the minimum wanted level is 1." "to make money and earn respect. Note that the minimum wanted level is 1.",
})); }));
UIElems.gangInfo.appendChild(createElement("br")); UIElems.gangInfo.appendChild(createElement("br"));
@ -1673,7 +1668,7 @@ Gang.prototype.updateGangContent = function() {
UIElems.gangInfo.appendChild(createElement("p", { // Wanted Level multiplier UIElems.gangInfo.appendChild(createElement("p", { // Wanted Level multiplier
display: "inline-block", display: "inline-block",
innerText: `Wanted Level Penalty: -${formatNumber(wantedPenalty, 2)}%`, innerText: `Wanted Level Penalty: -${formatNumber(wantedPenalty, 2)}%`,
tooltip: "Penalty for respect and money gain rates due to Wanted Level" tooltip: "Penalty for respect and money gain rates due to Wanted Level",
})); }));
UIElems.gangInfo.appendChild(createElement("br")); UIElems.gangInfo.appendChild(createElement("br"));
@ -1695,7 +1690,7 @@ Gang.prototype.updateGangContent = function() {
UIElems.gangInfo.appendChild(createElement("p", { // Territory multiplier UIElems.gangInfo.appendChild(createElement("p", { // Territory multiplier
display: "inline-block", display: "inline-block",
innerText: `Territory: ${formatNumber(displayNumber, 3)}%`, innerText: `Territory: ${formatNumber(displayNumber, 3)}%`,
tooltip: "The percentage of total territory your Gang controls" tooltip: "The percentage of total territory your Gang controls",
})); }));
UIElems.gangInfo.appendChild(createElement("br")); UIElems.gangInfo.appendChild(createElement("br"));
@ -1757,7 +1752,6 @@ Gang.prototype.createGangMemberDisplayElement = function(memberObj) {
hdrText: name, hdrText: name,
}); });
const li = accordion[0]; const li = accordion[0];
const hdr = accordion[1];
const gangMemberDiv = accordion[2]; const gangMemberDiv = accordion[2];
UIElems.gangMemberPanels[name]["panel"] = gangMemberDiv; UIElems.gangMemberPanels[name]["panel"] = gangMemberDiv;
@ -1819,7 +1813,7 @@ Gang.prototype.createGangMemberDisplayElement = function(memberObj) {
innerText: "Cancel", innerText: "Cancel",
}); });
createPopup(popupId, [txt, confirmBtn, cancelBtn]); createPopup(popupId, [txt, confirmBtn, cancelBtn]);
} },
}); });
const ascendHelpTip = createElement("div", { const ascendHelpTip = createElement("div", {
class: "help-tip", class: "help-tip",

Some files were not shown because too many files have changed in this diff Show More