mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-24 07:02:26 +01:00
commit
dd7b5c4316
379
.eslintrc.js
379
.eslintrc.js
@ -7,7 +7,7 @@ module.exports = {
|
|||||||
extends: [
|
extends: [
|
||||||
"eslint:recommended",
|
"eslint:recommended",
|
||||||
"plugin:@typescript-eslint/recommended",
|
"plugin:@typescript-eslint/recommended",
|
||||||
// "plugin:@typescript-eslint/recommended-requiring-type-checking",
|
"plugin:@typescript-eslint/recommended-requiring-type-checking",
|
||||||
],
|
],
|
||||||
parser: "@typescript-eslint/parser",
|
parser: "@typescript-eslint/parser",
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
@ -19,386 +19,9 @@ module.exports = {
|
|||||||
project: ["./tsconfig.json", "./test/tsconfig.json", "./tools/tsconfig.json", "./test/cypress/tsconfig.json"],
|
project: ["./tsconfig.json", "./test/tsconfig.json", "./tools/tsconfig.json", "./test/cypress/tsconfig.json"],
|
||||||
},
|
},
|
||||||
plugins: ["@typescript-eslint"],
|
plugins: ["@typescript-eslint"],
|
||||||
rules: {
|
|
||||||
"accessor-pairs": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
setWithoutGet: true,
|
|
||||||
getWithoutSet: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"array-bracket-newline": ["off"],
|
|
||||||
"array-bracket-spacing": ["off"],
|
|
||||||
"array-callback-return": ["off"],
|
|
||||||
"array-element-newline": ["off"],
|
|
||||||
"arrow-body-style": ["off"],
|
|
||||||
"arrow-parens": ["off"],
|
|
||||||
"arrow-spacing": ["off"],
|
|
||||||
"block-scoped-var": ["off"],
|
|
||||||
"block-spacing": ["off"],
|
|
||||||
"brace-style": ["off"],
|
|
||||||
"callback-return": ["error"],
|
|
||||||
camelcase: ["off"],
|
|
||||||
"capitalized-comments": ["off"],
|
|
||||||
"class-methods-use-this": ["off"],
|
|
||||||
complexity: ["off"],
|
|
||||||
"consistent-return": ["off"],
|
|
||||||
"consistent-this": ["off"],
|
|
||||||
"constructor-super": ["error"],
|
|
||||||
curly: ["off"],
|
|
||||||
"default-case": ["off"],
|
|
||||||
"dot-notation": ["off"],
|
|
||||||
"eol-last": ["error"],
|
|
||||||
eqeqeq: ["off"],
|
|
||||||
"for-direction": ["error"],
|
|
||||||
"func-call-spacing": ["off"],
|
|
||||||
"func-name-matching": ["error"],
|
|
||||||
"func-names": ["off", "never"],
|
|
||||||
"func-style": ["off"],
|
|
||||||
"function-paren-newline": ["off"],
|
|
||||||
"getter-return": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
allowImplicit: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"global-require": ["off"],
|
|
||||||
"guard-for-in": ["off"],
|
|
||||||
"handle-callback-err": ["error"],
|
|
||||||
"id-blacklist": ["error"],
|
|
||||||
"id-length": ["off"],
|
|
||||||
"id-match": ["error"],
|
|
||||||
indent: ["off"],
|
|
||||||
"indent-legacy": ["off"],
|
|
||||||
"init-declarations": ["off"],
|
|
||||||
"key-spacing": ["off"],
|
|
||||||
"keyword-spacing": ["off"],
|
|
||||||
"line-comment-position": ["off"],
|
|
||||||
"linebreak-style": [
|
|
||||||
"off", // Line endings automatically converted to LF on git commit so probably shouldn't care about it here
|
|
||||||
],
|
|
||||||
"lines-around-comment": ["off"],
|
|
||||||
"lines-around-directive": ["error"],
|
|
||||||
"lines-between-class-members": ["error"],
|
|
||||||
"max-depth": ["off"],
|
|
||||||
"max-len": ["off"],
|
|
||||||
"max-lines": ["off"],
|
|
||||||
"max-nested-callbacks": ["error"],
|
|
||||||
"max-params": ["off"],
|
|
||||||
"max-statements": ["off"],
|
|
||||||
"max-statements-per-line": ["off"],
|
|
||||||
"multiline-comment-style": ["off", "starred-block"],
|
|
||||||
"multiline-ternary": ["off", "never"],
|
|
||||||
"new-cap": ["off"],
|
|
||||||
"new-parens": ["off"],
|
|
||||||
"newline-after-var": ["off"],
|
|
||||||
"newline-before-return": ["off"],
|
|
||||||
"newline-per-chained-call": ["off"],
|
|
||||||
"no-alert": ["error"],
|
|
||||||
"no-array-constructor": ["error"],
|
|
||||||
"no-await-in-loop": ["error"],
|
|
||||||
"no-bitwise": ["off"],
|
|
||||||
"no-buffer-constructor": ["error"],
|
|
||||||
"no-caller": ["error"],
|
|
||||||
"no-case-declarations": ["error"],
|
|
||||||
"no-catch-shadow": ["error"],
|
|
||||||
"no-class-assign": ["error"],
|
|
||||||
"no-compare-neg-zero": ["error"],
|
|
||||||
"no-confusing-arrow": ["error"],
|
|
||||||
"no-console": ["off"],
|
|
||||||
"no-const-assign": ["error"],
|
|
||||||
"no-constant-condition": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
checkLoops: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"no-continue": ["off"],
|
|
||||||
"no-control-regex": ["error"],
|
|
||||||
"no-debugger": ["error"],
|
|
||||||
"no-delete-var": ["error"],
|
|
||||||
"no-div-regex": ["error"],
|
|
||||||
"no-dupe-args": ["error"],
|
|
||||||
"no-dupe-class-members": ["error"],
|
|
||||||
"no-dupe-keys": ["error"],
|
|
||||||
"no-duplicate-case": ["error"],
|
|
||||||
"no-duplicate-imports": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
includeExports: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"no-else-return": ["off"],
|
|
||||||
"no-empty": [
|
|
||||||
"off",
|
|
||||||
{
|
|
||||||
allowEmptyCatch: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"no-empty-character-class": ["error"],
|
|
||||||
"no-empty-function": ["off"],
|
|
||||||
"no-empty-pattern": ["error"],
|
|
||||||
"no-eq-null": ["off"],
|
|
||||||
"no-ex-assign": ["off"],
|
|
||||||
"no-extra-boolean-cast": ["error"],
|
|
||||||
"no-extra-parens": ["off"],
|
|
||||||
"no-extra-semi": ["error"],
|
|
||||||
"no-eval": ["off"],
|
|
||||||
"no-extend-native": ["off"],
|
|
||||||
"no-extra-bind": ["error"],
|
|
||||||
"no-extra-label": ["error"],
|
|
||||||
"no-fallthrough": ["off"],
|
|
||||||
"no-floating-decimal": ["off"],
|
|
||||||
"no-func-assign": ["error"],
|
|
||||||
"no-global-assign": ["error"],
|
|
||||||
"no-implicit-coercion": ["off"],
|
|
||||||
"no-implicit-globals": ["error"],
|
|
||||||
"no-implied-eval": ["error"],
|
|
||||||
"no-inline-comments": ["off"],
|
|
||||||
"no-inner-declarations": ["off", "both"],
|
|
||||||
"no-invalid-regexp": ["error"],
|
|
||||||
"no-invalid-this": ["off"],
|
|
||||||
"no-irregular-whitespace": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
skipStrings: false,
|
|
||||||
skipComments: false,
|
|
||||||
skipRegExps: false,
|
|
||||||
skipTemplates: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"no-iterator": ["error"],
|
|
||||||
"no-label-var": ["error"],
|
|
||||||
"no-labels": ["off"],
|
|
||||||
"no-lone-blocks": ["error"],
|
|
||||||
"no-lonely-if": ["error"],
|
|
||||||
"no-loop-func": ["off"],
|
|
||||||
"no-magic-numbers": ["off"],
|
|
||||||
"no-mixed-operators": ["off"],
|
|
||||||
"no-mixed-requires": ["error"],
|
|
||||||
"no-mixed-spaces-and-tabs": ["error"],
|
|
||||||
"no-multi-assign": ["off"],
|
|
||||||
"no-multi-spaces": ["off"],
|
|
||||||
"no-multi-str": ["error"],
|
|
||||||
"no-multiple-empty-lines": [
|
|
||||||
"off",
|
|
||||||
{
|
|
||||||
max: 1,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"no-native-reassign": ["error"],
|
|
||||||
"no-negated-condition": ["off"],
|
|
||||||
"no-negated-in-lhs": ["error"],
|
|
||||||
"no-nested-ternary": ["off"],
|
|
||||||
"no-new": ["error"],
|
|
||||||
"no-new-func": ["error"],
|
|
||||||
"no-new-object": ["error"],
|
|
||||||
"no-new-require": ["error"],
|
|
||||||
"no-new-symbol": ["error"],
|
|
||||||
"no-new-wrappers": ["error"],
|
|
||||||
"no-octal": ["error"],
|
|
||||||
"no-octal-escape": ["error"],
|
|
||||||
"no-obj-calls": ["error"],
|
|
||||||
"no-param-reassign": ["off"],
|
|
||||||
"no-path-concat": ["error"],
|
|
||||||
"no-plusplus": ["off"],
|
|
||||||
"no-process-env": ["off"],
|
|
||||||
"no-process-exit": ["error"],
|
|
||||||
"no-proto": ["error"],
|
|
||||||
"no-prototype-builtins": ["off"],
|
|
||||||
"no-redeclare": ["off"],
|
|
||||||
"no-regex-spaces": ["error"],
|
|
||||||
"no-restricted-globals": ["error"],
|
|
||||||
"no-restricted-imports": ["error"],
|
|
||||||
"no-restricted-modules": ["error"],
|
|
||||||
"no-restricted-properties": [
|
|
||||||
"off",
|
|
||||||
{
|
|
||||||
object: "console",
|
|
||||||
property: "log",
|
|
||||||
message: "'log' is too general, use an appropriate level when logging.",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"no-restricted-syntax": ["error"],
|
|
||||||
"no-return-assign": ["off"],
|
|
||||||
"no-return-await": ["error"],
|
|
||||||
"no-script-url": ["error"],
|
|
||||||
"no-self-assign": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
props: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"no-self-compare": ["error"],
|
|
||||||
"no-sequences": ["error"],
|
|
||||||
"no-shadow": ["off"],
|
|
||||||
"no-shadow-restricted-names": ["error"],
|
|
||||||
"no-spaced-func": ["off"],
|
|
||||||
"no-sparse-arrays": ["error"],
|
|
||||||
"no-sync": ["error"],
|
|
||||||
"no-tabs": ["off"],
|
|
||||||
"no-template-curly-in-string": ["error"],
|
|
||||||
"no-ternary": ["off"],
|
|
||||||
"no-this-before-super": ["off"],
|
|
||||||
"no-throw-literal": ["error"],
|
|
||||||
"no-trailing-spaces": ["error"],
|
|
||||||
"no-undef": ["off"],
|
|
||||||
"no-undef-init": ["error"],
|
|
||||||
"no-undefined": ["off"],
|
|
||||||
"no-underscore-dangle": ["off"],
|
|
||||||
"no-unexpected-multiline": ["error"],
|
|
||||||
"no-unmodified-loop-condition": ["error"],
|
|
||||||
"no-unneeded-ternary": ["off"],
|
|
||||||
"no-unreachable": ["off"],
|
|
||||||
"no-unsafe-finally": ["error"],
|
|
||||||
"no-unsafe-negation": ["error"],
|
|
||||||
"no-unused-expressions": ["off"],
|
|
||||||
"no-unused-labels": ["error"],
|
|
||||||
"no-unused-vars": ["off"],
|
|
||||||
"no-use-before-define": ["off"],
|
|
||||||
"no-useless-call": ["off"],
|
|
||||||
"no-useless-computed-key": ["error"],
|
|
||||||
"no-useless-concat": ["error"],
|
|
||||||
"no-useless-constructor": ["error"],
|
|
||||||
"no-useless-escape": ["off"],
|
|
||||||
"no-useless-rename": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
ignoreDestructuring: false,
|
|
||||||
ignoreExport: false,
|
|
||||||
ignoreImport: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"no-useless-return": ["off"],
|
|
||||||
"no-var": ["off"],
|
|
||||||
"no-void": ["off"],
|
|
||||||
"no-warning-comments": ["off"],
|
|
||||||
"no-whitespace-before-property": ["error"],
|
|
||||||
"no-with": ["error"],
|
|
||||||
"nonblock-statement-body-position": ["off", "below"],
|
|
||||||
"object-curly-newline": ["off"],
|
|
||||||
"object-curly-spacing": ["off"],
|
|
||||||
"object-property-newline": ["off"],
|
|
||||||
"object-shorthand": ["off"],
|
|
||||||
"one-var": ["off"],
|
|
||||||
"one-var-declaration-per-line": ["off"],
|
|
||||||
"operator-assignment": ["off"],
|
|
||||||
"operator-linebreak": ["off", "none"],
|
|
||||||
"padded-blocks": ["off"],
|
|
||||||
"padding-line-between-statements": ["error"],
|
|
||||||
"prefer-arrow-callback": ["off"],
|
|
||||||
"prefer-const": ["off"],
|
|
||||||
"prefer-destructuring": ["off"],
|
|
||||||
"prefer-numeric-literals": ["error"],
|
|
||||||
"prefer-promise-reject-errors": ["off"],
|
|
||||||
"prefer-reflect": ["off"],
|
|
||||||
"prefer-rest-params": ["off"],
|
|
||||||
"prefer-spread": ["off"],
|
|
||||||
"prefer-template": ["off"],
|
|
||||||
"quote-props": ["off"],
|
|
||||||
quotes: ["off"],
|
|
||||||
radix: ["off", "as-needed"],
|
|
||||||
"require-await": ["off"],
|
|
||||||
"require-jsdoc": ["off"],
|
|
||||||
"require-yield": ["error"],
|
|
||||||
"rest-spread-spacing": ["error", "never"],
|
|
||||||
semi: ["off"],
|
|
||||||
"semi-spacing": ["off"],
|
|
||||||
"semi-style": ["error", "last"],
|
|
||||||
"sort-imports": ["off"],
|
|
||||||
"sort-keys": ["off"],
|
|
||||||
"sort-vars": ["off"],
|
|
||||||
"space-before-blocks": ["off"],
|
|
||||||
"space-before-function-paren": ["off"],
|
|
||||||
"space-in-parens": ["off"],
|
|
||||||
"space-infix-ops": ["off"],
|
|
||||||
"space-unary-ops": ["off"],
|
|
||||||
"spaced-comment": ["off"],
|
|
||||||
strict: ["off"],
|
|
||||||
"switch-colon-spacing": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
after: true,
|
|
||||||
before: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"symbol-description": ["error"],
|
|
||||||
"template-curly-spacing": ["error"],
|
|
||||||
"template-tag-spacing": ["error"],
|
|
||||||
"unicode-bom": ["error", "never"],
|
|
||||||
"use-isnan": ["error"],
|
|
||||||
"valid-jsdoc": ["off"],
|
|
||||||
"valid-typeof": ["error"],
|
|
||||||
"vars-on-top": ["off"],
|
|
||||||
"wrap-iife": ["error", "any"],
|
|
||||||
"wrap-regex": ["off"],
|
|
||||||
"yield-star-spacing": ["error", "before"],
|
|
||||||
yoda: ["error", "never"],
|
|
||||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
|
||||||
"@typescript-eslint/explicit-function-return-type": "off",
|
|
||||||
},
|
|
||||||
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
|
|
||||||
files: ["**/*.ts", "**/*.tsx"],
|
|
||||||
parser: "@typescript-eslint/parser",
|
|
||||||
plugins: ["@typescript-eslint"],
|
|
||||||
extends: ["plugin:@typescript-eslint/recommended"],
|
extends: ["plugin:@typescript-eslint/recommended"],
|
||||||
rules: {
|
rules: {
|
||||||
"lines-between-class-members": "off",
|
|
||||||
"no-empty-pattern": "off",
|
|
||||||
"no-useless-constructor": [
|
|
||||||
"off", // Valid for typescript due to property ctor shorthand
|
|
||||||
],
|
|
||||||
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
|
|
||||||
"@typescript-eslint/ban-ts-comment": "off",
|
"@typescript-eslint/ban-ts-comment": "off",
|
||||||
"@typescript-eslint/ban-ts-ignore": "off",
|
|
||||||
"@typescript-eslint/camelcase": "off",
|
|
||||||
"@typescript-eslint/explicit-function-return-type": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
allowExpressions: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"@typescript-eslint/member-delimiter-style": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
multiline: {
|
|
||||||
delimiter: "semi",
|
|
||||||
requireLast: true,
|
|
||||||
},
|
|
||||||
singleline: {
|
|
||||||
delimiter: "semi",
|
|
||||||
requireLast: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"@typescript-eslint/member-ordering": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
default: [
|
|
||||||
"signature",
|
|
||||||
"static-field",
|
|
||||||
"instance-field",
|
|
||||||
"abstract-field",
|
|
||||||
"constructor",
|
|
||||||
"instance-method",
|
|
||||||
"abstract-method",
|
|
||||||
"static-method",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
"@typescript-eslint/no-use-before-define": "off",
|
|
||||||
},
|
},
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
4
dist/main.bundle.js
vendored
4
dist/main.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/main.bundle.js.map
vendored
2
dist/main.bundle.js.map
vendored
File diff suppressed because one or more lines are too long
42
dist/vendor.bundle.js
vendored
42
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
2
dist/vendor.bundle.js.map
vendored
2
dist/vendor.bundle.js.map
vendored
File diff suppressed because one or more lines are too long
801
package-lock.json
generated
801
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -18,8 +18,9 @@
|
|||||||
"@mui/material": "^5.0.3",
|
"@mui/material": "^5.0.3",
|
||||||
"@mui/styles": "^5.0.1",
|
"@mui/styles": "^5.0.1",
|
||||||
"@mui/system": "^5.0.3",
|
"@mui/system": "^5.0.3",
|
||||||
"acorn": "^8.4.1",
|
"@types/estree": "^1.0.0",
|
||||||
"acorn-walk": "^8.1.1",
|
"acorn": "^8.7.1",
|
||||||
|
"acorn-walk": "^8.2.0",
|
||||||
"arg": "^5.0.0",
|
"arg": "^5.0.0",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
"better-react-mathjax": "^1.0.3",
|
"better-react-mathjax": "^1.0.3",
|
||||||
@ -78,7 +79,7 @@
|
|||||||
"html-webpack-plugin": "^3.2.0",
|
"html-webpack-plugin": "^3.2.0",
|
||||||
"http-server": "^13.0.1",
|
"http-server": "^13.0.1",
|
||||||
"jest": "^27.1.0",
|
"jest": "^27.1.0",
|
||||||
"jsdom": "^15.0.0",
|
"jsdom": "^16.5.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"mini-css-extract-plugin": "^0.4.1",
|
"mini-css-extract-plugin": "^0.4.1",
|
||||||
"prettier": "^2.3.2",
|
"prettier": "^2.3.2",
|
||||||
|
@ -24,7 +24,7 @@ import { IMap } from "../types";
|
|||||||
import * as data from "./AchievementData.json";
|
import * as data from "./AchievementData.json";
|
||||||
import { FactionNames } from "../Faction/data/FactionNames";
|
import { FactionNames } from "../Faction/data/FactionNames";
|
||||||
import { BlackOperationNames } from "../Bladeburner/data/BlackOperationNames";
|
import { BlackOperationNames } from "../Bladeburner/data/BlackOperationNames";
|
||||||
import { ClassType } from "../utils/WorkType";
|
import { isClassWork } from "../Work/ClassWork";
|
||||||
|
|
||||||
// Unable to correctly cast the JSON data into AchievementDataJson type otherwise...
|
// Unable to correctly cast the JSON data into AchievementDataJson type otherwise...
|
||||||
const achievementData = (<AchievementDataJson>(<unknown>data)).achievements;
|
const achievementData = (<AchievementDataJson>(<unknown>data)).achievements;
|
||||||
@ -391,10 +391,7 @@ export const achievements: IMap<Achievement> = {
|
|||||||
WORKOUT: {
|
WORKOUT: {
|
||||||
...achievementData["WORKOUT"],
|
...achievementData["WORKOUT"],
|
||||||
Icon: "WORKOUT",
|
Icon: "WORKOUT",
|
||||||
Condition: () =>
|
Condition: () => isClassWork(Player.currentWork),
|
||||||
[ClassType.GymStrength, ClassType.GymDefense, ClassType.GymDexterity, ClassType.GymAgility].includes(
|
|
||||||
Player.className,
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
TOR: {
|
TOR: {
|
||||||
...achievementData["TOR"],
|
...achievementData["TOR"],
|
||||||
|
@ -9,7 +9,7 @@ const style = {
|
|||||||
width: "1060px",
|
width: "1060px",
|
||||||
height: "800px",
|
height: "800px",
|
||||||
border: "0px",
|
border: "0px",
|
||||||
} as any;
|
};
|
||||||
|
|
||||||
export function BBCabinetRoot(): React.ReactElement {
|
export function BBCabinetRoot(): React.ReactElement {
|
||||||
const player = use.Player();
|
const player = use.Player();
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
// Class definition for a single Augmentation object
|
// Class definition for a single Augmentation object
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { IMap } from "../types";
|
|
||||||
|
|
||||||
import { Faction } from "../Faction/Faction";
|
import { Faction } from "../Faction/Faction";
|
||||||
import { Factions } from "../Faction/Factions";
|
import { Factions } from "../Faction/Factions";
|
||||||
import { numeralWrapper } from "../ui/numeralFormat";
|
import { numeralWrapper } from "../ui/numeralFormat";
|
||||||
import { Money } from "../ui/React/Money";
|
import { Money } from "../ui/React/Money";
|
||||||
|
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import { FactionNames } from "../Faction/data/FactionNames";
|
import { FactionNames } from "../Faction/data/FactionNames";
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { AugmentationNames } from "./data/AugmentationNames";
|
import { AugmentationNames } from "./data/AugmentationNames";
|
||||||
@ -16,6 +15,7 @@ import { StaticAugmentations } from "./StaticAugmentations";
|
|||||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
import { getBaseAugmentationPriceMultiplier, getGenericAugmentationPriceMultiplier } from "./AugmentationHelpers";
|
import { getBaseAugmentationPriceMultiplier, getGenericAugmentationPriceMultiplier } from "./AugmentationHelpers";
|
||||||
import { initSoAAugmentations } from "./data/AugmentationCreator";
|
import { initSoAAugmentations } from "./data/AugmentationCreator";
|
||||||
|
import { Multipliers, defaultMultipliers } from "../PersonObjects/Multipliers";
|
||||||
|
|
||||||
export interface AugmentationCosts {
|
export interface AugmentationCosts {
|
||||||
moneyCost: number;
|
moneyCost: number;
|
||||||
@ -32,48 +32,48 @@ export interface IConstructorParams {
|
|||||||
repCost: number;
|
repCost: number;
|
||||||
factions: string[];
|
factions: string[];
|
||||||
|
|
||||||
hacking_mult?: number;
|
hacking?: number;
|
||||||
strength_mult?: number;
|
strength?: number;
|
||||||
defense_mult?: number;
|
defense?: number;
|
||||||
dexterity_mult?: number;
|
dexterity?: number;
|
||||||
agility_mult?: number;
|
agility?: number;
|
||||||
charisma_mult?: number;
|
charisma?: number;
|
||||||
hacking_exp_mult?: number;
|
hacking_exp?: number;
|
||||||
strength_exp_mult?: number;
|
strength_exp?: number;
|
||||||
defense_exp_mult?: number;
|
defense_exp?: number;
|
||||||
dexterity_exp_mult?: number;
|
dexterity_exp?: number;
|
||||||
agility_exp_mult?: number;
|
agility_exp?: number;
|
||||||
charisma_exp_mult?: number;
|
charisma_exp?: number;
|
||||||
hacking_chance_mult?: number;
|
hacking_chance?: number;
|
||||||
hacking_speed_mult?: number;
|
hacking_speed?: number;
|
||||||
hacking_money_mult?: number;
|
hacking_money?: number;
|
||||||
hacking_grow_mult?: number;
|
hacking_grow?: number;
|
||||||
company_rep_mult?: number;
|
company_rep?: number;
|
||||||
faction_rep_mult?: number;
|
faction_rep?: number;
|
||||||
crime_money_mult?: number;
|
crime_money?: number;
|
||||||
crime_success_mult?: number;
|
crime_success?: number;
|
||||||
work_money_mult?: number;
|
work_money?: number;
|
||||||
hacknet_node_money_mult?: number;
|
hacknet_node_money?: number;
|
||||||
hacknet_node_purchase_cost_mult?: number;
|
hacknet_node_purchase_cost?: number;
|
||||||
hacknet_node_ram_cost_mult?: number;
|
hacknet_node_ram_cost?: number;
|
||||||
hacknet_node_core_cost_mult?: number;
|
hacknet_node_core_cost?: number;
|
||||||
hacknet_node_level_cost_mult?: number;
|
hacknet_node_level_cost?: number;
|
||||||
bladeburner_max_stamina_mult?: number;
|
bladeburner_max_stamina?: number;
|
||||||
bladeburner_stamina_gain_mult?: number;
|
bladeburner_stamina_gain?: number;
|
||||||
bladeburner_analysis_mult?: number;
|
bladeburner_analysis?: number;
|
||||||
bladeburner_success_chance_mult?: number;
|
bladeburner_success_chance?: number;
|
||||||
infiltration_base_rep_increase?: number;
|
infiltration_base_rep_increase?: number;
|
||||||
infiltration_rep_mult?: number;
|
infiltration_rep?: number;
|
||||||
infiltration_trade_mult?: number;
|
infiltration_trade?: number;
|
||||||
infiltration_sell_mult?: number;
|
infiltration_sell?: number;
|
||||||
infiltration_timer_mult?: number;
|
infiltration_timer?: number;
|
||||||
infiltration_damage_reduction_mult?: number;
|
infiltration_damage_reduction?: number;
|
||||||
|
|
||||||
startingMoney?: number;
|
startingMoney?: number;
|
||||||
programs?: string[];
|
programs?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateStatsDescription(mults: IMap<number>, programs?: string[], startingMoney?: number): JSX.Element {
|
function generateStatsDescription(mults: Multipliers, programs?: string[], startingMoney?: number): JSX.Element {
|
||||||
const f = (x: number, decimals = 0): string => {
|
const f = (x: number, decimals = 0): string => {
|
||||||
// look, I don't know how to make a "smart decimals"
|
// look, I don't know how to make a "smart decimals"
|
||||||
// todo, make it smarter
|
// todo, make it smarter
|
||||||
@ -84,323 +84,278 @@ function generateStatsDescription(mults: IMap<number>, programs?: string[], star
|
|||||||
let desc = <>Effects:</>;
|
let desc = <>Effects:</>;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
mults.hacking_mult &&
|
mults.hacking !== 1 &&
|
||||||
mults.hacking_mult == mults.strength_mult &&
|
mults.hacking == mults.strength &&
|
||||||
mults.hacking_mult == mults.defense_mult &&
|
mults.hacking == mults.defense &&
|
||||||
mults.hacking_mult == mults.dexterity_mult &&
|
mults.hacking == mults.dexterity &&
|
||||||
mults.hacking_mult == mults.agility_mult &&
|
mults.hacking == mults.agility &&
|
||||||
mults.hacking_mult == mults.charisma_mult
|
mults.hacking == mults.charisma
|
||||||
) {
|
) {
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.hacking_mult - 1)} all skills
|
<br />+{f(mults.hacking - 1)} all skills
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (mults.hacking_mult)
|
if (mults.hacking !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.hacking_mult - 1)} hacking skill
|
<br />+{f(mults.hacking - 1)} hacking skill
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
mults.strength_mult &&
|
mults.strength !== 1 &&
|
||||||
mults.strength_mult == mults.defense_mult &&
|
mults.strength == mults.defense &&
|
||||||
mults.strength_mult == mults.dexterity_mult &&
|
mults.strength == mults.dexterity &&
|
||||||
mults.strength_mult == mults.agility_mult
|
mults.strength == mults.agility
|
||||||
) {
|
) {
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.strength_mult - 1)} combat skills
|
<br />+{f(mults.strength - 1)} combat skills
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (mults.strength_mult)
|
if (mults.strength !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.strength_mult - 1)} strength skill
|
<br />+{f(mults.strength - 1)} strength skill
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.defense_mult)
|
if (mults.defense !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.defense_mult - 1)} defense skill
|
<br />+{f(mults.defense - 1)} defense skill
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.dexterity_mult)
|
if (mults.dexterity !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.dexterity_mult - 1)} dexterity skill
|
<br />+{f(mults.dexterity - 1)} dexterity skill
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.agility_mult)
|
if (mults.agility !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.agility_mult - 1)} agility skill
|
<br />+{f(mults.agility - 1)} agility skill
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (mults.charisma_mult)
|
if (mults.charisma !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.charisma_mult - 1)} charisma skill
|
<br />+{f(mults.charisma - 1)} charisma skill
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
mults.hacking_exp_mult &&
|
mults.hacking_exp !== 1 &&
|
||||||
mults.hacking_exp_mult === mults.strength_exp_mult &&
|
mults.hacking_exp === mults.strength_exp &&
|
||||||
mults.hacking_exp_mult === mults.defense_exp_mult &&
|
mults.hacking_exp === mults.defense_exp &&
|
||||||
mults.hacking_exp_mult === mults.dexterity_exp_mult &&
|
mults.hacking_exp === mults.dexterity_exp &&
|
||||||
mults.hacking_exp_mult === mults.agility_exp_mult &&
|
mults.hacking_exp === mults.agility_exp &&
|
||||||
mults.hacking_exp_mult === mults.charisma_exp_mult
|
mults.hacking_exp === mults.charisma_exp
|
||||||
) {
|
) {
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.hacking_exp_mult - 1)} exp for all skills
|
<br />+{f(mults.hacking_exp - 1)} exp for all skills
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (mults.hacking_exp_mult)
|
if (mults.hacking_exp !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.hacking_exp_mult - 1)} hacking exp
|
<br />+{f(mults.hacking_exp - 1)} hacking exp
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
mults.strength_exp_mult &&
|
mults.strength_exp !== 1 &&
|
||||||
mults.strength_exp_mult === mults.defense_exp_mult &&
|
mults.strength_exp === mults.defense_exp &&
|
||||||
mults.strength_exp_mult === mults.dexterity_exp_mult &&
|
mults.strength_exp === mults.dexterity_exp &&
|
||||||
mults.strength_exp_mult === mults.agility_exp_mult
|
mults.strength_exp === mults.agility_exp
|
||||||
) {
|
) {
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.strength_exp_mult - 1)} combat exp
|
<br />+{f(mults.strength_exp - 1)} combat exp
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (mults.strength_exp_mult)
|
if (mults.strength_exp !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.strength_exp_mult - 1)} strength exp
|
<br />+{f(mults.strength_exp - 1)} strength exp
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.defense_exp_mult)
|
if (mults.defense_exp !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.defense_exp_mult - 1)} defense exp
|
<br />+{f(mults.defense_exp - 1)} defense exp
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.dexterity_exp_mult)
|
if (mults.dexterity_exp !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.dexterity_exp_mult - 1)} dexterity exp
|
<br />+{f(mults.dexterity_exp - 1)} dexterity exp
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.agility_exp_mult)
|
if (mults.agility_exp !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.agility_exp_mult - 1)} agility exp
|
<br />+{f(mults.agility_exp - 1)} agility exp
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (mults.charisma_exp_mult)
|
if (mults.charisma_exp !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.charisma_exp_mult - 1)} charisma exp
|
<br />+{f(mults.charisma_exp - 1)} charisma exp
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mults.hacking_speed_mult)
|
if (mults.hacking_speed !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.hacking_speed_mult - 1)} faster hack(), grow(), and weaken()
|
<br />+{f(mults.hacking_speed - 1)} faster hack(), grow(), and weaken()
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.hacking_chance_mult)
|
if (mults.hacking_chance !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.hacking_chance_mult - 1)} hack() success chance
|
<br />+{f(mults.hacking_chance - 1)} hack() success chance
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.hacking_money_mult)
|
if (mults.hacking_money !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.hacking_money_mult - 1)} hack() power
|
<br />+{f(mults.hacking_money - 1)} hack() power
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.hacking_grow_mult)
|
if (mults.hacking_grow !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.hacking_grow_mult - 1)} grow() power
|
<br />+{f(mults.hacking_grow - 1)} grow() power
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (mults.faction_rep_mult && mults.faction_rep_mult === mults.company_rep_mult) {
|
if (mults.faction_rep !== 1 && mults.faction_rep === mults.company_rep) {
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.faction_rep_mult - 1)} reputation from factions and companies
|
<br />+{f(mults.faction_rep - 1)} reputation from factions and companies
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (mults.faction_rep_mult)
|
if (mults.faction_rep !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.faction_rep_mult - 1)} reputation from factions
|
<br />+{f(mults.faction_rep - 1)} reputation from factions
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.company_rep_mult)
|
if (mults.company_rep !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.company_rep_mult - 1)} reputation from companies
|
<br />+{f(mults.company_rep - 1)} reputation from companies
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mults.crime_money_mult)
|
if (mults.crime_money !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.crime_money_mult - 1)} crime money
|
<br />+{f(mults.crime_money - 1)} crime money
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.crime_success_mult)
|
if (mults.crime_success !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.crime_success_mult - 1)} crime success rate
|
<br />+{f(mults.crime_success - 1)} crime success rate
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.work_money_mult)
|
if (mults.work_money !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.work_money_mult - 1)} work money
|
<br />+{f(mults.work_money - 1)} work money
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (mults.hacknet_node_money_mult)
|
if (mults.hacknet_node_money !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.hacknet_node_money_mult - 1)} hacknet production
|
<br />+{f(mults.hacknet_node_money - 1)} hacknet production
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.hacknet_node_purchase_cost_mult)
|
if (mults.hacknet_node_purchase_cost !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />-{f(-(mults.hacknet_node_purchase_cost_mult - 1))} hacknet nodes cost
|
<br />-{f(-(mults.hacknet_node_purchase_cost - 1))} hacknet nodes cost
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.hacknet_node_level_cost_mult)
|
if (mults.hacknet_node_level_cost !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />-{f(-(mults.hacknet_node_level_cost_mult - 1))} hacknet nodes upgrade cost
|
<br />-{f(-(mults.hacknet_node_level_cost - 1))} hacknet nodes upgrade cost
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (mults.bladeburner_max_stamina_mult)
|
if (mults.bladeburner_max_stamina !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.bladeburner_max_stamina_mult - 1)} Bladeburner Max Stamina
|
<br />+{f(mults.bladeburner_max_stamina - 1)} Bladeburner Max Stamina
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.bladeburner_stamina_gain_mult)
|
if (mults.bladeburner_stamina_gain !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.bladeburner_stamina_gain_mult - 1)} Bladeburner Stamina gain
|
<br />+{f(mults.bladeburner_stamina_gain - 1)} Bladeburner Stamina gain
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.bladeburner_analysis_mult)
|
if (mults.bladeburner_analysis !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.bladeburner_analysis_mult - 1)} Bladeburner Field Analysis effectiveness
|
<br />+{f(mults.bladeburner_analysis - 1)} Bladeburner Field Analysis effectiveness
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.bladeburner_success_chance_mult)
|
if (mults.bladeburner_success_chance !== 1)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
{desc}
|
{desc}
|
||||||
<br />+{f(mults.bladeburner_success_chance_mult - 1)} Bladeburner Contracts and Operations success chance
|
<br />+{f(mults.bladeburner_success_chance - 1)} Bladeburner Contracts and Operations success chance
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
if (mults.infiltration_base_rep_increase)
|
|
||||||
desc = (
|
|
||||||
<>
|
|
||||||
{desc}
|
|
||||||
<br />+{f(mults.infiltration_base_rep_increase - 1)} Infiltration {FactionNames.ShadowsOfAnarchy} Reputation
|
|
||||||
base reward
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
if (mults.infiltration_rep_mult)
|
|
||||||
desc = (
|
|
||||||
<>
|
|
||||||
{desc}
|
|
||||||
<br />+{f(mults.infiltration_rep_mult - 1)} Infiltration {FactionNames.ShadowsOfAnarchy} Reputation reward
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
if (mults.infiltration_trade_mult)
|
|
||||||
desc = (
|
|
||||||
<>
|
|
||||||
{desc}
|
|
||||||
<br />+{f(mults.infiltration_trade_mult - 1)} Infiltration Reputation for trading information
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
if (mults.infiltration_sell_mult)
|
|
||||||
desc = (
|
|
||||||
<>
|
|
||||||
{desc}
|
|
||||||
<br />+{f(mults.infiltration_sell_mult - 1)} Infiltration cash reward for selling information
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
if (mults.infiltration_timer_mult)
|
|
||||||
desc = (
|
|
||||||
<>
|
|
||||||
{desc}
|
|
||||||
<br />+{f(mults.infiltration_timer_mult - 1)} Infiltration time per minigame
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
if (mults.infiltration_damage_reduction_mult)
|
|
||||||
desc = (
|
|
||||||
<>
|
|
||||||
{desc}
|
|
||||||
<br />
|
|
||||||
{f(mults.infiltration_damage_reduction_mult - 1)} Infiltration health lost per failed minigame
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (startingMoney)
|
if (startingMoney)
|
||||||
desc = (
|
desc = (
|
||||||
<>
|
<>
|
||||||
@ -445,7 +400,7 @@ export class Augmentation {
|
|||||||
|
|
||||||
// Multipliers given by this Augmentation. Must match the property name in
|
// Multipliers given by this Augmentation. Must match the property name in
|
||||||
// The Player/Person classes
|
// The Player/Person classes
|
||||||
mults: IMap<number> = {};
|
mults: Multipliers = defaultMultipliers();
|
||||||
|
|
||||||
// Factions that offer this aug.
|
// Factions that offer this aug.
|
||||||
factions: string[] = [];
|
factions: string[] = [];
|
||||||
@ -474,114 +429,95 @@ export class Augmentation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set multipliers
|
// Set multipliers
|
||||||
if (params.hacking_mult) {
|
if (params.hacking) {
|
||||||
this.mults.hacking_mult = params.hacking_mult;
|
this.mults.hacking = params.hacking;
|
||||||
}
|
}
|
||||||
if (params.strength_mult) {
|
if (params.strength) {
|
||||||
this.mults.strength_mult = params.strength_mult;
|
this.mults.strength = params.strength;
|
||||||
}
|
}
|
||||||
if (params.defense_mult) {
|
if (params.defense) {
|
||||||
this.mults.defense_mult = params.defense_mult;
|
this.mults.defense = params.defense;
|
||||||
}
|
}
|
||||||
if (params.dexterity_mult) {
|
if (params.dexterity) {
|
||||||
this.mults.dexterity_mult = params.dexterity_mult;
|
this.mults.dexterity = params.dexterity;
|
||||||
}
|
}
|
||||||
if (params.agility_mult) {
|
if (params.agility) {
|
||||||
this.mults.agility_mult = params.agility_mult;
|
this.mults.agility = params.agility;
|
||||||
}
|
}
|
||||||
if (params.charisma_mult) {
|
if (params.charisma) {
|
||||||
this.mults.charisma_mult = params.charisma_mult;
|
this.mults.charisma = params.charisma;
|
||||||
}
|
}
|
||||||
if (params.hacking_exp_mult) {
|
if (params.hacking_exp) {
|
||||||
this.mults.hacking_exp_mult = params.hacking_exp_mult;
|
this.mults.hacking_exp = params.hacking_exp;
|
||||||
}
|
}
|
||||||
if (params.strength_exp_mult) {
|
if (params.strength_exp) {
|
||||||
this.mults.strength_exp_mult = params.strength_exp_mult;
|
this.mults.strength_exp = params.strength_exp;
|
||||||
}
|
}
|
||||||
if (params.defense_exp_mult) {
|
if (params.defense_exp) {
|
||||||
this.mults.defense_exp_mult = params.defense_exp_mult;
|
this.mults.defense_exp = params.defense_exp;
|
||||||
}
|
}
|
||||||
if (params.dexterity_exp_mult) {
|
if (params.dexterity_exp) {
|
||||||
this.mults.dexterity_exp_mult = params.dexterity_exp_mult;
|
this.mults.dexterity_exp = params.dexterity_exp;
|
||||||
}
|
}
|
||||||
if (params.agility_exp_mult) {
|
if (params.agility_exp) {
|
||||||
this.mults.agility_exp_mult = params.agility_exp_mult;
|
this.mults.agility_exp = params.agility_exp;
|
||||||
}
|
}
|
||||||
if (params.charisma_exp_mult) {
|
if (params.charisma_exp) {
|
||||||
this.mults.charisma_exp_mult = params.charisma_exp_mult;
|
this.mults.charisma_exp = params.charisma_exp;
|
||||||
}
|
}
|
||||||
if (params.hacking_chance_mult) {
|
if (params.hacking_chance) {
|
||||||
this.mults.hacking_chance_mult = params.hacking_chance_mult;
|
this.mults.hacking_chance = params.hacking_chance;
|
||||||
}
|
}
|
||||||
if (params.hacking_speed_mult) {
|
if (params.hacking_speed) {
|
||||||
this.mults.hacking_speed_mult = params.hacking_speed_mult;
|
this.mults.hacking_speed = params.hacking_speed;
|
||||||
}
|
}
|
||||||
if (params.hacking_money_mult) {
|
if (params.hacking_money) {
|
||||||
this.mults.hacking_money_mult = params.hacking_money_mult;
|
this.mults.hacking_money = params.hacking_money;
|
||||||
}
|
}
|
||||||
if (params.hacking_grow_mult) {
|
if (params.hacking_grow) {
|
||||||
this.mults.hacking_grow_mult = params.hacking_grow_mult;
|
this.mults.hacking_grow = params.hacking_grow;
|
||||||
}
|
}
|
||||||
if (params.company_rep_mult) {
|
if (params.company_rep) {
|
||||||
this.mults.company_rep_mult = params.company_rep_mult;
|
this.mults.company_rep = params.company_rep;
|
||||||
}
|
}
|
||||||
if (params.faction_rep_mult) {
|
if (params.faction_rep) {
|
||||||
this.mults.faction_rep_mult = params.faction_rep_mult;
|
this.mults.faction_rep = params.faction_rep;
|
||||||
}
|
}
|
||||||
if (params.crime_money_mult) {
|
if (params.crime_money) {
|
||||||
this.mults.crime_money_mult = params.crime_money_mult;
|
this.mults.crime_money = params.crime_money;
|
||||||
}
|
}
|
||||||
if (params.crime_success_mult) {
|
if (params.crime_success) {
|
||||||
this.mults.crime_success_mult = params.crime_success_mult;
|
this.mults.crime_success = params.crime_success;
|
||||||
}
|
}
|
||||||
if (params.work_money_mult) {
|
if (params.work_money) {
|
||||||
this.mults.work_money_mult = params.work_money_mult;
|
this.mults.work_money = params.work_money;
|
||||||
}
|
}
|
||||||
if (params.hacknet_node_money_mult) {
|
if (params.hacknet_node_money) {
|
||||||
this.mults.hacknet_node_money_mult = params.hacknet_node_money_mult;
|
this.mults.hacknet_node_money = params.hacknet_node_money;
|
||||||
}
|
}
|
||||||
if (params.hacknet_node_purchase_cost_mult) {
|
if (params.hacknet_node_purchase_cost) {
|
||||||
this.mults.hacknet_node_purchase_cost_mult = params.hacknet_node_purchase_cost_mult;
|
this.mults.hacknet_node_purchase_cost = params.hacknet_node_purchase_cost;
|
||||||
}
|
}
|
||||||
if (params.hacknet_node_ram_cost_mult) {
|
if (params.hacknet_node_ram_cost) {
|
||||||
this.mults.hacknet_node_ram_cost_mult = params.hacknet_node_ram_cost_mult;
|
this.mults.hacknet_node_ram_cost = params.hacknet_node_ram_cost;
|
||||||
}
|
}
|
||||||
if (params.hacknet_node_core_cost_mult) {
|
if (params.hacknet_node_core_cost) {
|
||||||
this.mults.hacknet_node_core_cost_mult = params.hacknet_node_core_cost_mult;
|
this.mults.hacknet_node_core_cost = params.hacknet_node_core_cost;
|
||||||
}
|
}
|
||||||
if (params.hacknet_node_level_cost_mult) {
|
if (params.hacknet_node_level_cost) {
|
||||||
this.mults.hacknet_node_level_cost_mult = params.hacknet_node_level_cost_mult;
|
this.mults.hacknet_node_level_cost = params.hacknet_node_level_cost;
|
||||||
}
|
}
|
||||||
if (params.bladeburner_max_stamina_mult) {
|
if (params.bladeburner_max_stamina) {
|
||||||
this.mults.bladeburner_max_stamina_mult = params.bladeburner_max_stamina_mult;
|
this.mults.bladeburner_max_stamina = params.bladeburner_max_stamina;
|
||||||
}
|
}
|
||||||
if (params.bladeburner_stamina_gain_mult) {
|
if (params.bladeburner_stamina_gain) {
|
||||||
this.mults.bladeburner_stamina_gain_mult = params.bladeburner_stamina_gain_mult;
|
this.mults.bladeburner_stamina_gain = params.bladeburner_stamina_gain;
|
||||||
}
|
}
|
||||||
if (params.bladeburner_analysis_mult) {
|
if (params.bladeburner_analysis) {
|
||||||
this.mults.bladeburner_analysis_mult = params.bladeburner_analysis_mult;
|
this.mults.bladeburner_analysis = params.bladeburner_analysis;
|
||||||
}
|
}
|
||||||
if (params.bladeburner_success_chance_mult) {
|
if (params.bladeburner_success_chance) {
|
||||||
this.mults.bladeburner_success_chance_mult = params.bladeburner_success_chance_mult;
|
this.mults.bladeburner_success_chance = params.bladeburner_success_chance;
|
||||||
}
|
|
||||||
|
|
||||||
if (params.infiltration_base_rep_increase) {
|
|
||||||
this.mults.infiltration_base_rep_increase = params.infiltration_base_rep_increase;
|
|
||||||
}
|
|
||||||
if (params.infiltration_rep_mult) {
|
|
||||||
this.mults.infiltration_rep_mult = params.infiltration_rep_mult;
|
|
||||||
}
|
|
||||||
if (params.infiltration_trade_mult) {
|
|
||||||
this.mults.infiltration_trade_mult = params.infiltration_trade_mult;
|
|
||||||
}
|
|
||||||
if (params.infiltration_sell_mult) {
|
|
||||||
this.mults.infiltration_sell_mult = params.infiltration_sell_mult;
|
|
||||||
}
|
|
||||||
if (params.infiltration_timer_mult) {
|
|
||||||
this.mults.infiltration_timer_mult = params.infiltration_timer_mult;
|
|
||||||
}
|
|
||||||
if (params.infiltration_damage_reduction_mult) {
|
|
||||||
this.mults.infiltration_damage_reduction_mult = params.infiltration_damage_reduction_mult;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.stats === undefined)
|
if (params.stats === undefined)
|
||||||
@ -673,13 +609,12 @@ export class Augmentation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Serialize the current object to a JSON save state.
|
// Serialize the current object to a JSON save state.
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("Augmentation", this);
|
return Generic_toJSON("Augmentation", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initiatizes a Augmentation object from a JSON save state.
|
// Initiatizes a Augmentation object from a JSON save state.
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): Augmentation {
|
||||||
static fromJSON(value: any): Augmentation {
|
|
||||||
return Generic_fromJSON(Augmentation, value.data);
|
return Generic_fromJSON(Augmentation, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import {
|
|||||||
initUnstableCircadianModulator,
|
initUnstableCircadianModulator,
|
||||||
} from "./data/AugmentationCreator";
|
} from "./data/AugmentationCreator";
|
||||||
import { Router } from "../ui/GameRoot";
|
import { Router } from "../ui/GameRoot";
|
||||||
|
import { mergeMultipliers } from "../PersonObjects/Multipliers";
|
||||||
|
|
||||||
export function AddToStaticAugmentations(aug: Augmentation): void {
|
export function AddToStaticAugmentations(aug: Augmentation): void {
|
||||||
const name = aug.name;
|
const name = aug.name;
|
||||||
@ -74,10 +75,7 @@ function applyAugmentation(aug: IPlayerOwnedAugmentation, reapply = false): void
|
|||||||
const staticAugmentation = StaticAugmentations[aug.name];
|
const staticAugmentation = StaticAugmentations[aug.name];
|
||||||
|
|
||||||
// Apply multipliers
|
// Apply multipliers
|
||||||
for (const mult of Object.keys(staticAugmentation.mults)) {
|
Player.mults = mergeMultipliers(Player.mults, staticAugmentation.mults);
|
||||||
const v = Player.getMult(mult) * staticAugmentation.mults[mult];
|
|
||||||
Player.setMult(mult, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special logic for Congruity Implant
|
// Special logic for Congruity Implant
|
||||||
if (aug.name === AugmentationNames.CongruityImplant && !reapply) {
|
if (aug.name === AugmentationNames.CongruityImplant && !reapply) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -4,24 +4,18 @@
|
|||||||
import { DoubleArrow } from "@mui/icons-material";
|
import { DoubleArrow } from "@mui/icons-material";
|
||||||
import { List, ListItem, ListItemText, Paper, Typography } from "@mui/material";
|
import { List, ListItem, ListItemText, Paper, Typography } from "@mui/material";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
import { Multipliers, defaultMultipliers, mergeMultipliers } from "../../PersonObjects/Multipliers";
|
||||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||||
import { Player } from "../../Player";
|
import { Player } from "../../Player";
|
||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../Settings/Settings";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
import { StaticAugmentations } from "../StaticAugmentations";
|
import { StaticAugmentations } from "../StaticAugmentations";
|
||||||
|
|
||||||
interface IAugmentedStats {
|
function calculateAugmentedStats(): Multipliers {
|
||||||
[index: string]: number;
|
let augP: Multipliers = defaultMultipliers();
|
||||||
}
|
|
||||||
|
|
||||||
function calculateAugmentedStats(): IAugmentedStats {
|
|
||||||
const augP: IAugmentedStats = {};
|
|
||||||
for (const aug of Player.queuedAugmentations) {
|
for (const aug of Player.queuedAugmentations) {
|
||||||
const augObj = StaticAugmentations[aug.name];
|
const augObj = StaticAugmentations[aug.name];
|
||||||
for (const mult of Object.keys(augObj.mults)) {
|
augP = mergeMultipliers(augP, augObj.mults);
|
||||||
const v = augP[mult] ? augP[mult] : 1;
|
|
||||||
augP[mult] = v * augObj.mults[mult];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return augP;
|
return augP;
|
||||||
}
|
}
|
||||||
@ -98,35 +92,35 @@ export function PlayerMultipliers(): React.ReactElement {
|
|||||||
...[
|
...[
|
||||||
{
|
{
|
||||||
mult: "Hacking Chance",
|
mult: "Hacking Chance",
|
||||||
current: Player.hacking_chance_mult,
|
current: Player.mults.hacking_chance,
|
||||||
augmented: Player.hacking_chance_mult * mults.hacking_chance_mult,
|
augmented: Player.mults.hacking_chance * mults.hacking_chance,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Hacking Speed",
|
mult: "Hacking Speed",
|
||||||
current: Player.hacking_speed_mult,
|
current: Player.mults.hacking_speed,
|
||||||
augmented: Player.hacking_speed_mult * mults.hacking_speed_mult,
|
augmented: Player.mults.hacking_speed * mults.hacking_speed,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Hacking Money",
|
mult: "Hacking Money",
|
||||||
current: Player.hacking_money_mult,
|
current: Player.mults.hacking_money,
|
||||||
augmented: Player.hacking_money_mult * mults.hacking_money_mult,
|
augmented: Player.mults.hacking_money * mults.hacking_money,
|
||||||
bnMult: BitNodeMultipliers.ScriptHackMoney,
|
bnMult: BitNodeMultipliers.ScriptHackMoney,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Hacking Growth",
|
mult: "Hacking Growth",
|
||||||
current: Player.hacking_grow_mult,
|
current: Player.mults.hacking_grow,
|
||||||
augmented: Player.hacking_grow_mult * mults.hacking_grow_mult,
|
augmented: Player.mults.hacking_grow * mults.hacking_grow,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Hacking Level",
|
mult: "Hacking Level",
|
||||||
current: Player.hacking_mult,
|
current: Player.mults.hacking,
|
||||||
augmented: Player.hacking_mult * mults.hacking_mult,
|
augmented: Player.mults.hacking * mults.hacking,
|
||||||
bnMult: BitNodeMultipliers.HackingLevelMultiplier,
|
bnMult: BitNodeMultipliers.HackingLevelMultiplier,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Hacking Experience",
|
mult: "Hacking Experience",
|
||||||
current: Player.hacking_exp_mult,
|
current: Player.mults.hacking_exp,
|
||||||
augmented: Player.hacking_exp_mult * mults.hacking_exp_mult,
|
augmented: Player.mults.hacking_exp * mults.hacking_exp,
|
||||||
bnMult: BitNodeMultipliers.HackExpGain,
|
bnMult: BitNodeMultipliers.HackExpGain,
|
||||||
},
|
},
|
||||||
].map((data: MultiplierListItemData) =>
|
].map((data: MultiplierListItemData) =>
|
||||||
@ -137,47 +131,47 @@ export function PlayerMultipliers(): React.ReactElement {
|
|||||||
...[
|
...[
|
||||||
{
|
{
|
||||||
mult: "Strength Level",
|
mult: "Strength Level",
|
||||||
current: Player.strength_mult,
|
current: Player.mults.strength,
|
||||||
augmented: Player.strength_mult * mults.strength_mult,
|
augmented: Player.mults.strength * mults.strength,
|
||||||
bnMult: BitNodeMultipliers.StrengthLevelMultiplier,
|
bnMult: BitNodeMultipliers.StrengthLevelMultiplier,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Strength Experience",
|
mult: "Strength Experience",
|
||||||
current: Player.strength_exp_mult,
|
current: Player.mults.strength_exp,
|
||||||
augmented: Player.strength_exp_mult * mults.strength_exp_mult,
|
augmented: Player.mults.strength_exp * mults.strength_exp,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Defense Level",
|
mult: "Defense Level",
|
||||||
current: Player.defense_mult,
|
current: Player.mults.defense,
|
||||||
augmented: Player.defense_mult * mults.defense_mult,
|
augmented: Player.mults.defense * mults.defense,
|
||||||
bnMult: BitNodeMultipliers.DefenseLevelMultiplier,
|
bnMult: BitNodeMultipliers.DefenseLevelMultiplier,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Defense Experience",
|
mult: "Defense Experience",
|
||||||
current: Player.defense_exp_mult,
|
current: Player.mults.defense_exp,
|
||||||
augmented: Player.defense_exp_mult * mults.defense_exp_mult,
|
augmented: Player.mults.defense_exp * mults.defense_exp,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Dexterity Level",
|
mult: "Dexterity Level",
|
||||||
current: Player.dexterity_mult,
|
current: Player.mults.dexterity,
|
||||||
augmented: Player.dexterity_mult * mults.dexterity_mult,
|
augmented: Player.mults.dexterity * mults.dexterity,
|
||||||
bnMult: BitNodeMultipliers.DexterityLevelMultiplier,
|
bnMult: BitNodeMultipliers.DexterityLevelMultiplier,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Dexterity Experience",
|
mult: "Dexterity Experience",
|
||||||
current: Player.dexterity_exp_mult,
|
current: Player.mults.dexterity_exp,
|
||||||
augmented: Player.dexterity_exp_mult * mults.dexterity_exp_mult,
|
augmented: Player.mults.dexterity_exp * mults.dexterity_exp,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Agility Level",
|
mult: "Agility Level",
|
||||||
current: Player.agility_mult,
|
current: Player.mults.agility,
|
||||||
augmented: Player.agility_mult * mults.agility_mult,
|
augmented: Player.mults.agility * mults.agility,
|
||||||
bnMult: BitNodeMultipliers.AgilityLevelMultiplier,
|
bnMult: BitNodeMultipliers.AgilityLevelMultiplier,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Agility Experience",
|
mult: "Agility Experience",
|
||||||
current: Player.agility_exp_mult,
|
current: Player.mults.agility_exp,
|
||||||
augmented: Player.agility_exp_mult * mults.agility_exp_mult,
|
augmented: Player.mults.agility_exp * mults.agility_exp,
|
||||||
},
|
},
|
||||||
].map((data: MultiplierListItemData) =>
|
].map((data: MultiplierListItemData) =>
|
||||||
Object.defineProperty(data, "color", {
|
Object.defineProperty(data, "color", {
|
||||||
@ -186,73 +180,73 @@ export function PlayerMultipliers(): React.ReactElement {
|
|||||||
),
|
),
|
||||||
{
|
{
|
||||||
mult: "Charisma Level",
|
mult: "Charisma Level",
|
||||||
current: Player.charisma_mult,
|
current: Player.mults.charisma,
|
||||||
augmented: Player.charisma_mult * mults.charisma_mult,
|
augmented: Player.mults.charisma * mults.charisma,
|
||||||
bnMult: BitNodeMultipliers.CharismaLevelMultiplier,
|
bnMult: BitNodeMultipliers.CharismaLevelMultiplier,
|
||||||
color: Settings.theme.cha,
|
color: Settings.theme.cha,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Charisma Experience",
|
mult: "Charisma Experience",
|
||||||
current: Player.charisma_exp_mult,
|
current: Player.mults.charisma_exp,
|
||||||
augmented: Player.charisma_exp_mult * mults.charisma_exp_mult,
|
augmented: Player.mults.charisma_exp * mults.charisma_exp,
|
||||||
color: Settings.theme.cha,
|
color: Settings.theme.cha,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const rightColData: MultiplierListItemData[] = [
|
const rightColData: MultiplierListItemData[] = [
|
||||||
{
|
{
|
||||||
mult: "Hacknet Node Production",
|
mult: "Hacknet Node Production",
|
||||||
current: Player.hacknet_node_money_mult,
|
current: Player.mults.hacknet_node_money,
|
||||||
augmented: Player.hacknet_node_money_mult * mults.hacknet_node_money_mult,
|
augmented: Player.mults.hacknet_node_money * mults.hacknet_node_money,
|
||||||
bnMult: BitNodeMultipliers.HacknetNodeMoney,
|
bnMult: BitNodeMultipliers.HacknetNodeMoney,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Hacknet Node Purchase Cost",
|
mult: "Hacknet Node Purchase Cost",
|
||||||
current: Player.hacknet_node_purchase_cost_mult,
|
current: Player.mults.hacknet_node_purchase_cost,
|
||||||
augmented: Player.hacknet_node_purchase_cost_mult * mults.hacknet_node_purchase_cost_mult,
|
augmented: Player.mults.hacknet_node_purchase_cost * mults.hacknet_node_purchase_cost,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Hacknet Node RAM Upgrade Cost",
|
mult: "Hacknet Node RAM Upgrade Cost",
|
||||||
current: Player.hacknet_node_ram_cost_mult,
|
current: Player.mults.hacknet_node_ram_cost,
|
||||||
augmented: Player.hacknet_node_ram_cost_mult * mults.hacknet_node_ram_cost_mult,
|
augmented: Player.mults.hacknet_node_ram_cost * mults.hacknet_node_ram_cost,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Hacknet Node Core Purchase Cost",
|
mult: "Hacknet Node Core Purchase Cost",
|
||||||
current: Player.hacknet_node_core_cost_mult,
|
current: Player.mults.hacknet_node_core_cost,
|
||||||
augmented: Player.hacknet_node_core_cost_mult * mults.hacknet_node_core_cost_mult,
|
augmented: Player.mults.hacknet_node_core_cost * mults.hacknet_node_core_cost,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Hacknet Node Level Upgrade Cost",
|
mult: "Hacknet Node Level Upgrade Cost",
|
||||||
current: Player.hacknet_node_level_cost_mult,
|
current: Player.mults.hacknet_node_level_cost,
|
||||||
augmented: Player.hacknet_node_level_cost_mult * mults.hacknet_node_level_cost_mult,
|
augmented: Player.mults.hacknet_node_level_cost * mults.hacknet_node_level_cost,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Company Reputation Gain",
|
mult: "Company Reputation Gain",
|
||||||
current: Player.company_rep_mult,
|
current: Player.mults.company_rep,
|
||||||
augmented: Player.company_rep_mult * mults.company_rep_mult,
|
augmented: Player.mults.company_rep * mults.company_rep,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Faction Reputation Gain",
|
mult: "Faction Reputation Gain",
|
||||||
current: Player.faction_rep_mult,
|
current: Player.mults.faction_rep,
|
||||||
augmented: Player.faction_rep_mult * mults.faction_rep_mult,
|
augmented: Player.mults.faction_rep * mults.faction_rep,
|
||||||
bnMult: BitNodeMultipliers.FactionWorkRepGain,
|
bnMult: BitNodeMultipliers.FactionWorkRepGain,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Salary",
|
mult: "Salary",
|
||||||
current: Player.work_money_mult,
|
current: Player.mults.work_money,
|
||||||
augmented: Player.work_money_mult * mults.work_money_mult,
|
augmented: Player.mults.work_money * mults.work_money,
|
||||||
bnMult: BitNodeMultipliers.CompanyWorkMoney,
|
bnMult: BitNodeMultipliers.CompanyWorkMoney,
|
||||||
color: Settings.theme.money,
|
color: Settings.theme.money,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Crime Success Chance",
|
mult: "Crime Success Chance",
|
||||||
current: Player.crime_success_mult,
|
current: Player.mults.crime_success,
|
||||||
augmented: Player.crime_success_mult * mults.crime_success_mult,
|
augmented: Player.mults.crime_success * mults.crime_success,
|
||||||
color: Settings.theme.combat,
|
color: Settings.theme.combat,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Crime Money",
|
mult: "Crime Money",
|
||||||
current: Player.crime_money_mult,
|
current: Player.mults.crime_money,
|
||||||
augmented: Player.crime_money_mult * mults.crime_money_mult,
|
augmented: Player.mults.crime_money * mults.crime_money,
|
||||||
bnMult: BitNodeMultipliers.CrimeMoney,
|
bnMult: BitNodeMultipliers.CrimeMoney,
|
||||||
color: Settings.theme.money,
|
color: Settings.theme.money,
|
||||||
},
|
},
|
||||||
@ -262,23 +256,23 @@ export function PlayerMultipliers(): React.ReactElement {
|
|||||||
rightColData.push(
|
rightColData.push(
|
||||||
{
|
{
|
||||||
mult: "Bladeburner Success Chance",
|
mult: "Bladeburner Success Chance",
|
||||||
current: Player.bladeburner_success_chance_mult,
|
current: Player.mults.bladeburner_success_chance,
|
||||||
augmented: Player.bladeburner_success_chance_mult * mults.bladeburner_success_chance_mult,
|
augmented: Player.mults.bladeburner_success_chance * mults.bladeburner_success_chance,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Bladeburner Max Stamina",
|
mult: "Bladeburner Max Stamina",
|
||||||
current: Player.bladeburner_max_stamina_mult,
|
current: Player.mults.bladeburner_max_stamina,
|
||||||
augmented: Player.bladeburner_max_stamina_mult * mults.bladeburner_max_stamina_mult,
|
augmented: Player.mults.bladeburner_max_stamina * mults.bladeburner_max_stamina,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Bladeburner Stamina Gain",
|
mult: "Bladeburner Stamina Gain",
|
||||||
current: Player.bladeburner_stamina_gain_mult,
|
current: Player.mults.bladeburner_stamina_gain,
|
||||||
augmented: Player.bladeburner_stamina_gain_mult * mults.bladeburner_stamina_gain_mult,
|
augmented: Player.mults.bladeburner_stamina_gain * mults.bladeburner_stamina_gain,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
mult: "Bladeburner Field Analysis",
|
mult: "Bladeburner Field Analysis",
|
||||||
current: Player.bladeburner_analysis_mult,
|
current: Player.mults.bladeburner_analysis,
|
||||||
augmented: Player.bladeburner_analysis_mult * mults.bladeburner_analysis_mult,
|
augmented: Player.mults.bladeburner_analysis * mults.bladeburner_analysis,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ interface IBNMultTableProps {
|
|||||||
|
|
||||||
const BNMultTable = (props: IBNMultTableProps): React.ReactElement => {
|
const BNMultTable = (props: IBNMultTableProps): React.ReactElement => {
|
||||||
const rowsArray = Object.entries(props.rowData)
|
const rowsArray = Object.entries(props.rowData)
|
||||||
.filter(([key, _value]) => props.mults[key] !== defaultMultipliers[key])
|
.filter(([key]) => props.mults[key] !== defaultMultipliers[key])
|
||||||
.map(([key, value]) => (
|
.map(([key, value]) => (
|
||||||
<StatsRow
|
<StatsRow
|
||||||
key={uniqueId()}
|
key={uniqueId()}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Player } from "../Player";
|
import { Player } from "../Player";
|
||||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
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, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import { BladeburnerConstants } from "./data/Constants";
|
import { BladeburnerConstants } from "./data/Constants";
|
||||||
import { IBladeburner } from "./IBladeburner";
|
import { IBladeburner } from "./IBladeburner";
|
||||||
import { IAction, ISuccessChanceParams } from "./IAction";
|
import { IAction, ISuccessChanceParams } from "./IAction";
|
||||||
@ -274,7 +274,7 @@ export class Action implements IAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Augmentation multiplier
|
// Augmentation multiplier
|
||||||
competence *= Player.bladeburner_success_chance_mult;
|
competence *= Player.mults.bladeburner_success_chance;
|
||||||
|
|
||||||
if (isNaN(competence)) {
|
if (isNaN(competence)) {
|
||||||
throw new Error("Competence calculated as NaN in Action.getSuccessChance()");
|
throw new Error("Competence calculated as NaN in Action.getSuccessChance()");
|
||||||
@ -292,12 +292,11 @@ export class Action implements IAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("Action", this);
|
return Generic_toJSON("Action", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): Action {
|
||||||
static fromJSON(value: any): Action {
|
|
||||||
return Generic_fromJSON(Action, value.data);
|
return Generic_fromJSON(Action, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { IActionIdentifier } from "./IActionIdentifier";
|
import { IActionIdentifier } from "./IActionIdentifier";
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
|
|
||||||
interface IParams {
|
interface IParams {
|
||||||
name?: string;
|
name?: string;
|
||||||
@ -15,12 +15,11 @@ export class ActionIdentifier implements IActionIdentifier {
|
|||||||
if (params.type) this.type = params.type;
|
if (params.type) this.type = params.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("ActionIdentifier", this);
|
return Generic_toJSON("ActionIdentifier", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): ActionIdentifier {
|
||||||
static fromJSON(value: any): ActionIdentifier {
|
|
||||||
return Generic_fromJSON(ActionIdentifier, value.data);
|
return Generic_fromJSON(ActionIdentifier, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Operation, IOperationParams } from "./Operation";
|
import { Operation, IOperationParams } from "./Operation";
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
|
|
||||||
export class BlackOperation extends Operation {
|
export class BlackOperation extends Operation {
|
||||||
constructor(params: IOperationParams | null = null) {
|
constructor(params: IOperationParams | null = null) {
|
||||||
@ -20,12 +20,11 @@ export class BlackOperation extends Operation {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("BlackOperation", this);
|
return Generic_toJSON("BlackOperation", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): Operation {
|
||||||
static fromJSON(value: any): Operation {
|
|
||||||
return Generic_fromJSON(BlackOperation, value.data);
|
return Generic_fromJSON(BlackOperation, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../utils/JSONReviver";
|
import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
||||||
import { IBladeburner } from "./IBladeburner";
|
import { IBladeburner } from "./IBladeburner";
|
||||||
import { IActionIdentifier } from "./IActionIdentifier";
|
import { IActionIdentifier } from "./IActionIdentifier";
|
||||||
import { ActionIdentifier } from "./ActionIdentifier";
|
import { ActionIdentifier } from "./ActionIdentifier";
|
||||||
@ -178,7 +178,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
return this.resetAction();
|
return this.resetAction();
|
||||||
}
|
}
|
||||||
this.actionTimeToComplete = action.getActionTime(this, person);
|
this.actionTimeToComplete = action.getActionTime(this, person);
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -195,7 +195,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
return this.resetAction();
|
return this.resetAction();
|
||||||
}
|
}
|
||||||
this.actionTimeToComplete = action.getActionTime(this, person);
|
this.actionTimeToComplete = action.getActionTime(this, person);
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -213,7 +213,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
throw new Error("action should not be null");
|
throw new Error("action should not be null");
|
||||||
}
|
}
|
||||||
this.actionTimeToComplete = testBlackOp.action.getActionTime(this, person);
|
this.actionTimeToComplete = testBlackOp.action.getActionTime(this, person);
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -264,7 +264,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
for (let i = 0; i < arrayOfCommands.length; ++i) {
|
for (let i = 0; i < arrayOfCommands.length; ++i) {
|
||||||
this.executeConsoleCommand(player, arrayOfCommands[i]);
|
this.executeConsoleCommand(player, arrayOfCommands[i]);
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -794,21 +794,9 @@ export class Bladeburner implements IBladeburner {
|
|||||||
let i = 0;
|
let i = 0;
|
||||||
while (i < command.length) {
|
while (i < command.length) {
|
||||||
const c = command.charAt(i);
|
const c = command.charAt(i);
|
||||||
if (c === '"') {
|
if (c === '"' || c === "'") {
|
||||||
// Double quotes
|
// Double quotes or Single quotes
|
||||||
const endQuote = command.indexOf('"', i + 1);
|
const endQuote = command.indexOf(c, i + 1);
|
||||||
if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === KEY.SPACE)) {
|
|
||||||
args.push(command.substr(i + 1, endQuote - i - 1));
|
|
||||||
if (endQuote === command.length - 1) {
|
|
||||||
start = i = endQuote + 1;
|
|
||||||
} else {
|
|
||||||
start = i = endQuote + 2; // Skip the space
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else if (c === "'") {
|
|
||||||
// Single quotes, same thing as above
|
|
||||||
const endQuote = command.indexOf("'", i + 1);
|
|
||||||
if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === KEY.SPACE)) {
|
if (endQuote !== -1 && (endQuote === command.length - 1 || command.charAt(endQuote + 1) === KEY.SPACE)) {
|
||||||
args.push(command.substr(i + 1, endQuote - i - 1));
|
args.push(command.substr(i + 1, endQuote - i - 1));
|
||||||
if (endQuote === command.length - 1) {
|
if (endQuote === command.length - 1) {
|
||||||
@ -1367,7 +1355,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
if (action.autoLevel) {
|
if (action.autoLevel) {
|
||||||
action.level = action.maxLevel;
|
action.level = action.maxLevel;
|
||||||
} // Autolevel
|
} // Autolevel
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1462,17 +1450,17 @@ export class Bladeburner implements IBladeburner {
|
|||||||
this.log(`${person.whoAmI()}: You lost ${formatNumber(losses, 0)} team members during ${action.name}`);
|
this.log(`${person.whoAmI()}: You lost ${formatNumber(losses, 0)} team members during ${action.name}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ActionTypes["Training"]: {
|
case ActionTypes["Training"]: {
|
||||||
this.stamina -= 0.5 * BladeburnerConstants.BaseStaminaLoss;
|
this.stamina -= 0.5 * BladeburnerConstants.BaseStaminaLoss;
|
||||||
const strExpGain = 30 * person.strength_exp_mult,
|
const strExpGain = 30 * person.mults.strength_exp,
|
||||||
defExpGain = 30 * person.defense_exp_mult,
|
defExpGain = 30 * person.mults.defense_exp,
|
||||||
dexExpGain = 30 * person.dexterity_exp_mult,
|
dexExpGain = 30 * person.mults.dexterity_exp,
|
||||||
agiExpGain = 30 * person.agility_exp_mult,
|
agiExpGain = 30 * person.mults.agility_exp,
|
||||||
staminaGain = 0.04 * this.skillMultipliers.stamina;
|
staminaGain = 0.04 * this.skillMultipliers.stamina;
|
||||||
retValue.str = strExpGain;
|
retValue.str = strExpGain;
|
||||||
retValue.def = defExpGain;
|
retValue.def = defExpGain;
|
||||||
@ -1504,12 +1492,12 @@ export class Bladeburner implements IBladeburner {
|
|||||||
0.04 * Math.pow(person.hacking, 0.3) +
|
0.04 * Math.pow(person.hacking, 0.3) +
|
||||||
0.04 * Math.pow(person.intelligence, 0.9) +
|
0.04 * Math.pow(person.intelligence, 0.9) +
|
||||||
0.02 * Math.pow(person.charisma, 0.3);
|
0.02 * Math.pow(person.charisma, 0.3);
|
||||||
eff *= person.bladeburner_analysis_mult;
|
eff *= person.mults.bladeburner_analysis;
|
||||||
if (isNaN(eff) || eff < 0) {
|
if (isNaN(eff) || eff < 0) {
|
||||||
throw new Error("Field Analysis Effectiveness calculated to be NaN or negative");
|
throw new Error("Field Analysis Effectiveness calculated to be NaN or negative");
|
||||||
}
|
}
|
||||||
const hackingExpGain = 20 * person.hacking_exp_mult;
|
const hackingExpGain = 20 * person.mults.hacking_exp;
|
||||||
const charismaExpGain = 20 * person.charisma_exp_mult;
|
const charismaExpGain = 20 * person.mults.charisma_exp;
|
||||||
const rankGain = 0.1 * BitNodeMultipliers.BladeburnerRank;
|
const rankGain = 0.1 * BitNodeMultipliers.BladeburnerRank;
|
||||||
retValue.hack = hackingExpGain;
|
retValue.hack = hackingExpGain;
|
||||||
retValue.cha = charismaExpGain;
|
retValue.cha = charismaExpGain;
|
||||||
@ -1647,7 +1635,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
if (bladeburnerFac.isMember) {
|
if (bladeburnerFac.isMember) {
|
||||||
const favorBonus = 1 + bladeburnerFac.favor / 100;
|
const favorBonus = 1 + bladeburnerFac.favor / 100;
|
||||||
bladeburnerFac.playerReputation +=
|
bladeburnerFac.playerReputation +=
|
||||||
BladeburnerConstants.RankToFactionRepFactor * change * person.faction_rep_mult * favorBonus;
|
BladeburnerConstants.RankToFactionRepFactor * change * person.mults.faction_rep * favorBonus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1695,7 +1683,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
const effAgility = player.agility * this.skillMultipliers.effAgi;
|
const effAgility = player.agility * this.skillMultipliers.effAgi;
|
||||||
const maxStaminaBonus = this.maxStamina / BladeburnerConstants.MaxStaminaToGainFactor;
|
const maxStaminaBonus = this.maxStamina / BladeburnerConstants.MaxStaminaToGainFactor;
|
||||||
const gain = (BladeburnerConstants.StaminaGainPerSecond + maxStaminaBonus) * Math.pow(effAgility, 0.17);
|
const gain = (BladeburnerConstants.StaminaGainPerSecond + maxStaminaBonus) * Math.pow(effAgility, 0.17);
|
||||||
return gain * (this.skillMultipliers.stamina * player.bladeburner_stamina_gain_mult);
|
return gain * (this.skillMultipliers.stamina * player.mults.bladeburner_stamina_gain);
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateMaxStamina(player: IPlayer): void {
|
calculateMaxStamina(player: IPlayer): void {
|
||||||
@ -1703,7 +1691,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
const maxStamina =
|
const maxStamina =
|
||||||
(Math.pow(effAgility, 0.8) + this.staminaBonus) *
|
(Math.pow(effAgility, 0.8) + this.staminaBonus) *
|
||||||
this.skillMultipliers.stamina *
|
this.skillMultipliers.stamina *
|
||||||
player.bladeburner_max_stamina_mult;
|
player.mults.bladeburner_max_stamina;
|
||||||
if (this.maxStamina !== maxStamina) {
|
if (this.maxStamina !== maxStamina) {
|
||||||
const oldMax = this.maxStamina;
|
const oldMax = this.maxStamina;
|
||||||
this.maxStamina = maxStamina;
|
this.maxStamina = maxStamina;
|
||||||
@ -1988,7 +1976,7 @@ export class Bladeburner implements IBladeburner {
|
|||||||
if (!router.isInitialized) return;
|
if (!router.isInitialized) return;
|
||||||
|
|
||||||
// If the Player starts doing some other actions, set action to idle and alert
|
// If the Player starts doing some other actions, set action to idle and alert
|
||||||
if (!player.hasAugmentation(AugmentationNames.BladesSimulacrum, true) && player.isWorking) {
|
if (!player.hasAugmentation(AugmentationNames.BladesSimulacrum, true) && player.currentWork) {
|
||||||
if (this.action.type !== ActionTypes["Idle"]) {
|
if (this.action.type !== ActionTypes["Idle"]) {
|
||||||
let msg = "Your Bladeburner action was cancelled because you started doing something else.";
|
let msg = "Your Bladeburner action was cancelled because you started doing something else.";
|
||||||
if (this.automateEnabled) {
|
if (this.automateEnabled) {
|
||||||
@ -2154,7 +2142,8 @@ export class Bladeburner implements IBladeburner {
|
|||||||
() => `Starting bladeburner action with type '${type}' and name '${name}'`,
|
() => `Starting bladeburner action with type '${type}' and name '${name}'`,
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
|
console.error(e);
|
||||||
this.resetAction();
|
this.resetAction();
|
||||||
workerScript.log("bladeburner.startAction", () => errorLogText);
|
workerScript.log("bladeburner.startAction", () => errorLogText);
|
||||||
return false;
|
return false;
|
||||||
@ -2409,15 +2398,14 @@ export class Bladeburner implements IBladeburner {
|
|||||||
/**
|
/**
|
||||||
* Serialize the current object to a JSON save state.
|
* Serialize the current object to a JSON save state.
|
||||||
*/
|
*/
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("Bladeburner", this);
|
return Generic_toJSON("Bladeburner", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiatizes a Bladeburner object from a JSON save state.
|
* Initiatizes a Bladeburner object from a JSON save state.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): Bladeburner {
|
||||||
static fromJSON(value: any): Bladeburner {
|
|
||||||
return Generic_fromJSON(Bladeburner, value.data);
|
return Generic_fromJSON(Bladeburner, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { BladeburnerConstants } from "./data/Constants";
|
import { BladeburnerConstants } from "./data/Constants";
|
||||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import { addOffset } from "../utils/helpers/addOffset";
|
import { addOffset } from "../utils/helpers/addOffset";
|
||||||
|
|
||||||
interface IChangePopulationByCountParams {
|
interface IChangePopulationByCountParams {
|
||||||
@ -177,15 +177,14 @@ export class City {
|
|||||||
/**
|
/**
|
||||||
* Serialize the current object to a JSON save state.
|
* Serialize the current object to a JSON save state.
|
||||||
*/
|
*/
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("City", this);
|
return Generic_toJSON("City", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiatizes a City object from a JSON save state.
|
* Initiatizes a City object from a JSON save state.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): City {
|
||||||
static fromJSON(value: any): City {
|
|
||||||
return Generic_fromJSON(City, value.data);
|
return Generic_fromJSON(City, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { IBladeburner } from "./IBladeburner";
|
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, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
|
|
||||||
export class Contract extends Action {
|
export class Contract extends Action {
|
||||||
constructor(params: IActionParams | null = null) {
|
constructor(params: IActionParams | null = null) {
|
||||||
@ -11,12 +11,11 @@ export class Contract extends Action {
|
|||||||
return inst.skillMultipliers.successChanceContract;
|
return inst.skillMultipliers.successChanceContract;
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("Contract", this);
|
return Generic_toJSON("Contract", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): Contract {
|
||||||
static fromJSON(value: any): Contract {
|
|
||||||
return Generic_fromJSON(Contract, value.data);
|
return Generic_fromJSON(Contract, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { IReviverValue } from "../utils/JSONReviver";
|
||||||
import { IPerson } from "../PersonObjects/IPerson";
|
import { IPerson } from "../PersonObjects/IPerson";
|
||||||
import { IBladeburner } from "./IBladeburner";
|
import { IBladeburner } from "./IBladeburner";
|
||||||
|
|
||||||
@ -67,5 +68,5 @@ export interface IAction {
|
|||||||
getSuccessChance(inst: IBladeburner, person: IPerson, params: ISuccessChanceParams): number;
|
getSuccessChance(inst: IBladeburner, person: IPerson, params: ISuccessChanceParams): number;
|
||||||
getSuccessesNeededForNextLevel(baseSuccessesPerLevel: number): number;
|
getSuccessesNeededForNextLevel(baseSuccessesPerLevel: number): number;
|
||||||
setMaxLevel(baseSuccessesPerLevel: number): void;
|
setMaxLevel(baseSuccessesPerLevel: number): void;
|
||||||
toJSON(): any;
|
toJSON(): IReviverValue;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ import { IPerson } from "../PersonObjects/IPerson";
|
|||||||
import { ITaskTracker } from "../PersonObjects/ITaskTracker";
|
import { ITaskTracker } from "../PersonObjects/ITaskTracker";
|
||||||
import { IRouter } from "../ui/Router";
|
import { IRouter } from "../ui/Router";
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
|
import { Contract } from "./Contract";
|
||||||
|
import { Operation } from "./Operation";
|
||||||
|
|
||||||
export interface IBladeburner {
|
export interface IBladeburner {
|
||||||
numHosp: number;
|
numHosp: number;
|
||||||
@ -31,17 +33,23 @@ export interface IBladeburner {
|
|||||||
|
|
||||||
action: IActionIdentifier;
|
action: IActionIdentifier;
|
||||||
|
|
||||||
cities: any;
|
cities: Record<string, City>;
|
||||||
city: string;
|
city: string;
|
||||||
skills: any;
|
skills: Record<string, number>;
|
||||||
skillMultipliers: any;
|
skillMultipliers: Record<string, number>;
|
||||||
staminaBonus: number;
|
staminaBonus: number;
|
||||||
maxStamina: number;
|
maxStamina: number;
|
||||||
stamina: number;
|
stamina: number;
|
||||||
contracts: any;
|
contracts: Record<string, Contract>;
|
||||||
operations: any;
|
operations: Record<string, Operation>;
|
||||||
blackops: any;
|
blackops: Record<string, boolean>;
|
||||||
logging: any;
|
logging: {
|
||||||
|
general: boolean;
|
||||||
|
contracts: boolean;
|
||||||
|
ops: boolean;
|
||||||
|
blackops: boolean;
|
||||||
|
events: boolean;
|
||||||
|
};
|
||||||
automateEnabled: boolean;
|
automateEnabled: boolean;
|
||||||
automateActionHigh: IActionIdentifier;
|
automateActionHigh: IActionIdentifier;
|
||||||
automateThreshHigh: number;
|
automateThreshHigh: number;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { IBladeburner } from "./IBladeburner";
|
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, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
|
|
||||||
export interface IOperationParams extends IActionParams {
|
export interface IOperationParams extends IActionParams {
|
||||||
reqdRank?: number;
|
reqdRank?: number;
|
||||||
@ -44,12 +44,11 @@ export class Operation extends Action {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("Operation", this);
|
return Generic_toJSON("Operation", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): Operation {
|
||||||
static fromJSON(value: any): Operation {
|
|
||||||
return Generic_fromJSON(Operation, value.data);
|
return Generic_fromJSON(Operation, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import makeStyles from "@mui/styles/makeStyles";
|
|||||||
import createStyles from "@mui/styles/createStyles";
|
import createStyles from "@mui/styles/createStyles";
|
||||||
|
|
||||||
interface ILineProps {
|
interface ILineProps {
|
||||||
content: any;
|
content: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) =>
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
@ -197,7 +197,7 @@ function Logs({ entries }: ILogProps): React.ReactElement {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<List sx={{ height: "100%", overflow: "auto", p: 1 }} ref={scrollHook}>
|
<List sx={{ height: "100%", overflow: "auto", p: 1 }} ref={scrollHook}>
|
||||||
{entries && entries.map((log: any, i: number) => <Line key={i} content={log} />)}
|
{entries && entries.map((log: string, i: number) => <Line key={i} content={log} />)}
|
||||||
</List>
|
</List>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -9,9 +9,10 @@ import Box from "@mui/material/Box";
|
|||||||
import Paper from "@mui/material/Paper";
|
import Paper from "@mui/material/Paper";
|
||||||
import AddIcon from "@mui/icons-material/Add";
|
import AddIcon from "@mui/icons-material/Add";
|
||||||
import CloseIcon from "@mui/icons-material/Close";
|
import CloseIcon from "@mui/icons-material/Close";
|
||||||
|
import { Skill } from "../Skill";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
skill: any;
|
skill: Skill;
|
||||||
bladeburner: IBladeburner;
|
bladeburner: IBladeburner;
|
||||||
onUpgrade: () => void;
|
onUpgrade: () => void;
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,8 @@ export function SkillPage(props: IProps): React.ReactElement {
|
|||||||
const setRerender = useState(false)[1];
|
const setRerender = useState(false)[1];
|
||||||
const mults = props.bladeburner.skillMultipliers;
|
const mults = props.bladeburner.skillMultipliers;
|
||||||
|
|
||||||
function valid(mult: any): boolean {
|
function valid(mult: number | undefined): boolean {
|
||||||
return mult && mult !== 1;
|
return mult !== undefined && mult !== 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -33,7 +33,7 @@ export function StartButton(props: IProps): React.ReactElement {
|
|||||||
if (disabled) return;
|
if (disabled) return;
|
||||||
props.bladeburner.action.type = props.type;
|
props.bladeburner.action.type = props.type;
|
||||||
props.bladeburner.action.name = props.name;
|
props.bladeburner.action.name = props.name;
|
||||||
if (!player.hasAugmentation(AugmentationNames.BladesSimulacrum, true)) player.singularityStopWork();
|
if (!player.hasAugmentation(AugmentationNames.BladesSimulacrum, true)) player.finishWork(true);
|
||||||
props.bladeburner.startAction(player, props.bladeburner.action);
|
props.bladeburner.startAction(player, props.bladeburner.action);
|
||||||
props.rerender();
|
props.rerender();
|
||||||
}
|
}
|
||||||
|
@ -173,13 +173,13 @@ export function Stats(props: IProps): React.ReactElement {
|
|||||||
<Typography>Skill Points: {formatNumber(props.bladeburner.skillPoints, 0)}</Typography>
|
<Typography>Skill Points: {formatNumber(props.bladeburner.skillPoints, 0)}</Typography>
|
||||||
<br />
|
<br />
|
||||||
<Typography>
|
<Typography>
|
||||||
Aug. Success Chance mult: {formatNumber(props.player.bladeburner_success_chance_mult * 100, 1)}%
|
Aug. Success Chance mult: {formatNumber(props.player.mults.bladeburner_success_chance * 100, 1)}%
|
||||||
<br />
|
<br />
|
||||||
Aug. Max Stamina mult: {formatNumber(props.player.bladeburner_max_stamina_mult * 100, 1)}%
|
Aug. Max Stamina mult: {formatNumber(props.player.mults.bladeburner_max_stamina * 100, 1)}%
|
||||||
<br />
|
<br />
|
||||||
Aug. Stamina Gain mult: {formatNumber(props.player.bladeburner_stamina_gain_mult * 100, 1)}%
|
Aug. Stamina Gain mult: {formatNumber(props.player.mults.bladeburner_stamina_gain * 100, 1)}%
|
||||||
<br />
|
<br />
|
||||||
Aug. Field Analysis mult: {formatNumber(props.player.bladeburner_analysis_mult * 100, 1)}%
|
Aug. Field Analysis mult: {formatNumber(props.player.mults.bladeburner_analysis * 100, 1)}%
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
export function trusted(f: () => void): (event: React.MouseEvent<HTMLElement, MouseEvent>) => any {
|
export function trusted(f: () => void): (event: React.MouseEvent<HTMLElement, MouseEvent>) => void {
|
||||||
return function (event: React.MouseEvent<HTMLElement, MouseEvent>): any {
|
return function (event: React.MouseEvent<HTMLElement, MouseEvent>): void {
|
||||||
if (!event.isTrusted) return;
|
if (!event.isTrusted) return;
|
||||||
f();
|
f();
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,7 @@ import { codingContractTypesMetadata, DescriptionFunc, GeneratorFunc, SolverFunc
|
|||||||
|
|
||||||
import { IMap } from "./types";
|
import { IMap } from "./types";
|
||||||
|
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "./utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "./utils/JSONReviver";
|
||||||
import { CodingContractEvent } from "./ui/React/CodingContractModal";
|
import { CodingContractEvent } from "./ui/React/CodingContractModal";
|
||||||
|
|
||||||
/* tslint:disable:no-magic-numbers completed-docs max-classes-per-file no-console */
|
/* tslint:disable:no-magic-numbers completed-docs max-classes-per-file no-console */
|
||||||
@ -106,7 +106,7 @@ export interface ICodingContractReward {
|
|||||||
*/
|
*/
|
||||||
export class CodingContract {
|
export class CodingContract {
|
||||||
/* Relevant data for the contract's problem */
|
/* Relevant data for the contract's problem */
|
||||||
data: any;
|
data: unknown;
|
||||||
|
|
||||||
/* Contract's filename */
|
/* Contract's filename */
|
||||||
fn: string;
|
fn: string;
|
||||||
@ -137,7 +137,7 @@ export class CodingContract {
|
|||||||
this.reward = reward;
|
this.reward = reward;
|
||||||
}
|
}
|
||||||
|
|
||||||
getData(): any {
|
getData(): unknown {
|
||||||
return this.data;
|
return this.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,15 +186,14 @@ export class CodingContract {
|
|||||||
/**
|
/**
|
||||||
* Serialize the current file to a JSON save state.
|
* Serialize the current file to a JSON save state.
|
||||||
*/
|
*/
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("CodingContract", this);
|
return Generic_toJSON("CodingContract", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiatizes a CodingContract from a JSON save state.
|
* Initiatizes a CodingContract from a JSON save state.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): CodingContract {
|
||||||
static fromJSON(value: any): CodingContract {
|
|
||||||
return Generic_fromJSON(CodingContract, value.data);
|
return Generic_fromJSON(CodingContract, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import { favorToRep, repToFavor } from "../Faction/formulas/favor";
|
|||||||
|
|
||||||
import { IMap } from "../types";
|
import { IMap } from "../types";
|
||||||
|
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
|
|
||||||
export interface IConstructorParams {
|
export interface IConstructorParams {
|
||||||
name: string;
|
name: string;
|
||||||
@ -151,15 +151,14 @@ export class Company {
|
|||||||
/**
|
/**
|
||||||
* Serialize the current object to a JSON save state.
|
* Serialize the current object to a JSON save state.
|
||||||
*/
|
*/
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("Company", this);
|
return Generic_toJSON("Company", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiatizes a Company from a JSON save state.
|
* Initiatizes a Company from a JSON save state.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): Company {
|
||||||
static fromJSON(value: any): Company {
|
|
||||||
return Generic_fromJSON(Company, value.data);
|
return Generic_fromJSON(Company, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
201
src/Constants.ts
201
src/Constants.ts
@ -88,8 +88,8 @@ export const CONSTANTS: {
|
|||||||
Donations: number; // number of blood/plasma/palette donation the dev have verified., boosts NFG
|
Donations: number; // number of blood/plasma/palette donation the dev have verified., boosts NFG
|
||||||
LatestUpdate: string;
|
LatestUpdate: string;
|
||||||
} = {
|
} = {
|
||||||
VersionString: "1.7.0",
|
VersionString: "2.0.0",
|
||||||
VersionNumber: 19,
|
VersionNumber: 21,
|
||||||
|
|
||||||
// Speed (in ms) at which the main loop is updated
|
// Speed (in ms) at which the main loop is updated
|
||||||
_idleSpeed: 200,
|
_idleSpeed: 200,
|
||||||
@ -104,7 +104,7 @@ export const CONSTANTS: {
|
|||||||
MilliPerCycle: 200,
|
MilliPerCycle: 200,
|
||||||
|
|
||||||
// How much reputation is needed to join a megacorporation's faction
|
// How much reputation is needed to join a megacorporation's faction
|
||||||
CorpFactionRepRequirement: 200e3,
|
CorpFactionRepRequirement: 400e3,
|
||||||
|
|
||||||
// Base RAM costs
|
// Base RAM costs
|
||||||
BaseCostFor1GBOfRamHome: 32000,
|
BaseCostFor1GBOfRamHome: 32000,
|
||||||
@ -229,171 +229,54 @@ export const CONSTANTS: {
|
|||||||
|
|
||||||
InfiniteLoopLimit: 2000,
|
InfiniteLoopLimit: 2000,
|
||||||
|
|
||||||
Donations: 20,
|
Donations: 21,
|
||||||
|
|
||||||
LatestUpdate: `
|
LatestUpdate: `
|
||||||
## [draft] v1.7.0 - 2022-04-13 to 2022-05-20
|
v2.0.0 - 2022-07-19 Work rework
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
#### Information
|
API break rewards
|
||||||
|
|
||||||
Modifications included between **2022-04-13** and **2022-05-20** 'b5e4d70' to '0fbe4a1').
|
* Everyone is awarded 10 NFG.
|
||||||
|
* All work in progress program is auto completed.
|
||||||
|
* All work in progress crafting is auto completed without adding entropy.
|
||||||
|
|
||||||
_[See Pull Requests on GitHub](https://github.com/search?q=user%3Adanielyxie%20repo%3Abitburner%20is%3Apr%20is%3Amerged%20merged%3A%222022-04-13T16%3A32%3A26.000Z..2022-05-20T06%3A08%3A51.000Z%22)_
|
Work (Create program / Work for faction / Studying / etc ...)
|
||||||
|
|
||||||
#### Merged Pull Requests
|
* Working has been rebuilt from the grounds up. The motivation for that change is that all
|
||||||
|
different types of work all required different cached variables on the main Player object.
|
||||||
|
This caused a lot of bugs and crashes. It's been reworked in such a way as to prevent bugs
|
||||||
|
and make it nearly trivial to add new kinds of work. However, since this caused a few API break
|
||||||
|
I've decided to mark this version following semver protocols and call it 2.0.0
|
||||||
|
* Crime can be unfocused and auto loops, no more spam clicking.
|
||||||
|
* All work type give their reward immediately. No need to stop work to bank rewards like reputation.
|
||||||
|
* Faction and Company work no longer have a time limit.
|
||||||
|
* Company work no longer reduces rep gain by half for quitting early.
|
||||||
|
* Company faction require 400k rep to join (from 200k)
|
||||||
|
* Backdooring company server reduces faction requirement to 300k.
|
||||||
|
* All work generally no longer keep track of cumulative gains like exp and reputation since it's applied instantly.
|
||||||
|
* getPlayer returns way less fields but does return the new 'currentWork' field.
|
||||||
|
|
||||||
- [Feature] Monaco Theme Editor (by @nickofolas) #[3438](https://github.com/danielyxie/bitburner/pull/3438)
|
API breaks
|
||||||
- [Fix] Dummy Stanek grid width (by @nickofolas) #[3442](https://github.com/danielyxie/bitburner/pull/3442)
|
|
||||||
- [Fix] Theme browser assets not loading (by @nickofolas) #[3446](https://github.com/danielyxie/bitburner/pull/3446)
|
|
||||||
- Accept valid JSON arrays in coding contracts (by @Savlik) #[3247](https://github.com/danielyxie/bitburner/pull/3247)
|
|
||||||
- another dark theme? (by @hydroflame) #[3450](https://github.com/danielyxie/bitburner/pull/3450)
|
|
||||||
- API: Add repFromDonation() to the Formula API (by @Hoekstraa) #[3461](https://github.com/danielyxie/bitburner/pull/3461)
|
|
||||||
- API: Add safeguard to ns.killall(), preventing killing itself by default (by @Hoekstraa) #[3607](https://github.com/danielyxie/bitburner/pull/3607)
|
|
||||||
- API: FIX #2993 sleeve.travel with invalid city names (by @TheMas3212) #[3458](https://github.com/danielyxie/bitburner/pull/3458)
|
|
||||||
- API: Fix inconsistent return value in 'ns.grafting.getAugmentationGraftTime' (by @nickofolas) #[3539](https://github.com/danielyxie/bitburner/pull/3539)
|
|
||||||
- API: Fix leak of real Employee object in hireEmployee (by @TheMas3212) #[3483](https://github.com/danielyxie/bitburner/pull/3483)
|
|
||||||
- API: replace a number of references to workerscript.log with \_ctx.log (by @TheMas3212) #[3470](https://github.com/danielyxie/bitburner/pull/3470)
|
|
||||||
- API: Terminal screen can now be cleared from within scripts with ns.ui.clearTerminal() (by @Hoekstraa) #[3618](https://github.com/danielyxie/bitburner/pull/3618)
|
|
||||||
- AUGMENTATIONS: Fix 'isSpecial' filter in helper (Removes NeuroFlux, Stanek's Gift, etc from gangs) (by @nickofolas) #[3565](https://github.com/danielyxie/bitburner/pull/3565)
|
|
||||||
- AUGMENTATIONS: Fix Augmentation rep req not being properly influenced by BitNode multipliers (by @nickofolas) #[3652](https://github.com/danielyxie/bitburner/pull/3652)
|
|
||||||
- AUGMENTATIONS: Fix NeuroFlux being applied improperly and migrate broken saves (by @nickofolas) #[3613](https://github.com/danielyxie/bitburner/pull/3613)
|
|
||||||
- AUGMENTATIONS: Fix reputation check for faction augs (by @nickofolas) #[3609](https://github.com/danielyxie/bitburner/pull/3609)
|
|
||||||
- AUGMENTATIONS: Tweak a couple small UI elements (by @nickofolas) #[3614](https://github.com/danielyxie/bitburner/pull/3614)
|
|
||||||
- basic doc no longer hacker themed (by @hydroflame) #[3449](https://github.com/danielyxie/bitburner/pull/3449)
|
|
||||||
- BITNODE: FIX #3546 BitVerse now shows proper BN level when accessed via flume (by @nickofolas) #[3550](https://github.com/danielyxie/bitburner/pull/3550)
|
|
||||||
- BLADEBURNER: fixes #3648 : Automate console command capitalisation inconsistent (by @Vic1970) #[3647](https://github.com/danielyxie/bitburner/pull/3647)
|
|
||||||
- BLADEBURNER: Fix #3594 Blade's Simulacrum worked without being installed (by @Undeemiss) #[3639](https://github.com/danielyxie/bitburner/pull/3639)
|
|
||||||
- blood (by @hydroflame) #[3495](https://github.com/danielyxie/bitburner/pull/3495)
|
|
||||||
- BUGFIX: getAugmentationCost response backwards (by @phyzical) #[3617](https://github.com/danielyxie/bitburner/pull/3617)
|
|
||||||
- BUGFIX: Handle edge case in LZ compression code and fix docs (by @stalefishies) #[3581](https://github.com/danielyxie/bitburner/pull/3581)
|
|
||||||
- BUGFIX: make bonustime for gang in miliseconds (by @phyzical) #[3578](https://github.com/danielyxie/bitburner/pull/3578)
|
|
||||||
- BUGFIX: sleeve stale object refence during augmentation (by @phyzical) #[3601](https://github.com/danielyxie/bitburner/pull/3601)
|
|
||||||
- Bugfix/corp updates (by @phyzical) #[3321](https://github.com/danielyxie/bitburner/pull/3321)
|
|
||||||
- Bump async from 2.6.3 to 2.6.4 (by @dependabot[bot]) #[3463](https://github.com/danielyxie/bitburner/pull/3463)
|
|
||||||
- CODINGCONTRACT: Fix #3391 Double contract reward exploit (by @Undeemiss) #[3646](https://github.com/danielyxie/bitburner/pull/3646)
|
|
||||||
- CODINGCONTRACT: FIX #3484 BREAKING Fixed capitalization in contract name (by @Undeemiss) #[3537](https://github.com/danielyxie/bitburner/pull/3537)
|
|
||||||
- CODINGCONTRACT: New "Proper 2-Coloring of a Graph" contract (by @Undeemiss) #[3530](https://github.com/danielyxie/bitburner/pull/3530)
|
|
||||||
- CODINGCONTRACT: Three new compression contracts (by @stalefishies) #[3541](https://github.com/danielyxie/bitburner/pull/3541)
|
|
||||||
- CODINGCONTRACT: Typo & clarity fixes to description of Encoded Binary to Integer contract (by @ActuallyCurtis) #[3469](https://github.com/danielyxie/bitburner/pull/3469)
|
|
||||||
- CODINGCONTRACT: Updated description of 2-coloring contract (by @Undeemiss) #[3531](https://github.com/danielyxie/bitburner/pull/3531)
|
|
||||||
- COMPANY: Fix #3551 Applying for a new job will not change active employer if player is performing company work (by @Snarling) #[3552](https://github.com/danielyxie/bitburner/pull/3552)
|
|
||||||
- CORPORATIONS: Expose makeProducts on NSDivision interface (by @DavidGrinberg) #[3570](https://github.com/danielyxie/bitburner/pull/3570)
|
|
||||||
- CORPORATIONS: Expose sales cost on NSMaterial interface (by @DavidGrinberg) #[3574](https://github.com/danielyxie/bitburner/pull/3574)
|
|
||||||
- Corrected example grids found in Stanek help (by @Undeemiss) #[3441](https://github.com/danielyxie/bitburner/pull/3441)
|
|
||||||
- Create program action no longer creates duplicates (by @Undeemiss) #[3436](https://github.com/danielyxie/bitburner/pull/3436)
|
|
||||||
- DOCUMENTATION: Add descriptions for compression contracts (by @stalefishies) #[3559](https://github.com/danielyxie/bitburner/pull/3559)
|
|
||||||
- DOCUMENTATION: Add new coding contract descriptions (by @stalefishies) #[3542](https://github.com/danielyxie/bitburner/pull/3542)
|
|
||||||
- DOCUMENTATION: Clarify definition for installAugmentations() (by @PSEUDOSTAGE) #[3560](https://github.com/danielyxie/bitburner/pull/3560)
|
|
||||||
- DOCUMENTATION: FIX #3516 "cannot" misspelled as "cannnot" (by @Undeemiss) #[3533](https://github.com/danielyxie/bitburner/pull/3533)
|
|
||||||
- EDITOR: FIX #3502 Editor theme migration crash (by @nickofolas) #[3503](https://github.com/danielyxie/bitburner/pull/3503)
|
|
||||||
- FEATURE: added logic to allow quitJob to be called from singularity (by @phyzical) #[3577](https://github.com/danielyxie/bitburner/pull/3577)
|
|
||||||
- fix #3395 donating to special factions possible via singularity (by @TheMas3212) #[3456](https://github.com/danielyxie/bitburner/pull/3456)
|
|
||||||
- fix b1tflum3 and destroyW0r1dD43m0n singularity functions to check for sf4 (by @TheMas3212) #[3443](https://github.com/danielyxie/bitburner/pull/3443)
|
|
||||||
- Fix inconsistancy with trying to work for gang factions while running a gang (by @TheMas3212) #[3454](https://github.com/danielyxie/bitburner/pull/3454)
|
|
||||||
- Fix infiltration rep BN mult calculation (by @trambelus) #[3632](https://github.com/danielyxie/bitburner/pull/3632)
|
|
||||||
- Fix script editor settings. (by @hydroflame) #[3504](https://github.com/danielyxie/bitburner/pull/3504)
|
|
||||||
- Fix test/jest/Netscript/DynamicRamCalculation.test.js (by @TheMas3212) #[3455](https://github.com/danielyxie/bitburner/pull/3455)
|
|
||||||
- GRAFTING: Fix Grafting not being handled in singularity stop work (by @nickofolas) #[3568](https://github.com/danielyxie/bitburner/pull/3568)
|
|
||||||
- GRAFTING: Implement sorting options (by @nickofolas) #[3654](https://github.com/danielyxie/bitburner/pull/3654)
|
|
||||||
- INFILTRATION: Added new faction called infiltrators that provide infiltration specific augs. (by @phyzical) #[3241](https://github.com/danielyxie/bitburner/pull/3241)
|
|
||||||
- INFILTRATION: Fix minigame cycle (by @nickofolas) #[3549](https://github.com/danielyxie/bitburner/pull/3549)
|
|
||||||
- INFILTRATION: Fix phyzical WKS aug effects being applied before aug is installed (by @nickofolas) #[3555](https://github.com/danielyxie/bitburner/pull/3555)
|
|
||||||
- INFILTRATION: Fix rep reward being substantially higher than intended (by @nickofolas) #[3562](https://github.com/danielyxie/bitburner/pull/3562)
|
|
||||||
- INFILTRATION: New faction, Shadows of Anarchy, provides various augs to help infiltrations. (by @hydroflame) #[3543](https://github.com/danielyxie/bitburner/pull/3543)
|
|
||||||
- INFILTRATION: Update gameplay UI (by @nickofolas) #[3587](https://github.com/danielyxie/bitburner/pull/3587)
|
|
||||||
- keeping up to date (by @hydroflame) #[3432](https://github.com/danielyxie/bitburner/pull/3432)
|
|
||||||
- Keeping up to date. (by @hydroflame) #[3561](https://github.com/danielyxie/bitburner/pull/3561)
|
|
||||||
- Make .lit and .msg files clickable (by @Chris380) #[3453](https://github.com/danielyxie/bitburner/pull/3453)
|
|
||||||
- MESSAGES: Added the name of NiteSec's server to their .msg (by @Undeemiss) #[3466](https://github.com/danielyxie/bitburner/pull/3466)
|
|
||||||
- MISC: add better typing to Electron.tsx (by @taralx) #[3540](https://github.com/danielyxie/bitburner/pull/3540)
|
|
||||||
- MISC: Added NS function closeTail to close tail windows (by @Undeemiss) #[3666](https://github.com/danielyxie/bitburner/pull/3666)
|
|
||||||
- MISC: Adjust deps to current usage (by @taralx) #[3519](https://github.com/danielyxie/bitburner/pull/3519)
|
|
||||||
- MISC: Close some GitHub issues that do not need action (by @Undeemiss) #[3640](https://github.com/danielyxie/bitburner/pull/3640)
|
|
||||||
- MISC: Closing more GitHub issues I missed last time (by @Undeemiss) #[3665](https://github.com/danielyxie/bitburner/pull/3665)
|
|
||||||
- MISC: Correct BB Skill point achievement name (by @Undeemiss) #[3571](https://github.com/danielyxie/bitburner/pull/3571)
|
|
||||||
- MISC: Correct typos in getScriptRam docs. (by @nzdjb) #[3590](https://github.com/danielyxie/bitburner/pull/3590)
|
|
||||||
- MISC: Fix #3125 BREAKING Renamed BN mult CorporationSoftCap to CorporationSoftcap (by @Undeemiss) #[3638](https://github.com/danielyxie/bitburner/pull/3638)
|
|
||||||
- MISC: FIX #3593 Float errors can no longer prevent full usage of a server's available ram. (by @Snarling) #[3619](https://github.com/danielyxie/bitburner/pull/3619)
|
|
||||||
- MISC: fix typing conflict between jest and cypress (by @taralx) #[3518](https://github.com/danielyxie/bitburner/pull/3518)
|
|
||||||
- MISC: fix typing conflict between jest and cypress (by @taralx) #[3644](https://github.com/danielyxie/bitburner/pull/3644)
|
|
||||||
- MISC: Fixed typo in exceptionAlert.ts (by @Undeemiss) #[3572](https://github.com/danielyxie/bitburner/pull/3572)
|
|
||||||
- MISC: Fixed typos in game options (by @notacompsciguy) #[3584](https://github.com/danielyxie/bitburner/pull/3584)
|
|
||||||
- MISC: HammingCodingContracts need rework (by @Hedrauta) #[3479](https://github.com/danielyxie/bitburner/pull/3479)
|
|
||||||
- MISC: Implemented infinite loop safety net. (by @hydroflame) #[3624](https://github.com/danielyxie/bitburner/pull/3624)
|
|
||||||
- MISC: make jQuery use explicit (by @taralx) #[3517](https://github.com/danielyxie/bitburner/pull/3517)
|
|
||||||
- MISC: Make tutorial explain ns1 vs ns2 better (by @hydroflame) #[3586](https://github.com/danielyxie/bitburner/pull/3586)
|
|
||||||
- MISC: Remove comments that describe nonexistent augs (by @Undeemiss) #[3569](https://github.com/danielyxie/bitburner/pull/3569)
|
|
||||||
- MISC: update @types/numeral and fix type errors (by @taralx) #[3521](https://github.com/danielyxie/bitburner/pull/3521)
|
|
||||||
- MISC: Update logic for stats page BitNode level (by @nickofolas) #[3512](https://github.com/danielyxie/bitburner/pull/3512)
|
|
||||||
- MISC: upgrade to eslint v8 (by @taralx) #[3523](https://github.com/danielyxie/bitburner/pull/3523)
|
|
||||||
- MISC: Wrap most of the API in the new api wrapper (by @hydroflame) #[3627](https://github.com/danielyxie/bitburner/pull/3627)
|
|
||||||
- OPTIONS: Fix sliders not sliding correctly (by @nickofolas) #[3642](https://github.com/danielyxie/bitburner/pull/3642)
|
|
||||||
- REFACTOR: augmentation cost, rep cost and level to be calculated in place (by @phyzical) #[3544](https://github.com/danielyxie/bitburner/pull/3544)
|
|
||||||
- REFACTOR: augmentation isSpecial adjustments (by @phyzical) #[3564](https://github.com/danielyxie/bitburner/pull/3564)
|
|
||||||
- Reran npm format and lint to fix formatting (by @Undeemiss) #[3434](https://github.com/danielyxie/bitburner/pull/3434)
|
|
||||||
- Revert "MISC: fix typing conflict between jest and cypress" (by @hydroflame) #[3608](https://github.com/danielyxie/bitburner/pull/3608)
|
|
||||||
- Revert "MISC: HammingCodingContracts need rework" (by @hydroflame) #[3500](https://github.com/danielyxie/bitburner/pull/3500)
|
|
||||||
- revert theme (by @hydroflame) #[3451](https://github.com/danielyxie/bitburner/pull/3451)
|
|
||||||
- Singularity: Fix #3489 Disable checkTixApiAccess for purchase4SMarketData (by @DavidGrinberg) #[3490](https://github.com/danielyxie/bitburner/pull/3490)
|
|
||||||
- SLEEVES: Fix issues with Sleeve UI crashing when Sleeve task faction becomes gang faction (by @nickofolas) #[3557](https://github.com/danielyxie/bitburner/pull/3557)
|
|
||||||
- STANEK: Fix #3196 Charging booster fragments throws an error (by @Undeemiss) #[3637](https://github.com/danielyxie/bitburner/pull/3637)
|
|
||||||
- STANEK: FIX #3277 Can no longer overlap rotated fragments (by @Undeemiss) #[3460](https://github.com/danielyxie/bitburner/pull/3460)
|
|
||||||
- STANEK: FIX #3282 Added NS function stanek.acceptGift (by @Undeemiss) #[3513](https://github.com/danielyxie/bitburner/pull/3513)
|
|
||||||
- STANEK: Properly reapply entropy in Stanek's Gift (by @nickofolas) #[3673](https://github.com/danielyxie/bitburner/pull/3673)
|
|
||||||
- STANEK: Stanek NS functions correctly throw errors when stanek not installed (by @Undeemiss) #[3660](https://github.com/danielyxie/bitburner/pull/3660)
|
|
||||||
- Started collecting lore so that additions to it are simpler (by @Undeemiss) #[3465](https://github.com/danielyxie/bitburner/pull/3465)
|
|
||||||
- TERMINAL: FIX #3492 Allow cd .. even when destination directory is empty (by @Snarling) #[3525](https://github.com/danielyxie/bitburner/pull/3525)
|
|
||||||
- TERMINAL: FIX #3651 Make directory name regex more flexible (by @Dane-Horn) #[3653](https://github.com/danielyxie/bitburner/pull/3653)
|
|
||||||
- TOOLING: Add GitHub action to validate PR titles (by @MartinFournier) #[3471](https://github.com/danielyxie/bitburner/pull/3471)
|
|
||||||
- UI FIX #3485 - Allow bulk purchasing when smart supply is enabled (by @phyzical) #[3486](https://github.com/danielyxie/bitburner/pull/3486)
|
|
||||||
- UI: Change text color of Augmentations page backup button (by @nickofolas) #[3511](https://github.com/danielyxie/bitburner/pull/3511)
|
|
||||||
- UI: FIX #1754 Stanek effect summary & slight tweak. (by @borisflagell) #[3622](https://github.com/danielyxie/bitburner/pull/3622)
|
|
||||||
- UI: FIX #2228,#2958 Fix tab highlights and highlight files not on home. (by @phyzical) #[2989](https://github.com/danielyxie/bitburner/pull/2989)
|
|
||||||
- UI: FIX #2256 Hacknet server's upgrade tooltip were not handling RAM… (by @borisflagell) #[3532](https://github.com/danielyxie/bitburner/pull/3532)
|
|
||||||
- UI: FIX #2741 Allow using modifier keys inside the typing infiltration (by @Dane-Horn) #[3634](https://github.com/danielyxie/bitburner/pull/3634)
|
|
||||||
- UI: FIX #2829 Remove defeated NPC gangs from territory page (by @Dane-Horn) #[3633](https://github.com/danielyxie/bitburner/pull/3633)
|
|
||||||
- UI: FIX #3313 Streamline the GraftingRoot page by making it rerender. (by @borisflagell) #[3558](https://github.com/danielyxie/bitburner/pull/3558)
|
|
||||||
- UI: FIX #3341 Enable touch-clicks in react-draggable (by @Snarling) #[3488](https://github.com/danielyxie/bitburner/pull/3488)
|
|
||||||
- UI: FIX #3415 Tweak Manage Gang button visibility (by @borisflagell) #[3528](https://github.com/danielyxie/bitburner/pull/3528)
|
|
||||||
- UI: FIX #3457 autocomplete suggestions no longer require hovering terminal input (by @Snarling) #[3493](https://github.com/danielyxie/bitburner/pull/3493)
|
|
||||||
- UI: FIX #3473 'mv' now says destination script is running instead of returning an error (by @Hoekstraa) #[3474](https://github.com/danielyxie/bitburner/pull/3474)
|
|
||||||
- UI: FIX #3522 realigned autocomplete popup (by @Snarling) #[3524](https://github.com/danielyxie/bitburner/pull/3524)
|
|
||||||
- UI: FIX #3592 Sidebar and bash shortcuts now work on MacOS with US-like layouts (by @Hoekstraa) #[3605](https://github.com/danielyxie/bitburner/pull/3605)
|
|
||||||
- UI: Fix Agility BitNode multiplier not appearing in UI (by @nickofolas) #[3662](https://github.com/danielyxie/bitburner/pull/3662)
|
|
||||||
- UI: Fix exclusive augs not always showing as purchasable through gangs when they should (by @nickofolas) #[3676](https://github.com/danielyxie/bitburner/pull/3676)
|
|
||||||
- UI: Fix the achievement covenant icon was not shown (by @Risenafis) #[3510](https://github.com/danielyxie/bitburner/pull/3510)
|
|
||||||
- UI: Fix z-index of modals overriding everything (by @nickofolas) #[3620](https://github.com/danielyxie/bitburner/pull/3620)
|
|
||||||
- UI: lightweight description update on "increase maximum money" hash spending option. (by @borisflagell) #[3547](https://github.com/danielyxie/bitburner/pull/3547)
|
|
||||||
- UI: Minor improvements to log boxes (by @nickofolas) #[3641](https://github.com/danielyxie/bitburner/pull/3641)
|
|
||||||
- UI: Overhaul GameOptions UI (by @nickofolas) #[3505](https://github.com/danielyxie/bitburner/pull/3505)
|
|
||||||
- UI: Positioning improved for tail titlebar buttons, and tail window has minimum size constraints. (by @Snarling) #[3548](https://github.com/danielyxie/bitburner/pull/3548)
|
|
||||||
- UI: Redesign purchasable Augmentations (by @nickofolas) #[3545](https://github.com/danielyxie/bitburner/pull/3545)
|
|
||||||
- UI: Refactor and redesign WorkInProgress interface (by @nickofolas) #[3611](https://github.com/danielyxie/bitburner/pull/3611)
|
|
||||||
- UI: Refactors, redesigns, and new section to stats page (by @nickofolas) #[3626](https://github.com/danielyxie/bitburner/pull/3626)
|
|
||||||
- UI: Sort and color Graft Augmentation list (by @jaype87) #[3616](https://github.com/danielyxie/bitburner/pull/3616)
|
|
||||||
- UI: Update Factions list interface (by @nickofolas) #[3675](https://github.com/danielyxie/bitburner/pull/3675)
|
|
||||||
- WORK: FIX #3435 Quitting the active job now sets first remaining job as active (by @Snarling) #[3507](https://github.com/danielyxie/bitburner/pull/3507)
|
|
||||||
- WORK: Refactor work types to use 'enum's instead of constants (by @nickofolas) #[3612](https://github.com/danielyxie/bitburner/pull/3612)
|
|
||||||
|
|
||||||
#### Other Changes
|
* workForCompany argument 'companyName' is now not-optional
|
||||||
|
* commitCrime now has 'focus' optional parameter
|
||||||
|
* using getScriptIncome to get total income has been separated to getTotalScriptIncome.
|
||||||
|
* using getScriptExpGain to get total income has been separated to getTotalScriptExpGain.
|
||||||
|
* scp has it's 2 last argument reversed, the signature is now (files, destination, optional_source)
|
||||||
|
* ns.connect and other singularity function are no longer available at the top level.
|
||||||
|
They were already hidden from documentation but now they're gone.
|
||||||
|
* stock.buy and stock.sell were renamed to stock.buyStock and stock.sellStock because 'buy' and 'sell'
|
||||||
|
are very common tokens.
|
||||||
|
|
||||||
- increase donation counter (by @hydroflame) - [8456410](https://github.com/danielyxie/bitburner/commit/84564100e90c46ae4b816853c2cdea0bc309af4d)
|
Multipliers
|
||||||
- allbuild commit 7f9e3775 (by @hydroflame) - [791c19c](https://github.com/danielyxie/bitburner/commit/791c19c4fe447c9231bfb423b9fc48114e783b43)
|
|
||||||
- allbuild commit bcbda22a (by @hydroflame) - [032c440](https://github.com/danielyxie/bitburner/commit/032c440eaeb069eecd720ec2f8e069f705a0c1b4)
|
* The main player object was also plagues with a million fields all called '*_mult'. Representing the different multipliers
|
||||||
- fix documentation for getDarkwebPrograms (by @hydroflame) - [4056956](https://github.com/danielyxie/bitburner/commit/4056956c2ada37946333bdad44cb0b6eb3909bf8)
|
* These have been refactored in a field called 'mults'.
|
||||||
- support ASNI (by @hydroflame) - [36c7ef1](https://github.com/danielyxie/bitburner/commit/36c7ef1ad7ea8bb69fca23bce5883a3c2e23f1e0)
|
|
||||||
- allbuild commit 22b6d0d5 (by @hydroflame) - [b46718d](https://github.com/danielyxie/bitburner/commit/b46718d188880ecf716ae045861d81d61e00af4b)
|
Misc.
|
||||||
- allbuild commit 36c7ef1a (by @hydroflame) - [d0ebf5e](https://github.com/danielyxie/bitburner/commit/d0ebf5e14e0498cb063fde35d63c9f59f2c01e35)
|
|
||||||
- Update documentation for employee (by @hydroflame) - [100e81c](https://github.com/danielyxie/bitburner/commit/100e81c8ab4a408f74cc9bd9ffe2b8bad3d03462)
|
* Nerf noodle bar, obviously.
|
||||||
- allbuild commit c799b291 (by @hydroflame) - [f5f5879](https://github.com/danielyxie/bitburner/commit/f5f5879fc380678d978e2b0a29ba7b6f0b4c9ec0)
|
|
||||||
- ideas (by @hydroflame) - [0121fee](https://github.com/danielyxie/bitburner/commit/0121fee6e4c690d01650d1e68a80ea363bb48bce)
|
|
||||||
- allbuild commit 0121fee6 (by @hydroflame) - [5c417e9](https://github.com/danielyxie/bitburner/commit/5c417e9b4df236df8bf3e2f8262b7bce87c934df)
|
|
||||||
- Update codebase for stanek (by @hydroflame) - [c2b4a5b](https://github.com/danielyxie/bitburner/commit/c2b4a5b52a2162d2e49c7317b0a60a349984eb47)
|
|
||||||
- fix lint (by @hydroflame) - [4cc518f](https://github.com/danielyxie/bitburner/commit/4cc518f37723aafb3168b64cd689408afdb74877)
|
|
||||||
- Fix (by @hydroflame) - [9af553f](https://github.com/danielyxie/bitburner/commit/9af553f63cb1380795550648b0134b608564fab8)
|
|
||||||
- Fix stanek leaking classes (by @hydroflame) - [fda3f02](https://github.com/danielyxie/bitburner/commit/fda3f02d73dba27034128c9be5e810a51e475e38)
|
|
||||||
- fix conflicts (by @hydroflame) - [ca1a2aa](https://github.com/danielyxie/bitburner/commit/ca1a2aad333fa838b6d0e57f89e1cedba086a4a0)
|
|
||||||
- Nerf noodle bar.
|
|
||||||
|
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
@ -11,7 +11,7 @@ import { LiteratureNames } from "../Literature/data/LiteratureNames";
|
|||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../utils/JSONReviver";
|
import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
||||||
import { isString } from "../utils/helpers/isString";
|
import { isString } from "../utils/helpers/isString";
|
||||||
|
|
||||||
interface IParams {
|
interface IParams {
|
||||||
@ -433,15 +433,14 @@ export class Corporation {
|
|||||||
/**
|
/**
|
||||||
* Serialize the current object to a JSON save state.
|
* Serialize the current object to a JSON save state.
|
||||||
*/
|
*/
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("Corporation", this);
|
return Generic_toJSON("Corporation", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiatizes a Corporation object from a JSON save state.
|
* Initiatizes a Corporation object from a JSON save state.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): Corporation {
|
||||||
static fromJSON(value: any): Corporation {
|
|
||||||
return Generic_fromJSON(Corporation, value.data);
|
return Generic_fromJSON(Corporation, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
|
|
||||||
// Array of all valid states
|
// Array of all valid states
|
||||||
const AllCorporationStates: string[] = ["START", "PURCHASE", "PRODUCTION", "SALE", "EXPORT"];
|
const AllCorporationStates: string[] = ["START", "PURCHASE", "PRODUCTION", "SALE", "EXPORT"];
|
||||||
@ -28,13 +28,12 @@ export class CorporationState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Serialize the current object to a JSON save state.
|
// Serialize the current object to a JSON save state.
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("CorporationState", this);
|
return Generic_toJSON("CorporationState", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initiatizes a CorporationState object from a JSON save state.
|
// Initiatizes a CorporationState object from a JSON save state.
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): CorporationState {
|
||||||
static fromJSON(value: any): CorporationState {
|
|
||||||
return Generic_fromJSON(CorporationState, value.data);
|
return Generic_fromJSON(CorporationState, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { CorporationConstants } from "./data/Constants";
|
import { CorporationConstants } from "./data/Constants";
|
||||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import { EmployeePositions } from "./EmployeePositions";
|
import { EmployeePositions } from "./EmployeePositions";
|
||||||
import { ICorporation } from "./ICorporation";
|
import { ICorporation } from "./ICorporation";
|
||||||
import { IIndustry } from "./IIndustry";
|
import { IIndustry } from "./IIndustry";
|
||||||
@ -113,12 +113,11 @@ export class Employee {
|
|||||||
return prodBase * prodMult;
|
return prodBase * prodMult;
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("Employee", this);
|
return Generic_toJSON("Employee", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): Employee {
|
||||||
static fromJSON(value: any): Employee {
|
|
||||||
return Generic_fromJSON(Employee, value.data);
|
return Generic_fromJSON(Employee, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { IPlayer } from "../PersonObjects/IPlayer";
|
|||||||
import { CorporationUnlockUpgrade } from "./data/CorporationUnlockUpgrades";
|
import { CorporationUnlockUpgrade } from "./data/CorporationUnlockUpgrades";
|
||||||
import { CorporationUpgrade } from "./data/CorporationUpgrades";
|
import { CorporationUpgrade } from "./data/CorporationUpgrades";
|
||||||
import { CorporationState } from "./CorporationState";
|
import { CorporationState } from "./CorporationState";
|
||||||
|
import { IReviverValue } from "../utils/JSONReviver";
|
||||||
|
|
||||||
export interface ICorporation {
|
export interface ICorporation {
|
||||||
name: string;
|
name: string;
|
||||||
@ -56,5 +57,5 @@ export interface ICorporation {
|
|||||||
getStarterGuide(player: IPlayer): void;
|
getStarterGuide(player: IPlayer): void;
|
||||||
updateDividendTax(): void;
|
updateDividendTax(): void;
|
||||||
getCycleDividends(): number;
|
getCycleDividends(): number;
|
||||||
toJSON(): any;
|
toJSON(): IReviverValue;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { Warehouse } from "./Warehouse";
|
|||||||
import { ICorporation } from "./ICorporation";
|
import { ICorporation } from "./ICorporation";
|
||||||
import { OfficeSpace } from "./OfficeSpace";
|
import { OfficeSpace } from "./OfficeSpace";
|
||||||
import { Product } from "./Product";
|
import { Product } from "./Product";
|
||||||
|
import { IReviverValue } from "../utils/JSONReviver";
|
||||||
|
|
||||||
export interface IIndustry {
|
export interface IIndustry {
|
||||||
name: string;
|
name: string;
|
||||||
@ -72,5 +73,5 @@ export interface IIndustry {
|
|||||||
getSalesMultiplier(): number;
|
getSalesMultiplier(): number;
|
||||||
getScientificResearchMultiplier(): number;
|
getScientificResearchMultiplier(): number;
|
||||||
getStorageMultiplier(): number;
|
getStorageMultiplier(): number;
|
||||||
toJSON(): any;
|
toJSON(): IReviverValue;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../utils/JSONReviver";
|
import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
||||||
import { CityName } from "../Locations/data/CityNames";
|
import { CityName } from "../Locations/data/CityNames";
|
||||||
import { Industries, IndustryStartingCosts, IndustryResearchTrees } from "./IndustryData";
|
import { Industries, IndustryStartingCosts, IndustryResearchTrees } from "./IndustryData";
|
||||||
import { CorporationConstants } from "./data/Constants";
|
import { CorporationConstants } from "./data/Constants";
|
||||||
@ -1403,15 +1403,14 @@ export class Industry implements IIndustry {
|
|||||||
/**
|
/**
|
||||||
* Serialize the current object to a JSON save state.
|
* Serialize the current object to a JSON save state.
|
||||||
*/
|
*/
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("Industry", this);
|
return Generic_toJSON("Industry", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiatizes a Industry object from a JSON save state.
|
* Initiatizes a Industry object from a JSON save state.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): Industry {
|
||||||
static fromJSON(value: any): Industry {
|
|
||||||
return Generic_fromJSON(Industry, value.data);
|
return Generic_fromJSON(Industry, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import { Export } from "./Export";
|
import { Export } from "./Export";
|
||||||
|
|
||||||
interface IConstructorParams {
|
interface IConstructorParams {
|
||||||
@ -229,13 +229,12 @@ export class Material {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Serialize the current object to a JSON save state.
|
// Serialize the current object to a JSON save state.
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("Material", this);
|
return Generic_toJSON("Material", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initiatizes a Material object from a JSON save state.
|
// Initiatizes a Material object from a JSON save state.
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): Material {
|
||||||
static fromJSON(value: any): Material {
|
|
||||||
return Generic_fromJSON(Material, value.data);
|
return Generic_fromJSON(Material, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import { EmployeePositions } from "./EmployeePositions";
|
|||||||
import { CorporationConstants } from "./data/Constants";
|
import { CorporationConstants } from "./data/Constants";
|
||||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||||
import { generateRandomString } from "../utils/StringHelperFunctions";
|
import { generateRandomString } from "../utils/StringHelperFunctions";
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import { Employee } from "./Employee";
|
import { Employee } from "./Employee";
|
||||||
import { IIndustry } from "./IIndustry";
|
import { IIndustry } from "./IIndustry";
|
||||||
import { ICorporation } from "./ICorporation";
|
import { ICorporation } from "./ICorporation";
|
||||||
@ -277,12 +277,11 @@ export class OfficeSpace {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("OfficeSpace", this);
|
return Generic_toJSON("OfficeSpace", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): OfficeSpace {
|
||||||
static fromJSON(value: any): OfficeSpace {
|
|
||||||
return Generic_fromJSON(OfficeSpace, value.data);
|
return Generic_fromJSON(OfficeSpace, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import { ProductRatingWeights, IProductRatingWeight } from "./ProductRatingWeigh
|
|||||||
import { createCityMap } from "../Locations/createCityMap";
|
import { createCityMap } from "../Locations/createCityMap";
|
||||||
import { IMap } from "../types";
|
import { IMap } from "../types";
|
||||||
|
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||||
|
|
||||||
interface IConstructorParams {
|
interface IConstructorParams {
|
||||||
@ -265,13 +265,12 @@ export class Product {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Serialize the current object to a JSON save state.
|
// Serialize the current object to a JSON save state.
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("Product", this);
|
return Generic_toJSON("Product", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initiatizes a Product object from a JSON save state.
|
// Initiatizes a Product object from a JSON save state.
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): Product {
|
||||||
static fromJSON(value: any): Product {
|
|
||||||
return Generic_fromJSON(Product, value.data);
|
return Generic_fromJSON(Product, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,6 @@ import { ResearchMap } from "./ResearchMap";
|
|||||||
|
|
||||||
import { IMap } from "../types";
|
import { IMap } from "../types";
|
||||||
|
|
||||||
import { numeralWrapper } from "../ui/numeralFormat";
|
|
||||||
|
|
||||||
interface IConstructorParams {
|
interface IConstructorParams {
|
||||||
children?: Node[];
|
children?: Node[];
|
||||||
cost: number;
|
cost: number;
|
||||||
@ -60,40 +58,6 @@ export class Node {
|
|||||||
n.parent = this;
|
n.parent = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return an object that describes a TreantJS-compatible markup/config for this Node
|
|
||||||
// See: http://fperucic.github.io/treant-js/
|
|
||||||
createTreantMarkup(): any {
|
|
||||||
const childrenArray = [];
|
|
||||||
for (let i = 0; i < this.children.length; ++i) {
|
|
||||||
childrenArray.push(this.children[i].createTreantMarkup());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine what css class this Node should have in the diagram
|
|
||||||
let htmlClass = "tooltip";
|
|
||||||
if (this.researched) {
|
|
||||||
htmlClass += " researched";
|
|
||||||
} else if (this.parent && this.parent.researched === false) {
|
|
||||||
htmlClass += " locked";
|
|
||||||
} else {
|
|
||||||
htmlClass += " unlocked";
|
|
||||||
}
|
|
||||||
|
|
||||||
const research: Research | null = ResearchMap[this.text];
|
|
||||||
const sanitizedName: string = this.text.replace(/\s/g, "");
|
|
||||||
return {
|
|
||||||
children: childrenArray,
|
|
||||||
HTMLclass: htmlClass,
|
|
||||||
innerHTML:
|
|
||||||
`<div id="${sanitizedName}-corp-research-click-listener">` +
|
|
||||||
`${this.text}<br>${numeralWrapper.format(this.cost, "0,0")} Scientific Research` +
|
|
||||||
`<span class="tooltiptext">` +
|
|
||||||
`${research.desc}` +
|
|
||||||
`</span>` +
|
|
||||||
`</div>`,
|
|
||||||
text: { name: this.text },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recursive function for finding a Node with the specified text
|
// Recursive function for finding a Node with the specified text
|
||||||
findNode(text: string): Node | null {
|
findNode(text: string): Node | null {
|
||||||
// Is this the Node?
|
// Is this the Node?
|
||||||
@ -127,23 +91,6 @@ export class ResearchTree {
|
|||||||
// Root Node
|
// Root Node
|
||||||
root: Node | null = null;
|
root: Node | null = null;
|
||||||
|
|
||||||
// Return an object that contains a Tree markup for TreantJS (using the JSON approach)
|
|
||||||
// See: http://fperucic.github.io/treant-js/
|
|
||||||
createTreantMarkup(): any {
|
|
||||||
if (this.root == null) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const treeMarkup = this.root.createTreantMarkup();
|
|
||||||
|
|
||||||
return {
|
|
||||||
chart: {
|
|
||||||
container: "",
|
|
||||||
},
|
|
||||||
nodeStructure: treeMarkup,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets an array with the 'text' values of ALL Nodes in the Research Tree
|
// Gets an array with the 'text' values of ALL Nodes in the Research Tree
|
||||||
getAllNodes(): string[] {
|
getAllNodes(): string[] {
|
||||||
const res: string[] = [];
|
const res: string[] = [];
|
||||||
@ -236,7 +183,20 @@ export class ResearchTree {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mult: any = (research as any)[propName];
|
const mult =
|
||||||
|
{
|
||||||
|
advertisingMult: research.advertisingMult,
|
||||||
|
employeeChaMult: research.employeeChaMult,
|
||||||
|
employeeCreMult: research.employeeCreMult,
|
||||||
|
employeeEffMult: research.employeeEffMult,
|
||||||
|
employeeIntMult: research.employeeIntMult,
|
||||||
|
productionMult: research.productionMult,
|
||||||
|
productProductionMult: research.productProductionMult,
|
||||||
|
salesMult: research.salesMult,
|
||||||
|
sciResearchMult: research.sciResearchMult,
|
||||||
|
storageMult: research.storageMult,
|
||||||
|
}[propName] ?? null;
|
||||||
|
|
||||||
if (mult == null) {
|
if (mult == null) {
|
||||||
console.warn(`Invalid propName specified in ResearchTree.getMultiplierHelper: ${propName}`);
|
console.warn(`Invalid propName specified in ResearchTree.getMultiplierHelper: ${propName}`);
|
||||||
continue;
|
continue;
|
||||||
|
@ -3,7 +3,7 @@ import { ICorporation } from "./ICorporation";
|
|||||||
import { IIndustry } from "./IIndustry";
|
import { IIndustry } from "./IIndustry";
|
||||||
import { MaterialSizes } from "./MaterialSizes";
|
import { MaterialSizes } from "./MaterialSizes";
|
||||||
import { IMap } from "../types";
|
import { IMap } from "../types";
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||||
|
|
||||||
interface IConstructorParams {
|
interface IConstructorParams {
|
||||||
@ -99,19 +99,18 @@ export class Warehouse {
|
|||||||
updateSize(corporation: ICorporation, industry: IIndustry): void {
|
updateSize(corporation: ICorporation, industry: IIndustry): void {
|
||||||
try {
|
try {
|
||||||
this.size = this.level * 100 * corporation.getStorageMultiplier() * industry.getStorageMultiplier();
|
this.size = this.level * 100 * corporation.getStorageMultiplier() * industry.getStorageMultiplier();
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serialize the current object to a JSON save state.
|
// Serialize the current object to a JSON save state.
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("Warehouse", this);
|
return Generic_toJSON("Warehouse", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initiatizes a Warehouse object from a JSON save state.
|
// Initiatizes a Warehouse object from a JSON save state.
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): Warehouse {
|
||||||
static fromJSON(value: any): Warehouse {
|
|
||||||
return Generic_fromJSON(Warehouse, value.data);
|
return Generic_fromJSON(Warehouse, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,8 +124,8 @@ export function IndustryOverview(props: IProps): React.ReactElement {
|
|||||||
<br />
|
<br />
|
||||||
<StatsTable
|
<StatsTable
|
||||||
rows={[
|
rows={[
|
||||||
["Awareness:", numeralWrapper.format(division.awareness, "0.000")],
|
["Awareness:", numeralWrapper.formatReallyBigNumber(division.awareness)],
|
||||||
["Popularity:", numeralWrapper.format(division.popularity, "0.000")],
|
["Popularity:", numeralWrapper.formatReallyBigNumber(division.popularity)],
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
{advertisingInfo !== false && (
|
{advertisingInfo !== false && (
|
||||||
@ -135,15 +135,15 @@ export function IndustryOverview(props: IProps): React.ReactElement {
|
|||||||
<Typography>Total multiplier for this industrys sales due to its awareness and popularity</Typography>
|
<Typography>Total multiplier for this industrys sales due to its awareness and popularity</Typography>
|
||||||
<StatsTable
|
<StatsTable
|
||||||
rows={[
|
rows={[
|
||||||
["Awareness Bonus:", "x" + numeralWrapper.format(Math.pow(awarenessFac, 0.85), "0.000")],
|
["Awareness Bonus:", "x" + numeralWrapper.formatReallyBigNumber(Math.pow(awarenessFac, 0.85))],
|
||||||
["Popularity Bonus:", "x" + numeralWrapper.format(Math.pow(popularityFac, 0.85), "0.000")],
|
["Popularity Bonus:", "x" + numeralWrapper.formatReallyBigNumber(Math.pow(popularityFac, 0.85))],
|
||||||
["Ratio Multiplier:", "x" + numeralWrapper.format(Math.pow(ratioFac, 0.85), "0.000")],
|
["Ratio Multiplier:", "x" + numeralWrapper.formatReallyBigNumber(Math.pow(ratioFac, 0.85))],
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Typography>Advertising Multiplier: x{numeralWrapper.format(totalAdvertisingFac, "0.000")}</Typography>
|
<Typography>Advertising Multiplier: x{numeralWrapper.formatReallyBigNumber(totalAdvertisingFac)}</Typography>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
<br />
|
<br />
|
||||||
@ -164,7 +164,7 @@ export function IndustryOverview(props: IProps): React.ReactElement {
|
|||||||
</Typography>
|
</Typography>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Typography>Production Multiplier: {numeralWrapper.format(division.prodMult, "0.00")}</Typography>
|
<Typography>Production Multiplier: {numeralWrapper.formatReallyBigNumber(division.prodMult)}</Typography>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<IconButton onClick={() => setHelpOpen(true)}>
|
<IconButton onClick={() => setHelpOpen(true)}>
|
||||||
<HelpIcon />
|
<HelpIcon />
|
||||||
@ -203,7 +203,7 @@ export function IndustryOverview(props: IProps): React.ReactElement {
|
|||||||
</Typography>
|
</Typography>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Typography>Scientific Research: {numeralWrapper.format(division.sciResearch.qty, "0.000a")}</Typography>
|
<Typography>Scientific Research: {numeralWrapper.formatReallyBigNumber(division.sciResearch.qty)}</Typography>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Button sx={{ mx: 1 }} onClick={() => setResearchOpen(true)}>
|
<Button sx={{ mx: 1 }} onClick={() => setResearchOpen(true)}>
|
||||||
Research
|
Research
|
||||||
|
@ -38,7 +38,7 @@ export function Overview({ rerender }: IProps): React.ReactElement {
|
|||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const profit: number = corp.revenue - corp.expenses;
|
const profit: number = corp.revenue - corp.expenses;
|
||||||
|
|
||||||
const multRows: any[][] = [];
|
const multRows: string[][] = [];
|
||||||
function appendMult(name: string, value: number): void {
|
function appendMult(name: string, value: number): void {
|
||||||
if (value === 1) return;
|
if (value === 1) return;
|
||||||
multRows.push([name, numeralWrapper.format(value, "0.000")]);
|
multRows.push([name, numeralWrapper.format(value, "0.000")]);
|
||||||
|
@ -9,7 +9,7 @@ import { useCorporation } from "../Context";
|
|||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import MenuItem from "@mui/material/MenuItem";
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
import TextField from "@mui/material/TextField";
|
import { NumberInput } from "../../../ui/React/NumberInput";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||||
|
|
||||||
@ -27,12 +27,10 @@ export function BribeFactionModal(props: IProps): React.ReactElement {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const [money, setMoney] = useState<number | null>(0);
|
const [money, setMoney] = useState<number>(NaN);
|
||||||
const [stock, setStock] = useState<number | null>(0);
|
const [stock, setStock] = useState<number>(NaN);
|
||||||
const [selectedFaction, setSelectedFaction] = useState(factions.length > 0 ? factions[0] : "");
|
const [selectedFaction, setSelectedFaction] = useState(factions.length > 0 ? factions[0] : "");
|
||||||
const disabled =
|
const disabled =
|
||||||
money === null ||
|
|
||||||
stock === null ||
|
|
||||||
(money === 0 && stock === 0) ||
|
(money === 0 && stock === 0) ||
|
||||||
isNaN(money) ||
|
isNaN(money) ||
|
||||||
isNaN(stock) ||
|
isNaN(stock) ||
|
||||||
@ -41,14 +39,6 @@ export function BribeFactionModal(props: IProps): React.ReactElement {
|
|||||||
corp.funds < money ||
|
corp.funds < money ||
|
||||||
stock > corp.numShares;
|
stock > corp.numShares;
|
||||||
|
|
||||||
function onMoneyChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
setMoney(parseFloat(event.target.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
function onStockChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
setStock(parseFloat(event.target.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeFaction(event: SelectChangeEvent<string>): void {
|
function changeFaction(event: SelectChangeEvent<string>): void {
|
||||||
setSelectedFaction(event.target.value);
|
setSelectedFaction(event.target.value);
|
||||||
}
|
}
|
||||||
@ -110,8 +100,8 @@ export function BribeFactionModal(props: IProps): React.ReactElement {
|
|||||||
</Select>
|
</Select>
|
||||||
</Box>
|
</Box>
|
||||||
<Typography>{getRepText(money ? money : 0, stock ? stock : 0)}</Typography>
|
<Typography>{getRepText(money ? money : 0, stock ? stock : 0)}</Typography>
|
||||||
<TextField onChange={onMoneyChange} placeholder="Corporation funds" />
|
<NumberInput onChange={setMoney} placeholder="Corporation funds" />
|
||||||
<TextField sx={{ mx: 1 }} onChange={onStockChange} placeholder="Stock Shares" />
|
<NumberInput sx={{ mx: 1 }} onChange={setStock} placeholder="Stock Shares" />
|
||||||
<Button disabled={disabled} sx={{ mx: 1 }} onClick={() => bribe(money ? money : 0, stock ? stock : 0)}>
|
<Button disabled={disabled} sx={{ mx: 1 }} onClick={() => bribe(money ? money : 0, stock ? stock : 0)}>
|
||||||
Bribe
|
Bribe
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -5,7 +5,7 @@ import { use } from "../../../ui/Context";
|
|||||||
import { useCorporation } from "../Context";
|
import { useCorporation } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import TextField from "@mui/material/TextField";
|
import { NumberInput } from "../../../ui/React/NumberInput";
|
||||||
import { BuyBackShares } from "../../Actions";
|
import { BuyBackShares } from "../../Actions";
|
||||||
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { KEY } from "../../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
@ -21,12 +21,7 @@ interface IProps {
|
|||||||
export function BuybackSharesModal(props: IProps): React.ReactElement {
|
export function BuybackSharesModal(props: IProps): React.ReactElement {
|
||||||
const player = use.Player();
|
const player = use.Player();
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const [shares, setShares] = useState<number | null>(null);
|
const [shares, setShares] = useState<number>(NaN);
|
||||||
|
|
||||||
function changeShares(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
if (event.target.value === "") setShares(null);
|
|
||||||
else setShares(Math.round(parseFloat(event.target.value)));
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentStockPrice = corp.sharePrice;
|
const currentStockPrice = corp.sharePrice;
|
||||||
const buybackPrice = currentStockPrice * 1.1;
|
const buybackPrice = currentStockPrice * 1.1;
|
||||||
@ -87,13 +82,7 @@ export function BuybackSharesModal(props: IProps): React.ReactElement {
|
|||||||
</Typography>
|
</Typography>
|
||||||
<CostIndicator />
|
<CostIndicator />
|
||||||
<br />
|
<br />
|
||||||
<TextField
|
<NumberInput autoFocus={true} placeholder="Shares to buyback" onChange={setShares} onKeyDown={onKeyDown} />
|
||||||
autoFocus={true}
|
|
||||||
type="number"
|
|
||||||
placeholder="Shares to buyback"
|
|
||||||
onChange={changeShares}
|
|
||||||
onKeyDown={onKeyDown}
|
|
||||||
/>
|
|
||||||
<Button disabled={disabled} onClick={buy}>
|
<Button disabled={disabled} onClick={buy}>
|
||||||
Buy shares
|
Buy shares
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -5,7 +5,7 @@ import { numeralWrapper } from "../../../ui/numeralFormat";
|
|||||||
import { useCorporation } from "../Context";
|
import { useCorporation } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import TextField from "@mui/material/TextField";
|
import { NumberInput } from "../../../ui/React/NumberInput";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import { KEY } from "../../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
|
|
||||||
@ -18,29 +18,28 @@ interface IProps {
|
|||||||
// Create a popup that lets the player manage exports
|
// Create a popup that lets the player manage exports
|
||||||
export function GoPublicModal(props: IProps): React.ReactElement {
|
export function GoPublicModal(props: IProps): React.ReactElement {
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const [shares, setShares] = useState("");
|
const [shares, setShares] = useState<number>(NaN);
|
||||||
const initialSharePrice = corp.determineValuation() / corp.totalShares;
|
const initialSharePrice = corp.determineValuation() / corp.totalShares;
|
||||||
|
|
||||||
function goPublic(): void {
|
function goPublic(): void {
|
||||||
const numShares = parseFloat(shares);
|
|
||||||
const initialSharePrice = corp.determineValuation() / corp.totalShares;
|
const initialSharePrice = corp.determineValuation() / corp.totalShares;
|
||||||
if (isNaN(numShares)) {
|
if (isNaN(shares)) {
|
||||||
dialogBoxCreate("Invalid value for number of issued shares");
|
dialogBoxCreate("Invalid value for number of issued shares");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (numShares > corp.numShares) {
|
if (shares > corp.numShares) {
|
||||||
dialogBoxCreate("Error: You don't have that many shares to issue!");
|
dialogBoxCreate("Error: You don't have that many shares to issue!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
corp.public = true;
|
corp.public = true;
|
||||||
corp.sharePrice = initialSharePrice;
|
corp.sharePrice = initialSharePrice;
|
||||||
corp.issuedShares = numShares;
|
corp.issuedShares = shares;
|
||||||
corp.numShares -= numShares;
|
corp.numShares -= shares;
|
||||||
corp.addFunds(numShares * initialSharePrice);
|
corp.addFunds(shares * initialSharePrice);
|
||||||
props.rerender();
|
props.rerender();
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
`You took your ${corp.name} public and earned ` +
|
`You took your ${corp.name} public and earned ` +
|
||||||
`${numeralWrapper.formatMoney(numShares * initialSharePrice)} in your IPO`,
|
`${numeralWrapper.formatMoney(shares * initialSharePrice)} in your IPO`,
|
||||||
);
|
);
|
||||||
props.onClose();
|
props.onClose();
|
||||||
}
|
}
|
||||||
@ -49,10 +48,6 @@ export function GoPublicModal(props: IProps): React.ReactElement {
|
|||||||
if (event.key === KEY.ENTER) goPublic();
|
if (event.key === KEY.ENTER) goPublic();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
setShares(event.target.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal open={props.open} onClose={props.onClose}>
|
<Modal open={props.open} onClose={props.onClose}>
|
||||||
<Typography>
|
<Typography>
|
||||||
@ -64,19 +59,8 @@ export function GoPublicModal(props: IProps): React.ReactElement {
|
|||||||
You have a total of {numeralWrapper.format(corp.numShares, "0.000a")} of shares that you can issue.
|
You have a total of {numeralWrapper.format(corp.numShares, "0.000a")} of shares that you can issue.
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box display="flex" alignItems="center">
|
<Box display="flex" alignItems="center">
|
||||||
<TextField
|
<NumberInput onChange={setShares} autoFocus placeholder="Shares to issue" onKeyDown={onKeyDown} />
|
||||||
value={shares}
|
<Button disabled={shares < 0 || shares > corp.numShares} sx={{ mx: 1 }} onClick={goPublic}>
|
||||||
onChange={onChange}
|
|
||||||
autoFocus
|
|
||||||
type="number"
|
|
||||||
placeholder="Shares to issue"
|
|
||||||
onKeyDown={onKeyDown}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
disabled={parseFloat(shares) < 0 || parseFloat(shares) > corp.numShares}
|
|
||||||
sx={{ mx: 1 }}
|
|
||||||
onClick={goPublic}
|
|
||||||
>
|
|
||||||
Go Public
|
Go Public
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -6,7 +6,7 @@ import { getRandomInt } from "../../../utils/helpers/getRandomInt";
|
|||||||
import { CorporationConstants } from "../../data/Constants";
|
import { CorporationConstants } from "../../data/Constants";
|
||||||
import { useCorporation } from "../Context";
|
import { useCorporation } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import TextField from "@mui/material/TextField";
|
import { NumberInput } from "../../../ui/React/NumberInput";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import { KEY } from "../../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
|
|
||||||
@ -54,15 +54,15 @@ interface IProps {
|
|||||||
// This is created when the player clicks the "Issue New Shares" buttons in the overview panel
|
// This is created when the player clicks the "Issue New Shares" buttons in the overview panel
|
||||||
export function IssueNewSharesModal(props: IProps): React.ReactElement {
|
export function IssueNewSharesModal(props: IProps): React.ReactElement {
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const [shares, setShares] = useState<number | null>(null);
|
const [shares, setShares] = useState<number>(NaN);
|
||||||
const maxNewSharesUnrounded = Math.round(corp.totalShares * 0.2);
|
const maxNewSharesUnrounded = Math.round(corp.totalShares * 0.2);
|
||||||
const maxNewShares = maxNewSharesUnrounded - (maxNewSharesUnrounded % 1e6);
|
const maxNewShares = maxNewSharesUnrounded - (maxNewSharesUnrounded % 1e6);
|
||||||
|
|
||||||
const newShares = Math.round((shares || 0) / 10e6) * 10e6;
|
const newShares = Math.round((shares || 0) / 10e6) * 10e6;
|
||||||
const disabled = shares === null || isNaN(newShares) || newShares < 10e6 || newShares > maxNewShares;
|
const disabled = isNaN(shares) || isNaN(newShares) || newShares < 10e6 || newShares > maxNewShares;
|
||||||
|
|
||||||
function issueNewShares(): void {
|
function issueNewShares(): void {
|
||||||
if (shares === null) return;
|
if (isNaN(shares)) return;
|
||||||
if (disabled) return;
|
if (disabled) return;
|
||||||
|
|
||||||
const newSharePrice = Math.round(corp.sharePrice * 0.9);
|
const newSharePrice = Math.round(corp.sharePrice * 0.9);
|
||||||
@ -97,11 +97,6 @@ export function IssueNewSharesModal(props: IProps): React.ReactElement {
|
|||||||
if (event.key === KEY.ENTER) issueNewShares();
|
if (event.key === KEY.ENTER) issueNewShares();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
if (event.target.value === "") setShares(null);
|
|
||||||
else setShares(parseFloat(event.target.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal open={props.open} onClose={props.onClose}>
|
<Modal open={props.open} onClose={props.onClose}>
|
||||||
<Typography>
|
<Typography>
|
||||||
@ -124,7 +119,7 @@ export function IssueNewSharesModal(props: IProps): React.ReactElement {
|
|||||||
you cannot buy them back.
|
you cannot buy them back.
|
||||||
</Typography>
|
</Typography>
|
||||||
<EffectText shares={shares} />
|
<EffectText shares={shares} />
|
||||||
<TextField autoFocus placeholder="# New Shares" onChange={onChange} onKeyDown={onKeyDown} />
|
<NumberInput autoFocus placeholder="# New Shares" onChange={setShares} onKeyDown={onKeyDown} />
|
||||||
<Button disabled={disabled} onClick={issueNewShares} sx={{ mx: 1 }}>
|
<Button disabled={disabled} onClick={issueNewShares} sx={{ mx: 1 }}>
|
||||||
Issue New Shares
|
Issue New Shares
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -10,6 +10,7 @@ import Button from "@mui/material/Button";
|
|||||||
import MenuItem from "@mui/material/MenuItem";
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||||
import { KEY } from "../../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
|
import { NumberInput } from "../../../ui/React/NumberInput";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@ -34,8 +35,8 @@ export function MakeProductModal(props: IProps): React.ReactElement {
|
|||||||
const allCities = Object.keys(division.offices).filter((cityName: string) => division.offices[cityName] !== 0);
|
const allCities = Object.keys(division.offices).filter((cityName: string) => division.offices[cityName] !== 0);
|
||||||
const [city, setCity] = useState(allCities.length > 0 ? allCities[0] : "");
|
const [city, setCity] = useState(allCities.length > 0 ? allCities[0] : "");
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
const [design, setDesign] = useState<number | null>(null);
|
const [design, setDesign] = useState<number>(NaN);
|
||||||
const [marketing, setMarketing] = useState<number | null>(null);
|
const [marketing, setMarketing] = useState<number>(NaN);
|
||||||
if (division.hasMaximumNumberProducts()) return <></>;
|
if (division.hasMaximumNumberProducts()) return <></>;
|
||||||
|
|
||||||
let createProductPopupText = <></>;
|
let createProductPopupText = <></>;
|
||||||
@ -138,7 +139,7 @@ export function MakeProductModal(props: IProps): React.ReactElement {
|
|||||||
);
|
);
|
||||||
|
|
||||||
function makeProduct(): void {
|
function makeProduct(): void {
|
||||||
if (design === null || marketing === null) return;
|
if (isNaN(design) || isNaN(marketing)) return;
|
||||||
try {
|
try {
|
||||||
MakeProduct(corp, division, city, name, design, marketing);
|
MakeProduct(corp, division, city, name, design, marketing);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -155,16 +156,6 @@ export function MakeProductModal(props: IProps): React.ReactElement {
|
|||||||
setName(event.target.value);
|
setName(event.target.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDesignChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
if (event.target.value === "") setDesign(null);
|
|
||||||
else setDesign(parseFloat(event.target.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMarketingChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
if (event.target.value === "") setMarketing(null);
|
|
||||||
else setMarketing(parseFloat(event.target.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): void {
|
function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): void {
|
||||||
if (event.key === KEY.ENTER) makeProduct();
|
if (event.key === KEY.ENTER) makeProduct();
|
||||||
}
|
}
|
||||||
@ -181,13 +172,8 @@ export function MakeProductModal(props: IProps): React.ReactElement {
|
|||||||
</Select>
|
</Select>
|
||||||
<TextField onChange={onProductNameChange} placeholder={productPlaceholder(division.type)} />
|
<TextField onChange={onProductNameChange} placeholder={productPlaceholder(division.type)} />
|
||||||
<br />
|
<br />
|
||||||
<TextField onChange={onDesignChange} autoFocus={true} type="number" placeholder={"Design investment"} />
|
<NumberInput onChange={setDesign} autoFocus={true} placeholder={"Design investment"} />
|
||||||
<TextField
|
<NumberInput onChange={setMarketing} onKeyDown={onKeyDown} placeholder={"Marketing investment"} />
|
||||||
onChange={onMarketingChange}
|
|
||||||
onKeyDown={onKeyDown}
|
|
||||||
type="number"
|
|
||||||
placeholder={"Marketing investment"}
|
|
||||||
/>
|
|
||||||
<Button onClick={makeProduct}>Develop Product</Button>
|
<Button onClick={makeProduct}>Develop Product</Button>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
|
@ -6,11 +6,11 @@ import { use } from "../../../ui/Context";
|
|||||||
import { useCorporation } from "../Context";
|
import { useCorporation } from "../Context";
|
||||||
import { ICorporation } from "../../ICorporation";
|
import { ICorporation } from "../../ICorporation";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import TextField from "@mui/material/TextField";
|
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import { Money } from "../../../ui/React/Money";
|
import { Money } from "../../../ui/React/Money";
|
||||||
import { SellShares } from "../../Actions";
|
import { SellShares } from "../../Actions";
|
||||||
import { KEY } from "../../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
|
import { NumberInput } from "../../../ui/React/NumberInput";
|
||||||
interface IProps {
|
interface IProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@ -22,14 +22,9 @@ interface IProps {
|
|||||||
export function SellSharesModal(props: IProps): React.ReactElement {
|
export function SellSharesModal(props: IProps): React.ReactElement {
|
||||||
const player = use.Player();
|
const player = use.Player();
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const [shares, setShares] = useState<number | null>(null);
|
const [shares, setShares] = useState<number>(NaN);
|
||||||
|
|
||||||
const disabled = shares === null || isNaN(shares) || shares <= 0 || shares > corp.numShares;
|
const disabled = isNaN(shares) || shares <= 0 || shares > corp.numShares;
|
||||||
|
|
||||||
function changeShares(event: React.ChangeEvent<HTMLInputElement>): void {
|
|
||||||
if (event.target.value === "") setShares(null);
|
|
||||||
else setShares(Math.round(parseFloat(event.target.value)));
|
|
||||||
}
|
|
||||||
|
|
||||||
function ProfitIndicator(props: { shares: number | null; corp: ICorporation }): React.ReactElement {
|
function ProfitIndicator(props: { shares: number | null; corp: ICorporation }): React.ReactElement {
|
||||||
if (props.shares === null) return <></>;
|
if (props.shares === null) return <></>;
|
||||||
@ -88,12 +83,11 @@ export function SellSharesModal(props: IProps): React.ReactElement {
|
|||||||
The current price of your company's stock is {numeralWrapper.formatMoney(corp.sharePrice)}
|
The current price of your company's stock is {numeralWrapper.formatMoney(corp.sharePrice)}
|
||||||
</Typography>
|
</Typography>
|
||||||
<br />
|
<br />
|
||||||
<TextField
|
<NumberInput
|
||||||
variant="standard"
|
variant="standard"
|
||||||
autoFocus
|
autoFocus
|
||||||
type="number"
|
|
||||||
placeholder="Shares to sell"
|
placeholder="Shares to sell"
|
||||||
onChange={changeShares}
|
onChange={setShares}
|
||||||
onKeyDown={onKeyDown}
|
onKeyDown={onKeyDown}
|
||||||
/>
|
/>
|
||||||
<Button disabled={disabled} onClick={sell} sx={{ mx: 1 }}>
|
<Button disabled={disabled} onClick={sell} sx={{ mx: 1 }}>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Fragment, FragmentById } from "./Fragment";
|
import { Fragment, FragmentById } from "./Fragment";
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
|
|
||||||
export interface IActiveFragmentParams {
|
export interface IActiveFragmentParams {
|
||||||
x: number;
|
x: number;
|
||||||
@ -74,15 +74,14 @@ export class ActiveFragment {
|
|||||||
/**
|
/**
|
||||||
* Serialize an active fragment to a JSON save state.
|
* Serialize an active fragment to a JSON save state.
|
||||||
*/
|
*/
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("ActiveFragment", this);
|
return Generic_toJSON("ActiveFragment", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes an acive fragment from a JSON save state
|
* Initializes an acive fragment from a JSON save state
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): ActiveFragment {
|
||||||
static fromJSON(value: any): ActiveFragment {
|
|
||||||
return Generic_fromJSON(ActiveFragment, value.data);
|
return Generic_fromJSON(ActiveFragment, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,22 +19,22 @@ export class DummyGift implements IStaneksGift {
|
|||||||
height(): number {
|
height(): number {
|
||||||
return this._height;
|
return this._height;
|
||||||
}
|
}
|
||||||
charge(): any {
|
charge(): void {
|
||||||
throw new Error("unimplemented for dummy gift");
|
throw new Error("unimplemented for dummy gift");
|
||||||
}
|
}
|
||||||
process(): any {
|
process(): void {
|
||||||
throw new Error("unimplemented for dummy gift");
|
throw new Error("unimplemented for dummy gift");
|
||||||
}
|
}
|
||||||
effect(): any {
|
effect(): number {
|
||||||
throw new Error("unimplemented for dummy gift");
|
throw new Error("unimplemented for dummy gift");
|
||||||
}
|
}
|
||||||
canPlace(): any {
|
canPlace(): boolean {
|
||||||
throw new Error("unimplemented for dummy gift");
|
throw new Error("unimplemented for dummy gift");
|
||||||
}
|
}
|
||||||
place(): any {
|
place(): boolean {
|
||||||
throw new Error("unimplemented for dummy gift");
|
throw new Error("unimplemented for dummy gift");
|
||||||
}
|
}
|
||||||
findFragment(): any {
|
findFragment(): ActiveFragment | undefined {
|
||||||
throw new Error("unimplemented for dummy gift");
|
throw new Error("unimplemented for dummy gift");
|
||||||
}
|
}
|
||||||
fragmentAt(worldX: number, worldY: number): ActiveFragment | undefined {
|
fragmentAt(worldX: number, worldY: number): ActiveFragment | undefined {
|
||||||
@ -46,22 +46,22 @@ export class DummyGift implements IStaneksGift {
|
|||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
delete(): any {
|
delete(): boolean {
|
||||||
throw new Error("unimplemented for dummy gift");
|
throw new Error("unimplemented for dummy gift");
|
||||||
}
|
}
|
||||||
clear(): any {
|
clear(): void {
|
||||||
throw new Error("unimplemented for dummy gift");
|
throw new Error("unimplemented for dummy gift");
|
||||||
}
|
}
|
||||||
count(): any {
|
count(): number {
|
||||||
throw new Error("unimplemented for dummy gift");
|
throw new Error("unimplemented for dummy gift");
|
||||||
}
|
}
|
||||||
inBonus(): any {
|
inBonus(): boolean {
|
||||||
throw new Error("unimplemented for dummy gift");
|
throw new Error("unimplemented for dummy gift");
|
||||||
}
|
}
|
||||||
prestigeAugmentation(): any {
|
prestigeAugmentation(): void {
|
||||||
throw new Error("unimplemented for dummy gift");
|
throw new Error("unimplemented for dummy gift");
|
||||||
}
|
}
|
||||||
prestigeSourceFile(): any {
|
prestigeSourceFile(): void {
|
||||||
throw new Error("unimplemented for dummy gift");
|
throw new Error("unimplemented for dummy gift");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,18 +13,18 @@ export function loadStaneksGift(saveString: string): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function zeros(dimensions: number[]): any {
|
export function zeros(width: number, height: number): number[][] {
|
||||||
const array = [];
|
const array = [];
|
||||||
|
|
||||||
for (let i = 0; i < dimensions[0]; ++i) {
|
for (let i = 0; i < width; ++i) {
|
||||||
array.push(dimensions.length == 1 ? 0 : zeros(dimensions.slice(1)));
|
array.push(Array(height).fill(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calculateGrid(gift: IStaneksGift): number[][] {
|
export function calculateGrid(gift: IStaneksGift): number[][] {
|
||||||
const newgrid = zeros([gift.width(), gift.height()]) as unknown as number[][];
|
const newgrid = zeros(gift.width(), gift.height()) as unknown as number[][];
|
||||||
for (let i = 0; i < gift.width(); i++) {
|
for (let i = 0; i < gift.width(); i++) {
|
||||||
for (let j = 0; j < gift.height(); j++) {
|
for (let j = 0; j < gift.height(); j++) {
|
||||||
const fragment = gift.fragmentAt(i, j);
|
const fragment = gift.fragmentAt(i, j);
|
||||||
|
@ -7,7 +7,7 @@ import { IPlayer } from "../PersonObjects/IPlayer";
|
|||||||
import { Factions } from "../Faction/Factions";
|
import { Factions } from "../Faction/Factions";
|
||||||
import { CalculateEffect } from "./formulas/effect";
|
import { CalculateEffect } from "./formulas/effect";
|
||||||
import { StaneksGiftEvents } from "./StaneksGiftEvents";
|
import { StaneksGiftEvents } from "./StaneksGiftEvents";
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import { CONSTANTS } from "../Constants";
|
import { CONSTANTS } from "../Constants";
|
||||||
import { StanekConstants } from "./data/Constants";
|
import { StanekConstants } from "./data/Constants";
|
||||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
@ -38,7 +38,7 @@ export class StaneksGift implements IStaneksGift {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const cotmg = Factions[FactionNames.ChurchOfTheMachineGod];
|
const cotmg = Factions[FactionNames.ChurchOfTheMachineGod];
|
||||||
cotmg.playerReputation += (player.faction_rep_mult * (Math.pow(threads, 0.95) * (cotmg.favor + 100))) / 1000;
|
cotmg.playerReputation += (player.mults.faction_rep * (Math.pow(threads, 0.95) * (cotmg.favor + 100))) / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
inBonus(): boolean {
|
inBonus(): boolean {
|
||||||
@ -146,66 +146,66 @@ export class StaneksGift implements IStaneksGift {
|
|||||||
const power = this.effect(aFrag);
|
const power = this.effect(aFrag);
|
||||||
switch (fragment.type) {
|
switch (fragment.type) {
|
||||||
case FragmentType.HackingChance:
|
case FragmentType.HackingChance:
|
||||||
p.hacking_chance_mult *= power;
|
p.mults.hacking_chance *= power;
|
||||||
break;
|
break;
|
||||||
case FragmentType.HackingSpeed:
|
case FragmentType.HackingSpeed:
|
||||||
p.hacking_speed_mult *= power;
|
p.mults.hacking_speed *= power;
|
||||||
break;
|
break;
|
||||||
case FragmentType.HackingMoney:
|
case FragmentType.HackingMoney:
|
||||||
p.hacking_money_mult *= power;
|
p.mults.hacking_money *= power;
|
||||||
break;
|
break;
|
||||||
case FragmentType.HackingGrow:
|
case FragmentType.HackingGrow:
|
||||||
p.hacking_grow_mult *= power;
|
p.mults.hacking_grow *= power;
|
||||||
break;
|
break;
|
||||||
case FragmentType.Hacking:
|
case FragmentType.Hacking:
|
||||||
p.hacking_mult *= power;
|
p.mults.hacking *= power;
|
||||||
p.hacking_exp_mult *= power;
|
p.mults.hacking_exp *= power;
|
||||||
break;
|
break;
|
||||||
case FragmentType.Strength:
|
case FragmentType.Strength:
|
||||||
p.strength_mult *= power;
|
p.mults.strength *= power;
|
||||||
p.strength_exp_mult *= power;
|
p.mults.strength_exp *= power;
|
||||||
break;
|
break;
|
||||||
case FragmentType.Defense:
|
case FragmentType.Defense:
|
||||||
p.defense_mult *= power;
|
p.mults.defense *= power;
|
||||||
p.defense_exp_mult *= power;
|
p.mults.defense_exp *= power;
|
||||||
break;
|
break;
|
||||||
case FragmentType.Dexterity:
|
case FragmentType.Dexterity:
|
||||||
p.dexterity_mult *= power;
|
p.mults.dexterity *= power;
|
||||||
p.dexterity_exp_mult *= power;
|
p.mults.dexterity_exp *= power;
|
||||||
break;
|
break;
|
||||||
case FragmentType.Agility:
|
case FragmentType.Agility:
|
||||||
p.agility_mult *= power;
|
p.mults.agility *= power;
|
||||||
p.agility_exp_mult *= power;
|
p.mults.agility_exp *= power;
|
||||||
break;
|
break;
|
||||||
case FragmentType.Charisma:
|
case FragmentType.Charisma:
|
||||||
p.charisma_mult *= power;
|
p.mults.charisma *= power;
|
||||||
p.charisma_exp_mult *= power;
|
p.mults.charisma_exp *= power;
|
||||||
break;
|
break;
|
||||||
case FragmentType.HacknetMoney:
|
case FragmentType.HacknetMoney:
|
||||||
p.hacknet_node_money_mult *= power;
|
p.mults.hacknet_node_money *= power;
|
||||||
break;
|
break;
|
||||||
case FragmentType.HacknetCost:
|
case FragmentType.HacknetCost:
|
||||||
p.hacknet_node_purchase_cost_mult /= power;
|
p.mults.hacknet_node_purchase_cost /= power;
|
||||||
p.hacknet_node_ram_cost_mult /= power;
|
p.mults.hacknet_node_ram_cost /= power;
|
||||||
p.hacknet_node_core_cost_mult /= power;
|
p.mults.hacknet_node_core_cost /= power;
|
||||||
p.hacknet_node_level_cost_mult /= power;
|
p.mults.hacknet_node_level_cost /= power;
|
||||||
break;
|
break;
|
||||||
case FragmentType.Rep:
|
case FragmentType.Rep:
|
||||||
p.company_rep_mult *= power;
|
p.mults.company_rep *= power;
|
||||||
p.faction_rep_mult *= power;
|
p.mults.faction_rep *= power;
|
||||||
break;
|
break;
|
||||||
case FragmentType.WorkMoney:
|
case FragmentType.WorkMoney:
|
||||||
p.work_money_mult *= power;
|
p.mults.work_money *= power;
|
||||||
break;
|
break;
|
||||||
case FragmentType.Crime:
|
case FragmentType.Crime:
|
||||||
p.crime_success_mult *= power;
|
p.mults.crime_success *= power;
|
||||||
p.crime_money_mult *= power;
|
p.mults.crime_money *= power;
|
||||||
break;
|
break;
|
||||||
case FragmentType.Bladeburner:
|
case FragmentType.Bladeburner:
|
||||||
p.bladeburner_max_stamina_mult *= power;
|
p.mults.bladeburner_max_stamina *= power;
|
||||||
p.bladeburner_stamina_gain_mult *= power;
|
p.mults.bladeburner_stamina_gain *= power;
|
||||||
p.bladeburner_analysis_mult *= power;
|
p.mults.bladeburner_analysis *= power;
|
||||||
p.bladeburner_success_chance_mult *= power;
|
p.mults.bladeburner_success_chance *= power;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,15 +224,14 @@ export class StaneksGift implements IStaneksGift {
|
|||||||
/**
|
/**
|
||||||
* Serialize Staneks Gift to a JSON save state.
|
* Serialize Staneks Gift to a JSON save state.
|
||||||
*/
|
*/
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("StaneksGift", this);
|
return Generic_toJSON("StaneksGift", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes Staneks Gift from a JSON save state
|
* Initializes Staneks Gift from a JSON save state
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): StaneksGift {
|
||||||
static fromJSON(value: any): StaneksGift {
|
|
||||||
return Generic_fromJSON(StaneksGift, value.data);
|
return Generic_fromJSON(StaneksGift, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ interface IProps {
|
|||||||
|
|
||||||
export function DummyGrid(props: IProps): React.ReactElement {
|
export function DummyGrid(props: IProps): React.ReactElement {
|
||||||
const gift = new DummyGift(props.width, props.height, props.fragments);
|
const gift = new DummyGift(props.width, props.height, props.fragments);
|
||||||
const ghostGrid = zeros([props.width, props.height]);
|
const ghostGrid = zeros(props.width, props.height);
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Table sx={{ width: props.width, height: props.height }}>
|
<Table sx={{ width: props.width, height: props.height }}>
|
||||||
|
@ -18,7 +18,7 @@ interface IProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function MainBoard(props: IProps): React.ReactElement {
|
export function MainBoard(props: IProps): React.ReactElement {
|
||||||
const [ghostGrid, setGhostGrid] = React.useState(zeros([props.gift.width(), props.gift.height()]));
|
const [ghostGrid, setGhostGrid] = React.useState(zeros(props.gift.width(), props.gift.height()));
|
||||||
const [pos, setPos] = React.useState([0, 0]);
|
const [pos, setPos] = React.useState([0, 0]);
|
||||||
const [rotation, setRotation] = React.useState(0);
|
const [rotation, setRotation] = React.useState(0);
|
||||||
const [selectedFragment, setSelectedFragment] = React.useState(NoneFragment);
|
const [selectedFragment, setSelectedFragment] = React.useState(NoneFragment);
|
||||||
@ -26,7 +26,7 @@ export function MainBoard(props: IProps): React.ReactElement {
|
|||||||
function moveGhost(worldX: number, worldY: number, rotation: number): void {
|
function moveGhost(worldX: number, worldY: number, rotation: number): void {
|
||||||
setPos([worldX, worldY]);
|
setPos([worldX, worldY]);
|
||||||
if (selectedFragment.type === FragmentType.None || selectedFragment.type === FragmentType.Delete) return;
|
if (selectedFragment.type === FragmentType.None || selectedFragment.type === FragmentType.Delete) return;
|
||||||
const newgrid = zeros([props.gift.width(), props.gift.height()]);
|
const newgrid = zeros(props.gift.width(), props.gift.height());
|
||||||
for (let y = 0; y < selectedFragment.height(rotation); y++) {
|
for (let y = 0; y < selectedFragment.height(rotation); y++) {
|
||||||
for (let x = 0; x < selectedFragment.width(rotation); x++) {
|
for (let x = 0; x < selectedFragment.width(rotation); x++) {
|
||||||
if (!selectedFragment.fullAt(x, y, rotation)) continue;
|
if (!selectedFragment.fullAt(x, y, rotation)) continue;
|
||||||
@ -61,7 +61,7 @@ export function MainBoard(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
function updateSelectedFragment(fragment: Fragment): void {
|
function updateSelectedFragment(fragment: Fragment): void {
|
||||||
setSelectedFragment(fragment);
|
setSelectedFragment(fragment);
|
||||||
const newgrid = zeros([props.gift.width(), props.gift.height()]);
|
const newgrid = zeros(props.gift.width(), props.gift.height());
|
||||||
setGhostGrid(newgrid);
|
setGhostGrid(newgrid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { CONSTANTS } from "../Constants";
|
import { CONSTANTS } from "../Constants";
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { IPerson } from "../PersonObjects/IPerson";
|
import { IPerson } from "../PersonObjects/IPerson";
|
||||||
import { IRouter } from "../ui/Router";
|
|
||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
import { CrimeType } from "../utils/WorkType";
|
import { CrimeType } from "../utils/WorkType";
|
||||||
|
import { CrimeWork } from "../Work/CrimeWork";
|
||||||
|
|
||||||
interface IConstructorParams {
|
interface IConstructorParams {
|
||||||
hacking_success_weight?: number;
|
hacking_success_weight?: number;
|
||||||
@ -96,22 +96,15 @@ export class Crime {
|
|||||||
this.kills = params.kills ? params.kills : 0;
|
this.kills = params.kills ? params.kills : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
commit(router: IRouter, p: IPlayer, div = 1, workerScript: WorkerScript | null = null): number {
|
commit(p: IPlayer, div = 1, workerScript: WorkerScript | null = null): number {
|
||||||
if (div <= 0) {
|
if (div <= 0) {
|
||||||
div = 1;
|
div = 1;
|
||||||
}
|
}
|
||||||
p.startCrime(
|
p.startWork(
|
||||||
router,
|
new CrimeWork({
|
||||||
this.type,
|
crimeType: this.type,
|
||||||
this.hacking_exp / div,
|
singularity: workerScript !== null,
|
||||||
this.strength_exp / div,
|
}),
|
||||||
this.defense_exp / div,
|
|
||||||
this.dexterity_exp / div,
|
|
||||||
this.agility_exp / div,
|
|
||||||
this.charisma_exp / div,
|
|
||||||
this.money / div,
|
|
||||||
this.time,
|
|
||||||
workerScript,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return this.time;
|
return this.time;
|
||||||
@ -128,7 +121,7 @@ export class Crime {
|
|||||||
CONSTANTS.IntelligenceCrimeWeight * p.intelligence;
|
CONSTANTS.IntelligenceCrimeWeight * p.intelligence;
|
||||||
chance /= CONSTANTS.MaxSkillLevel;
|
chance /= CONSTANTS.MaxSkillLevel;
|
||||||
chance /= this.difficulty;
|
chance /= this.difficulty;
|
||||||
chance *= p.crime_success_mult;
|
chance *= p.mults.crime_success;
|
||||||
chance *= p.getIntelligenceBonus(1);
|
chance *= p.getIntelligenceBonus(1);
|
||||||
|
|
||||||
return Math.min(chance, 1);
|
return Math.min(chance, 1);
|
||||||
|
@ -7,6 +7,7 @@ import { SpecialServers } from "../Server/data/SpecialServers";
|
|||||||
import { numeralWrapper } from "../ui/numeralFormat";
|
import { numeralWrapper } from "../ui/numeralFormat";
|
||||||
import { Money } from "../ui/React/Money";
|
import { Money } from "../ui/React/Money";
|
||||||
import { DarkWebItem } from "./DarkWebItem";
|
import { DarkWebItem } from "./DarkWebItem";
|
||||||
|
import { isCreateProgramWork } from "../Work/CreateProgramWork";
|
||||||
|
|
||||||
//Posts a "help" message if connected to DarkWeb
|
//Posts a "help" message if connected to DarkWeb
|
||||||
export function checkIfConnectedToDarkweb(): void {
|
export function checkIfConnectedToDarkweb(): void {
|
||||||
@ -74,9 +75,8 @@ export function buyDarkwebItem(itemName: string): void {
|
|||||||
|
|
||||||
Player.getHomeComputer().pushProgram(item.program);
|
Player.getHomeComputer().pushProgram(item.program);
|
||||||
// Cancel if the program is in progress of writing
|
// Cancel if the program is in progress of writing
|
||||||
if (Player.createProgramName === item.program) {
|
if (isCreateProgramWork(Player.currentWork) && Player.currentWork.programName === item.program) {
|
||||||
Player.isWorking = false;
|
Player.finishWork(true);
|
||||||
Player.resetWorkStatus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Terminal.print(
|
Terminal.print(
|
||||||
|
@ -24,8 +24,8 @@ export function SaveFile(): React.ReactElement {
|
|||||||
const base64Save = await saveObject.getImportStringFromFile(event.target.files);
|
const base64Save = await saveObject.getImportStringFromFile(event.target.files);
|
||||||
const save = atob(base64Save);
|
const save = atob(base64Save);
|
||||||
setSaveFile(save);
|
setSaveFile(save);
|
||||||
} catch (ex: any) {
|
} catch (e: unknown) {
|
||||||
SnackbarEvents.emit(ex.toString(), ToastVariant.ERROR, 5000);
|
SnackbarEvents.emit(String(e), ToastVariant.ERROR, 5000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,8 +38,8 @@ export function SaveFile(): React.ReactElement {
|
|||||||
|
|
||||||
function doRestore(): void {
|
function doRestore(): void {
|
||||||
const save = JSON.parse(saveFile);
|
const save = JSON.parse(saveFile);
|
||||||
console.log(Object.keys(save));
|
|
||||||
// TODO: Continue here.
|
// TODO: Continue here.
|
||||||
|
console.error(save);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -31,7 +31,7 @@ declare global {
|
|||||||
};
|
};
|
||||||
electronBridge: {
|
electronBridge: {
|
||||||
send: (channel: string, data?: unknown) => void;
|
send: (channel: string, data?: unknown) => void;
|
||||||
receive: (channel: string, func: (...args: any[]) => void) => void;
|
receive: (channel: string, func: (...args: unknown[]) => void) => void;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
interface Document {
|
interface Document {
|
||||||
@ -150,7 +150,7 @@ function initSaveFunctions(): void {
|
|||||||
try {
|
try {
|
||||||
saveObject.exportGame();
|
saveObject.exportGame();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.error(error);
|
||||||
SnackbarEvents.emit("Could not export game.", ToastVariant.ERROR, 2000);
|
SnackbarEvents.emit("Could not export game.", ToastVariant.ERROR, 2000);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -185,11 +185,14 @@ function initElectronBridge(): void {
|
|||||||
const data = window.appSaveFns.getSaveData();
|
const data = window.appSaveFns.getSaveData();
|
||||||
bridge.send("get-save-data-response", data);
|
bridge.send("get-save-data-response", data);
|
||||||
});
|
});
|
||||||
bridge.receive("get-save-info-request", async (save: string) => {
|
bridge.receive("get-save-info-request", async (save: unknown) => {
|
||||||
|
if (typeof save !== "string") throw new Error("Error while trying to get save info");
|
||||||
const data = await window.appSaveFns.getSaveInfo(save);
|
const data = await window.appSaveFns.getSaveInfo(save);
|
||||||
bridge.send("get-save-info-response", data);
|
bridge.send("get-save-info-response", data);
|
||||||
});
|
});
|
||||||
bridge.receive("push-save-request", ({ save, automatic = false }: { save: string; automatic: boolean }) => {
|
bridge.receive("push-save-request", (params: unknown) => {
|
||||||
|
if (typeof params !== "object") throw new Error("Error trying to push save request");
|
||||||
|
const { save, automatic = false } = params as { save: string; automatic: boolean };
|
||||||
window.appSaveFns.pushSaveData(save, automatic);
|
window.appSaveFns.pushSaveData(save, automatic);
|
||||||
});
|
});
|
||||||
bridge.receive("trigger-save", () => {
|
bridge.receive("trigger-save", () => {
|
||||||
@ -199,7 +202,7 @@ function initElectronBridge(): void {
|
|||||||
bridge.send("save-completed");
|
bridge.send("save-completed");
|
||||||
})
|
})
|
||||||
.catch((error: unknown) => {
|
.catch((error: unknown) => {
|
||||||
console.log(error);
|
console.error(error);
|
||||||
SnackbarEvents.emit("Could not save game.", ToastVariant.ERROR, 2000);
|
SnackbarEvents.emit("Could not save game.", ToastVariant.ERROR, 2000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -207,7 +210,7 @@ function initElectronBridge(): void {
|
|||||||
try {
|
try {
|
||||||
window.appSaveFns.triggerGameExport();
|
window.appSaveFns.triggerGameExport();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.error(error);
|
||||||
SnackbarEvents.emit("Could not export game.", ToastVariant.ERROR, 2000);
|
SnackbarEvents.emit("Could not export game.", ToastVariant.ERROR, 2000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -215,7 +218,7 @@ function initElectronBridge(): void {
|
|||||||
try {
|
try {
|
||||||
window.appSaveFns.triggerScriptsExport();
|
window.appSaveFns.triggerScriptsExport();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.error(error);
|
||||||
SnackbarEvents.emit("Could not export scripts.", ToastVariant.ERROR, 2000);
|
SnackbarEvents.emit("Could not export scripts.", ToastVariant.ERROR, 2000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -9,36 +9,36 @@ export function applyExploit(): void {
|
|||||||
const inc = Math.pow(1.001, Player.exploits.length);
|
const inc = Math.pow(1.001, Player.exploits.length);
|
||||||
const dec = Math.pow(0.999, Player.exploits.length);
|
const dec = Math.pow(0.999, Player.exploits.length);
|
||||||
|
|
||||||
Player.hacking_chance_mult *= inc;
|
Player.mults.hacking_chance *= inc;
|
||||||
Player.hacking_speed_mult *= inc;
|
Player.mults.hacking_speed *= inc;
|
||||||
Player.hacking_money_mult *= inc;
|
Player.mults.hacking_money *= inc;
|
||||||
Player.hacking_grow_mult *= inc;
|
Player.mults.hacking_grow *= inc;
|
||||||
Player.hacking_mult *= inc;
|
Player.mults.hacking *= inc;
|
||||||
|
|
||||||
Player.strength_mult *= inc;
|
Player.mults.strength *= inc;
|
||||||
Player.defense_mult *= inc;
|
Player.mults.defense *= inc;
|
||||||
Player.dexterity_mult *= inc;
|
Player.mults.dexterity *= inc;
|
||||||
Player.agility_mult *= inc;
|
Player.mults.agility *= inc;
|
||||||
Player.charisma_mult *= inc;
|
Player.mults.charisma *= inc;
|
||||||
|
|
||||||
Player.hacking_exp_mult *= inc;
|
Player.mults.hacking_exp *= inc;
|
||||||
Player.strength_exp_mult *= inc;
|
Player.mults.strength_exp *= inc;
|
||||||
Player.defense_exp_mult *= inc;
|
Player.mults.defense_exp *= inc;
|
||||||
Player.dexterity_exp_mult *= inc;
|
Player.mults.dexterity_exp *= inc;
|
||||||
Player.agility_exp_mult *= inc;
|
Player.mults.agility_exp *= inc;
|
||||||
Player.charisma_exp_mult *= inc;
|
Player.mults.charisma_exp *= inc;
|
||||||
|
|
||||||
Player.company_rep_mult *= inc;
|
Player.mults.company_rep *= inc;
|
||||||
Player.faction_rep_mult *= inc;
|
Player.mults.faction_rep *= inc;
|
||||||
|
|
||||||
Player.crime_money_mult *= inc;
|
Player.mults.crime_money *= inc;
|
||||||
Player.crime_success_mult *= inc;
|
Player.mults.crime_success *= inc;
|
||||||
|
|
||||||
Player.hacknet_node_money_mult *= inc;
|
Player.mults.hacknet_node_money *= inc;
|
||||||
Player.hacknet_node_purchase_cost_mult *= dec;
|
Player.mults.hacknet_node_purchase_cost *= dec;
|
||||||
Player.hacknet_node_ram_cost_mult *= dec;
|
Player.mults.hacknet_node_ram_cost *= dec;
|
||||||
Player.hacknet_node_core_cost_mult *= dec;
|
Player.mults.hacknet_node_core_cost *= dec;
|
||||||
Player.hacknet_node_level_cost_mult *= dec;
|
Player.mults.hacknet_node_level_cost *= dec;
|
||||||
|
|
||||||
Player.work_money_mult *= inc;
|
Player.mults.work_money *= inc;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { FactionInfo, FactionInfos } from "./FactionInfo";
|
import { FactionInfo, FactionInfos } from "./FactionInfo";
|
||||||
import { favorToRep, repToFavor } from "./formulas/favor";
|
import { favorToRep, repToFavor } from "./formulas/favor";
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
|
|
||||||
export class Faction {
|
export class Faction {
|
||||||
/**
|
/**
|
||||||
@ -75,15 +75,14 @@ export class Faction {
|
|||||||
/**
|
/**
|
||||||
* Serialize the current object to a JSON save state.
|
* Serialize the current object to a JSON save state.
|
||||||
*/
|
*/
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("Faction", this);
|
return Generic_toJSON("Faction", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiatizes a Faction object from a JSON save state.
|
* Initiatizes a Faction object from a JSON save state.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): Faction {
|
||||||
static fromJSON(value: any): Faction {
|
|
||||||
return Generic_fromJSON(Faction, value.data);
|
return Generic_fromJSON(Faction, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import { dialogBoxCreate } from "../ui/React/DialogBox";
|
|||||||
import { InvitationEvent } from "./ui/InvitationModal";
|
import { InvitationEvent } from "./ui/InvitationModal";
|
||||||
import { FactionNames } from "./data/FactionNames";
|
import { FactionNames } from "./data/FactionNames";
|
||||||
import { SFC32RNG } from "../Casino/RNG";
|
import { SFC32RNG } from "../Casino/RNG";
|
||||||
|
import { isFactionWork } from "../Work/FactionWork";
|
||||||
|
|
||||||
export function inviteToFaction(faction: Faction): void {
|
export function inviteToFaction(faction: Faction): void {
|
||||||
Player.receiveInvite(faction.name);
|
Player.receiveInvite(faction.name);
|
||||||
@ -113,7 +114,7 @@ export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = fal
|
|||||||
|
|
||||||
export function processPassiveFactionRepGain(numCycles: number): void {
|
export function processPassiveFactionRepGain(numCycles: number): void {
|
||||||
for (const name of Object.keys(Factions)) {
|
for (const name of Object.keys(Factions)) {
|
||||||
if (name === Player.currentWorkFactionName) continue;
|
if (isFactionWork(Player.currentWork) && name === Player.currentWork.factionName) continue;
|
||||||
if (!Factions.hasOwnProperty(name)) continue;
|
if (!Factions.hasOwnProperty(name)) continue;
|
||||||
const faction = Factions[name];
|
const faction = Factions[name];
|
||||||
if (!faction.isMember) continue;
|
if (!faction.isMember) continue;
|
||||||
@ -132,7 +133,7 @@ export function processPassiveFactionRepGain(numCycles: number): void {
|
|||||||
const fRep = getFactionFieldWorkRepGain(Player, faction);
|
const fRep = getFactionFieldWorkRepGain(Player, faction);
|
||||||
const rate = Math.max(hRep * favorMult, sRep * favorMult, fRep * favorMult, 1 / 120);
|
const rate = Math.max(hRep * favorMult, sRep * favorMult, fRep * favorMult, 1 / 120);
|
||||||
|
|
||||||
faction.playerReputation += rate * numCycles * Player.faction_rep_mult * BitNodeMultipliers.FactionPassiveRepGain;
|
faction.playerReputation += rate * numCycles * Player.mults.faction_rep * BitNodeMultipliers.FactionPassiveRepGain;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
export enum FactionWorkType {
|
|
||||||
Field,
|
|
||||||
Hacking,
|
|
||||||
None,
|
|
||||||
Security,
|
|
||||||
}
|
|
@ -2,5 +2,5 @@ import { CONSTANTS } from "../../Constants";
|
|||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
|
|
||||||
export function repFromDonation(amt: number, player: IPlayer): number {
|
export function repFromDonation(amt: number, player: IPlayer): number {
|
||||||
return (amt / CONSTANTS.DonateMoneyToRepDivisor) * player.faction_rep_mult;
|
return (amt / CONSTANTS.DonateMoneyToRepDivisor) * player.mults.faction_rep;
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,6 @@ import { Favor } from "../../ui/React/Favor";
|
|||||||
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 { numeralWrapper } from "../../ui/numeralFormat";
|
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||||
import { MathJaxWrapper } from "../../MathJaxWrapper";
|
import { MathJaxWrapper } from "../../MathJaxWrapper";
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@ import { Typography, Button } from "@mui/material";
|
|||||||
import { CovenantPurchasesRoot } from "../../PersonObjects/Sleeve/ui/CovenantPurchasesRoot";
|
import { CovenantPurchasesRoot } from "../../PersonObjects/Sleeve/ui/CovenantPurchasesRoot";
|
||||||
import { FactionNames } from "../data/FactionNames";
|
import { FactionNames } from "../data/FactionNames";
|
||||||
import { GangButton } from "./GangButton";
|
import { GangButton } from "./GangButton";
|
||||||
|
import { FactionWork } from "../../Work/FactionWork";
|
||||||
|
import { FactionWorkType } from "../../Work/data/FactionWorkType";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
faction: Faction;
|
faction: Faction;
|
||||||
@ -67,17 +69,35 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea
|
|||||||
}
|
}
|
||||||
|
|
||||||
function startFieldWork(faction: Faction): void {
|
function startFieldWork(faction: Faction): void {
|
||||||
player.startFactionFieldWork(faction);
|
player.startWork(
|
||||||
|
new FactionWork({
|
||||||
|
singularity: false,
|
||||||
|
faction: faction.name,
|
||||||
|
factionWorkType: FactionWorkType.FIELD,
|
||||||
|
}),
|
||||||
|
);
|
||||||
startWork();
|
startWork();
|
||||||
}
|
}
|
||||||
|
|
||||||
function startHackingContracts(faction: Faction): void {
|
function startHackingContracts(faction: Faction): void {
|
||||||
player.startFactionHackWork(faction);
|
player.startWork(
|
||||||
|
new FactionWork({
|
||||||
|
singularity: false,
|
||||||
|
faction: faction.name,
|
||||||
|
factionWorkType: FactionWorkType.HACKING,
|
||||||
|
}),
|
||||||
|
);
|
||||||
startWork();
|
startWork();
|
||||||
}
|
}
|
||||||
|
|
||||||
function startSecurityWork(faction: Faction): void {
|
function startSecurityWork(faction: Faction): void {
|
||||||
player.startFactionSecurityWork(faction);
|
player.startWork(
|
||||||
|
new FactionWork({
|
||||||
|
singularity: false,
|
||||||
|
faction: faction.name,
|
||||||
|
factionWorkType: FactionWorkType.SECURITY,
|
||||||
|
}),
|
||||||
|
);
|
||||||
startWork();
|
startWork();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
src/Faction/ui/v2.txt
Normal file
1
src/Faction/ui/v2.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
- https://github.com/danielyxie/bitburner/pull/3812
|
@ -23,32 +23,50 @@ export const CurrentOptionsPage = (props: IProps): React.ReactElement => {
|
|||||||
const [timestampFormat, setTimestampFormat] = useState(Settings.TimestampsFormat);
|
const [timestampFormat, setTimestampFormat] = useState(Settings.TimestampsFormat);
|
||||||
const [locale, setLocale] = useState(Settings.Locale);
|
const [locale, setLocale] = useState(Settings.Locale);
|
||||||
|
|
||||||
function handleExecTimeChange(event: any, newValue: number | number[]): void {
|
function handleExecTimeChange(
|
||||||
|
_event: Event | React.SyntheticEvent<Element, Event>,
|
||||||
|
newValue: number | number[],
|
||||||
|
): void {
|
||||||
setExecTime(newValue as number);
|
setExecTime(newValue as number);
|
||||||
Settings.CodeInstructionRunTime = newValue as number;
|
Settings.CodeInstructionRunTime = newValue as number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleRecentScriptsSizeChange(event: any, newValue: number | number[]): void {
|
function handleRecentScriptsSizeChange(
|
||||||
|
_event: Event | React.SyntheticEvent<Element, Event>,
|
||||||
|
newValue: number | number[],
|
||||||
|
): void {
|
||||||
setRecentScriptsSize(newValue as number);
|
setRecentScriptsSize(newValue as number);
|
||||||
Settings.MaxRecentScriptsCapacity = newValue as number;
|
Settings.MaxRecentScriptsCapacity = newValue as number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleLogSizeChange(event: any, newValue: number | number[]): void {
|
function handleLogSizeChange(
|
||||||
|
_event: Event | React.SyntheticEvent<Element, Event>,
|
||||||
|
newValue: number | number[],
|
||||||
|
): void {
|
||||||
setLogSize(newValue as number);
|
setLogSize(newValue as number);
|
||||||
Settings.MaxLogCapacity = newValue as number;
|
Settings.MaxLogCapacity = newValue as number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePortSizeChange(event: any, newValue: number | number[]): void {
|
function handlePortSizeChange(
|
||||||
|
_event: Event | React.SyntheticEvent<Element, Event>,
|
||||||
|
newValue: number | number[],
|
||||||
|
): void {
|
||||||
setPortSize(newValue as number);
|
setPortSize(newValue as number);
|
||||||
Settings.MaxPortCapacity = newValue as number;
|
Settings.MaxPortCapacity = newValue as number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleTerminalSizeChange(event: any, newValue: number | number[]): void {
|
function handleTerminalSizeChange(
|
||||||
|
_event: Event | React.SyntheticEvent<Element, Event>,
|
||||||
|
newValue: number | number[],
|
||||||
|
): void {
|
||||||
setTerminalSize(newValue as number);
|
setTerminalSize(newValue as number);
|
||||||
Settings.MaxTerminalCapacity = newValue as number;
|
Settings.MaxTerminalCapacity = newValue as number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleAutosaveIntervalChange(event: any, newValue: number | number[]): void {
|
function handleAutosaveIntervalChange(
|
||||||
|
_event: Event | React.SyntheticEvent<Element, Event>,
|
||||||
|
newValue: number | number[],
|
||||||
|
): void {
|
||||||
setAutosaveInterval(newValue as number);
|
setAutosaveInterval(newValue as number);
|
||||||
Settings.AutosaveInterval = newValue as number;
|
Settings.AutosaveInterval = newValue as number;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import {
|
|||||||
Download,
|
Download,
|
||||||
LibraryBooks,
|
LibraryBooks,
|
||||||
Palette,
|
Palette,
|
||||||
Public,
|
|
||||||
Reddit,
|
Reddit,
|
||||||
Save,
|
Save,
|
||||||
SystemUpdateAlt,
|
SystemUpdateAlt,
|
||||||
@ -75,8 +74,8 @@ export const GameOptionsSidebar = (props: IProps): React.ReactElement => {
|
|||||||
const data = await saveObject.getImportDataFromString(base64Save);
|
const data = await saveObject.getImportDataFromString(base64Save);
|
||||||
setImportData(data);
|
setImportData(data);
|
||||||
setImportSaveOpen(true);
|
setImportSaveOpen(true);
|
||||||
} catch (ex: any) {
|
} catch (e: unknown) {
|
||||||
SnackbarEvents.emit(ex.toString(), ToastVariant.ERROR, 5000);
|
SnackbarEvents.emit(String(e), ToastVariant.ERROR, 5000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,8 +84,8 @@ export const GameOptionsSidebar = (props: IProps): React.ReactElement => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await saveObject.importGame(importData.base64);
|
await saveObject.importGame(importData.base64);
|
||||||
} catch (ex: any) {
|
} catch (e: unknown) {
|
||||||
SnackbarEvents.emit(ex.toString(), ToastVariant.ERROR, 5000);
|
SnackbarEvents.emit(String(e), ToastVariant.ERROR, 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
setImportSaveOpen(false);
|
setImportSaveOpen(false);
|
||||||
|
@ -2,8 +2,8 @@ import { Slider, Tooltip, Typography, Box } from "@mui/material";
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
initialValue: any;
|
initialValue: number;
|
||||||
callback: (event: any, newValue: number | number[]) => void;
|
callback: (event: Event | React.SyntheticEvent<Element, Event>, newValue: number | number[]) => void;
|
||||||
step: number;
|
step: number;
|
||||||
min: number;
|
min: number;
|
||||||
max: number;
|
max: number;
|
||||||
@ -16,7 +16,7 @@ export const OptionsSlider = (props: IProps): React.ReactElement => {
|
|||||||
const [value, setValue] = useState(props.initialValue);
|
const [value, setValue] = useState(props.initialValue);
|
||||||
|
|
||||||
const onChange = (_evt: Event, newValue: number | Array<number>): void => {
|
const onChange = (_evt: Event, newValue: number | Array<number>): void => {
|
||||||
setValue(newValue);
|
if (typeof newValue === "number") setValue(newValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -8,7 +8,7 @@ import { Faction } from "../Faction/Faction";
|
|||||||
import { Factions } from "../Faction/Factions";
|
import { Factions } from "../Faction/Factions";
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../utils/JSONReviver";
|
import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
||||||
|
|
||||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||||
@ -99,7 +99,7 @@ export class Gang implements IGang {
|
|||||||
this.processExperienceGains(cycles);
|
this.processExperienceGains(cycles);
|
||||||
this.processTerritoryAndPowerGains(cycles);
|
this.processTerritoryAndPowerGains(cycles);
|
||||||
this.storedCycles -= cycles;
|
this.storedCycles -= cycles;
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
console.error(`Exception caught when processing Gang: ${e}`);
|
console.error(`Exception caught when processing Gang: ${e}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,7 +132,7 @@ export class Gang implements IGang {
|
|||||||
}
|
}
|
||||||
const favorMult = 1 + fac.favor / 100;
|
const favorMult = 1 + fac.favor / 100;
|
||||||
|
|
||||||
fac.playerReputation += (player.faction_rep_mult * gain * favorMult) / GangConstants.GangRespectToReputationRatio;
|
fac.playerReputation += (player.mults.faction_rep * gain * favorMult) / GangConstants.GangRespectToReputationRatio;
|
||||||
|
|
||||||
// Keep track of respect gained per member
|
// Keep track of respect gained per member
|
||||||
for (let i = 0; i < this.members.length; ++i) {
|
for (let i = 0; i < this.members.length; ++i) {
|
||||||
@ -358,7 +358,7 @@ export class Gang implements IGang {
|
|||||||
workerScript.log("gang.ascendMember", () => `Ascended Gang member ${member.name}`);
|
workerScript.log("gang.ascendMember", () => `Ascended Gang member ${member.name}`);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
if (workerScript == null) {
|
if (workerScript == null) {
|
||||||
exceptionAlert(e);
|
exceptionAlert(e);
|
||||||
}
|
}
|
||||||
@ -399,15 +399,14 @@ export class Gang implements IGang {
|
|||||||
/**
|
/**
|
||||||
* Serialize the current object to a JSON save state.
|
* Serialize the current object to a JSON save state.
|
||||||
*/
|
*/
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("Gang", this);
|
return Generic_toJSON("Gang", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiatizes a Gang object from a JSON save state.
|
* Initiatizes a Gang object from a JSON save state.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): Gang {
|
||||||
static fromJSON(value: any): Gang {
|
|
||||||
return Generic_fromJSON(Gang, value.data);
|
return Generic_fromJSON(Gang, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import { GangMemberUpgrades } from "./GangMemberUpgrades";
|
|||||||
import { IAscensionResult } from "./IAscensionResult";
|
import { IAscensionResult } from "./IAscensionResult";
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { IGang } from "./IGang";
|
import { IGang } from "./IGang";
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import {
|
import {
|
||||||
calculateRespectGain,
|
calculateRespectGain,
|
||||||
calculateMoneyGain,
|
calculateMoneyGain,
|
||||||
@ -320,15 +320,14 @@ export class GangMember {
|
|||||||
/**
|
/**
|
||||||
* Serialize the current object to a JSON save state.
|
* Serialize the current object to a JSON save state.
|
||||||
*/
|
*/
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("GangMember", this);
|
return Generic_toJSON("GangMember", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiatizes a GangMember object from a JSON save state.
|
* Initiatizes a GangMember object from a JSON save state.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): GangMember {
|
||||||
static fromJSON(value: any): GangMember {
|
|
||||||
return Generic_fromJSON(GangMember, value.data);
|
return Generic_fromJSON(GangMember, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { GangMember } from "./GangMember";
|
|||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { IAscensionResult } from "./IAscensionResult";
|
import { IAscensionResult } from "./IAscensionResult";
|
||||||
|
import { IReviverValue } from "src/utils/JSONReviver";
|
||||||
|
|
||||||
export interface IGang {
|
export interface IGang {
|
||||||
facName: string;
|
facName: string;
|
||||||
@ -42,5 +43,5 @@ export interface IGang {
|
|||||||
getDiscount(): number;
|
getDiscount(): number;
|
||||||
getAllTaskNames(): string[];
|
getAllTaskNames(): string[];
|
||||||
getUpgradeCost(upg: GangMemberUpgrade): number;
|
getUpgradeCost(upg: GangMemberUpgrade): number;
|
||||||
toJSON(): any;
|
toJSON(): IReviverValue;
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,17 @@ import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
|||||||
import { GangMember } from "../GangMember";
|
import { GangMember } from "../GangMember";
|
||||||
import { GangMemberTask } from "../GangMemberTask";
|
import { GangMemberTask } from "../GangMemberTask";
|
||||||
|
|
||||||
interface Gang {
|
export interface FormulaGang {
|
||||||
respect: number;
|
respect: number;
|
||||||
territory: number;
|
territory: number;
|
||||||
wantedLevel: number;
|
wantedLevel: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calculateWantedPenalty(gang: Gang): number {
|
export function calculateWantedPenalty(gang: FormulaGang): number {
|
||||||
return gang.respect / (gang.respect + gang.wantedLevel);
|
return gang.respect / (gang.respect + gang.wantedLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calculateRespectGain(gang: Gang, member: GangMember, task: GangMemberTask): number {
|
export function calculateRespectGain(gang: FormulaGang, member: GangMember, task: GangMemberTask): number {
|
||||||
if (task.baseRespect === 0) return 0;
|
if (task.baseRespect === 0) return 0;
|
||||||
let statWeight =
|
let statWeight =
|
||||||
(task.hackWeight / 100) * member.hack +
|
(task.hackWeight / 100) * member.hack +
|
||||||
@ -30,7 +30,7 @@ export function calculateRespectGain(gang: Gang, member: GangMember, task: GangM
|
|||||||
return Math.pow(11 * task.baseRespect * statWeight * territoryMult * respectMult, territoryPenalty);
|
return Math.pow(11 * task.baseRespect * statWeight * territoryMult * respectMult, territoryPenalty);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calculateWantedLevelGain(gang: Gang, member: GangMember, task: GangMemberTask): number {
|
export function calculateWantedLevelGain(gang: FormulaGang, member: GangMember, task: GangMemberTask): number {
|
||||||
if (task.baseWanted === 0) return 0;
|
if (task.baseWanted === 0) return 0;
|
||||||
let statWeight =
|
let statWeight =
|
||||||
(task.hackWeight / 100) * member.hack +
|
(task.hackWeight / 100) * member.hack +
|
||||||
@ -53,7 +53,7 @@ export function calculateWantedLevelGain(gang: Gang, member: GangMember, task: G
|
|||||||
return Math.min(100, calc);
|
return Math.min(100, calc);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calculateMoneyGain(gang: Gang, member: GangMember, task: GangMemberTask): number {
|
export function calculateMoneyGain(gang: FormulaGang, member: GangMember, task: GangMemberTask): number {
|
||||||
if (task.baseMoney === 0) return 0;
|
if (task.baseMoney === 0) return 0;
|
||||||
let statWeight =
|
let statWeight =
|
||||||
(task.hackWeight / 100) * member.hack +
|
(task.hackWeight / 100) * member.hack +
|
||||||
|
@ -12,7 +12,7 @@ export function calculateHackingChance(server: Server, player: IPlayer): number
|
|||||||
const skillMult = hackFactor * player.hacking;
|
const skillMult = hackFactor * player.hacking;
|
||||||
const skillChance = (skillMult - server.requiredHackingSkill) / skillMult;
|
const skillChance = (skillMult - server.requiredHackingSkill) / skillMult;
|
||||||
const chance =
|
const chance =
|
||||||
skillChance * difficultyMult * player.hacking_chance_mult * calculateIntelligenceBonus(player.intelligence, 1);
|
skillChance * difficultyMult * player.mults.hacking_chance * calculateIntelligenceBonus(player.intelligence, 1);
|
||||||
if (chance > 1) {
|
if (chance > 1) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ export function calculateHackingExpGain(server: Server, player: IPlayer): number
|
|||||||
let expGain = baseExpGain;
|
let expGain = baseExpGain;
|
||||||
expGain += server.baseDifficulty * diffFactor;
|
expGain += server.baseDifficulty * diffFactor;
|
||||||
|
|
||||||
return expGain * player.hacking_exp_mult * BitNodeMultipliers.HackExpGain;
|
return expGain * player.mults.hacking_exp * BitNodeMultipliers.HackExpGain;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,7 +50,7 @@ export function calculatePercentMoneyHacked(server: Server, player: IPlayer): nu
|
|||||||
const difficultyMult = (100 - server.hackDifficulty) / 100;
|
const difficultyMult = (100 - server.hackDifficulty) / 100;
|
||||||
const skillMult = (player.hacking - (server.requiredHackingSkill - 1)) / player.hacking;
|
const skillMult = (player.hacking - (server.requiredHackingSkill - 1)) / player.hacking;
|
||||||
const percentMoneyHacked =
|
const percentMoneyHacked =
|
||||||
(difficultyMult * skillMult * player.hacking_money_mult * BitNodeMultipliers.ScriptHackMoney) / balanceFactor;
|
(difficultyMult * skillMult * player.mults.hacking_money * BitNodeMultipliers.ScriptHackMoney) / balanceFactor;
|
||||||
if (percentMoneyHacked < 0) {
|
if (percentMoneyHacked < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ export function calculateHackingTime(server: Server, player: IPlayer): number {
|
|||||||
const hackTimeMultiplier = 5;
|
const hackTimeMultiplier = 5;
|
||||||
const hackingTime =
|
const hackingTime =
|
||||||
(hackTimeMultiplier * skillFactor) /
|
(hackTimeMultiplier * skillFactor) /
|
||||||
(player.hacking_speed_mult * calculateIntelligenceBonus(player.intelligence, 1));
|
(player.mults.hacking_speed * calculateIntelligenceBonus(player.intelligence, 1));
|
||||||
|
|
||||||
return hackingTime;
|
return hackingTime;
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ export function purchaseHacknet(player: IPlayer): number {
|
|||||||
|
|
||||||
// Auto generate a name for the Node
|
// Auto generate a name for the Node
|
||||||
const name = "hacknet-node-" + numOwned;
|
const name = "hacknet-node-" + numOwned;
|
||||||
const node = new HacknetNode(name, player.hacknet_node_money_mult);
|
const node = new HacknetNode(name, player.mults.hacknet_node_money);
|
||||||
|
|
||||||
player.loseMoney(cost, "hacknet_expenses");
|
player.loseMoney(cost, "hacknet_expenses");
|
||||||
player.hacknetNodes.push(node);
|
player.hacknetNodes.push(node);
|
||||||
@ -80,11 +80,11 @@ export function hasMaxNumberHacknetServers(player: IPlayer): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getCostOfNextHacknetNode(player: IPlayer): number {
|
export function getCostOfNextHacknetNode(player: IPlayer): number {
|
||||||
return calculateNodeCost(player.hacknetNodes.length + 1, player.hacknet_node_purchase_cost_mult);
|
return calculateNodeCost(player.hacknetNodes.length + 1, player.mults.hacknet_node_purchase_cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCostOfNextHacknetServer(player: IPlayer): number {
|
export function getCostOfNextHacknetServer(player: IPlayer): number {
|
||||||
return calculateServerCost(player.hacknetNodes.length + 1, player.hacknet_node_purchase_cost_mult);
|
return calculateServerCost(player.hacknetNodes.length + 1, player.mults.hacknet_node_purchase_cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the maximum number of times the Player can afford to upgrade a Hacknet Node's level
|
// Calculate the maximum number of times the Player can afford to upgrade a Hacknet Node's level
|
||||||
@ -97,14 +97,14 @@ export function getMaxNumberLevelUpgrades(
|
|||||||
throw new Error(`getMaxNumberLevelUpgrades() called without maxLevel arg`);
|
throw new Error(`getMaxNumberLevelUpgrades() called without maxLevel arg`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.money < nodeObj.calculateLevelUpgradeCost(1, player.hacknet_node_level_cost_mult)) {
|
if (player.money < nodeObj.calculateLevelUpgradeCost(1, player.mults.hacknet_node_level_cost)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let min = 1;
|
let min = 1;
|
||||||
let max = maxLevel - 1;
|
let max = maxLevel - 1;
|
||||||
const levelsToMax = maxLevel - nodeObj.level;
|
const levelsToMax = maxLevel - nodeObj.level;
|
||||||
if (player.money > nodeObj.calculateLevelUpgradeCost(levelsToMax, player.hacknet_node_level_cost_mult)) {
|
if (player.money > nodeObj.calculateLevelUpgradeCost(levelsToMax, player.mults.hacknet_node_level_cost)) {
|
||||||
return levelsToMax;
|
return levelsToMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,13 +112,13 @@ export function getMaxNumberLevelUpgrades(
|
|||||||
const curr = ((min + max) / 2) | 0;
|
const curr = ((min + max) / 2) | 0;
|
||||||
if (
|
if (
|
||||||
curr !== maxLevel &&
|
curr !== maxLevel &&
|
||||||
player.money > nodeObj.calculateLevelUpgradeCost(curr, player.hacknet_node_level_cost_mult) &&
|
player.money > nodeObj.calculateLevelUpgradeCost(curr, player.mults.hacknet_node_level_cost) &&
|
||||||
player.money < nodeObj.calculateLevelUpgradeCost(curr + 1, player.hacknet_node_level_cost_mult)
|
player.money < nodeObj.calculateLevelUpgradeCost(curr + 1, player.mults.hacknet_node_level_cost)
|
||||||
) {
|
) {
|
||||||
return Math.min(levelsToMax, curr);
|
return Math.min(levelsToMax, curr);
|
||||||
} else if (player.money < nodeObj.calculateLevelUpgradeCost(curr, player.hacknet_node_level_cost_mult)) {
|
} else if (player.money < nodeObj.calculateLevelUpgradeCost(curr, player.mults.hacknet_node_level_cost)) {
|
||||||
max = curr - 1;
|
max = curr - 1;
|
||||||
} else if (player.money > nodeObj.calculateLevelUpgradeCost(curr, player.hacknet_node_level_cost_mult)) {
|
} else if (player.money > nodeObj.calculateLevelUpgradeCost(curr, player.mults.hacknet_node_level_cost)) {
|
||||||
min = curr + 1;
|
min = curr + 1;
|
||||||
} else {
|
} else {
|
||||||
return Math.min(levelsToMax, curr);
|
return Math.min(levelsToMax, curr);
|
||||||
@ -137,7 +137,7 @@ export function getMaxNumberRamUpgrades(
|
|||||||
throw new Error(`getMaxNumberRamUpgrades() called without maxLevel arg`);
|
throw new Error(`getMaxNumberRamUpgrades() called without maxLevel arg`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.money < nodeObj.calculateRamUpgradeCost(1, player.hacknet_node_ram_cost_mult)) {
|
if (player.money < nodeObj.calculateRamUpgradeCost(1, player.mults.hacknet_node_ram_cost)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,13 +147,13 @@ export function getMaxNumberRamUpgrades(
|
|||||||
} else {
|
} else {
|
||||||
levelsToMax = Math.round(Math.log2(maxLevel / nodeObj.ram));
|
levelsToMax = Math.round(Math.log2(maxLevel / nodeObj.ram));
|
||||||
}
|
}
|
||||||
if (player.money > nodeObj.calculateRamUpgradeCost(levelsToMax, player.hacknet_node_ram_cost_mult)) {
|
if (player.money > nodeObj.calculateRamUpgradeCost(levelsToMax, player.mults.hacknet_node_ram_cost)) {
|
||||||
return levelsToMax;
|
return levelsToMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
//We'll just loop until we find the max
|
//We'll just loop until we find the max
|
||||||
for (let i = levelsToMax - 1; i >= 0; --i) {
|
for (let i = levelsToMax - 1; i >= 0; --i) {
|
||||||
if (player.money > nodeObj.calculateRamUpgradeCost(i, player.hacknet_node_ram_cost_mult)) {
|
if (player.money > nodeObj.calculateRamUpgradeCost(i, player.mults.hacknet_node_ram_cost)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,14 +170,14 @@ export function getMaxNumberCoreUpgrades(
|
|||||||
throw new Error(`getMaxNumberCoreUpgrades() called without maxLevel arg`);
|
throw new Error(`getMaxNumberCoreUpgrades() called without maxLevel arg`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.money < nodeObj.calculateCoreUpgradeCost(1, player.hacknet_node_core_cost_mult)) {
|
if (player.money < nodeObj.calculateCoreUpgradeCost(1, player.mults.hacknet_node_core_cost)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let min = 1;
|
let min = 1;
|
||||||
let max = maxLevel - 1;
|
let max = maxLevel - 1;
|
||||||
const levelsToMax = maxLevel - nodeObj.cores;
|
const levelsToMax = maxLevel - nodeObj.cores;
|
||||||
if (player.money > nodeObj.calculateCoreUpgradeCost(levelsToMax, player.hacknet_node_core_cost_mult)) {
|
if (player.money > nodeObj.calculateCoreUpgradeCost(levelsToMax, player.mults.hacknet_node_core_cost)) {
|
||||||
return levelsToMax;
|
return levelsToMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,13 +186,13 @@ export function getMaxNumberCoreUpgrades(
|
|||||||
const curr = ((min + max) / 2) | 0;
|
const curr = ((min + max) / 2) | 0;
|
||||||
if (
|
if (
|
||||||
curr != maxLevel &&
|
curr != maxLevel &&
|
||||||
player.money > nodeObj.calculateCoreUpgradeCost(curr, player.hacknet_node_core_cost_mult) &&
|
player.money > nodeObj.calculateCoreUpgradeCost(curr, player.mults.hacknet_node_core_cost) &&
|
||||||
player.money < nodeObj.calculateCoreUpgradeCost(curr + 1, player.hacknet_node_core_cost_mult)
|
player.money < nodeObj.calculateCoreUpgradeCost(curr + 1, player.mults.hacknet_node_core_cost)
|
||||||
) {
|
) {
|
||||||
return Math.min(levelsToMax, curr);
|
return Math.min(levelsToMax, curr);
|
||||||
} else if (player.money < nodeObj.calculateCoreUpgradeCost(curr, player.hacknet_node_core_cost_mult)) {
|
} else if (player.money < nodeObj.calculateCoreUpgradeCost(curr, player.mults.hacknet_node_core_cost)) {
|
||||||
max = curr - 1;
|
max = curr - 1;
|
||||||
} else if (player.money > nodeObj.calculateCoreUpgradeCost(curr, player.hacknet_node_core_cost_mult)) {
|
} else if (player.money > nodeObj.calculateCoreUpgradeCost(curr, player.mults.hacknet_node_core_cost)) {
|
||||||
min = curr + 1;
|
min = curr + 1;
|
||||||
} else {
|
} else {
|
||||||
return Math.min(levelsToMax, curr);
|
return Math.min(levelsToMax, curr);
|
||||||
@ -242,7 +242,7 @@ export function getMaxNumberCacheUpgrades(player: IPlayer, nodeObj: HacknetServe
|
|||||||
|
|
||||||
export function purchaseLevelUpgrade(player: IPlayer, node: HacknetNode | HacknetServer, levels = 1): boolean {
|
export function purchaseLevelUpgrade(player: IPlayer, node: HacknetNode | HacknetServer, levels = 1): boolean {
|
||||||
const sanitizedLevels = Math.round(levels);
|
const sanitizedLevels = Math.round(levels);
|
||||||
const cost = node.calculateLevelUpgradeCost(sanitizedLevels, player.hacknet_node_level_cost_mult);
|
const cost = node.calculateLevelUpgradeCost(sanitizedLevels, player.mults.hacknet_node_level_cost);
|
||||||
if (isNaN(cost) || cost <= 0 || sanitizedLevels < 0) {
|
if (isNaN(cost) || cost <= 0 || sanitizedLevels < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -266,14 +266,14 @@ export function purchaseLevelUpgrade(player: IPlayer, node: HacknetNode | Hackne
|
|||||||
}
|
}
|
||||||
|
|
||||||
player.loseMoney(cost, "hacknet_expenses");
|
player.loseMoney(cost, "hacknet_expenses");
|
||||||
node.upgradeLevel(sanitizedLevels, player.hacknet_node_money_mult);
|
node.upgradeLevel(sanitizedLevels, player.mults.hacknet_node_money);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function purchaseRamUpgrade(player: IPlayer, node: HacknetNode | HacknetServer, levels = 1): boolean {
|
export function purchaseRamUpgrade(player: IPlayer, node: HacknetNode | HacknetServer, levels = 1): boolean {
|
||||||
const sanitizedLevels = Math.round(levels);
|
const sanitizedLevels = Math.round(levels);
|
||||||
const cost = node.calculateRamUpgradeCost(sanitizedLevels, player.hacknet_node_ram_cost_mult);
|
const cost = node.calculateRamUpgradeCost(sanitizedLevels, player.mults.hacknet_node_ram_cost);
|
||||||
if (isNaN(cost) || cost <= 0 || sanitizedLevels < 0) {
|
if (isNaN(cost) || cost <= 0 || sanitizedLevels < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -305,14 +305,14 @@ export function purchaseRamUpgrade(player: IPlayer, node: HacknetNode | HacknetS
|
|||||||
}
|
}
|
||||||
|
|
||||||
player.loseMoney(cost, "hacknet_expenses");
|
player.loseMoney(cost, "hacknet_expenses");
|
||||||
node.upgradeRam(sanitizedLevels, player.hacknet_node_money_mult);
|
node.upgradeRam(sanitizedLevels, player.mults.hacknet_node_money);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function purchaseCoreUpgrade(player: IPlayer, node: HacknetNode | HacknetServer, levels = 1): boolean {
|
export function purchaseCoreUpgrade(player: IPlayer, node: HacknetNode | HacknetServer, levels = 1): boolean {
|
||||||
const sanitizedLevels = Math.round(levels);
|
const sanitizedLevels = Math.round(levels);
|
||||||
const cost = node.calculateCoreUpgradeCost(sanitizedLevels, player.hacknet_node_core_cost_mult);
|
const cost = node.calculateCoreUpgradeCost(sanitizedLevels, player.mults.hacknet_node_core_cost);
|
||||||
if (isNaN(cost) || cost <= 0 || sanitizedLevels < 0) {
|
if (isNaN(cost) || cost <= 0 || sanitizedLevels < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -336,7 +336,7 @@ export function purchaseCoreUpgrade(player: IPlayer, node: HacknetNode | Hacknet
|
|||||||
}
|
}
|
||||||
|
|
||||||
player.loseMoney(cost, "hacknet_expenses");
|
player.loseMoney(cost, "hacknet_expenses");
|
||||||
node.upgradeCore(sanitizedLevels, player.hacknet_node_money_mult);
|
node.upgradeCore(sanitizedLevels, player.mults.hacknet_node_money);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -415,7 +415,7 @@ function processAllHacknetServerEarnings(player: IPlayer, numCycles: number): nu
|
|||||||
if (ip instanceof HacknetNode) throw new Error(`player nodes should not be HacketNode`);
|
if (ip instanceof HacknetNode) throw new Error(`player nodes should not be HacketNode`);
|
||||||
const hserver = GetServer(ip);
|
const hserver = GetServer(ip);
|
||||||
if (!(hserver instanceof HacknetServer)) throw new Error(`player nodes shoud not be Server`);
|
if (!(hserver instanceof HacknetServer)) throw new Error(`player nodes shoud not be Server`);
|
||||||
hserver.updateHashRate(player.hacknet_node_money_mult);
|
hserver.updateHashRate(player.mults.hacknet_node_money);
|
||||||
const h = hserver.process(numCycles);
|
const h = hserver.process(numCycles);
|
||||||
hashes += h;
|
hashes += h;
|
||||||
}
|
}
|
||||||
@ -467,7 +467,7 @@ export function updateHashManagerCapacity(player: IPlayer): void {
|
|||||||
player.hashManager.updateCapacity(total);
|
player.hashManager.updateCapacity(total);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget: string): boolean {
|
export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget: string, count = 1): boolean {
|
||||||
if (!(player.hashManager instanceof HashManager)) {
|
if (!(player.hashManager instanceof HashManager)) {
|
||||||
console.error(`Player does not have a HashManager`);
|
console.error(`Player does not have a HashManager`);
|
||||||
return false;
|
return false;
|
||||||
@ -475,21 +475,21 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
|||||||
|
|
||||||
// HashManager handles the transaction. This just needs to actually implement
|
// HashManager handles the transaction. This just needs to actually implement
|
||||||
// the effects of the upgrade
|
// the effects of the upgrade
|
||||||
if (player.hashManager.upgrade(upgName)) {
|
if (player.hashManager.upgrade(upgName, count)) {
|
||||||
const upg = HashUpgrades[upgName];
|
const upg = HashUpgrades[upgName];
|
||||||
|
|
||||||
switch (upgName) {
|
switch (upgName) {
|
||||||
case "Sell for Money": {
|
case "Sell for Money": {
|
||||||
player.gainMoney(upg.value, "hacknet");
|
player.gainMoney(upg.value * count, "hacknet");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Sell for Corporation Funds": {
|
case "Sell for Corporation Funds": {
|
||||||
const corp = player.corporation;
|
const corp = player.corporation;
|
||||||
if (corp === null) {
|
if (corp === null) {
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName, count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
corp.funds = corp.funds + upg.value;
|
corp.funds = corp.funds + upg.value * count;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Reduce Minimum Security": {
|
case "Reduce Minimum Security": {
|
||||||
@ -497,13 +497,13 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
|||||||
const target = GetServer(upgTarget);
|
const target = GetServer(upgTarget);
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
console.error(`Invalid target specified in purchaseHashUpgrade(): ${upgTarget}`);
|
console.error(`Invalid target specified in purchaseHashUpgrade(): ${upgTarget}`);
|
||||||
return false;
|
throw new Error(`'${upgTarget}' is not a server.`);
|
||||||
}
|
}
|
||||||
if (!(target instanceof Server)) throw new Error(`'${upgTarget}' is not a normal server.`);
|
if (!(target instanceof Server)) throw new Error(`'${upgTarget}' is not a normal server.`);
|
||||||
|
|
||||||
target.changeMinimumSecurity(upg.value, true);
|
target.changeMinimumSecurity(upg.value ** count, true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName, count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -513,13 +513,16 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
|||||||
const target = GetServer(upgTarget);
|
const target = GetServer(upgTarget);
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
console.error(`Invalid target specified in purchaseHashUpgrade(): ${upgTarget}`);
|
console.error(`Invalid target specified in purchaseHashUpgrade(): ${upgTarget}`);
|
||||||
return false;
|
throw new Error(`'${upgTarget}' is not a server.`);
|
||||||
}
|
}
|
||||||
if (!(target instanceof Server)) throw new Error(`'${upgTarget}' is not a normal server.`);
|
if (!(target instanceof Server)) throw new Error(`'${upgTarget}' is not a normal server.`);
|
||||||
|
|
||||||
|
//Manually loop the change so as to properly handle the softcap
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
target.changeMaximumMoney(upg.value);
|
target.changeMaximumMoney(upg.value);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName, count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -536,11 +539,11 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
|||||||
// This will throw if player doesn't have a corporation
|
// This will throw if player doesn't have a corporation
|
||||||
const corp = player.corporation;
|
const corp = player.corporation;
|
||||||
if (corp === null) {
|
if (corp === null) {
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName, count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (const division of corp.divisions) {
|
for (const division of corp.divisions) {
|
||||||
division.sciResearch.qty += upg.value;
|
division.sciResearch.qty += upg.value * count;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -548,30 +551,31 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
|||||||
// This will throw if player isnt in Bladeburner
|
// This will throw if player isnt in Bladeburner
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) {
|
if (bladeburner === null) {
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName, count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bladeburner.changeRank(player, upg.value);
|
bladeburner.changeRank(player, upg.value * count);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Exchange for Bladeburner SP": {
|
case "Exchange for Bladeburner SP": {
|
||||||
// This will throw if player isnt in Bladeburner
|
// This will throw if player isnt in Bladeburner
|
||||||
const bladeburner = player.bladeburner;
|
const bladeburner = player.bladeburner;
|
||||||
if (bladeburner === null) {
|
if (bladeburner === null) {
|
||||||
player.hashManager.refundUpgrade(upgName);
|
player.hashManager.refundUpgrade(upgName, count);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bladeburner.skillPoints += upg.value;
|
bladeburner.skillPoints += upg.value * count;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "Generate Coding Contract": {
|
case "Generate Coding Contract": {
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
generateRandomContract();
|
generateRandomContract();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
console.warn(`Unrecognized upgrade name ${upgName}. Upgrade has no effect`);
|
console.warn(`Unrecognized upgrade name ${upgName}. Upgrade has no effect`);
|
||||||
player.hashManager.refundUpgrade(upgName);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import {
|
|||||||
import { HacknetNodeConstants } from "./data/Constants";
|
import { HacknetNodeConstants } from "./data/Constants";
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import { ObjectValidator, minMax } from "../utils/Validator";
|
import { ObjectValidator, minMax } from "../utils/Validator";
|
||||||
|
|
||||||
export class HacknetNode implements IHacknetNode {
|
export class HacknetNode implements IHacknetNode {
|
||||||
@ -123,15 +123,14 @@ export class HacknetNode implements IHacknetNode {
|
|||||||
/**
|
/**
|
||||||
* Serialize the current object to a JSON save state.
|
* Serialize the current object to a JSON save state.
|
||||||
*/
|
*/
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("HacknetNode", this);
|
return Generic_toJSON("HacknetNode", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiatizes a HacknetNode object from a JSON save state.
|
* Initiatizes a HacknetNode object from a JSON save state.
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): HacknetNode {
|
||||||
static fromJSON(value: any): HacknetNode {
|
|
||||||
return Generic_fromJSON(HacknetNode, value.data);
|
return Generic_fromJSON(HacknetNode, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ import {
|
|||||||
|
|
||||||
import { createRandomIp } from "../utils/IPAddress";
|
import { createRandomIp } from "../utils/IPAddress";
|
||||||
|
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
|
||||||
interface IConstructorParams {
|
interface IConstructorParams {
|
||||||
@ -125,7 +125,7 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
|
|||||||
|
|
||||||
updateRamUsed(ram: number, player: IPlayer): void {
|
updateRamUsed(ram: number, player: IPlayer): void {
|
||||||
super.updateRamUsed(ram, player);
|
super.updateRamUsed(ram, player);
|
||||||
this.updateHashRate(player.hacknet_node_money_mult);
|
this.updateHashRate(player.mults.hacknet_node_money);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateHashCapacity(): void {
|
updateHashCapacity(): void {
|
||||||
@ -145,13 +145,12 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Serialize the current object to a JSON save state
|
// Serialize the current object to a JSON save state
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("HacknetServer", this);
|
return Generic_toJSON("HacknetServer", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializes a HacknetServer Object from a JSON save state
|
// Initializes a HacknetServer Object from a JSON save state
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): HacknetServer {
|
||||||
static fromJSON(value: any): HacknetServer {
|
|
||||||
return Generic_fromJSON(HacknetServer, value.data);
|
return Generic_fromJSON(HacknetServer, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import { HashUpgrades } from "./HashUpgrades";
|
|||||||
import { HashUpgrade } from "./HashUpgrade";
|
import { HashUpgrade } from "./HashUpgrade";
|
||||||
|
|
||||||
import { IMap } from "../types";
|
import { IMap } from "../types";
|
||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||||
|
|
||||||
export class HashManager {
|
export class HashManager {
|
||||||
// Max number of hashes this can hold. Equal to the sum of capacities of
|
// Max number of hashes this can hold. Equal to the sum of capacities of
|
||||||
@ -73,7 +73,7 @@ export class HashManager {
|
|||||||
/**
|
/**
|
||||||
* Get the cost (in hashes) of an upgrade
|
* Get the cost (in hashes) of an upgrade
|
||||||
*/
|
*/
|
||||||
getUpgradeCost(upgName: string): number {
|
getUpgradeCost(upgName: string, count = 1): number {
|
||||||
const upg = this.getUpgrade(upgName);
|
const upg = this.getUpgrade(upgName);
|
||||||
const currLevel = this.upgrades[upgName];
|
const currLevel = this.upgrades[upgName];
|
||||||
if (upg == null || currLevel == null) {
|
if (upg == null || currLevel == null) {
|
||||||
@ -81,7 +81,7 @@ export class HashManager {
|
|||||||
return Infinity;
|
return Infinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
return upg.getCost(currLevel);
|
return upg.getCost(currLevel, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
prestige(): void {
|
prestige(): void {
|
||||||
@ -97,11 +97,11 @@ export class HashManager {
|
|||||||
/**
|
/**
|
||||||
* Reverts an upgrade and refunds the hashes used to buy it
|
* Reverts an upgrade and refunds the hashes used to buy it
|
||||||
*/
|
*/
|
||||||
refundUpgrade(upgName: string): void {
|
refundUpgrade(upgName: string, count = 1): void {
|
||||||
const upg = HashUpgrades[upgName];
|
const upg = HashUpgrades[upgName];
|
||||||
|
|
||||||
// Reduce the level first, so we get the right cost
|
// Reduce the level first, so we get the right cost
|
||||||
--this.upgrades[upgName];
|
this.upgrades[upgName] -= count;
|
||||||
|
|
||||||
const currLevel = this.upgrades[upgName];
|
const currLevel = this.upgrades[upgName];
|
||||||
if (upg == null || currLevel == null || currLevel < 0) {
|
if (upg == null || currLevel == null || currLevel < 0) {
|
||||||
@ -109,7 +109,7 @@ export class HashManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cost = upg.getCost(currLevel);
|
const cost = upg.getCost(currLevel, count);
|
||||||
this.hashes += cost;
|
this.hashes += cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,33 +137,32 @@ export class HashManager {
|
|||||||
* Returns boolean indicating whether or not the upgrade was successfully purchased
|
* Returns boolean indicating whether or not the upgrade was successfully purchased
|
||||||
* Note that this does NOT actually implement the effect
|
* Note that this does NOT actually implement the effect
|
||||||
*/
|
*/
|
||||||
upgrade(upgName: string): boolean {
|
upgrade(upgName: string, count = 1): boolean {
|
||||||
const upg = HashUpgrades[upgName];
|
const upg = HashUpgrades[upgName];
|
||||||
if (upg == null) {
|
if (upg == null) {
|
||||||
console.error(`Invalid Upgrade Name given to HashManager.upgrade(): ${upgName}`);
|
console.error(`Invalid Upgrade Name given to HashManager.upgrade(): ${upgName}`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cost = this.getUpgradeCost(upgName);
|
const cost = this.getUpgradeCost(upgName, count);
|
||||||
|
|
||||||
if (this.hashes < cost) {
|
if (this.hashes < cost) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.hashes -= cost;
|
this.hashes -= cost;
|
||||||
++this.upgrades[upgName];
|
this.upgrades[upgName] += count;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Serialize the current object to a JSON save state.
|
//Serialize the current object to a JSON save state.
|
||||||
toJSON(): any {
|
toJSON(): IReviverValue {
|
||||||
return Generic_toJSON("HashManager", this);
|
return Generic_toJSON("HashManager", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initiatizes a HashManager object from a JSON save state.
|
// Initiatizes a HashManager object from a JSON save state.
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
static fromJSON(value: IReviverValue): HashManager {
|
||||||
static fromJSON(value: any): HashManager {
|
|
||||||
return Generic_fromJSON(HashManager, value.data);
|
return Generic_fromJSON(HashManager, value.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,11 +62,15 @@ export class HashUpgrade {
|
|||||||
// Functions that returns the UI element to display the effect of this upgrade.
|
// Functions that returns the UI element to display the effect of this upgrade.
|
||||||
effectText: (level: number) => JSX.Element | null = () => null;
|
effectText: (level: number) => JSX.Element | null = () => null;
|
||||||
|
|
||||||
getCost(levels: number): number {
|
getCost(currentLevel: number, count = 1): number {
|
||||||
if (typeof this.cost === "number") {
|
if (typeof this.cost === "number") {
|
||||||
return this.cost;
|
return this.cost * count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.round((levels + 1) * this.costPerLevel);
|
//This formula is equivalent to
|
||||||
|
//(currentLevel + 1) * this.costPerLevel
|
||||||
|
//being performed repeatedly
|
||||||
|
const collapsedSum = 0.5 * count * (count + 2 * currentLevel + 1);
|
||||||
|
return this.costPerLevel * collapsedSum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,9 +58,9 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const increase =
|
const increase =
|
||||||
calculateMoneyGainRate(node.level + multiplier, node.ram, node.cores, props.player.hacknet_node_money_mult) -
|
calculateMoneyGainRate(node.level + multiplier, node.ram, node.cores, props.player.mults.hacknet_node_money) -
|
||||||
node.moneyGainRatePerSecond;
|
node.moneyGainRatePerSecond;
|
||||||
const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, props.player.hacknet_node_level_cost_mult);
|
const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, props.player.mults.hacknet_node_level_cost);
|
||||||
upgradeLevelButton = (
|
upgradeLevelButton = (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={
|
title={
|
||||||
@ -102,9 +102,9 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
|
|||||||
node.level,
|
node.level,
|
||||||
node.ram * Math.pow(2, multiplier),
|
node.ram * Math.pow(2, multiplier),
|
||||||
node.cores,
|
node.cores,
|
||||||
props.player.hacknet_node_money_mult,
|
props.player.mults.hacknet_node_money,
|
||||||
) - node.moneyGainRatePerSecond;
|
) - node.moneyGainRatePerSecond;
|
||||||
const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, props.player.hacknet_node_ram_cost_mult);
|
const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, props.player.mults.hacknet_node_ram_cost);
|
||||||
upgradeRAMButton = (
|
upgradeRAMButton = (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={
|
title={
|
||||||
@ -148,9 +148,9 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const increase =
|
const increase =
|
||||||
calculateMoneyGainRate(node.level, node.ram, node.cores + multiplier, props.player.hacknet_node_money_mult) -
|
calculateMoneyGainRate(node.level, node.ram, node.cores + multiplier, props.player.mults.hacknet_node_money) -
|
||||||
node.moneyGainRatePerSecond;
|
node.moneyGainRatePerSecond;
|
||||||
const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, props.player.hacknet_node_core_cost_mult);
|
const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, props.player.mults.hacknet_node_core_cost);
|
||||||
upgradeCoresButton = (
|
upgradeCoresButton = (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={
|
title={
|
||||||
|
@ -61,11 +61,16 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const base_increase =
|
const base_increase =
|
||||||
calculateHashGainRate(node.level + multiplier, 0, node.maxRam, node.cores, props.player.hacknet_node_money_mult) -
|
calculateHashGainRate(
|
||||||
calculateHashGainRate(node.level, 0, node.maxRam, node.cores, props.player.hacknet_node_money_mult);
|
node.level + multiplier,
|
||||||
|
0,
|
||||||
|
node.maxRam,
|
||||||
|
node.cores,
|
||||||
|
props.player.mults.hacknet_node_money,
|
||||||
|
) - calculateHashGainRate(node.level, 0, node.maxRam, node.cores, props.player.mults.hacknet_node_money);
|
||||||
const modded_increase = (base_increase * (node.maxRam - node.ramUsed)) / node.maxRam;
|
const modded_increase = (base_increase * (node.maxRam - node.ramUsed)) / node.maxRam;
|
||||||
|
|
||||||
const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, props.player.hacknet_node_level_cost_mult);
|
const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, props.player.mults.hacknet_node_level_cost);
|
||||||
upgradeLevelButton = (
|
upgradeLevelButton = (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={
|
title={
|
||||||
@ -122,8 +127,8 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
|||||||
0,
|
0,
|
||||||
node.maxRam * Math.pow(2, multiplier),
|
node.maxRam * Math.pow(2, multiplier),
|
||||||
node.cores,
|
node.cores,
|
||||||
props.player.hacknet_node_money_mult,
|
props.player.mults.hacknet_node_money,
|
||||||
) - calculateHashGainRate(node.level, 0, node.maxRam, node.cores, props.player.hacknet_node_money_mult);
|
) - calculateHashGainRate(node.level, 0, node.maxRam, node.cores, props.player.mults.hacknet_node_money);
|
||||||
|
|
||||||
const modded_increase =
|
const modded_increase =
|
||||||
calculateHashGainRate(
|
calculateHashGainRate(
|
||||||
@ -131,11 +136,11 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
|||||||
node.ramUsed,
|
node.ramUsed,
|
||||||
node.maxRam * Math.pow(2, multiplier),
|
node.maxRam * Math.pow(2, multiplier),
|
||||||
node.cores,
|
node.cores,
|
||||||
props.player.hacknet_node_money_mult,
|
props.player.mults.hacknet_node_money,
|
||||||
) -
|
) -
|
||||||
calculateHashGainRate(node.level, node.ramUsed, node.maxRam, node.cores, props.player.hacknet_node_money_mult);
|
calculateHashGainRate(node.level, node.ramUsed, node.maxRam, node.cores, props.player.mults.hacknet_node_money);
|
||||||
|
|
||||||
const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, props.player.hacknet_node_ram_cost_mult);
|
const upgradeRamCost = node.calculateRamUpgradeCost(multiplier, props.player.mults.hacknet_node_ram_cost);
|
||||||
upgradeRamButton = (
|
upgradeRamButton = (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={
|
title={
|
||||||
@ -179,11 +184,16 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const base_increase =
|
const base_increase =
|
||||||
calculateHashGainRate(node.level, 0, node.maxRam, node.cores + multiplier, props.player.hacknet_node_money_mult) -
|
calculateHashGainRate(
|
||||||
calculateHashGainRate(node.level, 0, node.maxRam, node.cores, props.player.hacknet_node_money_mult);
|
node.level,
|
||||||
|
0,
|
||||||
|
node.maxRam,
|
||||||
|
node.cores + multiplier,
|
||||||
|
props.player.mults.hacknet_node_money,
|
||||||
|
) - calculateHashGainRate(node.level, 0, node.maxRam, node.cores, props.player.mults.hacknet_node_money);
|
||||||
const modded_increase = (base_increase * (node.maxRam - node.ramUsed)) / node.maxRam;
|
const modded_increase = (base_increase * (node.maxRam - node.ramUsed)) / node.maxRam;
|
||||||
|
|
||||||
const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, props.player.hacknet_node_core_cost_mult);
|
const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, props.player.mults.hacknet_node_core_cost);
|
||||||
upgradeCoresButton = (
|
upgradeCoresButton = (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={
|
title={
|
||||||
|
@ -16,10 +16,10 @@ export function calculateDifficulty(player: IPlayer, startingSecurityLevel: numb
|
|||||||
export function calculateReward(player: IPlayer, startingSecurityLevel: number): number {
|
export function calculateReward(player: IPlayer, startingSecurityLevel: number): number {
|
||||||
const xpMult = 10 * 60 * 15;
|
const xpMult = 10 * 60 * 15;
|
||||||
const total =
|
const total =
|
||||||
calculateSkill(player.strength_exp_mult * xpMult, player.strength_mult) +
|
calculateSkill(player.mults.strength_exp * xpMult, player.mults.strength) +
|
||||||
calculateSkill(player.defense_exp_mult * xpMult, player.defense_mult) +
|
calculateSkill(player.mults.defense_exp * xpMult, player.mults.defense) +
|
||||||
calculateSkill(player.agility_exp_mult * xpMult, player.agility_mult) +
|
calculateSkill(player.mults.agility_exp * xpMult, player.mults.agility) +
|
||||||
calculateSkill(player.dexterity_exp_mult * xpMult, player.dexterity_mult) +
|
calculateSkill(player.mults.dexterity_exp * xpMult, player.mults.dexterity) +
|
||||||
calculateSkill(player.charisma_exp_mult * xpMult, player.charisma_mult);
|
calculateSkill(player.mults.charisma_exp * xpMult, player.mults.charisma);
|
||||||
return calculateRawDiff(player, total, startingSecurityLevel);
|
return calculateRawDiff(player, total, startingSecurityLevel);
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ const types = [KEY.PIPE, KEY.DOT, KEY.FORWARD_SLASH, KEY.HYPHEN, "█", KEY.HASH
|
|||||||
|
|
||||||
const colors = ["red", "#FFC107", "blue", "white"];
|
const colors = ["red", "#FFC107", "blue", "white"];
|
||||||
|
|
||||||
const colorNames: any = {
|
const colorNames: Record<string, string> = {
|
||||||
red: "red",
|
red: "red",
|
||||||
"#FFC107": "yellow",
|
"#FFC107": "yellow",
|
||||||
blue: "blue",
|
blue: "blue",
|
||||||
|
@ -77,7 +77,9 @@ function LocationLetter(location: Location): React.ReactElement {
|
|||||||
|
|
||||||
function ASCIICity(props: IProps): React.ReactElement {
|
function ASCIICity(props: IProps): React.ReactElement {
|
||||||
const locationLettersRegex = /[A-Z]/g;
|
const locationLettersRegex = /[A-Z]/g;
|
||||||
const letterMap: any = {
|
const letterMap: {
|
||||||
|
[key: string]: number;
|
||||||
|
} = {
|
||||||
A: 0,
|
A: 0,
|
||||||
B: 1,
|
B: 1,
|
||||||
C: 2,
|
C: 2,
|
||||||
@ -106,10 +108,10 @@ function ASCIICity(props: IProps): React.ReactElement {
|
|||||||
Z: 25,
|
Z: 25,
|
||||||
};
|
};
|
||||||
|
|
||||||
const lineElems = (s: string): JSX.Element[] => {
|
const lineElems = (s: string): (string | React.ReactElement)[] => {
|
||||||
const elems: any[] = [];
|
const elems: (string | React.ReactElement)[] = [];
|
||||||
const matches: any[] = [];
|
const matches: RegExpExecArray[] = [];
|
||||||
let match: any;
|
let match: RegExpExecArray | null = null;
|
||||||
while ((match = locationLettersRegex.exec(s)) !== null) {
|
while ((match = locationLettersRegex.exec(s)) !== null) {
|
||||||
matches.push(match);
|
matches.push(match);
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import { Reputation } from "../../ui/React/Reputation";
|
|||||||
import { Favor } from "../../ui/React/Favor";
|
import { Favor } from "../../ui/React/Favor";
|
||||||
import { use } from "../../ui/Context";
|
import { use } from "../../ui/Context";
|
||||||
import { QuitJobModal } from "../../Company/ui/QuitJobModal";
|
import { QuitJobModal } from "../../Company/ui/QuitJobModal";
|
||||||
|
import { CompanyWork } from "../../Work/CompanyWork";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
locName: LocationName;
|
locName: LocationName;
|
||||||
@ -175,11 +176,12 @@ export function CompanyLocation(props: IProps): React.ReactElement {
|
|||||||
|
|
||||||
const pos = companyPosition;
|
const pos = companyPosition;
|
||||||
if (pos instanceof CompanyPosition) {
|
if (pos instanceof CompanyPosition) {
|
||||||
if (pos.isPartTimeJob() || pos.isSoftwareConsultantJob() || pos.isBusinessConsultantJob()) {
|
p.startWork(
|
||||||
p.startWorkPartTime(props.locName);
|
new CompanyWork({
|
||||||
} else {
|
singularity: false,
|
||||||
p.startWork(props.locName);
|
companyName: props.locName,
|
||||||
}
|
}),
|
||||||
|
);
|
||||||
p.startFocusing();
|
p.startFocusing();
|
||||||
router.toWork();
|
router.toWork();
|
||||||
}
|
}
|
||||||
|
@ -8,16 +8,13 @@ import Button from "@mui/material/Button";
|
|||||||
|
|
||||||
import { Location } from "../Location";
|
import { Location } from "../Location";
|
||||||
|
|
||||||
import { CONSTANTS } from "../../Constants";
|
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { GetServer } from "../../Server/AllServers";
|
|
||||||
import { Server } from "../../Server/Server";
|
|
||||||
|
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
import { IRouter } from "../../ui/Router";
|
import { IRouter } from "../../ui/Router";
|
||||||
import { serverMetadata } from "../../Server/data/servers";
|
|
||||||
import { Box } from "@mui/material";
|
import { Box } from "@mui/material";
|
||||||
import { ClassType } from "../../utils/WorkType";
|
import { ClassWork, ClassType, Classes } from "../../Work/ClassWork";
|
||||||
|
import { calculateCost } from "../../Work/formulas/Class";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
loc: Location;
|
loc: Location;
|
||||||
@ -26,51 +23,32 @@ type IProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function GymLocation(props: IProps): React.ReactElement {
|
export function GymLocation(props: IProps): React.ReactElement {
|
||||||
function calculateCost(): number {
|
|
||||||
const serverMeta = serverMetadata.find((s) => s.specialName === props.loc.name);
|
|
||||||
const server = GetServer(serverMeta ? serverMeta.hostname : "");
|
|
||||||
if (server == null || !server.hasOwnProperty("backdoorInstalled")) return props.loc.costMult;
|
|
||||||
const discount = (server as Server).backdoorInstalled ? 0.9 : 1;
|
|
||||||
return props.loc.costMult * discount;
|
|
||||||
}
|
|
||||||
|
|
||||||
function train(stat: ClassType): void {
|
function train(stat: ClassType): void {
|
||||||
const loc = props.loc;
|
props.p.startWork(
|
||||||
props.p.startClass(calculateCost(), loc.expMult, stat);
|
new ClassWork({
|
||||||
|
classType: stat,
|
||||||
|
location: props.loc.name,
|
||||||
|
singularity: false,
|
||||||
|
}),
|
||||||
|
);
|
||||||
props.p.startFocusing();
|
props.p.startFocusing();
|
||||||
props.router.toWork();
|
props.router.toWork();
|
||||||
}
|
}
|
||||||
|
|
||||||
function trainStrength(): void {
|
const cost = calculateCost(Classes[ClassType.GymStrength], props.loc);
|
||||||
train(ClassType.GymStrength);
|
|
||||||
}
|
|
||||||
|
|
||||||
function trainDefense(): void {
|
|
||||||
train(ClassType.GymDefense);
|
|
||||||
}
|
|
||||||
|
|
||||||
function trainDexterity(): void {
|
|
||||||
train(ClassType.GymDexterity);
|
|
||||||
}
|
|
||||||
|
|
||||||
function trainAgility(): void {
|
|
||||||
train(ClassType.GymAgility);
|
|
||||||
}
|
|
||||||
|
|
||||||
const cost = CONSTANTS.ClassGymBaseCost * calculateCost();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{ display: "grid", width: "fit-content" }}>
|
<Box sx={{ display: "grid", width: "fit-content" }}>
|
||||||
<Button onClick={trainStrength}>
|
<Button onClick={() => train(ClassType.GymStrength)}>
|
||||||
Train Strength (<Money money={cost} player={props.p} /> / sec)
|
Train Strength (<Money money={cost} player={props.p} /> / sec)
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={trainDefense}>
|
<Button onClick={() => train(ClassType.GymDefense)}>
|
||||||
Train Defense (<Money money={cost} player={props.p} /> / sec)
|
Train Defense (<Money money={cost} player={props.p} /> / sec)
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={trainDexterity}>
|
<Button onClick={() => train(ClassType.GymDexterity)}>
|
||||||
Train Dexterity (<Money money={cost} player={props.p} /> / sec)
|
Train Dexterity (<Money money={cost} player={props.p} /> / sec)
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={trainAgility}>
|
<Button onClick={() => train(ClassType.GymAgility)}>
|
||||||
Train Agility (<Money money={cost} player={props.p} /> / sec)
|
Train Agility (<Money money={cost} player={props.p} /> / sec)
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -25,13 +25,11 @@ export class HospitalLocation extends React.Component<IProps, IState> {
|
|||||||
/**
|
/**
|
||||||
* Stores button styling that sets them all to block display
|
* Stores button styling that sets them all to block display
|
||||||
*/
|
*/
|
||||||
btnStyle: any;
|
btnStyle = { display: "block" };
|
||||||
|
|
||||||
constructor(props: IProps) {
|
constructor(props: IProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.btnStyle = { display: "block" };
|
|
||||||
|
|
||||||
this.getCost = this.getCost.bind(this);
|
this.getCost = this.getCost.bind(this);
|
||||||
this.getHealed = this.getHealed.bind(this);
|
this.getHealed = this.getHealed.bind(this);
|
||||||
|
|
||||||
|
@ -20,84 +20,108 @@ export function SlumsLocation(): React.ReactElement {
|
|||||||
if (!e.isTrusted) {
|
if (!e.isTrusted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Crimes.Shoplift.commit(router, player);
|
Crimes.Shoplift.commit(player);
|
||||||
|
router.toWork();
|
||||||
|
player.focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function robStore(e: React.MouseEvent<HTMLElement>): void {
|
function robStore(e: React.MouseEvent<HTMLElement>): void {
|
||||||
if (!e.isTrusted) {
|
if (!e.isTrusted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Crimes.RobStore.commit(router, player);
|
Crimes.RobStore.commit(player);
|
||||||
|
router.toWork();
|
||||||
|
player.focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function mug(e: React.MouseEvent<HTMLElement>): void {
|
function mug(e: React.MouseEvent<HTMLElement>): void {
|
||||||
if (!e.isTrusted) {
|
if (!e.isTrusted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Crimes.Mug.commit(router, player);
|
Crimes.Mug.commit(player);
|
||||||
|
router.toWork();
|
||||||
|
player.focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function larceny(e: React.MouseEvent<HTMLElement>): void {
|
function larceny(e: React.MouseEvent<HTMLElement>): void {
|
||||||
if (!e.isTrusted) {
|
if (!e.isTrusted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Crimes.Larceny.commit(router, player);
|
Crimes.Larceny.commit(player);
|
||||||
|
router.toWork();
|
||||||
|
player.focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function dealDrugs(e: React.MouseEvent<HTMLElement>): void {
|
function dealDrugs(e: React.MouseEvent<HTMLElement>): void {
|
||||||
if (!e.isTrusted) {
|
if (!e.isTrusted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Crimes.DealDrugs.commit(router, player);
|
Crimes.DealDrugs.commit(player);
|
||||||
|
router.toWork();
|
||||||
|
player.focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function bondForgery(e: React.MouseEvent<HTMLElement>): void {
|
function bondForgery(e: React.MouseEvent<HTMLElement>): void {
|
||||||
if (!e.isTrusted) {
|
if (!e.isTrusted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Crimes.BondForgery.commit(router, player);
|
Crimes.BondForgery.commit(player);
|
||||||
|
router.toWork();
|
||||||
|
player.focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function traffickArms(e: React.MouseEvent<HTMLElement>): void {
|
function traffickArms(e: React.MouseEvent<HTMLElement>): void {
|
||||||
if (!e.isTrusted) {
|
if (!e.isTrusted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Crimes.TraffickArms.commit(router, player);
|
Crimes.TraffickArms.commit(player);
|
||||||
|
router.toWork();
|
||||||
|
player.focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function homicide(e: React.MouseEvent<HTMLElement>): void {
|
function homicide(e: React.MouseEvent<HTMLElement>): void {
|
||||||
if (!e.isTrusted) {
|
if (!e.isTrusted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Crimes.Homicide.commit(router, player);
|
Crimes.Homicide.commit(player);
|
||||||
|
router.toWork();
|
||||||
|
player.focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function grandTheftAuto(e: React.MouseEvent<HTMLElement>): void {
|
function grandTheftAuto(e: React.MouseEvent<HTMLElement>): void {
|
||||||
if (!e.isTrusted) {
|
if (!e.isTrusted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Crimes.GrandTheftAuto.commit(router, player);
|
Crimes.GrandTheftAuto.commit(player);
|
||||||
|
router.toWork();
|
||||||
|
player.focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function kidnap(e: React.MouseEvent<HTMLElement>): void {
|
function kidnap(e: React.MouseEvent<HTMLElement>): void {
|
||||||
if (!e.isTrusted) {
|
if (!e.isTrusted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Crimes.Kidnap.commit(router, player);
|
Crimes.Kidnap.commit(player);
|
||||||
|
router.toWork();
|
||||||
|
player.focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function assassinate(e: React.MouseEvent<HTMLElement>): void {
|
function assassinate(e: React.MouseEvent<HTMLElement>): void {
|
||||||
if (!e.isTrusted) {
|
if (!e.isTrusted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Crimes.Assassination.commit(router, player);
|
Crimes.Assassination.commit(player);
|
||||||
|
router.toWork();
|
||||||
|
player.focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function heist(e: React.MouseEvent<HTMLElement>): void {
|
function heist(e: React.MouseEvent<HTMLElement>): void {
|
||||||
if (!e.isTrusted) {
|
if (!e.isTrusted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Crimes.Heist.commit(router, player);
|
Crimes.Heist.commit(player);
|
||||||
|
router.toWork();
|
||||||
|
player.focus = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const shopliftChance = Crimes.Shoplift.successRate(player);
|
const shopliftChance = Crimes.Shoplift.successRate(player);
|
||||||
|
@ -56,7 +56,7 @@ export function SpecialLocation(props: IProps): React.ReactElement {
|
|||||||
router.toBladeburner();
|
router.toBladeburner();
|
||||||
} else if (p.strength >= 100 && p.defense >= 100 && p.dexterity >= 100 && p.agility >= 100) {
|
} else if (p.strength >= 100 && p.defense >= 100 && p.dexterity >= 100 && p.agility >= 100) {
|
||||||
// Apply for Bladeburner division
|
// Apply for Bladeburner division
|
||||||
p.startBladeburner({ new: true });
|
p.startBladeburner();
|
||||||
dialogBoxCreate("You have been accepted into the Bladeburner division!");
|
dialogBoxCreate("You have been accepted into the Bladeburner division!");
|
||||||
setRerender((old) => !old);
|
setRerender((old) => !old);
|
||||||
|
|
||||||
|
@ -9,15 +9,12 @@ import Button from "@mui/material/Button";
|
|||||||
|
|
||||||
import { Location } from "../Location";
|
import { Location } from "../Location";
|
||||||
|
|
||||||
import { CONSTANTS } from "../../Constants";
|
|
||||||
import { GetServer } from "../../Server/AllServers";
|
|
||||||
import { Server } from "../../Server/Server";
|
|
||||||
|
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
import { use } from "../../ui/Context";
|
import { use } from "../../ui/Context";
|
||||||
import { Box } from "@mui/material";
|
import { Box } from "@mui/material";
|
||||||
|
|
||||||
import { ClassType } from "../../utils/WorkType";
|
import { ClassWork, ClassType, Classes } from "../../Work/ClassWork";
|
||||||
|
import { calculateCost } from "../../Work/formulas/Class";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
loc: Location;
|
loc: Location;
|
||||||
@ -27,51 +24,23 @@ export function UniversityLocation(props: IProps): React.ReactElement {
|
|||||||
const player = use.Player();
|
const player = use.Player();
|
||||||
const router = use.Router();
|
const router = use.Router();
|
||||||
|
|
||||||
function calculateCost(): number {
|
function take(classType: ClassType): void {
|
||||||
const server = GetServer(props.loc.name);
|
player.startWork(
|
||||||
if (server == null || !server.hasOwnProperty("backdoorInstalled")) return props.loc.costMult;
|
new ClassWork({
|
||||||
const discount = (server as Server).backdoorInstalled ? 0.9 : 1;
|
classType: classType,
|
||||||
return props.loc.costMult * discount;
|
location: props.loc.name,
|
||||||
}
|
singularity: false,
|
||||||
|
}),
|
||||||
function take(stat: ClassType): void {
|
);
|
||||||
const loc = props.loc;
|
|
||||||
player.startClass(calculateCost(), loc.expMult, stat);
|
|
||||||
player.startFocusing();
|
player.startFocusing();
|
||||||
router.toWork();
|
router.toWork();
|
||||||
}
|
}
|
||||||
|
|
||||||
function study(): void {
|
const dataStructuresCost = calculateCost(Classes[ClassType.DataStructures], props.loc);
|
||||||
take(ClassType.StudyComputerScience);
|
const networksCost = calculateCost(Classes[ClassType.Networks], props.loc);
|
||||||
}
|
const algorithmsCost = calculateCost(Classes[ClassType.Algorithms], props.loc);
|
||||||
|
const managementCost = calculateCost(Classes[ClassType.Management], props.loc);
|
||||||
function dataStructures(): void {
|
const leadershipCost = calculateCost(Classes[ClassType.Leadership], props.loc);
|
||||||
take(ClassType.DataStructures);
|
|
||||||
}
|
|
||||||
|
|
||||||
function networks(): void {
|
|
||||||
take(ClassType.Networks);
|
|
||||||
}
|
|
||||||
|
|
||||||
function algorithms(): void {
|
|
||||||
take(ClassType.Algorithms);
|
|
||||||
}
|
|
||||||
|
|
||||||
function management(): void {
|
|
||||||
take(ClassType.Management);
|
|
||||||
}
|
|
||||||
|
|
||||||
function leadership(): void {
|
|
||||||
take(ClassType.Leadership);
|
|
||||||
}
|
|
||||||
|
|
||||||
const costMult: number = calculateCost();
|
|
||||||
|
|
||||||
const dataStructuresCost = CONSTANTS.ClassDataStructuresBaseCost * costMult;
|
|
||||||
const networksCost = CONSTANTS.ClassNetworksBaseCost * costMult;
|
|
||||||
const algorithmsCost = CONSTANTS.ClassAlgorithmsBaseCost * costMult;
|
|
||||||
const managementCost = CONSTANTS.ClassManagementBaseCost * costMult;
|
|
||||||
const leadershipCost = CONSTANTS.ClassLeadershipBaseCost * costMult;
|
|
||||||
|
|
||||||
const earnHackingExpTooltip = `Gain hacking experience!`;
|
const earnHackingExpTooltip = `Gain hacking experience!`;
|
||||||
const earnCharismaExpTooltip = `Gain charisma experience!`;
|
const earnCharismaExpTooltip = `Gain charisma experience!`;
|
||||||
@ -79,34 +48,34 @@ export function UniversityLocation(props: IProps): React.ReactElement {
|
|||||||
return (
|
return (
|
||||||
<Box sx={{ display: "grid", width: "fit-content" }}>
|
<Box sx={{ display: "grid", width: "fit-content" }}>
|
||||||
<Tooltip title={earnHackingExpTooltip}>
|
<Tooltip title={earnHackingExpTooltip}>
|
||||||
<Button onClick={study}>Study Computer Science (free)</Button>
|
<Button onClick={() => take(ClassType.StudyComputerScience)}>Study Computer Science (free)</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title={earnHackingExpTooltip}>
|
<Tooltip title={earnHackingExpTooltip}>
|
||||||
<Button onClick={dataStructures}>
|
<Button onClick={() => take(ClassType.DataStructures)}>
|
||||||
Take Data Structures course (
|
Take Data Structures course (
|
||||||
<Money money={dataStructuresCost} player={player} /> / sec)
|
<Money money={dataStructuresCost} player={player} /> / sec)
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title={earnHackingExpTooltip}>
|
<Tooltip title={earnHackingExpTooltip}>
|
||||||
<Button onClick={networks}>
|
<Button onClick={() => take(ClassType.Networks)}>
|
||||||
Take Networks course (
|
Take Networks course (
|
||||||
<Money money={networksCost} player={player} /> / sec)
|
<Money money={networksCost} player={player} /> / sec)
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title={earnHackingExpTooltip}>
|
<Tooltip title={earnHackingExpTooltip}>
|
||||||
<Button onClick={algorithms}>
|
<Button onClick={() => take(ClassType.Algorithms)}>
|
||||||
Take Algorithms course (
|
Take Algorithms course (
|
||||||
<Money money={algorithmsCost} player={player} /> / sec)
|
<Money money={algorithmsCost} player={player} /> / sec)
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title={earnCharismaExpTooltip}>
|
<Tooltip title={earnCharismaExpTooltip}>
|
||||||
<Button onClick={management}>
|
<Button onClick={() => take(ClassType.Management)}>
|
||||||
Take Management course (
|
Take Management course (
|
||||||
<Money money={managementCost} player={player} /> / sec)
|
<Money money={managementCost} player={player} /> / sec)
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title={earnCharismaExpTooltip}>
|
<Tooltip title={earnCharismaExpTooltip}>
|
||||||
<Button onClick={leadership}>
|
<Button onClick={() => take(ClassType.Leadership)}>
|
||||||
Take Leadership course (
|
Take Leadership course (
|
||||||
<Money money={leadershipCost} player={player} /> / sec)
|
<Money money={leadershipCost} player={player} /> / sec)
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -4,6 +4,7 @@ import { Factions } from "../Faction/Factions";
|
|||||||
import { Faction } from "../Faction/Faction";
|
import { Faction } from "../Faction/Faction";
|
||||||
import { GetServer } from "../Server/AllServers";
|
import { GetServer } from "../Server/AllServers";
|
||||||
import { FactionNames } from "../Faction/data/FactionNames";
|
import { FactionNames } from "../Faction/data/FactionNames";
|
||||||
|
import { Server } from "../Server/Server";
|
||||||
|
|
||||||
function allFactionAugs(p: IPlayer, f: Faction): boolean {
|
function allFactionAugs(p: IPlayer, f: Faction): boolean {
|
||||||
const factionAugs = f.augmentations.slice().filter((aug) => aug !== "NeuroFlux Governor");
|
const factionAugs = f.augmentations.slice().filter((aug) => aug !== "NeuroFlux Governor");
|
||||||
@ -24,7 +25,7 @@ export const Milestones: Milestone[] = [
|
|||||||
fulfilled: (): boolean => {
|
fulfilled: (): boolean => {
|
||||||
const server = GetServer("CSEC");
|
const server = GetServer("CSEC");
|
||||||
if (!server || !server.hasOwnProperty("hasAdminRights")) return false;
|
if (!server || !server.hasOwnProperty("hasAdminRights")) return false;
|
||||||
return (server as any).hasAdminRights;
|
return server instanceof Server && server.hasAdminRights;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -32,7 +33,7 @@ export const Milestones: Milestone[] = [
|
|||||||
fulfilled: (): boolean => {
|
fulfilled: (): boolean => {
|
||||||
const server = GetServer("CSEC");
|
const server = GetServer("CSEC");
|
||||||
if (!server || !server.hasOwnProperty("backdoorInstalled")) return false;
|
if (!server || !server.hasOwnProperty("backdoorInstalled")) return false;
|
||||||
return (server as any).backdoorInstalled;
|
return server instanceof Server && server.backdoorInstalled;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -4,11 +4,17 @@ import type { BaseServer } from "../Server/BaseServer";
|
|||||||
import type { WorkerScript } from "./WorkerScript";
|
import type { WorkerScript } from "./WorkerScript";
|
||||||
import { makeRuntimeRejectMsg } from "../NetscriptEvaluator";
|
import { makeRuntimeRejectMsg } from "../NetscriptEvaluator";
|
||||||
import { Player } from "../Player";
|
import { Player } from "../Player";
|
||||||
import { CityName } from "src/Locations/data/CityNames";
|
import { CityName } from "../Locations/data/CityNames";
|
||||||
import { Settings } from "../Settings/Settings";
|
import { BasicHGWOptions } from "../ScriptEditor/NetscriptDefinitions";
|
||||||
import { CONSTANTS } from "../Constants";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
import { Server } from "../Server/Server";
|
||||||
|
import { FormulaGang } from "../Gang/formulas/formulas";
|
||||||
|
import { INetscriptHelper, ScriptIdentifier } from "../NetscriptFunctions/INetscriptHelper";
|
||||||
|
import { GangMember } from "../Gang/GangMember";
|
||||||
|
import { GangMemberTask } from "../Gang/GangMemberTask";
|
||||||
|
import { ScriptArg } from "./ScriptArg";
|
||||||
|
|
||||||
type ExternalFunction = (...args: any[]) => any;
|
type ExternalFunction = (...args: unknown[]) => unknown;
|
||||||
export type ExternalAPI = {
|
export type ExternalAPI = {
|
||||||
[string: string]: ExternalAPI | ExternalFunction;
|
[string: string]: ExternalAPI | ExternalFunction;
|
||||||
};
|
};
|
||||||
@ -36,39 +42,30 @@ export type NetscriptContext = {
|
|||||||
helper: WrappedNetscriptHelpers;
|
helper: WrappedNetscriptHelpers;
|
||||||
};
|
};
|
||||||
|
|
||||||
type NetscriptHelpers = {
|
|
||||||
updateDynamicRam: (fnName: string, ramCost: number) => void;
|
|
||||||
makeRuntimeErrorMsg: (caller: string, msg: string) => string;
|
|
||||||
string: (funcName: string, argName: string, v: unknown) => string;
|
|
||||||
number: (funcName: string, argName: string, v: unknown) => number;
|
|
||||||
city: (funcName: string, argName: string, v: unknown) => CityName;
|
|
||||||
boolean: (v: unknown) => boolean;
|
|
||||||
getServer: (hostname: string, ctx: NetscriptContext) => BaseServer;
|
|
||||||
checkSingularityAccess: (func: string) => void;
|
|
||||||
hack: (
|
|
||||||
ctx: NetscriptContext,
|
|
||||||
hostname: any,
|
|
||||||
manual: any,
|
|
||||||
{ threads: requestedThreads, stock }?: any,
|
|
||||||
) => Promise<number>;
|
|
||||||
getValidPort: (funcName: string, port: any) => IPort;
|
|
||||||
};
|
|
||||||
|
|
||||||
type WrappedNetscriptHelpers = {
|
type WrappedNetscriptHelpers = {
|
||||||
makeRuntimeErrorMsg: (msg: string) => string;
|
makeRuntimeErrorMsg: (msg: string) => string;
|
||||||
string: (argName: string, v: unknown) => string;
|
string: (argName: string, v: unknown) => string;
|
||||||
number: (argName: string, v: unknown) => number;
|
number: (argName: string, v: unknown) => number;
|
||||||
|
ustring: (argName: string, v: unknown) => string | undefined;
|
||||||
|
unumber: (argName: string, v: unknown) => number | undefined;
|
||||||
|
scriptArgs(args: unknown): ScriptArg[];
|
||||||
|
scriptIdentifier: (fn: unknown, hostname: unknown, args: unknown) => ScriptIdentifier;
|
||||||
city: (argName: string, v: unknown) => CityName;
|
city: (argName: string, v: unknown) => CityName;
|
||||||
boolean: (v: unknown) => boolean;
|
boolean: (v: unknown) => boolean;
|
||||||
getServer: (hostname: string) => BaseServer;
|
getServer: (hostname: string) => BaseServer;
|
||||||
checkSingularityAccess: () => void;
|
checkSingularityAccess: () => void;
|
||||||
hack: (hostname: any, manual: any, { threads: requestedThreads, stock }?: any) => Promise<number>;
|
hack: (hostname: string, manual: boolean, { threads: requestedThreads, stock }?: BasicHGWOptions) => Promise<number>;
|
||||||
getValidPort: (port: any) => IPort;
|
getValidPort: (port: number) => IPort;
|
||||||
|
player(p: unknown): IPlayer;
|
||||||
|
server(s: unknown): Server;
|
||||||
|
gang(g: unknown): FormulaGang;
|
||||||
|
gangMember: (m: unknown) => GangMember;
|
||||||
|
gangTask: (t: unknown) => GangMemberTask;
|
||||||
};
|
};
|
||||||
|
|
||||||
function wrapFunction(
|
function wrapFunction(
|
||||||
helpers: NetscriptHelpers,
|
helpers: INetscriptHelper,
|
||||||
wrappedAPI: any,
|
wrappedAPI: ExternalAPI,
|
||||||
workerScript: WorkerScript,
|
workerScript: WorkerScript,
|
||||||
func: (_ctx: NetscriptContext) => (...args: unknown[]) => unknown,
|
func: (_ctx: NetscriptContext) => (...args: unknown[]) => unknown,
|
||||||
...tree: string[]
|
...tree: string[]
|
||||||
@ -91,12 +88,22 @@ function wrapFunction(
|
|||||||
makeRuntimeErrorMsg: (msg: string) => helpers.makeRuntimeErrorMsg(functionPath, msg),
|
makeRuntimeErrorMsg: (msg: string) => helpers.makeRuntimeErrorMsg(functionPath, msg),
|
||||||
string: (argName: string, v: unknown) => helpers.string(functionPath, argName, v),
|
string: (argName: string, v: unknown) => helpers.string(functionPath, argName, v),
|
||||||
number: (argName: string, v: unknown) => helpers.number(functionPath, argName, v),
|
number: (argName: string, v: unknown) => helpers.number(functionPath, argName, v),
|
||||||
|
ustring: (argName: string, v: unknown) => helpers.ustring(functionPath, argName, v),
|
||||||
|
unumber: (argName: string, v: unknown) => helpers.unumber(functionPath, argName, v),
|
||||||
|
scriptArgs: (v: unknown) => helpers.scriptArgs(functionPath, v),
|
||||||
|
scriptIdentifier: (fn: unknown, hostname: unknown, args: unknown) =>
|
||||||
|
helpers.scriptIdentifier(functionPath, fn, hostname, args),
|
||||||
city: (argName: string, v: unknown) => helpers.city(functionPath, argName, v),
|
city: (argName: string, v: unknown) => helpers.city(functionPath, argName, v),
|
||||||
boolean: helpers.boolean,
|
boolean: helpers.boolean,
|
||||||
getServer: (hostname: string) => helpers.getServer(hostname, ctx),
|
getServer: (hostname: string) => helpers.getServer(hostname, ctx),
|
||||||
checkSingularityAccess: () => helpers.checkSingularityAccess(functionName),
|
checkSingularityAccess: () => helpers.checkSingularityAccess(functionName),
|
||||||
hack: (hostname: any, manual: any, extra?: any) => helpers.hack(ctx, hostname, manual, extra),
|
hack: (hostname: string, manual: boolean, extra?: BasicHGWOptions) => helpers.hack(ctx, hostname, manual, extra),
|
||||||
getValidPort: (port: any) => helpers.getValidPort(functionPath, port),
|
getValidPort: (port: number) => helpers.getValidPort(functionPath, port),
|
||||||
|
player: (p: unknown) => helpers.player(functionPath, p),
|
||||||
|
server: (s: unknown) => helpers.server(functionPath, s),
|
||||||
|
gang: (g: unknown) => helpers.gang(functionPath, g),
|
||||||
|
gangMember: (m: unknown) => helpers.gangMember(functionPath, m),
|
||||||
|
gangTask: (t: unknown) => helpers.gangTask(functionPath, t),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
function wrappedFunction(...args: unknown[]): unknown {
|
function wrappedFunction(...args: unknown[]): unknown {
|
||||||
@ -112,48 +119,43 @@ function wrapFunction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function wrapAPI(
|
export function wrapAPI(
|
||||||
helpers: NetscriptHelpers,
|
helpers: INetscriptHelper,
|
||||||
wrappedAPI: ExternalAPI,
|
wrappedAPI: ExternalAPI,
|
||||||
workerScript: WorkerScript,
|
workerScript: WorkerScript,
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
namespace: object,
|
||||||
namespace: any,
|
|
||||||
...tree: string[]
|
...tree: string[]
|
||||||
): WrappedNetscriptAPI {
|
): WrappedNetscriptAPI {
|
||||||
if (typeof namespace !== "object") throw new Error("Invalid namespace?");
|
for (const [key, value] of Object.entries(namespace)) {
|
||||||
for (const property of Object.getOwnPropertyNames(namespace)) {
|
if (typeof value === "function") {
|
||||||
switch (typeof namespace[property]) {
|
wrapFunction(helpers, wrappedAPI, workerScript, value, ...tree, key);
|
||||||
case "function": {
|
} else if (Array.isArray(value)) {
|
||||||
wrapFunction(helpers, wrappedAPI, workerScript, namespace[property], ...tree, property);
|
setNestedProperty(wrappedAPI, value, key);
|
||||||
break;
|
} else if (typeof value === "object") {
|
||||||
}
|
wrapAPI(helpers, wrappedAPI, workerScript, value, ...tree, key);
|
||||||
case "object": {
|
} else {
|
||||||
wrapAPI(helpers, wrappedAPI, workerScript, namespace[property], ...tree, property);
|
setNestedProperty(wrappedAPI, value, ...tree, key);
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
setNestedProperty(wrappedAPI, namespace[property], ...tree, property);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wrappedAPI;
|
return wrappedAPI;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setNestedProperty(root: any, value: any, ...tree: string[]): any {
|
// TODO: This doesn't even work properly.
|
||||||
|
function setNestedProperty(root: object, value: unknown, ...tree: string[]): void {
|
||||||
let target = root;
|
let target = root;
|
||||||
const key = tree.pop();
|
const key = tree.pop();
|
||||||
if (typeof key !== "string") {
|
if (!key) {
|
||||||
throw new Error("Failure occured while wrapping netscript api (setNestedProperty)");
|
throw new Error("Failure occured while wrapping netscript api (setNestedProperty)");
|
||||||
}
|
}
|
||||||
for (const branch of tree) {
|
for (let branch of Object.values(target)) {
|
||||||
if (target[branch] === undefined) {
|
if (branch === undefined) {
|
||||||
target[branch] = {};
|
branch = {};
|
||||||
}
|
}
|
||||||
target = target[branch];
|
target = branch;
|
||||||
}
|
}
|
||||||
target[key] = value;
|
Object.assign(target, { [key]: value });
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNestedProperty(root: any, ...tree: string[]): any {
|
function getNestedProperty(root: any, ...tree: string[]): unknown {
|
||||||
let target = root;
|
let target = root;
|
||||||
for (const branch of tree) {
|
for (const branch of tree) {
|
||||||
if (target[branch] === undefined) {
|
if (target[branch] === undefined) {
|
||||||
|
@ -1,16 +1,10 @@
|
|||||||
|
import { NS } from "../ScriptEditor/NetscriptDefinitions";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The environment in which a script runs. The environment holds
|
* The environment in which a script runs. The environment holds
|
||||||
* Netscript functions and arguments for that script.
|
* Netscript functions and arguments for that script.
|
||||||
*/
|
*/
|
||||||
import { NS } from "src/ScriptEditor/NetscriptDefinitions";
|
|
||||||
import { IMap } from "../types";
|
|
||||||
|
|
||||||
export class Environment {
|
export class Environment {
|
||||||
/**
|
|
||||||
* Parent environment. Used to implement "scope"
|
|
||||||
*/
|
|
||||||
parent: Environment | null = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not the script that uses this Environment should stop running
|
* Whether or not the script that uses this Environment should stop running
|
||||||
*/
|
*/
|
||||||
@ -19,58 +13,5 @@ export class Environment {
|
|||||||
/**
|
/**
|
||||||
* Environment variables (currently only Netscript functions)
|
* Environment variables (currently only Netscript functions)
|
||||||
*/
|
*/
|
||||||
vars: any = {};
|
vars: NS | null = null;
|
||||||
|
|
||||||
constructor(parent: Environment | null) {
|
|
||||||
if (parent instanceof Environment) {
|
|
||||||
this.vars = Object.assign({}, parent.vars);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds the scope where the variable with the given name is defined
|
|
||||||
*/
|
|
||||||
lookup(name: string): Environment | null {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
||||||
let scope: Environment | null = this;
|
|
||||||
while (scope) {
|
|
||||||
if (Object.prototype.hasOwnProperty.call(scope.vars, name)) {
|
|
||||||
return scope;
|
|
||||||
}
|
|
||||||
scope = scope.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Get the current value of a variable
|
|
||||||
get(name: string): any {
|
|
||||||
if (name in this.vars) {
|
|
||||||
return this.vars[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(`Undefined variable ${name}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Sets the value of a variable in any scope
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
||||||
set(name: string, value: any): any {
|
|
||||||
const scope = this.lookup(name);
|
|
||||||
|
|
||||||
//If scope has a value, then this variable is already set in a higher scope, so
|
|
||||||
//set is there. Otherwise, create a new variable in the local scope
|
|
||||||
if (scope !== null) {
|
|
||||||
return (scope.vars[name] = value);
|
|
||||||
} else {
|
|
||||||
return (this.vars[name] = value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Creates (or overwrites) a variable in the current scope
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
||||||
def(name: string, value: any): any {
|
|
||||||
return (this.vars[name] = value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,6 @@ export const RamCostConstants: IMap<number> = {
|
|||||||
ScriptGetFavorToDonate: 0.1,
|
ScriptGetFavorToDonate: 0.1,
|
||||||
ScriptCodingContractBaseRamCost: 10,
|
ScriptCodingContractBaseRamCost: 10,
|
||||||
ScriptSleeveBaseRamCost: 4,
|
ScriptSleeveBaseRamCost: 4,
|
||||||
ScriptGetOwnedSourceFiles: 5,
|
|
||||||
ScriptClearTerminalCost: 0.2,
|
ScriptClearTerminalCost: 0.2,
|
||||||
|
|
||||||
ScriptSingularityFn1RamCost: 2,
|
ScriptSingularityFn1RamCost: 2,
|
||||||
@ -135,8 +134,8 @@ const stock = {
|
|||||||
getMaxShares: RamCostConstants.ScriptGetStockRamCost,
|
getMaxShares: RamCostConstants.ScriptGetStockRamCost,
|
||||||
getPurchaseCost: RamCostConstants.ScriptGetStockRamCost,
|
getPurchaseCost: RamCostConstants.ScriptGetStockRamCost,
|
||||||
getSaleGain: RamCostConstants.ScriptGetStockRamCost,
|
getSaleGain: RamCostConstants.ScriptGetStockRamCost,
|
||||||
buy: RamCostConstants.ScriptBuySellStockRamCost,
|
buyStock: RamCostConstants.ScriptBuySellStockRamCost,
|
||||||
sell: RamCostConstants.ScriptBuySellStockRamCost,
|
sellStock: RamCostConstants.ScriptBuySellStockRamCost,
|
||||||
short: RamCostConstants.ScriptBuySellStockRamCost,
|
short: RamCostConstants.ScriptBuySellStockRamCost,
|
||||||
sellShort: RamCostConstants.ScriptBuySellStockRamCost,
|
sellShort: RamCostConstants.ScriptBuySellStockRamCost,
|
||||||
placeOrder: RamCostConstants.ScriptBuySellStockRamCost,
|
placeOrder: RamCostConstants.ScriptBuySellStockRamCost,
|
||||||
@ -191,10 +190,12 @@ const singularity = {
|
|||||||
getCrimeChance: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
getCrimeChance: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||||
getCrimeStats: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
getCrimeStats: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||||
getOwnedAugmentations: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
getOwnedAugmentations: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||||
|
getOwnedSourceFiles: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||||
getAugmentationsFromFaction: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
getAugmentationsFromFaction: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||||
getAugmentationCost: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
getAugmentationCost: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||||
getAugmentationPrereq: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
getAugmentationPrereq: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||||
getAugmentationPrice: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost / 2),
|
getAugmentationPrice: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost / 2),
|
||||||
|
getAugmentationBasePrice: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost / 2),
|
||||||
getAugmentationRepReq: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost / 2),
|
getAugmentationRepReq: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost / 2),
|
||||||
getAugmentationStats: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
getAugmentationStats: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||||
purchaseAugmentation: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
purchaseAugmentation: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||||
@ -505,7 +506,9 @@ const SourceRamCosts = {
|
|||||||
getHackTime: RamCostConstants.ScriptGetHackTimeRamCost,
|
getHackTime: RamCostConstants.ScriptGetHackTimeRamCost,
|
||||||
getGrowTime: RamCostConstants.ScriptGetHackTimeRamCost,
|
getGrowTime: RamCostConstants.ScriptGetHackTimeRamCost,
|
||||||
getWeakenTime: RamCostConstants.ScriptGetHackTimeRamCost,
|
getWeakenTime: RamCostConstants.ScriptGetHackTimeRamCost,
|
||||||
|
getTotalScriptIncome: RamCostConstants.ScriptGetScriptRamCost,
|
||||||
getScriptIncome: RamCostConstants.ScriptGetScriptRamCost,
|
getScriptIncome: RamCostConstants.ScriptGetScriptRamCost,
|
||||||
|
getTotalScriptExpGain: RamCostConstants.ScriptGetScriptRamCost,
|
||||||
getScriptExpGain: RamCostConstants.ScriptGetScriptRamCost,
|
getScriptExpGain: RamCostConstants.ScriptGetScriptRamCost,
|
||||||
getRunningScript: RamCostConstants.ScriptGetRunningScriptRamCost,
|
getRunningScript: RamCostConstants.ScriptGetRunningScriptRamCost,
|
||||||
nFormat: 0,
|
nFormat: 0,
|
||||||
@ -516,7 +519,6 @@ const SourceRamCosts = {
|
|||||||
getFavorToDonate: RamCostConstants.ScriptGetFavorToDonate,
|
getFavorToDonate: RamCostConstants.ScriptGetFavorToDonate,
|
||||||
getPlayer: RamCostConstants.ScriptSingularityFn1RamCost / 4,
|
getPlayer: RamCostConstants.ScriptSingularityFn1RamCost / 4,
|
||||||
mv: 0,
|
mv: 0,
|
||||||
getOwnedSourceFiles: RamCostConstants.ScriptGetOwnedSourceFiles,
|
|
||||||
tail: 0,
|
tail: 0,
|
||||||
toast: 0,
|
toast: 0,
|
||||||
closeTail: 0,
|
closeTail: 0,
|
||||||
|
1
src/Netscript/ScriptArg.ts
Normal file
1
src/Netscript/ScriptArg.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type ScriptArg = string | number | boolean;
|
@ -15,12 +15,14 @@ import { GetServer } from "../Server/AllServers";
|
|||||||
import { BaseServer } from "../Server/BaseServer";
|
import { BaseServer } from "../Server/BaseServer";
|
||||||
import { IMap } from "../types";
|
import { IMap } from "../types";
|
||||||
import { NS } from "../ScriptEditor/NetscriptDefinitions";
|
import { NS } from "../ScriptEditor/NetscriptDefinitions";
|
||||||
|
import { ScriptDeath } from "./ScriptDeath";
|
||||||
|
import { ScriptArg } from "./ScriptArg";
|
||||||
|
|
||||||
export class WorkerScript {
|
export class WorkerScript {
|
||||||
/**
|
/**
|
||||||
* Script's arguments
|
* Script's arguments
|
||||||
*/
|
*/
|
||||||
args: any[];
|
args: ScriptArg[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy of the script's code
|
* Copy of the script's code
|
||||||
@ -36,7 +38,7 @@ export class WorkerScript {
|
|||||||
/**
|
/**
|
||||||
* Holds the Promise reject() function while the script is "blocked" by an async op
|
* Holds the Promise reject() function while the script is "blocked" by an async op
|
||||||
*/
|
*/
|
||||||
delayReject?: (reason?: any) => void;
|
delayReject?: (reason?: ScriptDeath) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores names of all functions that have logging disabled
|
* Stores names of all functions that have logging disabled
|
||||||
@ -110,7 +112,7 @@ export class WorkerScript {
|
|||||||
/**
|
/**
|
||||||
* Function called when the script ends.
|
* Function called when the script ends.
|
||||||
*/
|
*/
|
||||||
atExit: any;
|
atExit?: () => void;
|
||||||
|
|
||||||
constructor(runningScriptObj: RunningScript, pid: number, nsFuncsGenerator?: (ws: WorkerScript) => NS) {
|
constructor(runningScriptObj: RunningScript, pid: number, nsFuncsGenerator?: (ws: WorkerScript) => NS) {
|
||||||
this.name = runningScriptObj.filename;
|
this.name = runningScriptObj.filename;
|
||||||
@ -140,11 +142,10 @@ export class WorkerScript {
|
|||||||
}
|
}
|
||||||
this.scriptRef = runningScriptObj;
|
this.scriptRef = runningScriptObj;
|
||||||
this.args = runningScriptObj.args.slice();
|
this.args = runningScriptObj.args.slice();
|
||||||
this.env = new Environment(null);
|
this.env = new Environment();
|
||||||
if (typeof nsFuncsGenerator === "function") {
|
if (typeof nsFuncsGenerator === "function") {
|
||||||
this.env.vars = nsFuncsGenerator(this);
|
this.env.vars = nsFuncsGenerator(this);
|
||||||
}
|
}
|
||||||
this.env.set("args", runningScriptObj.args.slice());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,52 +15,43 @@ import { dialogBoxCreate } from "../ui/React/DialogBox";
|
|||||||
import { AddRecentScript } from "./RecentScripts";
|
import { AddRecentScript } from "./RecentScripts";
|
||||||
import { Player } from "../Player";
|
import { Player } from "../Player";
|
||||||
|
|
||||||
export function killWorkerScript(runningScriptObj: RunningScript, hostname: string, rerenderUi?: boolean): boolean;
|
export type killScriptParams = WorkerScript | number | { runningScript: RunningScript; hostname: string };
|
||||||
export function killWorkerScript(workerScript: WorkerScript): boolean;
|
|
||||||
export function killWorkerScript(pid: number): boolean;
|
|
||||||
export function killWorkerScript(
|
|
||||||
script: RunningScript | WorkerScript | number,
|
|
||||||
hostname?: string,
|
|
||||||
rerenderUi?: boolean,
|
|
||||||
): boolean {
|
|
||||||
if (rerenderUi == null || typeof rerenderUi !== "boolean") {
|
|
||||||
rerenderUi = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (script instanceof WorkerScript) {
|
export function killWorkerScript(params: killScriptParams): boolean {
|
||||||
stopAndCleanUpWorkerScript(script);
|
if (params instanceof WorkerScript) {
|
||||||
|
stopAndCleanUpWorkerScript(params);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else if (script instanceof RunningScript && typeof hostname === "string") {
|
} else if (typeof params === "number") {
|
||||||
|
return killWorkerScriptByPid(params);
|
||||||
|
} else {
|
||||||
// Try to kill by PID
|
// Try to kill by PID
|
||||||
const res = killWorkerScriptByPid(script.pid, rerenderUi);
|
const res = killWorkerScriptByPid(params.runningScript.pid);
|
||||||
if (res) {
|
if (res) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If for some reason that doesn't work, we'll try the old way
|
// If for some reason that doesn't work, we'll try the old way
|
||||||
for (const ws of workerScripts.values()) {
|
for (const ws of workerScripts.values()) {
|
||||||
if (ws.name == script.filename && ws.hostname == hostname && compareArrays(ws.args, script.args)) {
|
if (
|
||||||
stopAndCleanUpWorkerScript(ws, rerenderUi);
|
ws.name == params.runningScript.filename &&
|
||||||
|
ws.hostname == params.hostname &&
|
||||||
|
compareArrays(ws.args, params.runningScript.args)
|
||||||
|
) {
|
||||||
|
stopAndCleanUpWorkerScript(ws);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
} else if (typeof script === "number") {
|
|
||||||
return killWorkerScriptByPid(script, rerenderUi);
|
|
||||||
} else {
|
|
||||||
console.error(`killWorkerScript() called with invalid argument:`);
|
|
||||||
console.error(script);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function killWorkerScriptByPid(pid: number, rerenderUi = true): boolean {
|
function killWorkerScriptByPid(pid: number): boolean {
|
||||||
const ws = workerScripts.get(pid);
|
const ws = workerScripts.get(pid);
|
||||||
if (ws instanceof WorkerScript) {
|
if (ws instanceof WorkerScript) {
|
||||||
stopAndCleanUpWorkerScript(ws, rerenderUi);
|
stopAndCleanUpWorkerScript(ws);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -68,20 +59,22 @@ function killWorkerScriptByPid(pid: number, rerenderUi = true): boolean {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopAndCleanUpWorkerScript(workerScript: WorkerScript, rerenderUi = true): void {
|
function stopAndCleanUpWorkerScript(workerScript: WorkerScript): void {
|
||||||
if (typeof workerScript.atExit === "function") {
|
if (typeof workerScript.atExit === "function") {
|
||||||
try {
|
try {
|
||||||
workerScript.atExit();
|
workerScript.atExit();
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
`Error trying to call atExit for script ${workerScript.name} on ${workerScript.hostname} ${workerScript.scriptRef.args} ${e}`,
|
`Error trying to call atExit for script ${workerScript.name} on ${workerScript.hostname} ${
|
||||||
|
workerScript.scriptRef.args
|
||||||
|
} ${String(e)}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
workerScript.atExit = undefined;
|
workerScript.atExit = undefined;
|
||||||
}
|
}
|
||||||
workerScript.env.stopFlag = true;
|
workerScript.env.stopFlag = true;
|
||||||
killNetscriptDelay(workerScript);
|
killNetscriptDelay(workerScript);
|
||||||
removeWorkerScript(workerScript, rerenderUi);
|
removeWorkerScript(workerScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,7 +84,7 @@ function stopAndCleanUpWorkerScript(workerScript: WorkerScript, rerenderUi = tru
|
|||||||
* @param {WorkerScript} - Identifier for WorkerScript. Either the object itself, or
|
* @param {WorkerScript} - Identifier for WorkerScript. Either the object itself, or
|
||||||
* its index in the global workerScripts array
|
* its index in the global workerScripts array
|
||||||
*/
|
*/
|
||||||
function removeWorkerScript(workerScript: WorkerScript, rerenderUi = true): void {
|
function removeWorkerScript(workerScript: WorkerScript): void {
|
||||||
const ip = workerScript.hostname;
|
const ip = workerScript.hostname;
|
||||||
const name = workerScript.name;
|
const name = workerScript.name;
|
||||||
|
|
||||||
@ -125,10 +118,8 @@ function removeWorkerScript(workerScript: WorkerScript, rerenderUi = true): void
|
|||||||
// }
|
// }
|
||||||
AddRecentScript(workerScript);
|
AddRecentScript(workerScript);
|
||||||
|
|
||||||
if (rerenderUi) {
|
|
||||||
WorkerScriptStartStopEventEmitter.emit();
|
WorkerScriptStartStopEventEmitter.emit();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function that interrupts a script's delay if it is in the middle of a
|
* Helper function that interrupts a script's delay if it is in the middle of a
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user