mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-19 12:45:45 +01:00
commit
dd7b5c4316
379
.eslintrc.js
379
.eslintrc.js
@ -7,7 +7,7 @@ module.exports = {
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
// "plugin:@typescript-eslint/recommended-requiring-type-checking",
|
||||
"plugin:@typescript-eslint/recommended-requiring-type-checking",
|
||||
],
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
@ -19,386 +19,9 @@ module.exports = {
|
||||
project: ["./tsconfig.json", "./test/tsconfig.json", "./tools/tsconfig.json", "./test/cypress/tsconfig.json"],
|
||||
},
|
||||
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"],
|
||||
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-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-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/styles": "^5.0.1",
|
||||
"@mui/system": "^5.0.3",
|
||||
"acorn": "^8.4.1",
|
||||
"acorn-walk": "^8.1.1",
|
||||
"@types/estree": "^1.0.0",
|
||||
"acorn": "^8.7.1",
|
||||
"acorn-walk": "^8.2.0",
|
||||
"arg": "^5.0.0",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"better-react-mathjax": "^1.0.3",
|
||||
@ -78,7 +79,7 @@
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"http-server": "^13.0.1",
|
||||
"jest": "^27.1.0",
|
||||
"jsdom": "^15.0.0",
|
||||
"jsdom": "^16.5.0",
|
||||
"lodash": "^4.17.21",
|
||||
"mini-css-extract-plugin": "^0.4.1",
|
||||
"prettier": "^2.3.2",
|
||||
|
@ -24,7 +24,7 @@ import { IMap } from "../types";
|
||||
import * as data from "./AchievementData.json";
|
||||
import { FactionNames } from "../Faction/data/FactionNames";
|
||||
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...
|
||||
const achievementData = (<AchievementDataJson>(<unknown>data)).achievements;
|
||||
@ -391,10 +391,7 @@ export const achievements: IMap<Achievement> = {
|
||||
WORKOUT: {
|
||||
...achievementData["WORKOUT"],
|
||||
Icon: "WORKOUT",
|
||||
Condition: () =>
|
||||
[ClassType.GymStrength, ClassType.GymDefense, ClassType.GymDexterity, ClassType.GymAgility].includes(
|
||||
Player.className,
|
||||
),
|
||||
Condition: () => isClassWork(Player.currentWork),
|
||||
},
|
||||
TOR: {
|
||||
...achievementData["TOR"],
|
||||
|
@ -9,7 +9,7 @@ const style = {
|
||||
width: "1060px",
|
||||
height: "800px",
|
||||
border: "0px",
|
||||
} as any;
|
||||
};
|
||||
|
||||
export function BBCabinetRoot(): React.ReactElement {
|
||||
const player = use.Player();
|
||||
|
@ -1,13 +1,12 @@
|
||||
// Class definition for a single Augmentation object
|
||||
import * as React from "react";
|
||||
import { IMap } from "../types";
|
||||
|
||||
import { Faction } from "../Faction/Faction";
|
||||
import { Factions } from "../Faction/Factions";
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
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 { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { AugmentationNames } from "./data/AugmentationNames";
|
||||
@ -16,6 +15,7 @@ import { StaticAugmentations } from "./StaticAugmentations";
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import { getBaseAugmentationPriceMultiplier, getGenericAugmentationPriceMultiplier } from "./AugmentationHelpers";
|
||||
import { initSoAAugmentations } from "./data/AugmentationCreator";
|
||||
import { Multipliers, defaultMultipliers } from "../PersonObjects/Multipliers";
|
||||
|
||||
export interface AugmentationCosts {
|
||||
moneyCost: number;
|
||||
@ -32,48 +32,48 @@ export interface IConstructorParams {
|
||||
repCost: number;
|
||||
factions: string[];
|
||||
|
||||
hacking_mult?: number;
|
||||
strength_mult?: number;
|
||||
defense_mult?: number;
|
||||
dexterity_mult?: number;
|
||||
agility_mult?: number;
|
||||
charisma_mult?: number;
|
||||
hacking_exp_mult?: number;
|
||||
strength_exp_mult?: number;
|
||||
defense_exp_mult?: number;
|
||||
dexterity_exp_mult?: number;
|
||||
agility_exp_mult?: number;
|
||||
charisma_exp_mult?: number;
|
||||
hacking_chance_mult?: number;
|
||||
hacking_speed_mult?: number;
|
||||
hacking_money_mult?: number;
|
||||
hacking_grow_mult?: number;
|
||||
company_rep_mult?: number;
|
||||
faction_rep_mult?: number;
|
||||
crime_money_mult?: number;
|
||||
crime_success_mult?: number;
|
||||
work_money_mult?: number;
|
||||
hacknet_node_money_mult?: number;
|
||||
hacknet_node_purchase_cost_mult?: number;
|
||||
hacknet_node_ram_cost_mult?: number;
|
||||
hacknet_node_core_cost_mult?: number;
|
||||
hacknet_node_level_cost_mult?: number;
|
||||
bladeburner_max_stamina_mult?: number;
|
||||
bladeburner_stamina_gain_mult?: number;
|
||||
bladeburner_analysis_mult?: number;
|
||||
bladeburner_success_chance_mult?: number;
|
||||
hacking?: number;
|
||||
strength?: number;
|
||||
defense?: number;
|
||||
dexterity?: number;
|
||||
agility?: number;
|
||||
charisma?: number;
|
||||
hacking_exp?: number;
|
||||
strength_exp?: number;
|
||||
defense_exp?: number;
|
||||
dexterity_exp?: number;
|
||||
agility_exp?: number;
|
||||
charisma_exp?: number;
|
||||
hacking_chance?: number;
|
||||
hacking_speed?: number;
|
||||
hacking_money?: number;
|
||||
hacking_grow?: number;
|
||||
company_rep?: number;
|
||||
faction_rep?: number;
|
||||
crime_money?: number;
|
||||
crime_success?: number;
|
||||
work_money?: number;
|
||||
hacknet_node_money?: number;
|
||||
hacknet_node_purchase_cost?: number;
|
||||
hacknet_node_ram_cost?: number;
|
||||
hacknet_node_core_cost?: number;
|
||||
hacknet_node_level_cost?: number;
|
||||
bladeburner_max_stamina?: number;
|
||||
bladeburner_stamina_gain?: number;
|
||||
bladeburner_analysis?: number;
|
||||
bladeburner_success_chance?: number;
|
||||
infiltration_base_rep_increase?: number;
|
||||
infiltration_rep_mult?: number;
|
||||
infiltration_trade_mult?: number;
|
||||
infiltration_sell_mult?: number;
|
||||
infiltration_timer_mult?: number;
|
||||
infiltration_damage_reduction_mult?: number;
|
||||
infiltration_rep?: number;
|
||||
infiltration_trade?: number;
|
||||
infiltration_sell?: number;
|
||||
infiltration_timer?: number;
|
||||
infiltration_damage_reduction?: number;
|
||||
|
||||
startingMoney?: number;
|
||||
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 => {
|
||||
// look, I don't know how to make a "smart decimals"
|
||||
// todo, make it smarter
|
||||
@ -84,323 +84,278 @@ function generateStatsDescription(mults: IMap<number>, programs?: string[], star
|
||||
let desc = <>Effects:</>;
|
||||
|
||||
if (
|
||||
mults.hacking_mult &&
|
||||
mults.hacking_mult == mults.strength_mult &&
|
||||
mults.hacking_mult == mults.defense_mult &&
|
||||
mults.hacking_mult == mults.dexterity_mult &&
|
||||
mults.hacking_mult == mults.agility_mult &&
|
||||
mults.hacking_mult == mults.charisma_mult
|
||||
mults.hacking !== 1 &&
|
||||
mults.hacking == mults.strength &&
|
||||
mults.hacking == mults.defense &&
|
||||
mults.hacking == mults.dexterity &&
|
||||
mults.hacking == mults.agility &&
|
||||
mults.hacking == mults.charisma
|
||||
) {
|
||||
desc = (
|
||||
<>
|
||||
{desc}
|
||||
<br />+{f(mults.hacking_mult - 1)} all skills
|
||||
<br />+{f(mults.hacking - 1)} all skills
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
if (mults.hacking_mult)
|
||||
if (mults.hacking !== 1)
|
||||
desc = (
|
||||
<>
|
||||
{desc}
|
||||
<br />+{f(mults.hacking_mult - 1)} hacking skill
|
||||
<br />+{f(mults.hacking - 1)} hacking skill
|
||||
</>
|
||||
);
|
||||
|
||||
if (
|
||||
mults.strength_mult &&
|
||||
mults.strength_mult == mults.defense_mult &&
|
||||
mults.strength_mult == mults.dexterity_mult &&
|
||||
mults.strength_mult == mults.agility_mult
|
||||
mults.strength !== 1 &&
|
||||
mults.strength == mults.defense &&
|
||||
mults.strength == mults.dexterity &&
|
||||
mults.strength == mults.agility
|
||||
) {
|
||||
desc = (
|
||||
<>
|
||||
{desc}
|
||||
<br />+{f(mults.strength_mult - 1)} combat skills
|
||||
<br />+{f(mults.strength - 1)} combat skills
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
if (mults.strength_mult)
|
||||
if (mults.strength !== 1)
|
||||
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}
|
||||
<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}
|
||||
<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}
|
||||
<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}
|
||||
<br />+{f(mults.charisma_mult - 1)} charisma skill
|
||||
<br />+{f(mults.charisma - 1)} charisma skill
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
mults.hacking_exp_mult &&
|
||||
mults.hacking_exp_mult === mults.strength_exp_mult &&
|
||||
mults.hacking_exp_mult === mults.defense_exp_mult &&
|
||||
mults.hacking_exp_mult === mults.dexterity_exp_mult &&
|
||||
mults.hacking_exp_mult === mults.agility_exp_mult &&
|
||||
mults.hacking_exp_mult === mults.charisma_exp_mult
|
||||
mults.hacking_exp !== 1 &&
|
||||
mults.hacking_exp === mults.strength_exp &&
|
||||
mults.hacking_exp === mults.defense_exp &&
|
||||
mults.hacking_exp === mults.dexterity_exp &&
|
||||
mults.hacking_exp === mults.agility_exp &&
|
||||
mults.hacking_exp === mults.charisma_exp
|
||||
) {
|
||||
desc = (
|
||||
<>
|
||||
{desc}
|
||||
<br />+{f(mults.hacking_exp_mult - 1)} exp for all skills
|
||||
<br />+{f(mults.hacking_exp - 1)} exp for all skills
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
if (mults.hacking_exp_mult)
|
||||
if (mults.hacking_exp !== 1)
|
||||
desc = (
|
||||
<>
|
||||
{desc}
|
||||
<br />+{f(mults.hacking_exp_mult - 1)} hacking exp
|
||||
<br />+{f(mults.hacking_exp - 1)} hacking exp
|
||||
</>
|
||||
);
|
||||
|
||||
if (
|
||||
mults.strength_exp_mult &&
|
||||
mults.strength_exp_mult === mults.defense_exp_mult &&
|
||||
mults.strength_exp_mult === mults.dexterity_exp_mult &&
|
||||
mults.strength_exp_mult === mults.agility_exp_mult
|
||||
mults.strength_exp !== 1 &&
|
||||
mults.strength_exp === mults.defense_exp &&
|
||||
mults.strength_exp === mults.dexterity_exp &&
|
||||
mults.strength_exp === mults.agility_exp
|
||||
) {
|
||||
desc = (
|
||||
<>
|
||||
{desc}
|
||||
<br />+{f(mults.strength_exp_mult - 1)} combat exp
|
||||
<br />+{f(mults.strength_exp - 1)} combat exp
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
if (mults.strength_exp_mult)
|
||||
if (mults.strength_exp !== 1)
|
||||
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}
|
||||
<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}
|
||||
<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}
|
||||
<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}
|
||||
<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}
|
||||
<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}
|
||||
<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}
|
||||
<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}
|
||||
<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}
|
||||
<br />+{f(mults.faction_rep_mult - 1)} reputation from factions and companies
|
||||
<br />+{f(mults.faction_rep - 1)} reputation from factions and companies
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
if (mults.faction_rep_mult)
|
||||
if (mults.faction_rep !== 1)
|
||||
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}
|
||||
<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}
|
||||
<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}
|
||||
<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}
|
||||
<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}
|
||||
<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}
|
||||
<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}
|
||||
<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}
|
||||
<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}
|
||||
<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}
|
||||
<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}
|
||||
<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)
|
||||
desc = (
|
||||
<>
|
||||
@ -445,7 +400,7 @@ export class Augmentation {
|
||||
|
||||
// Multipliers given by this Augmentation. Must match the property name in
|
||||
// The Player/Person classes
|
||||
mults: IMap<number> = {};
|
||||
mults: Multipliers = defaultMultipliers();
|
||||
|
||||
// Factions that offer this aug.
|
||||
factions: string[] = [];
|
||||
@ -474,114 +429,95 @@ export class Augmentation {
|
||||
}
|
||||
|
||||
// Set multipliers
|
||||
if (params.hacking_mult) {
|
||||
this.mults.hacking_mult = params.hacking_mult;
|
||||
if (params.hacking) {
|
||||
this.mults.hacking = params.hacking;
|
||||
}
|
||||
if (params.strength_mult) {
|
||||
this.mults.strength_mult = params.strength_mult;
|
||||
if (params.strength) {
|
||||
this.mults.strength = params.strength;
|
||||
}
|
||||
if (params.defense_mult) {
|
||||
this.mults.defense_mult = params.defense_mult;
|
||||
if (params.defense) {
|
||||
this.mults.defense = params.defense;
|
||||
}
|
||||
if (params.dexterity_mult) {
|
||||
this.mults.dexterity_mult = params.dexterity_mult;
|
||||
if (params.dexterity) {
|
||||
this.mults.dexterity = params.dexterity;
|
||||
}
|
||||
if (params.agility_mult) {
|
||||
this.mults.agility_mult = params.agility_mult;
|
||||
if (params.agility) {
|
||||
this.mults.agility = params.agility;
|
||||
}
|
||||
if (params.charisma_mult) {
|
||||
this.mults.charisma_mult = params.charisma_mult;
|
||||
if (params.charisma) {
|
||||
this.mults.charisma = params.charisma;
|
||||
}
|
||||
if (params.hacking_exp_mult) {
|
||||
this.mults.hacking_exp_mult = params.hacking_exp_mult;
|
||||
if (params.hacking_exp) {
|
||||
this.mults.hacking_exp = params.hacking_exp;
|
||||
}
|
||||
if (params.strength_exp_mult) {
|
||||
this.mults.strength_exp_mult = params.strength_exp_mult;
|
||||
if (params.strength_exp) {
|
||||
this.mults.strength_exp = params.strength_exp;
|
||||
}
|
||||
if (params.defense_exp_mult) {
|
||||
this.mults.defense_exp_mult = params.defense_exp_mult;
|
||||
if (params.defense_exp) {
|
||||
this.mults.defense_exp = params.defense_exp;
|
||||
}
|
||||
if (params.dexterity_exp_mult) {
|
||||
this.mults.dexterity_exp_mult = params.dexterity_exp_mult;
|
||||
if (params.dexterity_exp) {
|
||||
this.mults.dexterity_exp = params.dexterity_exp;
|
||||
}
|
||||
if (params.agility_exp_mult) {
|
||||
this.mults.agility_exp_mult = params.agility_exp_mult;
|
||||
if (params.agility_exp) {
|
||||
this.mults.agility_exp = params.agility_exp;
|
||||
}
|
||||
if (params.charisma_exp_mult) {
|
||||
this.mults.charisma_exp_mult = params.charisma_exp_mult;
|
||||
if (params.charisma_exp) {
|
||||
this.mults.charisma_exp = params.charisma_exp;
|
||||
}
|
||||
if (params.hacking_chance_mult) {
|
||||
this.mults.hacking_chance_mult = params.hacking_chance_mult;
|
||||
if (params.hacking_chance) {
|
||||
this.mults.hacking_chance = params.hacking_chance;
|
||||
}
|
||||
if (params.hacking_speed_mult) {
|
||||
this.mults.hacking_speed_mult = params.hacking_speed_mult;
|
||||
if (params.hacking_speed) {
|
||||
this.mults.hacking_speed = params.hacking_speed;
|
||||
}
|
||||
if (params.hacking_money_mult) {
|
||||
this.mults.hacking_money_mult = params.hacking_money_mult;
|
||||
if (params.hacking_money) {
|
||||
this.mults.hacking_money = params.hacking_money;
|
||||
}
|
||||
if (params.hacking_grow_mult) {
|
||||
this.mults.hacking_grow_mult = params.hacking_grow_mult;
|
||||
if (params.hacking_grow) {
|
||||
this.mults.hacking_grow = params.hacking_grow;
|
||||
}
|
||||
if (params.company_rep_mult) {
|
||||
this.mults.company_rep_mult = params.company_rep_mult;
|
||||
if (params.company_rep) {
|
||||
this.mults.company_rep = params.company_rep;
|
||||
}
|
||||
if (params.faction_rep_mult) {
|
||||
this.mults.faction_rep_mult = params.faction_rep_mult;
|
||||
if (params.faction_rep) {
|
||||
this.mults.faction_rep = params.faction_rep;
|
||||
}
|
||||
if (params.crime_money_mult) {
|
||||
this.mults.crime_money_mult = params.crime_money_mult;
|
||||
if (params.crime_money) {
|
||||
this.mults.crime_money = params.crime_money;
|
||||
}
|
||||
if (params.crime_success_mult) {
|
||||
this.mults.crime_success_mult = params.crime_success_mult;
|
||||
if (params.crime_success) {
|
||||
this.mults.crime_success = params.crime_success;
|
||||
}
|
||||
if (params.work_money_mult) {
|
||||
this.mults.work_money_mult = params.work_money_mult;
|
||||
if (params.work_money) {
|
||||
this.mults.work_money = params.work_money;
|
||||
}
|
||||
if (params.hacknet_node_money_mult) {
|
||||
this.mults.hacknet_node_money_mult = params.hacknet_node_money_mult;
|
||||
if (params.hacknet_node_money) {
|
||||
this.mults.hacknet_node_money = params.hacknet_node_money;
|
||||
}
|
||||
if (params.hacknet_node_purchase_cost_mult) {
|
||||
this.mults.hacknet_node_purchase_cost_mult = params.hacknet_node_purchase_cost_mult;
|
||||
if (params.hacknet_node_purchase_cost) {
|
||||
this.mults.hacknet_node_purchase_cost = params.hacknet_node_purchase_cost;
|
||||
}
|
||||
if (params.hacknet_node_ram_cost_mult) {
|
||||
this.mults.hacknet_node_ram_cost_mult = params.hacknet_node_ram_cost_mult;
|
||||
if (params.hacknet_node_ram_cost) {
|
||||
this.mults.hacknet_node_ram_cost = params.hacknet_node_ram_cost;
|
||||
}
|
||||
if (params.hacknet_node_core_cost_mult) {
|
||||
this.mults.hacknet_node_core_cost_mult = params.hacknet_node_core_cost_mult;
|
||||
if (params.hacknet_node_core_cost) {
|
||||
this.mults.hacknet_node_core_cost = params.hacknet_node_core_cost;
|
||||
}
|
||||
if (params.hacknet_node_level_cost_mult) {
|
||||
this.mults.hacknet_node_level_cost_mult = params.hacknet_node_level_cost_mult;
|
||||
if (params.hacknet_node_level_cost) {
|
||||
this.mults.hacknet_node_level_cost = params.hacknet_node_level_cost;
|
||||
}
|
||||
if (params.bladeburner_max_stamina_mult) {
|
||||
this.mults.bladeburner_max_stamina_mult = params.bladeburner_max_stamina_mult;
|
||||
if (params.bladeburner_max_stamina) {
|
||||
this.mults.bladeburner_max_stamina = params.bladeburner_max_stamina;
|
||||
}
|
||||
if (params.bladeburner_stamina_gain_mult) {
|
||||
this.mults.bladeburner_stamina_gain_mult = params.bladeburner_stamina_gain_mult;
|
||||
if (params.bladeburner_stamina_gain) {
|
||||
this.mults.bladeburner_stamina_gain = params.bladeburner_stamina_gain;
|
||||
}
|
||||
if (params.bladeburner_analysis_mult) {
|
||||
this.mults.bladeburner_analysis_mult = params.bladeburner_analysis_mult;
|
||||
if (params.bladeburner_analysis) {
|
||||
this.mults.bladeburner_analysis = params.bladeburner_analysis;
|
||||
}
|
||||
if (params.bladeburner_success_chance_mult) {
|
||||
this.mults.bladeburner_success_chance_mult = params.bladeburner_success_chance_mult;
|
||||
}
|
||||
|
||||
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.bladeburner_success_chance) {
|
||||
this.mults.bladeburner_success_chance = params.bladeburner_success_chance;
|
||||
}
|
||||
|
||||
if (params.stats === undefined)
|
||||
@ -673,13 +609,12 @@ export class Augmentation {
|
||||
}
|
||||
|
||||
// Serialize the current object to a JSON save state.
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("Augmentation", this);
|
||||
}
|
||||
|
||||
// Initiatizes a Augmentation object from a JSON save state.
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Augmentation {
|
||||
static fromJSON(value: IReviverValue): Augmentation {
|
||||
return Generic_fromJSON(Augmentation, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import {
|
||||
initUnstableCircadianModulator,
|
||||
} from "./data/AugmentationCreator";
|
||||
import { Router } from "../ui/GameRoot";
|
||||
import { mergeMultipliers } from "../PersonObjects/Multipliers";
|
||||
|
||||
export function AddToStaticAugmentations(aug: Augmentation): void {
|
||||
const name = aug.name;
|
||||
@ -74,10 +75,7 @@ function applyAugmentation(aug: IPlayerOwnedAugmentation, reapply = false): void
|
||||
const staticAugmentation = StaticAugmentations[aug.name];
|
||||
|
||||
// Apply multipliers
|
||||
for (const mult of Object.keys(staticAugmentation.mults)) {
|
||||
const v = Player.getMult(mult) * staticAugmentation.mults[mult];
|
||||
Player.setMult(mult, v);
|
||||
}
|
||||
Player.mults = mergeMultipliers(Player.mults, staticAugmentation.mults);
|
||||
|
||||
// Special logic for Congruity Implant
|
||||
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 { List, ListItem, ListItemText, Paper, Typography } from "@mui/material";
|
||||
import * as React from "react";
|
||||
import { Multipliers, defaultMultipliers, mergeMultipliers } from "../../PersonObjects/Multipliers";
|
||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||
import { Player } from "../../Player";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { StaticAugmentations } from "../StaticAugmentations";
|
||||
|
||||
interface IAugmentedStats {
|
||||
[index: string]: number;
|
||||
}
|
||||
|
||||
function calculateAugmentedStats(): IAugmentedStats {
|
||||
const augP: IAugmentedStats = {};
|
||||
function calculateAugmentedStats(): Multipliers {
|
||||
let augP: Multipliers = defaultMultipliers();
|
||||
for (const aug of Player.queuedAugmentations) {
|
||||
const augObj = StaticAugmentations[aug.name];
|
||||
for (const mult of Object.keys(augObj.mults)) {
|
||||
const v = augP[mult] ? augP[mult] : 1;
|
||||
augP[mult] = v * augObj.mults[mult];
|
||||
}
|
||||
augP = mergeMultipliers(augP, augObj.mults);
|
||||
}
|
||||
return augP;
|
||||
}
|
||||
@ -98,35 +92,35 @@ export function PlayerMultipliers(): React.ReactElement {
|
||||
...[
|
||||
{
|
||||
mult: "Hacking Chance",
|
||||
current: Player.hacking_chance_mult,
|
||||
augmented: Player.hacking_chance_mult * mults.hacking_chance_mult,
|
||||
current: Player.mults.hacking_chance,
|
||||
augmented: Player.mults.hacking_chance * mults.hacking_chance,
|
||||
},
|
||||
{
|
||||
mult: "Hacking Speed",
|
||||
current: Player.hacking_speed_mult,
|
||||
augmented: Player.hacking_speed_mult * mults.hacking_speed_mult,
|
||||
current: Player.mults.hacking_speed,
|
||||
augmented: Player.mults.hacking_speed * mults.hacking_speed,
|
||||
},
|
||||
{
|
||||
mult: "Hacking Money",
|
||||
current: Player.hacking_money_mult,
|
||||
augmented: Player.hacking_money_mult * mults.hacking_money_mult,
|
||||
current: Player.mults.hacking_money,
|
||||
augmented: Player.mults.hacking_money * mults.hacking_money,
|
||||
bnMult: BitNodeMultipliers.ScriptHackMoney,
|
||||
},
|
||||
{
|
||||
mult: "Hacking Growth",
|
||||
current: Player.hacking_grow_mult,
|
||||
augmented: Player.hacking_grow_mult * mults.hacking_grow_mult,
|
||||
current: Player.mults.hacking_grow,
|
||||
augmented: Player.mults.hacking_grow * mults.hacking_grow,
|
||||
},
|
||||
{
|
||||
mult: "Hacking Level",
|
||||
current: Player.hacking_mult,
|
||||
augmented: Player.hacking_mult * mults.hacking_mult,
|
||||
current: Player.mults.hacking,
|
||||
augmented: Player.mults.hacking * mults.hacking,
|
||||
bnMult: BitNodeMultipliers.HackingLevelMultiplier,
|
||||
},
|
||||
{
|
||||
mult: "Hacking Experience",
|
||||
current: Player.hacking_exp_mult,
|
||||
augmented: Player.hacking_exp_mult * mults.hacking_exp_mult,
|
||||
current: Player.mults.hacking_exp,
|
||||
augmented: Player.mults.hacking_exp * mults.hacking_exp,
|
||||
bnMult: BitNodeMultipliers.HackExpGain,
|
||||
},
|
||||
].map((data: MultiplierListItemData) =>
|
||||
@ -137,47 +131,47 @@ export function PlayerMultipliers(): React.ReactElement {
|
||||
...[
|
||||
{
|
||||
mult: "Strength Level",
|
||||
current: Player.strength_mult,
|
||||
augmented: Player.strength_mult * mults.strength_mult,
|
||||
current: Player.mults.strength,
|
||||
augmented: Player.mults.strength * mults.strength,
|
||||
bnMult: BitNodeMultipliers.StrengthLevelMultiplier,
|
||||
},
|
||||
{
|
||||
mult: "Strength Experience",
|
||||
current: Player.strength_exp_mult,
|
||||
augmented: Player.strength_exp_mult * mults.strength_exp_mult,
|
||||
current: Player.mults.strength_exp,
|
||||
augmented: Player.mults.strength_exp * mults.strength_exp,
|
||||
},
|
||||
{
|
||||
mult: "Defense Level",
|
||||
current: Player.defense_mult,
|
||||
augmented: Player.defense_mult * mults.defense_mult,
|
||||
current: Player.mults.defense,
|
||||
augmented: Player.mults.defense * mults.defense,
|
||||
bnMult: BitNodeMultipliers.DefenseLevelMultiplier,
|
||||
},
|
||||
{
|
||||
mult: "Defense Experience",
|
||||
current: Player.defense_exp_mult,
|
||||
augmented: Player.defense_exp_mult * mults.defense_exp_mult,
|
||||
current: Player.mults.defense_exp,
|
||||
augmented: Player.mults.defense_exp * mults.defense_exp,
|
||||
},
|
||||
{
|
||||
mult: "Dexterity Level",
|
||||
current: Player.dexterity_mult,
|
||||
augmented: Player.dexterity_mult * mults.dexterity_mult,
|
||||
current: Player.mults.dexterity,
|
||||
augmented: Player.mults.dexterity * mults.dexterity,
|
||||
bnMult: BitNodeMultipliers.DexterityLevelMultiplier,
|
||||
},
|
||||
{
|
||||
mult: "Dexterity Experience",
|
||||
current: Player.dexterity_exp_mult,
|
||||
augmented: Player.dexterity_exp_mult * mults.dexterity_exp_mult,
|
||||
current: Player.mults.dexterity_exp,
|
||||
augmented: Player.mults.dexterity_exp * mults.dexterity_exp,
|
||||
},
|
||||
{
|
||||
mult: "Agility Level",
|
||||
current: Player.agility_mult,
|
||||
augmented: Player.agility_mult * mults.agility_mult,
|
||||
current: Player.mults.agility,
|
||||
augmented: Player.mults.agility * mults.agility,
|
||||
bnMult: BitNodeMultipliers.AgilityLevelMultiplier,
|
||||
},
|
||||
{
|
||||
mult: "Agility Experience",
|
||||
current: Player.agility_exp_mult,
|
||||
augmented: Player.agility_exp_mult * mults.agility_exp_mult,
|
||||
current: Player.mults.agility_exp,
|
||||
augmented: Player.mults.agility_exp * mults.agility_exp,
|
||||
},
|
||||
].map((data: MultiplierListItemData) =>
|
||||
Object.defineProperty(data, "color", {
|
||||
@ -186,73 +180,73 @@ export function PlayerMultipliers(): React.ReactElement {
|
||||
),
|
||||
{
|
||||
mult: "Charisma Level",
|
||||
current: Player.charisma_mult,
|
||||
augmented: Player.charisma_mult * mults.charisma_mult,
|
||||
current: Player.mults.charisma,
|
||||
augmented: Player.mults.charisma * mults.charisma,
|
||||
bnMult: BitNodeMultipliers.CharismaLevelMultiplier,
|
||||
color: Settings.theme.cha,
|
||||
},
|
||||
{
|
||||
mult: "Charisma Experience",
|
||||
current: Player.charisma_exp_mult,
|
||||
augmented: Player.charisma_exp_mult * mults.charisma_exp_mult,
|
||||
current: Player.mults.charisma_exp,
|
||||
augmented: Player.mults.charisma_exp * mults.charisma_exp,
|
||||
color: Settings.theme.cha,
|
||||
},
|
||||
];
|
||||
const rightColData: MultiplierListItemData[] = [
|
||||
{
|
||||
mult: "Hacknet Node Production",
|
||||
current: Player.hacknet_node_money_mult,
|
||||
augmented: Player.hacknet_node_money_mult * mults.hacknet_node_money_mult,
|
||||
current: Player.mults.hacknet_node_money,
|
||||
augmented: Player.mults.hacknet_node_money * mults.hacknet_node_money,
|
||||
bnMult: BitNodeMultipliers.HacknetNodeMoney,
|
||||
},
|
||||
{
|
||||
mult: "Hacknet Node Purchase Cost",
|
||||
current: Player.hacknet_node_purchase_cost_mult,
|
||||
augmented: Player.hacknet_node_purchase_cost_mult * mults.hacknet_node_purchase_cost_mult,
|
||||
current: Player.mults.hacknet_node_purchase_cost,
|
||||
augmented: Player.mults.hacknet_node_purchase_cost * mults.hacknet_node_purchase_cost,
|
||||
},
|
||||
{
|
||||
mult: "Hacknet Node RAM Upgrade Cost",
|
||||
current: Player.hacknet_node_ram_cost_mult,
|
||||
augmented: Player.hacknet_node_ram_cost_mult * mults.hacknet_node_ram_cost_mult,
|
||||
current: Player.mults.hacknet_node_ram_cost,
|
||||
augmented: Player.mults.hacknet_node_ram_cost * mults.hacknet_node_ram_cost,
|
||||
},
|
||||
{
|
||||
mult: "Hacknet Node Core Purchase Cost",
|
||||
current: Player.hacknet_node_core_cost_mult,
|
||||
augmented: Player.hacknet_node_core_cost_mult * mults.hacknet_node_core_cost_mult,
|
||||
current: Player.mults.hacknet_node_core_cost,
|
||||
augmented: Player.mults.hacknet_node_core_cost * mults.hacknet_node_core_cost,
|
||||
},
|
||||
{
|
||||
mult: "Hacknet Node Level Upgrade Cost",
|
||||
current: Player.hacknet_node_level_cost_mult,
|
||||
augmented: Player.hacknet_node_level_cost_mult * mults.hacknet_node_level_cost_mult,
|
||||
current: Player.mults.hacknet_node_level_cost,
|
||||
augmented: Player.mults.hacknet_node_level_cost * mults.hacknet_node_level_cost,
|
||||
},
|
||||
{
|
||||
mult: "Company Reputation Gain",
|
||||
current: Player.company_rep_mult,
|
||||
augmented: Player.company_rep_mult * mults.company_rep_mult,
|
||||
current: Player.mults.company_rep,
|
||||
augmented: Player.mults.company_rep * mults.company_rep,
|
||||
},
|
||||
{
|
||||
mult: "Faction Reputation Gain",
|
||||
current: Player.faction_rep_mult,
|
||||
augmented: Player.faction_rep_mult * mults.faction_rep_mult,
|
||||
current: Player.mults.faction_rep,
|
||||
augmented: Player.mults.faction_rep * mults.faction_rep,
|
||||
bnMult: BitNodeMultipliers.FactionWorkRepGain,
|
||||
},
|
||||
{
|
||||
mult: "Salary",
|
||||
current: Player.work_money_mult,
|
||||
augmented: Player.work_money_mult * mults.work_money_mult,
|
||||
current: Player.mults.work_money,
|
||||
augmented: Player.mults.work_money * mults.work_money,
|
||||
bnMult: BitNodeMultipliers.CompanyWorkMoney,
|
||||
color: Settings.theme.money,
|
||||
},
|
||||
{
|
||||
mult: "Crime Success Chance",
|
||||
current: Player.crime_success_mult,
|
||||
augmented: Player.crime_success_mult * mults.crime_success_mult,
|
||||
current: Player.mults.crime_success,
|
||||
augmented: Player.mults.crime_success * mults.crime_success,
|
||||
color: Settings.theme.combat,
|
||||
},
|
||||
{
|
||||
mult: "Crime Money",
|
||||
current: Player.crime_money_mult,
|
||||
augmented: Player.crime_money_mult * mults.crime_money_mult,
|
||||
current: Player.mults.crime_money,
|
||||
augmented: Player.mults.crime_money * mults.crime_money,
|
||||
bnMult: BitNodeMultipliers.CrimeMoney,
|
||||
color: Settings.theme.money,
|
||||
},
|
||||
@ -262,23 +256,23 @@ export function PlayerMultipliers(): React.ReactElement {
|
||||
rightColData.push(
|
||||
{
|
||||
mult: "Bladeburner Success Chance",
|
||||
current: Player.bladeburner_success_chance_mult,
|
||||
augmented: Player.bladeburner_success_chance_mult * mults.bladeburner_success_chance_mult,
|
||||
current: Player.mults.bladeburner_success_chance,
|
||||
augmented: Player.mults.bladeburner_success_chance * mults.bladeburner_success_chance,
|
||||
},
|
||||
{
|
||||
mult: "Bladeburner Max Stamina",
|
||||
current: Player.bladeburner_max_stamina_mult,
|
||||
augmented: Player.bladeburner_max_stamina_mult * mults.bladeburner_max_stamina_mult,
|
||||
current: Player.mults.bladeburner_max_stamina,
|
||||
augmented: Player.mults.bladeburner_max_stamina * mults.bladeburner_max_stamina,
|
||||
},
|
||||
{
|
||||
mult: "Bladeburner Stamina Gain",
|
||||
current: Player.bladeburner_stamina_gain_mult,
|
||||
augmented: Player.bladeburner_stamina_gain_mult * mults.bladeburner_stamina_gain_mult,
|
||||
current: Player.mults.bladeburner_stamina_gain,
|
||||
augmented: Player.mults.bladeburner_stamina_gain * mults.bladeburner_stamina_gain,
|
||||
},
|
||||
{
|
||||
mult: "Bladeburner Field Analysis",
|
||||
current: Player.bladeburner_analysis_mult,
|
||||
augmented: Player.bladeburner_analysis_mult * mults.bladeburner_analysis_mult,
|
||||
current: Player.mults.bladeburner_analysis,
|
||||
augmented: Player.mults.bladeburner_analysis * mults.bladeburner_analysis,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ interface IBNMultTableProps {
|
||||
|
||||
const BNMultTable = (props: IBNMultTableProps): React.ReactElement => {
|
||||
const rowsArray = Object.entries(props.rowData)
|
||||
.filter(([key, _value]) => props.mults[key] !== defaultMultipliers[key])
|
||||
.filter(([key]) => props.mults[key] !== defaultMultipliers[key])
|
||||
.map(([key, value]) => (
|
||||
<StatsRow
|
||||
key={uniqueId()}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Player } from "../Player";
|
||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||
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 { IBladeburner } from "./IBladeburner";
|
||||
import { IAction, ISuccessChanceParams } from "./IAction";
|
||||
@ -274,7 +274,7 @@ export class Action implements IAction {
|
||||
}
|
||||
|
||||
// Augmentation multiplier
|
||||
competence *= Player.bladeburner_success_chance_mult;
|
||||
competence *= Player.mults.bladeburner_success_chance;
|
||||
|
||||
if (isNaN(competence)) {
|
||||
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);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Action {
|
||||
static fromJSON(value: IReviverValue): Action {
|
||||
return Generic_fromJSON(Action, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 {
|
||||
name?: string;
|
||||
@ -15,12 +15,11 @@ export class ActionIdentifier implements IActionIdentifier {
|
||||
if (params.type) this.type = params.type;
|
||||
}
|
||||
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("ActionIdentifier", this);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): ActionIdentifier {
|
||||
static fromJSON(value: IReviverValue): ActionIdentifier {
|
||||
return Generic_fromJSON(ActionIdentifier, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 {
|
||||
constructor(params: IOperationParams | null = null) {
|
||||
@ -20,12 +20,11 @@ export class BlackOperation extends Operation {
|
||||
return 1;
|
||||
}
|
||||
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("BlackOperation", this);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Operation {
|
||||
static fromJSON(value: IReviverValue): Operation {
|
||||
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 { IActionIdentifier } from "./IActionIdentifier";
|
||||
import { ActionIdentifier } from "./ActionIdentifier";
|
||||
@ -178,7 +178,7 @@ export class Bladeburner implements IBladeburner {
|
||||
return this.resetAction();
|
||||
}
|
||||
this.actionTimeToComplete = action.getActionTime(this, person);
|
||||
} catch (e: any) {
|
||||
} catch (e: unknown) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
break;
|
||||
@ -195,7 +195,7 @@ export class Bladeburner implements IBladeburner {
|
||||
return this.resetAction();
|
||||
}
|
||||
this.actionTimeToComplete = action.getActionTime(this, person);
|
||||
} catch (e: any) {
|
||||
} catch (e: unknown) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
break;
|
||||
@ -213,7 +213,7 @@ export class Bladeburner implements IBladeburner {
|
||||
throw new Error("action should not be null");
|
||||
}
|
||||
this.actionTimeToComplete = testBlackOp.action.getActionTime(this, person);
|
||||
} catch (e: any) {
|
||||
} catch (e: unknown) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
break;
|
||||
@ -264,7 +264,7 @@ export class Bladeburner implements IBladeburner {
|
||||
for (let i = 0; i < arrayOfCommands.length; ++i) {
|
||||
this.executeConsoleCommand(player, arrayOfCommands[i]);
|
||||
}
|
||||
} catch (e: any) {
|
||||
} catch (e: unknown) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
}
|
||||
@ -794,21 +794,9 @@ export class Bladeburner implements IBladeburner {
|
||||
let i = 0;
|
||||
while (i < command.length) {
|
||||
const c = command.charAt(i);
|
||||
if (c === '"') {
|
||||
// Double quotes
|
||||
const endQuote = command.indexOf('"', 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 (c === '"' || c === "'") {
|
||||
// Double quotes or Single quotes
|
||||
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) {
|
||||
@ -1367,7 +1355,7 @@ export class Bladeburner implements IBladeburner {
|
||||
if (action.autoLevel) {
|
||||
action.level = action.maxLevel;
|
||||
} // Autolevel
|
||||
} catch (e: any) {
|
||||
} catch (e: unknown) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
break;
|
||||
@ -1462,17 +1450,17 @@ export class Bladeburner implements IBladeburner {
|
||||
this.log(`${person.whoAmI()}: You lost ${formatNumber(losses, 0)} team members during ${action.name}`);
|
||||
}
|
||||
}
|
||||
} catch (e: any) {
|
||||
} catch (e: unknown) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ActionTypes["Training"]: {
|
||||
this.stamina -= 0.5 * BladeburnerConstants.BaseStaminaLoss;
|
||||
const strExpGain = 30 * person.strength_exp_mult,
|
||||
defExpGain = 30 * person.defense_exp_mult,
|
||||
dexExpGain = 30 * person.dexterity_exp_mult,
|
||||
agiExpGain = 30 * person.agility_exp_mult,
|
||||
const strExpGain = 30 * person.mults.strength_exp,
|
||||
defExpGain = 30 * person.mults.defense_exp,
|
||||
dexExpGain = 30 * person.mults.dexterity_exp,
|
||||
agiExpGain = 30 * person.mults.agility_exp,
|
||||
staminaGain = 0.04 * this.skillMultipliers.stamina;
|
||||
retValue.str = strExpGain;
|
||||
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.intelligence, 0.9) +
|
||||
0.02 * Math.pow(person.charisma, 0.3);
|
||||
eff *= person.bladeburner_analysis_mult;
|
||||
eff *= person.mults.bladeburner_analysis;
|
||||
if (isNaN(eff) || eff < 0) {
|
||||
throw new Error("Field Analysis Effectiveness calculated to be NaN or negative");
|
||||
}
|
||||
const hackingExpGain = 20 * person.hacking_exp_mult;
|
||||
const charismaExpGain = 20 * person.charisma_exp_mult;
|
||||
const hackingExpGain = 20 * person.mults.hacking_exp;
|
||||
const charismaExpGain = 20 * person.mults.charisma_exp;
|
||||
const rankGain = 0.1 * BitNodeMultipliers.BladeburnerRank;
|
||||
retValue.hack = hackingExpGain;
|
||||
retValue.cha = charismaExpGain;
|
||||
@ -1647,7 +1635,7 @@ export class Bladeburner implements IBladeburner {
|
||||
if (bladeburnerFac.isMember) {
|
||||
const favorBonus = 1 + bladeburnerFac.favor / 100;
|
||||
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 maxStaminaBonus = this.maxStamina / BladeburnerConstants.MaxStaminaToGainFactor;
|
||||
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 {
|
||||
@ -1703,7 +1691,7 @@ export class Bladeburner implements IBladeburner {
|
||||
const maxStamina =
|
||||
(Math.pow(effAgility, 0.8) + this.staminaBonus) *
|
||||
this.skillMultipliers.stamina *
|
||||
player.bladeburner_max_stamina_mult;
|
||||
player.mults.bladeburner_max_stamina;
|
||||
if (this.maxStamina !== maxStamina) {
|
||||
const oldMax = this.maxStamina;
|
||||
this.maxStamina = maxStamina;
|
||||
@ -1988,7 +1976,7 @@ export class Bladeburner implements IBladeburner {
|
||||
if (!router.isInitialized) return;
|
||||
|
||||
// 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"]) {
|
||||
let msg = "Your Bladeburner action was cancelled because you started doing something else.";
|
||||
if (this.automateEnabled) {
|
||||
@ -2154,7 +2142,8 @@ export class Bladeburner implements IBladeburner {
|
||||
() => `Starting bladeburner action with type '${type}' and name '${name}'`,
|
||||
);
|
||||
return true;
|
||||
} catch (e: any) {
|
||||
} catch (e: unknown) {
|
||||
console.error(e);
|
||||
this.resetAction();
|
||||
workerScript.log("bladeburner.startAction", () => errorLogText);
|
||||
return false;
|
||||
@ -2409,15 +2398,14 @@ export class Bladeburner implements IBladeburner {
|
||||
/**
|
||||
* Serialize the current object to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("Bladeburner", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiatizes a Bladeburner object from a JSON save state.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Bladeburner {
|
||||
static fromJSON(value: IReviverValue): Bladeburner {
|
||||
return Generic_fromJSON(Bladeburner, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { BladeburnerConstants } from "./data/Constants";
|
||||
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";
|
||||
|
||||
interface IChangePopulationByCountParams {
|
||||
@ -177,15 +177,14 @@ export class City {
|
||||
/**
|
||||
* Serialize the current object to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("City", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiatizes a City object from a JSON save state.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): City {
|
||||
static fromJSON(value: IReviverValue): City {
|
||||
return Generic_fromJSON(City, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { IBladeburner } from "./IBladeburner";
|
||||
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 {
|
||||
constructor(params: IActionParams | null = null) {
|
||||
@ -11,12 +11,11 @@ export class Contract extends Action {
|
||||
return inst.skillMultipliers.successChanceContract;
|
||||
}
|
||||
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("Contract", this);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Contract {
|
||||
static fromJSON(value: IReviverValue): Contract {
|
||||
return Generic_fromJSON(Contract, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { IReviverValue } from "../utils/JSONReviver";
|
||||
import { IPerson } from "../PersonObjects/IPerson";
|
||||
import { IBladeburner } from "./IBladeburner";
|
||||
|
||||
@ -67,5 +68,5 @@ export interface IAction {
|
||||
getSuccessChance(inst: IBladeburner, person: IPerson, params: ISuccessChanceParams): number;
|
||||
getSuccessesNeededForNextLevel(baseSuccessesPerLevel: number): number;
|
||||
setMaxLevel(baseSuccessesPerLevel: number): void;
|
||||
toJSON(): any;
|
||||
toJSON(): IReviverValue;
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ import { IPerson } from "../PersonObjects/IPerson";
|
||||
import { ITaskTracker } from "../PersonObjects/ITaskTracker";
|
||||
import { IRouter } from "../ui/Router";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { Contract } from "./Contract";
|
||||
import { Operation } from "./Operation";
|
||||
|
||||
export interface IBladeburner {
|
||||
numHosp: number;
|
||||
@ -31,17 +33,23 @@ export interface IBladeburner {
|
||||
|
||||
action: IActionIdentifier;
|
||||
|
||||
cities: any;
|
||||
cities: Record<string, City>;
|
||||
city: string;
|
||||
skills: any;
|
||||
skillMultipliers: any;
|
||||
skills: Record<string, number>;
|
||||
skillMultipliers: Record<string, number>;
|
||||
staminaBonus: number;
|
||||
maxStamina: number;
|
||||
stamina: number;
|
||||
contracts: any;
|
||||
operations: any;
|
||||
blackops: any;
|
||||
logging: any;
|
||||
contracts: Record<string, Contract>;
|
||||
operations: Record<string, Operation>;
|
||||
blackops: Record<string, boolean>;
|
||||
logging: {
|
||||
general: boolean;
|
||||
contracts: boolean;
|
||||
ops: boolean;
|
||||
blackops: boolean;
|
||||
events: boolean;
|
||||
};
|
||||
automateEnabled: boolean;
|
||||
automateActionHigh: IActionIdentifier;
|
||||
automateThreshHigh: number;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { IBladeburner } from "./IBladeburner";
|
||||
import { BladeburnerConstants } from "./data/Constants";
|
||||
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 {
|
||||
reqdRank?: number;
|
||||
@ -44,12 +44,11 @@ export class Operation extends Action {
|
||||
return 1;
|
||||
}
|
||||
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("Operation", this);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Operation {
|
||||
static fromJSON(value: IReviverValue): Operation {
|
||||
return Generic_fromJSON(Operation, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import makeStyles from "@mui/styles/makeStyles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
|
||||
interface ILineProps {
|
||||
content: any;
|
||||
content: React.ReactNode;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
@ -197,7 +197,7 @@ function Logs({ entries }: ILogProps): React.ReactElement {
|
||||
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
@ -9,9 +9,10 @@ import Box from "@mui/material/Box";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import AddIcon from "@mui/icons-material/Add";
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import { Skill } from "../Skill";
|
||||
|
||||
interface IProps {
|
||||
skill: any;
|
||||
skill: Skill;
|
||||
bladeburner: IBladeburner;
|
||||
onUpgrade: () => void;
|
||||
}
|
||||
|
@ -12,8 +12,8 @@ export function SkillPage(props: IProps): React.ReactElement {
|
||||
const setRerender = useState(false)[1];
|
||||
const mults = props.bladeburner.skillMultipliers;
|
||||
|
||||
function valid(mult: any): boolean {
|
||||
return mult && mult !== 1;
|
||||
function valid(mult: number | undefined): boolean {
|
||||
return mult !== undefined && mult !== 1;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -33,7 +33,7 @@ export function StartButton(props: IProps): React.ReactElement {
|
||||
if (disabled) return;
|
||||
props.bladeburner.action.type = props.type;
|
||||
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.rerender();
|
||||
}
|
||||
|
@ -173,13 +173,13 @@ export function Stats(props: IProps): React.ReactElement {
|
||||
<Typography>Skill Points: {formatNumber(props.bladeburner.skillPoints, 0)}</Typography>
|
||||
<br />
|
||||
<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 />
|
||||
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 />
|
||||
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 />
|
||||
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>
|
||||
</Box>
|
||||
</Paper>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import * as React from "react";
|
||||
|
||||
export function trusted(f: () => void): (event: React.MouseEvent<HTMLElement, MouseEvent>) => any {
|
||||
return function (event: React.MouseEvent<HTMLElement, MouseEvent>): any {
|
||||
export function trusted(f: () => void): (event: React.MouseEvent<HTMLElement, MouseEvent>) => void {
|
||||
return function (event: React.MouseEvent<HTMLElement, MouseEvent>): void {
|
||||
if (!event.isTrusted) return;
|
||||
f();
|
||||
};
|
||||
|
@ -2,7 +2,7 @@ import { codingContractTypesMetadata, DescriptionFunc, GeneratorFunc, SolverFunc
|
||||
|
||||
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";
|
||||
|
||||
/* tslint:disable:no-magic-numbers completed-docs max-classes-per-file no-console */
|
||||
@ -106,7 +106,7 @@ export interface ICodingContractReward {
|
||||
*/
|
||||
export class CodingContract {
|
||||
/* Relevant data for the contract's problem */
|
||||
data: any;
|
||||
data: unknown;
|
||||
|
||||
/* Contract's filename */
|
||||
fn: string;
|
||||
@ -137,7 +137,7 @@ export class CodingContract {
|
||||
this.reward = reward;
|
||||
}
|
||||
|
||||
getData(): any {
|
||||
getData(): unknown {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
@ -186,15 +186,14 @@ export class CodingContract {
|
||||
/**
|
||||
* Serialize the current file to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("CodingContract", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiatizes a CodingContract from a JSON save state.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): CodingContract {
|
||||
static fromJSON(value: IReviverValue): CodingContract {
|
||||
return Generic_fromJSON(CodingContract, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import { favorToRep, repToFavor } from "../Faction/formulas/favor";
|
||||
|
||||
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 {
|
||||
name: string;
|
||||
@ -151,15 +151,14 @@ export class Company {
|
||||
/**
|
||||
* Serialize the current object to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("Company", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiatizes a Company from a JSON save state.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Company {
|
||||
static fromJSON(value: IReviverValue): Company {
|
||||
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
|
||||
LatestUpdate: string;
|
||||
} = {
|
||||
VersionString: "1.7.0",
|
||||
VersionNumber: 19,
|
||||
VersionString: "2.0.0",
|
||||
VersionNumber: 21,
|
||||
|
||||
// Speed (in ms) at which the main loop is updated
|
||||
_idleSpeed: 200,
|
||||
@ -104,7 +104,7 @@ export const CONSTANTS: {
|
||||
MilliPerCycle: 200,
|
||||
|
||||
// How much reputation is needed to join a megacorporation's faction
|
||||
CorpFactionRepRequirement: 200e3,
|
||||
CorpFactionRepRequirement: 400e3,
|
||||
|
||||
// Base RAM costs
|
||||
BaseCostFor1GBOfRamHome: 32000,
|
||||
@ -229,171 +229,54 @@ export const CONSTANTS: {
|
||||
|
||||
InfiniteLoopLimit: 2000,
|
||||
|
||||
Donations: 20,
|
||||
Donations: 21,
|
||||
|
||||
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)
|
||||
- [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)
|
||||
API breaks
|
||||
|
||||
#### 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)
|
||||
- allbuild commit 7f9e3775 (by @hydroflame) - [791c19c](https://github.com/danielyxie/bitburner/commit/791c19c4fe447c9231bfb423b9fc48114e783b43)
|
||||
- allbuild commit bcbda22a (by @hydroflame) - [032c440](https://github.com/danielyxie/bitburner/commit/032c440eaeb069eecd720ec2f8e069f705a0c1b4)
|
||||
- fix documentation for getDarkwebPrograms (by @hydroflame) - [4056956](https://github.com/danielyxie/bitburner/commit/4056956c2ada37946333bdad44cb0b6eb3909bf8)
|
||||
- support ASNI (by @hydroflame) - [36c7ef1](https://github.com/danielyxie/bitburner/commit/36c7ef1ad7ea8bb69fca23bce5883a3c2e23f1e0)
|
||||
- allbuild commit 22b6d0d5 (by @hydroflame) - [b46718d](https://github.com/danielyxie/bitburner/commit/b46718d188880ecf716ae045861d81d61e00af4b)
|
||||
- allbuild commit 36c7ef1a (by @hydroflame) - [d0ebf5e](https://github.com/danielyxie/bitburner/commit/d0ebf5e14e0498cb063fde35d63c9f59f2c01e35)
|
||||
- Update documentation for employee (by @hydroflame) - [100e81c](https://github.com/danielyxie/bitburner/commit/100e81c8ab4a408f74cc9bd9ffe2b8bad3d03462)
|
||||
- allbuild commit c799b291 (by @hydroflame) - [f5f5879](https://github.com/danielyxie/bitburner/commit/f5f5879fc380678d978e2b0a29ba7b6f0b4c9ec0)
|
||||
- ideas (by @hydroflame) - [0121fee](https://github.com/danielyxie/bitburner/commit/0121fee6e4c690d01650d1e68a80ea363bb48bce)
|
||||
- allbuild commit 0121fee6 (by @hydroflame) - [5c417e9](https://github.com/danielyxie/bitburner/commit/5c417e9b4df236df8bf3e2f8262b7bce87c934df)
|
||||
- Update codebase for stanek (by @hydroflame) - [c2b4a5b](https://github.com/danielyxie/bitburner/commit/c2b4a5b52a2162d2e49c7317b0a60a349984eb47)
|
||||
- fix lint (by @hydroflame) - [4cc518f](https://github.com/danielyxie/bitburner/commit/4cc518f37723aafb3168b64cd689408afdb74877)
|
||||
- Fix (by @hydroflame) - [9af553f](https://github.com/danielyxie/bitburner/commit/9af553f63cb1380795550648b0134b608564fab8)
|
||||
- Fix stanek leaking classes (by @hydroflame) - [fda3f02](https://github.com/danielyxie/bitburner/commit/fda3f02d73dba27034128c9be5e810a51e475e38)
|
||||
- fix conflicts (by @hydroflame) - [ca1a2aa](https://github.com/danielyxie/bitburner/commit/ca1a2aad333fa838b6d0e57f89e1cedba086a4a0)
|
||||
- Nerf noodle bar.
|
||||
Multipliers
|
||||
|
||||
* The main player object was also plagues with a million fields all called '*_mult'. Representing the different multipliers
|
||||
* These have been refactored in a field called 'mults'.
|
||||
|
||||
Misc.
|
||||
|
||||
* Nerf noodle bar, obviously.
|
||||
|
||||
`,
|
||||
};
|
||||
|
@ -11,7 +11,7 @@ import { LiteratureNames } from "../Literature/data/LiteratureNames";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
|
||||
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";
|
||||
|
||||
interface IParams {
|
||||
@ -433,15 +433,14 @@ export class Corporation {
|
||||
/**
|
||||
* Serialize the current object to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("Corporation", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiatizes a Corporation object from a JSON save state.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Corporation {
|
||||
static fromJSON(value: IReviverValue): Corporation {
|
||||
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
|
||||
const AllCorporationStates: string[] = ["START", "PURCHASE", "PRODUCTION", "SALE", "EXPORT"];
|
||||
@ -28,13 +28,12 @@ export class CorporationState {
|
||||
}
|
||||
|
||||
// Serialize the current object to a JSON save state.
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("CorporationState", this);
|
||||
}
|
||||
|
||||
// Initiatizes a CorporationState object from a JSON save state.
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): CorporationState {
|
||||
static fromJSON(value: IReviverValue): CorporationState {
|
||||
return Generic_fromJSON(CorporationState, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { CorporationConstants } from "./data/Constants";
|
||||
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 { ICorporation } from "./ICorporation";
|
||||
import { IIndustry } from "./IIndustry";
|
||||
@ -113,12 +113,11 @@ export class Employee {
|
||||
return prodBase * prodMult;
|
||||
}
|
||||
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("Employee", this);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Employee {
|
||||
static fromJSON(value: IReviverValue): Employee {
|
||||
return Generic_fromJSON(Employee, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { CorporationUnlockUpgrade } from "./data/CorporationUnlockUpgrades";
|
||||
import { CorporationUpgrade } from "./data/CorporationUpgrades";
|
||||
import { CorporationState } from "./CorporationState";
|
||||
import { IReviverValue } from "../utils/JSONReviver";
|
||||
|
||||
export interface ICorporation {
|
||||
name: string;
|
||||
@ -56,5 +57,5 @@ export interface ICorporation {
|
||||
getStarterGuide(player: IPlayer): void;
|
||||
updateDividendTax(): void;
|
||||
getCycleDividends(): number;
|
||||
toJSON(): any;
|
||||
toJSON(): IReviverValue;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { Warehouse } from "./Warehouse";
|
||||
import { ICorporation } from "./ICorporation";
|
||||
import { OfficeSpace } from "./OfficeSpace";
|
||||
import { Product } from "./Product";
|
||||
import { IReviverValue } from "../utils/JSONReviver";
|
||||
|
||||
export interface IIndustry {
|
||||
name: string;
|
||||
@ -72,5 +73,5 @@ export interface IIndustry {
|
||||
getSalesMultiplier(): number;
|
||||
getScientificResearchMultiplier(): 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 { Industries, IndustryStartingCosts, IndustryResearchTrees } from "./IndustryData";
|
||||
import { CorporationConstants } from "./data/Constants";
|
||||
@ -1403,15 +1403,14 @@ export class Industry implements IIndustry {
|
||||
/**
|
||||
* Serialize the current object to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("Industry", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiatizes a Industry object from a JSON save state.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Industry {
|
||||
static fromJSON(value: IReviverValue): Industry {
|
||||
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";
|
||||
|
||||
interface IConstructorParams {
|
||||
@ -229,13 +229,12 @@ export class Material {
|
||||
}
|
||||
|
||||
// Serialize the current object to a JSON save state.
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("Material", this);
|
||||
}
|
||||
|
||||
// Initiatizes a Material object from a JSON save state.
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Material {
|
||||
static fromJSON(value: IReviverValue): Material {
|
||||
return Generic_fromJSON(Material, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { EmployeePositions } from "./EmployeePositions";
|
||||
import { CorporationConstants } from "./data/Constants";
|
||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||
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 { IIndustry } from "./IIndustry";
|
||||
import { ICorporation } from "./ICorporation";
|
||||
@ -277,12 +277,11 @@ export class OfficeSpace {
|
||||
return false;
|
||||
}
|
||||
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("OfficeSpace", this);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): OfficeSpace {
|
||||
static fromJSON(value: IReviverValue): OfficeSpace {
|
||||
return Generic_fromJSON(OfficeSpace, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import { ProductRatingWeights, IProductRatingWeight } from "./ProductRatingWeigh
|
||||
import { createCityMap } from "../Locations/createCityMap";
|
||||
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";
|
||||
|
||||
interface IConstructorParams {
|
||||
@ -265,13 +265,12 @@ export class Product {
|
||||
}
|
||||
|
||||
// Serialize the current object to a JSON save state.
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("Product", this);
|
||||
}
|
||||
|
||||
// Initiatizes a Product object from a JSON save state.
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Product {
|
||||
static fromJSON(value: IReviverValue): Product {
|
||||
return Generic_fromJSON(Product, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,6 @@ import { ResearchMap } from "./ResearchMap";
|
||||
|
||||
import { IMap } from "../types";
|
||||
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
|
||||
interface IConstructorParams {
|
||||
children?: Node[];
|
||||
cost: number;
|
||||
@ -60,40 +58,6 @@ export class Node {
|
||||
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
|
||||
findNode(text: string): Node | null {
|
||||
// Is this the Node?
|
||||
@ -127,23 +91,6 @@ export class ResearchTree {
|
||||
// Root Node
|
||||
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
|
||||
getAllNodes(): string[] {
|
||||
const res: string[] = [];
|
||||
@ -236,7 +183,20 @@ export class ResearchTree {
|
||||
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) {
|
||||
console.warn(`Invalid propName specified in ResearchTree.getMultiplierHelper: ${propName}`);
|
||||
continue;
|
||||
|
@ -3,7 +3,7 @@ import { ICorporation } from "./ICorporation";
|
||||
import { IIndustry } from "./IIndustry";
|
||||
import { MaterialSizes } from "./MaterialSizes";
|
||||
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";
|
||||
|
||||
interface IConstructorParams {
|
||||
@ -99,19 +99,18 @@ export class Warehouse {
|
||||
updateSize(corporation: ICorporation, industry: IIndustry): void {
|
||||
try {
|
||||
this.size = this.level * 100 * corporation.getStorageMultiplier() * industry.getStorageMultiplier();
|
||||
} catch (e: any) {
|
||||
} catch (e: unknown) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Serialize the current object to a JSON save state.
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("Warehouse", this);
|
||||
}
|
||||
|
||||
// Initiatizes a Warehouse object from a JSON save state.
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Warehouse {
|
||||
static fromJSON(value: IReviverValue): Warehouse {
|
||||
return Generic_fromJSON(Warehouse, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -124,8 +124,8 @@ export function IndustryOverview(props: IProps): React.ReactElement {
|
||||
<br />
|
||||
<StatsTable
|
||||
rows={[
|
||||
["Awareness:", numeralWrapper.format(division.awareness, "0.000")],
|
||||
["Popularity:", numeralWrapper.format(division.popularity, "0.000")],
|
||||
["Awareness:", numeralWrapper.formatReallyBigNumber(division.awareness)],
|
||||
["Popularity:", numeralWrapper.formatReallyBigNumber(division.popularity)],
|
||||
]}
|
||||
/>
|
||||
{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>
|
||||
<StatsTable
|
||||
rows={[
|
||||
["Awareness Bonus:", "x" + numeralWrapper.format(Math.pow(awarenessFac, 0.85), "0.000")],
|
||||
["Popularity Bonus:", "x" + numeralWrapper.format(Math.pow(popularityFac, 0.85), "0.000")],
|
||||
["Ratio Multiplier:", "x" + numeralWrapper.format(Math.pow(ratioFac, 0.85), "0.000")],
|
||||
["Awareness Bonus:", "x" + numeralWrapper.formatReallyBigNumber(Math.pow(awarenessFac, 0.85))],
|
||||
["Popularity Bonus:", "x" + numeralWrapper.formatReallyBigNumber(Math.pow(popularityFac, 0.85))],
|
||||
["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>
|
||||
)}
|
||||
<br />
|
||||
@ -164,7 +164,7 @@ export function IndustryOverview(props: IProps): React.ReactElement {
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<Typography>Production Multiplier: {numeralWrapper.format(division.prodMult, "0.00")}</Typography>
|
||||
<Typography>Production Multiplier: {numeralWrapper.formatReallyBigNumber(division.prodMult)}</Typography>
|
||||
</Tooltip>
|
||||
<IconButton onClick={() => setHelpOpen(true)}>
|
||||
<HelpIcon />
|
||||
@ -203,7 +203,7 @@ export function IndustryOverview(props: IProps): React.ReactElement {
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<Typography>Scientific Research: {numeralWrapper.format(division.sciResearch.qty, "0.000a")}</Typography>
|
||||
<Typography>Scientific Research: {numeralWrapper.formatReallyBigNumber(division.sciResearch.qty)}</Typography>
|
||||
</Tooltip>
|
||||
<Button sx={{ mx: 1 }} onClick={() => setResearchOpen(true)}>
|
||||
Research
|
||||
|
@ -38,7 +38,7 @@ export function Overview({ rerender }: IProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const profit: number = corp.revenue - corp.expenses;
|
||||
|
||||
const multRows: any[][] = [];
|
||||
const multRows: string[][] = [];
|
||||
function appendMult(name: string, value: number): void {
|
||||
if (value === 1) return;
|
||||
multRows.push([name, numeralWrapper.format(value, "0.000")]);
|
||||
|
@ -9,7 +9,7 @@ import { useCorporation } from "../Context";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
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 Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||
|
||||
@ -27,12 +27,10 @@ export function BribeFactionModal(props: IProps): React.ReactElement {
|
||||
return true;
|
||||
});
|
||||
const corp = useCorporation();
|
||||
const [money, setMoney] = useState<number | null>(0);
|
||||
const [stock, setStock] = useState<number | null>(0);
|
||||
const [money, setMoney] = useState<number>(NaN);
|
||||
const [stock, setStock] = useState<number>(NaN);
|
||||
const [selectedFaction, setSelectedFaction] = useState(factions.length > 0 ? factions[0] : "");
|
||||
const disabled =
|
||||
money === null ||
|
||||
stock === null ||
|
||||
(money === 0 && stock === 0) ||
|
||||
isNaN(money) ||
|
||||
isNaN(stock) ||
|
||||
@ -41,14 +39,6 @@ export function BribeFactionModal(props: IProps): React.ReactElement {
|
||||
corp.funds < money ||
|
||||
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 {
|
||||
setSelectedFaction(event.target.value);
|
||||
}
|
||||
@ -110,8 +100,8 @@ export function BribeFactionModal(props: IProps): React.ReactElement {
|
||||
</Select>
|
||||
</Box>
|
||||
<Typography>{getRepText(money ? money : 0, stock ? stock : 0)}</Typography>
|
||||
<TextField onChange={onMoneyChange} placeholder="Corporation funds" />
|
||||
<TextField sx={{ mx: 1 }} onChange={onStockChange} placeholder="Stock Shares" />
|
||||
<NumberInput onChange={setMoney} placeholder="Corporation funds" />
|
||||
<NumberInput sx={{ mx: 1 }} onChange={setStock} placeholder="Stock Shares" />
|
||||
<Button disabled={disabled} sx={{ mx: 1 }} onClick={() => bribe(money ? money : 0, stock ? stock : 0)}>
|
||||
Bribe
|
||||
</Button>
|
||||
|
@ -5,7 +5,7 @@ import { use } from "../../../ui/Context";
|
||||
import { useCorporation } from "../Context";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { NumberInput } from "../../../ui/React/NumberInput";
|
||||
import { BuyBackShares } from "../../Actions";
|
||||
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||
@ -21,12 +21,7 @@ interface IProps {
|
||||
export function BuybackSharesModal(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const corp = useCorporation();
|
||||
const [shares, setShares] = useState<number | null>(null);
|
||||
|
||||
function changeShares(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
if (event.target.value === "") setShares(null);
|
||||
else setShares(Math.round(parseFloat(event.target.value)));
|
||||
}
|
||||
const [shares, setShares] = useState<number>(NaN);
|
||||
|
||||
const currentStockPrice = corp.sharePrice;
|
||||
const buybackPrice = currentStockPrice * 1.1;
|
||||
@ -87,13 +82,7 @@ export function BuybackSharesModal(props: IProps): React.ReactElement {
|
||||
</Typography>
|
||||
<CostIndicator />
|
||||
<br />
|
||||
<TextField
|
||||
autoFocus={true}
|
||||
type="number"
|
||||
placeholder="Shares to buyback"
|
||||
onChange={changeShares}
|
||||
onKeyDown={onKeyDown}
|
||||
/>
|
||||
<NumberInput autoFocus={true} placeholder="Shares to buyback" onChange={setShares} onKeyDown={onKeyDown} />
|
||||
<Button disabled={disabled} onClick={buy}>
|
||||
Buy shares
|
||||
</Button>
|
||||
|
@ -5,7 +5,7 @@ import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||
import { useCorporation } from "../Context";
|
||||
import Typography from "@mui/material/Typography";
|
||||
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 { KEY } from "../../../utils/helpers/keyCodes";
|
||||
|
||||
@ -18,29 +18,28 @@ interface IProps {
|
||||
// Create a popup that lets the player manage exports
|
||||
export function GoPublicModal(props: IProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const [shares, setShares] = useState("");
|
||||
const [shares, setShares] = useState<number>(NaN);
|
||||
const initialSharePrice = corp.determineValuation() / corp.totalShares;
|
||||
|
||||
function goPublic(): void {
|
||||
const numShares = parseFloat(shares);
|
||||
const initialSharePrice = corp.determineValuation() / corp.totalShares;
|
||||
if (isNaN(numShares)) {
|
||||
if (isNaN(shares)) {
|
||||
dialogBoxCreate("Invalid value for number of issued shares");
|
||||
return;
|
||||
}
|
||||
if (numShares > corp.numShares) {
|
||||
if (shares > corp.numShares) {
|
||||
dialogBoxCreate("Error: You don't have that many shares to issue!");
|
||||
return;
|
||||
}
|
||||
corp.public = true;
|
||||
corp.sharePrice = initialSharePrice;
|
||||
corp.issuedShares = numShares;
|
||||
corp.numShares -= numShares;
|
||||
corp.addFunds(numShares * initialSharePrice);
|
||||
corp.issuedShares = shares;
|
||||
corp.numShares -= shares;
|
||||
corp.addFunds(shares * initialSharePrice);
|
||||
props.rerender();
|
||||
dialogBoxCreate(
|
||||
`You took your ${corp.name} public and earned ` +
|
||||
`${numeralWrapper.formatMoney(numShares * initialSharePrice)} in your IPO`,
|
||||
`${numeralWrapper.formatMoney(shares * initialSharePrice)} in your IPO`,
|
||||
);
|
||||
props.onClose();
|
||||
}
|
||||
@ -49,10 +48,6 @@ export function GoPublicModal(props: IProps): React.ReactElement {
|
||||
if (event.key === KEY.ENTER) goPublic();
|
||||
}
|
||||
|
||||
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
setShares(event.target.value);
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal open={props.open} onClose={props.onClose}>
|
||||
<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.
|
||||
</Typography>
|
||||
<Box display="flex" alignItems="center">
|
||||
<TextField
|
||||
value={shares}
|
||||
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}
|
||||
>
|
||||
<NumberInput onChange={setShares} autoFocus placeholder="Shares to issue" onKeyDown={onKeyDown} />
|
||||
<Button disabled={shares < 0 || shares > corp.numShares} sx={{ mx: 1 }} onClick={goPublic}>
|
||||
Go Public
|
||||
</Button>
|
||||
</Box>
|
||||
|
@ -6,7 +6,7 @@ import { getRandomInt } from "../../../utils/helpers/getRandomInt";
|
||||
import { CorporationConstants } from "../../data/Constants";
|
||||
import { useCorporation } from "../Context";
|
||||
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 { 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
|
||||
export function IssueNewSharesModal(props: IProps): React.ReactElement {
|
||||
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 maxNewShares = maxNewSharesUnrounded - (maxNewSharesUnrounded % 1e6);
|
||||
|
||||
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 {
|
||||
if (shares === null) return;
|
||||
if (isNaN(shares)) return;
|
||||
if (disabled) return;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
if (event.target.value === "") setShares(null);
|
||||
else setShares(parseFloat(event.target.value));
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal open={props.open} onClose={props.onClose}>
|
||||
<Typography>
|
||||
@ -124,7 +119,7 @@ export function IssueNewSharesModal(props: IProps): React.ReactElement {
|
||||
you cannot buy them back.
|
||||
</Typography>
|
||||
<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 }}>
|
||||
Issue New Shares
|
||||
</Button>
|
||||
|
@ -10,6 +10,7 @@ import Button from "@mui/material/Button";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||
import { NumberInput } from "../../../ui/React/NumberInput";
|
||||
|
||||
interface IProps {
|
||||
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 [city, setCity] = useState(allCities.length > 0 ? allCities[0] : "");
|
||||
const [name, setName] = useState("");
|
||||
const [design, setDesign] = useState<number | null>(null);
|
||||
const [marketing, setMarketing] = useState<number | null>(null);
|
||||
const [design, setDesign] = useState<number>(NaN);
|
||||
const [marketing, setMarketing] = useState<number>(NaN);
|
||||
if (division.hasMaximumNumberProducts()) return <></>;
|
||||
|
||||
let createProductPopupText = <></>;
|
||||
@ -138,7 +139,7 @@ export function MakeProductModal(props: IProps): React.ReactElement {
|
||||
);
|
||||
|
||||
function makeProduct(): void {
|
||||
if (design === null || marketing === null) return;
|
||||
if (isNaN(design) || isNaN(marketing)) return;
|
||||
try {
|
||||
MakeProduct(corp, division, city, name, design, marketing);
|
||||
} catch (err) {
|
||||
@ -155,16 +156,6 @@ export function MakeProductModal(props: IProps): React.ReactElement {
|
||||
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 {
|
||||
if (event.key === KEY.ENTER) makeProduct();
|
||||
}
|
||||
@ -181,13 +172,8 @@ export function MakeProductModal(props: IProps): React.ReactElement {
|
||||
</Select>
|
||||
<TextField onChange={onProductNameChange} placeholder={productPlaceholder(division.type)} />
|
||||
<br />
|
||||
<TextField onChange={onDesignChange} autoFocus={true} type="number" placeholder={"Design investment"} />
|
||||
<TextField
|
||||
onChange={onMarketingChange}
|
||||
onKeyDown={onKeyDown}
|
||||
type="number"
|
||||
placeholder={"Marketing investment"}
|
||||
/>
|
||||
<NumberInput onChange={setDesign} autoFocus={true} placeholder={"Design investment"} />
|
||||
<NumberInput onChange={setMarketing} onKeyDown={onKeyDown} placeholder={"Marketing investment"} />
|
||||
<Button onClick={makeProduct}>Develop Product</Button>
|
||||
</Modal>
|
||||
);
|
||||
|
@ -6,11 +6,11 @@ import { use } from "../../../ui/Context";
|
||||
import { useCorporation } from "../Context";
|
||||
import { ICorporation } from "../../ICorporation";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import Button from "@mui/material/Button";
|
||||
import { Money } from "../../../ui/React/Money";
|
||||
import { SellShares } from "../../Actions";
|
||||
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||
import { NumberInput } from "../../../ui/React/NumberInput";
|
||||
interface IProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
@ -22,14 +22,9 @@ interface IProps {
|
||||
export function SellSharesModal(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
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;
|
||||
|
||||
function changeShares(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
if (event.target.value === "") setShares(null);
|
||||
else setShares(Math.round(parseFloat(event.target.value)));
|
||||
}
|
||||
const disabled = isNaN(shares) || shares <= 0 || shares > corp.numShares;
|
||||
|
||||
function ProfitIndicator(props: { shares: number | null; corp: ICorporation }): React.ReactElement {
|
||||
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)}
|
||||
</Typography>
|
||||
<br />
|
||||
<TextField
|
||||
<NumberInput
|
||||
variant="standard"
|
||||
autoFocus
|
||||
type="number"
|
||||
placeholder="Shares to sell"
|
||||
onChange={changeShares}
|
||||
onChange={setShares}
|
||||
onKeyDown={onKeyDown}
|
||||
/>
|
||||
<Button disabled={disabled} onClick={sell} sx={{ mx: 1 }}>
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 {
|
||||
x: number;
|
||||
@ -74,15 +74,14 @@ export class ActiveFragment {
|
||||
/**
|
||||
* Serialize an active fragment to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("ActiveFragment", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes an acive fragment from a JSON save state
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): ActiveFragment {
|
||||
static fromJSON(value: IReviverValue): ActiveFragment {
|
||||
return Generic_fromJSON(ActiveFragment, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -19,22 +19,22 @@ export class DummyGift implements IStaneksGift {
|
||||
height(): number {
|
||||
return this._height;
|
||||
}
|
||||
charge(): any {
|
||||
charge(): void {
|
||||
throw new Error("unimplemented for dummy gift");
|
||||
}
|
||||
process(): any {
|
||||
process(): void {
|
||||
throw new Error("unimplemented for dummy gift");
|
||||
}
|
||||
effect(): any {
|
||||
effect(): number {
|
||||
throw new Error("unimplemented for dummy gift");
|
||||
}
|
||||
canPlace(): any {
|
||||
canPlace(): boolean {
|
||||
throw new Error("unimplemented for dummy gift");
|
||||
}
|
||||
place(): any {
|
||||
place(): boolean {
|
||||
throw new Error("unimplemented for dummy gift");
|
||||
}
|
||||
findFragment(): any {
|
||||
findFragment(): ActiveFragment | undefined {
|
||||
throw new Error("unimplemented for dummy gift");
|
||||
}
|
||||
fragmentAt(worldX: number, worldY: number): ActiveFragment | undefined {
|
||||
@ -46,22 +46,22 @@ export class DummyGift implements IStaneksGift {
|
||||
|
||||
return undefined;
|
||||
}
|
||||
delete(): any {
|
||||
delete(): boolean {
|
||||
throw new Error("unimplemented for dummy gift");
|
||||
}
|
||||
clear(): any {
|
||||
clear(): void {
|
||||
throw new Error("unimplemented for dummy gift");
|
||||
}
|
||||
count(): any {
|
||||
count(): number {
|
||||
throw new Error("unimplemented for dummy gift");
|
||||
}
|
||||
inBonus(): any {
|
||||
inBonus(): boolean {
|
||||
throw new Error("unimplemented for dummy gift");
|
||||
}
|
||||
prestigeAugmentation(): any {
|
||||
prestigeAugmentation(): void {
|
||||
throw new Error("unimplemented for dummy gift");
|
||||
}
|
||||
prestigeSourceFile(): any {
|
||||
prestigeSourceFile(): void {
|
||||
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 = [];
|
||||
|
||||
for (let i = 0; i < dimensions[0]; ++i) {
|
||||
array.push(dimensions.length == 1 ? 0 : zeros(dimensions.slice(1)));
|
||||
for (let i = 0; i < width; ++i) {
|
||||
array.push(Array(height).fill(0));
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
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 j = 0; j < gift.height(); j++) {
|
||||
const fragment = gift.fragmentAt(i, j);
|
||||
|
@ -7,7 +7,7 @@ import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Factions } from "../Faction/Factions";
|
||||
import { CalculateEffect } from "./formulas/effect";
|
||||
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 { StanekConstants } from "./data/Constants";
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
@ -38,7 +38,7 @@ export class StaneksGift implements IStaneksGift {
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -146,66 +146,66 @@ export class StaneksGift implements IStaneksGift {
|
||||
const power = this.effect(aFrag);
|
||||
switch (fragment.type) {
|
||||
case FragmentType.HackingChance:
|
||||
p.hacking_chance_mult *= power;
|
||||
p.mults.hacking_chance *= power;
|
||||
break;
|
||||
case FragmentType.HackingSpeed:
|
||||
p.hacking_speed_mult *= power;
|
||||
p.mults.hacking_speed *= power;
|
||||
break;
|
||||
case FragmentType.HackingMoney:
|
||||
p.hacking_money_mult *= power;
|
||||
p.mults.hacking_money *= power;
|
||||
break;
|
||||
case FragmentType.HackingGrow:
|
||||
p.hacking_grow_mult *= power;
|
||||
p.mults.hacking_grow *= power;
|
||||
break;
|
||||
case FragmentType.Hacking:
|
||||
p.hacking_mult *= power;
|
||||
p.hacking_exp_mult *= power;
|
||||
p.mults.hacking *= power;
|
||||
p.mults.hacking_exp *= power;
|
||||
break;
|
||||
case FragmentType.Strength:
|
||||
p.strength_mult *= power;
|
||||
p.strength_exp_mult *= power;
|
||||
p.mults.strength *= power;
|
||||
p.mults.strength_exp *= power;
|
||||
break;
|
||||
case FragmentType.Defense:
|
||||
p.defense_mult *= power;
|
||||
p.defense_exp_mult *= power;
|
||||
p.mults.defense *= power;
|
||||
p.mults.defense_exp *= power;
|
||||
break;
|
||||
case FragmentType.Dexterity:
|
||||
p.dexterity_mult *= power;
|
||||
p.dexterity_exp_mult *= power;
|
||||
p.mults.dexterity *= power;
|
||||
p.mults.dexterity_exp *= power;
|
||||
break;
|
||||
case FragmentType.Agility:
|
||||
p.agility_mult *= power;
|
||||
p.agility_exp_mult *= power;
|
||||
p.mults.agility *= power;
|
||||
p.mults.agility_exp *= power;
|
||||
break;
|
||||
case FragmentType.Charisma:
|
||||
p.charisma_mult *= power;
|
||||
p.charisma_exp_mult *= power;
|
||||
p.mults.charisma *= power;
|
||||
p.mults.charisma_exp *= power;
|
||||
break;
|
||||
case FragmentType.HacknetMoney:
|
||||
p.hacknet_node_money_mult *= power;
|
||||
p.mults.hacknet_node_money *= power;
|
||||
break;
|
||||
case FragmentType.HacknetCost:
|
||||
p.hacknet_node_purchase_cost_mult /= power;
|
||||
p.hacknet_node_ram_cost_mult /= power;
|
||||
p.hacknet_node_core_cost_mult /= power;
|
||||
p.hacknet_node_level_cost_mult /= power;
|
||||
p.mults.hacknet_node_purchase_cost /= power;
|
||||
p.mults.hacknet_node_ram_cost /= power;
|
||||
p.mults.hacknet_node_core_cost /= power;
|
||||
p.mults.hacknet_node_level_cost /= power;
|
||||
break;
|
||||
case FragmentType.Rep:
|
||||
p.company_rep_mult *= power;
|
||||
p.faction_rep_mult *= power;
|
||||
p.mults.company_rep *= power;
|
||||
p.mults.faction_rep *= power;
|
||||
break;
|
||||
case FragmentType.WorkMoney:
|
||||
p.work_money_mult *= power;
|
||||
p.mults.work_money *= power;
|
||||
break;
|
||||
case FragmentType.Crime:
|
||||
p.crime_success_mult *= power;
|
||||
p.crime_money_mult *= power;
|
||||
p.mults.crime_success *= power;
|
||||
p.mults.crime_money *= power;
|
||||
break;
|
||||
case FragmentType.Bladeburner:
|
||||
p.bladeburner_max_stamina_mult *= power;
|
||||
p.bladeburner_stamina_gain_mult *= power;
|
||||
p.bladeburner_analysis_mult *= power;
|
||||
p.bladeburner_success_chance_mult *= power;
|
||||
p.mults.bladeburner_max_stamina *= power;
|
||||
p.mults.bladeburner_stamina_gain *= power;
|
||||
p.mults.bladeburner_analysis *= power;
|
||||
p.mults.bladeburner_success_chance *= power;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -224,15 +224,14 @@ export class StaneksGift implements IStaneksGift {
|
||||
/**
|
||||
* Serialize Staneks Gift to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("StaneksGift", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes Staneks Gift from a JSON save state
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): StaneksGift {
|
||||
static fromJSON(value: IReviverValue): StaneksGift {
|
||||
return Generic_fromJSON(StaneksGift, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ interface IProps {
|
||||
|
||||
export function DummyGrid(props: IProps): React.ReactElement {
|
||||
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 (
|
||||
<Box>
|
||||
<Table sx={{ width: props.width, height: props.height }}>
|
||||
|
@ -18,7 +18,7 @@ interface IProps {
|
||||
}
|
||||
|
||||
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 [rotation, setRotation] = React.useState(0);
|
||||
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 {
|
||||
setPos([worldX, worldY]);
|
||||
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 x = 0; x < selectedFragment.width(rotation); x++) {
|
||||
if (!selectedFragment.fullAt(x, y, rotation)) continue;
|
||||
@ -61,7 +61,7 @@ export function MainBoard(props: IProps): React.ReactElement {
|
||||
|
||||
function updateSelectedFragment(fragment: Fragment): void {
|
||||
setSelectedFragment(fragment);
|
||||
const newgrid = zeros([props.gift.width(), props.gift.height()]);
|
||||
const newgrid = zeros(props.gift.width(), props.gift.height());
|
||||
setGhostGrid(newgrid);
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { IPerson } from "../PersonObjects/IPerson";
|
||||
import { IRouter } from "../ui/Router";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { CrimeType } from "../utils/WorkType";
|
||||
import { CrimeWork } from "../Work/CrimeWork";
|
||||
|
||||
interface IConstructorParams {
|
||||
hacking_success_weight?: number;
|
||||
@ -96,22 +96,15 @@ export class Crime {
|
||||
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) {
|
||||
div = 1;
|
||||
}
|
||||
p.startCrime(
|
||||
router,
|
||||
this.type,
|
||||
this.hacking_exp / div,
|
||||
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,
|
||||
p.startWork(
|
||||
new CrimeWork({
|
||||
crimeType: this.type,
|
||||
singularity: workerScript !== null,
|
||||
}),
|
||||
);
|
||||
|
||||
return this.time;
|
||||
@ -128,7 +121,7 @@ export class Crime {
|
||||
CONSTANTS.IntelligenceCrimeWeight * p.intelligence;
|
||||
chance /= CONSTANTS.MaxSkillLevel;
|
||||
chance /= this.difficulty;
|
||||
chance *= p.crime_success_mult;
|
||||
chance *= p.mults.crime_success;
|
||||
chance *= p.getIntelligenceBonus(1);
|
||||
|
||||
return Math.min(chance, 1);
|
||||
|
@ -7,6 +7,7 @@ import { SpecialServers } from "../Server/data/SpecialServers";
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
import { Money } from "../ui/React/Money";
|
||||
import { DarkWebItem } from "./DarkWebItem";
|
||||
import { isCreateProgramWork } from "../Work/CreateProgramWork";
|
||||
|
||||
//Posts a "help" message if connected to DarkWeb
|
||||
export function checkIfConnectedToDarkweb(): void {
|
||||
@ -74,9 +75,8 @@ export function buyDarkwebItem(itemName: string): void {
|
||||
|
||||
Player.getHomeComputer().pushProgram(item.program);
|
||||
// Cancel if the program is in progress of writing
|
||||
if (Player.createProgramName === item.program) {
|
||||
Player.isWorking = false;
|
||||
Player.resetWorkStatus();
|
||||
if (isCreateProgramWork(Player.currentWork) && Player.currentWork.programName === item.program) {
|
||||
Player.finishWork(true);
|
||||
}
|
||||
|
||||
Terminal.print(
|
||||
|
@ -24,8 +24,8 @@ export function SaveFile(): React.ReactElement {
|
||||
const base64Save = await saveObject.getImportStringFromFile(event.target.files);
|
||||
const save = atob(base64Save);
|
||||
setSaveFile(save);
|
||||
} catch (ex: any) {
|
||||
SnackbarEvents.emit(ex.toString(), ToastVariant.ERROR, 5000);
|
||||
} catch (e: unknown) {
|
||||
SnackbarEvents.emit(String(e), ToastVariant.ERROR, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,8 +38,8 @@ export function SaveFile(): React.ReactElement {
|
||||
|
||||
function doRestore(): void {
|
||||
const save = JSON.parse(saveFile);
|
||||
console.log(Object.keys(save));
|
||||
// TODO: Continue here.
|
||||
console.error(save);
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -31,7 +31,7 @@ declare global {
|
||||
};
|
||||
electronBridge: {
|
||||
send: (channel: string, data?: unknown) => void;
|
||||
receive: (channel: string, func: (...args: any[]) => void) => void;
|
||||
receive: (channel: string, func: (...args: unknown[]) => void) => void;
|
||||
};
|
||||
}
|
||||
interface Document {
|
||||
@ -150,7 +150,7 @@ function initSaveFunctions(): void {
|
||||
try {
|
||||
saveObject.exportGame();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
console.error(error);
|
||||
SnackbarEvents.emit("Could not export game.", ToastVariant.ERROR, 2000);
|
||||
}
|
||||
},
|
||||
@ -185,11 +185,14 @@ function initElectronBridge(): void {
|
||||
const data = window.appSaveFns.getSaveData();
|
||||
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);
|
||||
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);
|
||||
});
|
||||
bridge.receive("trigger-save", () => {
|
||||
@ -199,7 +202,7 @@ function initElectronBridge(): void {
|
||||
bridge.send("save-completed");
|
||||
})
|
||||
.catch((error: unknown) => {
|
||||
console.log(error);
|
||||
console.error(error);
|
||||
SnackbarEvents.emit("Could not save game.", ToastVariant.ERROR, 2000);
|
||||
});
|
||||
});
|
||||
@ -207,7 +210,7 @@ function initElectronBridge(): void {
|
||||
try {
|
||||
window.appSaveFns.triggerGameExport();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
console.error(error);
|
||||
SnackbarEvents.emit("Could not export game.", ToastVariant.ERROR, 2000);
|
||||
}
|
||||
});
|
||||
@ -215,7 +218,7 @@ function initElectronBridge(): void {
|
||||
try {
|
||||
window.appSaveFns.triggerScriptsExport();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
console.error(error);
|
||||
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 dec = Math.pow(0.999, Player.exploits.length);
|
||||
|
||||
Player.hacking_chance_mult *= inc;
|
||||
Player.hacking_speed_mult *= inc;
|
||||
Player.hacking_money_mult *= inc;
|
||||
Player.hacking_grow_mult *= inc;
|
||||
Player.hacking_mult *= inc;
|
||||
Player.mults.hacking_chance *= inc;
|
||||
Player.mults.hacking_speed *= inc;
|
||||
Player.mults.hacking_money *= inc;
|
||||
Player.mults.hacking_grow *= inc;
|
||||
Player.mults.hacking *= inc;
|
||||
|
||||
Player.strength_mult *= inc;
|
||||
Player.defense_mult *= inc;
|
||||
Player.dexterity_mult *= inc;
|
||||
Player.agility_mult *= inc;
|
||||
Player.charisma_mult *= inc;
|
||||
Player.mults.strength *= inc;
|
||||
Player.mults.defense *= inc;
|
||||
Player.mults.dexterity *= inc;
|
||||
Player.mults.agility *= inc;
|
||||
Player.mults.charisma *= inc;
|
||||
|
||||
Player.hacking_exp_mult *= inc;
|
||||
Player.strength_exp_mult *= inc;
|
||||
Player.defense_exp_mult *= inc;
|
||||
Player.dexterity_exp_mult *= inc;
|
||||
Player.agility_exp_mult *= inc;
|
||||
Player.charisma_exp_mult *= inc;
|
||||
Player.mults.hacking_exp *= inc;
|
||||
Player.mults.strength_exp *= inc;
|
||||
Player.mults.defense_exp *= inc;
|
||||
Player.mults.dexterity_exp *= inc;
|
||||
Player.mults.agility_exp *= inc;
|
||||
Player.mults.charisma_exp *= inc;
|
||||
|
||||
Player.company_rep_mult *= inc;
|
||||
Player.faction_rep_mult *= inc;
|
||||
Player.mults.company_rep *= inc;
|
||||
Player.mults.faction_rep *= inc;
|
||||
|
||||
Player.crime_money_mult *= inc;
|
||||
Player.crime_success_mult *= inc;
|
||||
Player.mults.crime_money *= inc;
|
||||
Player.mults.crime_success *= inc;
|
||||
|
||||
Player.hacknet_node_money_mult *= inc;
|
||||
Player.hacknet_node_purchase_cost_mult *= dec;
|
||||
Player.hacknet_node_ram_cost_mult *= dec;
|
||||
Player.hacknet_node_core_cost_mult *= dec;
|
||||
Player.hacknet_node_level_cost_mult *= dec;
|
||||
Player.mults.hacknet_node_money *= inc;
|
||||
Player.mults.hacknet_node_purchase_cost *= dec;
|
||||
Player.mults.hacknet_node_ram_cost *= dec;
|
||||
Player.mults.hacknet_node_core_cost *= 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 { 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 {
|
||||
/**
|
||||
@ -75,15 +75,14 @@ export class Faction {
|
||||
/**
|
||||
* Serialize the current object to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("Faction", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiatizes a Faction object from a JSON save state.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Faction {
|
||||
static fromJSON(value: IReviverValue): Faction {
|
||||
return Generic_fromJSON(Faction, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
import { InvitationEvent } from "./ui/InvitationModal";
|
||||
import { FactionNames } from "./data/FactionNames";
|
||||
import { SFC32RNG } from "../Casino/RNG";
|
||||
import { isFactionWork } from "../Work/FactionWork";
|
||||
|
||||
export function inviteToFaction(faction: Faction): void {
|
||||
Player.receiveInvite(faction.name);
|
||||
@ -113,7 +114,7 @@ export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = fal
|
||||
|
||||
export function processPassiveFactionRepGain(numCycles: number): void {
|
||||
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;
|
||||
const faction = Factions[name];
|
||||
if (!faction.isMember) continue;
|
||||
@ -132,7 +133,7 @@ export function processPassiveFactionRepGain(numCycles: number): void {
|
||||
const fRep = getFactionFieldWorkRepGain(Player, faction);
|
||||
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";
|
||||
|
||||
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 { Reputation } from "../../ui/React/Reputation";
|
||||
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
|
||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||
import { MathJaxWrapper } from "../../MathJaxWrapper";
|
||||
|
||||
|
@ -21,6 +21,8 @@ import { Typography, Button } from "@mui/material";
|
||||
import { CovenantPurchasesRoot } from "../../PersonObjects/Sleeve/ui/CovenantPurchasesRoot";
|
||||
import { FactionNames } from "../data/FactionNames";
|
||||
import { GangButton } from "./GangButton";
|
||||
import { FactionWork } from "../../Work/FactionWork";
|
||||
import { FactionWorkType } from "../../Work/data/FactionWorkType";
|
||||
|
||||
type IProps = {
|
||||
faction: Faction;
|
||||
@ -67,17 +69,35 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea
|
||||
}
|
||||
|
||||
function startFieldWork(faction: Faction): void {
|
||||
player.startFactionFieldWork(faction);
|
||||
player.startWork(
|
||||
new FactionWork({
|
||||
singularity: false,
|
||||
faction: faction.name,
|
||||
factionWorkType: FactionWorkType.FIELD,
|
||||
}),
|
||||
);
|
||||
startWork();
|
||||
}
|
||||
|
||||
function startHackingContracts(faction: Faction): void {
|
||||
player.startFactionHackWork(faction);
|
||||
player.startWork(
|
||||
new FactionWork({
|
||||
singularity: false,
|
||||
faction: faction.name,
|
||||
factionWorkType: FactionWorkType.HACKING,
|
||||
}),
|
||||
);
|
||||
startWork();
|
||||
}
|
||||
|
||||
function startSecurityWork(faction: Faction): void {
|
||||
player.startFactionSecurityWork(faction);
|
||||
player.startWork(
|
||||
new FactionWork({
|
||||
singularity: false,
|
||||
faction: faction.name,
|
||||
factionWorkType: FactionWorkType.SECURITY,
|
||||
}),
|
||||
);
|
||||
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 [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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
Settings.AutosaveInterval = newValue as number;
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import {
|
||||
Download,
|
||||
LibraryBooks,
|
||||
Palette,
|
||||
Public,
|
||||
Reddit,
|
||||
Save,
|
||||
SystemUpdateAlt,
|
||||
@ -75,8 +74,8 @@ export const GameOptionsSidebar = (props: IProps): React.ReactElement => {
|
||||
const data = await saveObject.getImportDataFromString(base64Save);
|
||||
setImportData(data);
|
||||
setImportSaveOpen(true);
|
||||
} catch (ex: any) {
|
||||
SnackbarEvents.emit(ex.toString(), ToastVariant.ERROR, 5000);
|
||||
} catch (e: unknown) {
|
||||
SnackbarEvents.emit(String(e), ToastVariant.ERROR, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,8 +84,8 @@ export const GameOptionsSidebar = (props: IProps): React.ReactElement => {
|
||||
|
||||
try {
|
||||
await saveObject.importGame(importData.base64);
|
||||
} catch (ex: any) {
|
||||
SnackbarEvents.emit(ex.toString(), ToastVariant.ERROR, 5000);
|
||||
} catch (e: unknown) {
|
||||
SnackbarEvents.emit(String(e), ToastVariant.ERROR, 5000);
|
||||
}
|
||||
|
||||
setImportSaveOpen(false);
|
||||
|
@ -2,8 +2,8 @@ import { Slider, Tooltip, Typography, Box } from "@mui/material";
|
||||
import React, { useState } from "react";
|
||||
|
||||
interface IProps {
|
||||
initialValue: any;
|
||||
callback: (event: any, newValue: number | number[]) => void;
|
||||
initialValue: number;
|
||||
callback: (event: Event | React.SyntheticEvent<Element, Event>, newValue: number | number[]) => void;
|
||||
step: number;
|
||||
min: number;
|
||||
max: number;
|
||||
@ -16,7 +16,7 @@ export const OptionsSlider = (props: IProps): React.ReactElement => {
|
||||
const [value, setValue] = useState(props.initialValue);
|
||||
|
||||
const onChange = (_evt: Event, newValue: number | Array<number>): void => {
|
||||
setValue(newValue);
|
||||
if (typeof newValue === "number") setValue(newValue);
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -8,7 +8,7 @@ import { Faction } from "../Faction/Faction";
|
||||
import { Factions } from "../Faction/Factions";
|
||||
|
||||
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 { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||
@ -99,7 +99,7 @@ export class Gang implements IGang {
|
||||
this.processExperienceGains(cycles);
|
||||
this.processTerritoryAndPowerGains(cycles);
|
||||
this.storedCycles -= cycles;
|
||||
} catch (e: any) {
|
||||
} catch (e: unknown) {
|
||||
console.error(`Exception caught when processing Gang: ${e}`);
|
||||
}
|
||||
}
|
||||
@ -132,7 +132,7 @@ export class Gang implements IGang {
|
||||
}
|
||||
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
|
||||
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}`);
|
||||
}
|
||||
return res;
|
||||
} catch (e: any) {
|
||||
} catch (e: unknown) {
|
||||
if (workerScript == null) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
@ -399,15 +399,14 @@ export class Gang implements IGang {
|
||||
/**
|
||||
* Serialize the current object to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("Gang", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiatizes a Gang object from a JSON save state.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): Gang {
|
||||
static fromJSON(value: IReviverValue): Gang {
|
||||
return Generic_fromJSON(Gang, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { GangMemberUpgrades } from "./GangMemberUpgrades";
|
||||
import { IAscensionResult } from "./IAscensionResult";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { IGang } from "./IGang";
|
||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../utils/JSONReviver";
|
||||
import {
|
||||
calculateRespectGain,
|
||||
calculateMoneyGain,
|
||||
@ -320,15 +320,14 @@ export class GangMember {
|
||||
/**
|
||||
* Serialize the current object to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("GangMember", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiatizes a GangMember object from a JSON save state.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): GangMember {
|
||||
static fromJSON(value: IReviverValue): GangMember {
|
||||
return Generic_fromJSON(GangMember, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { GangMember } from "./GangMember";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { IAscensionResult } from "./IAscensionResult";
|
||||
import { IReviverValue } from "src/utils/JSONReviver";
|
||||
|
||||
export interface IGang {
|
||||
facName: string;
|
||||
@ -42,5 +43,5 @@ export interface IGang {
|
||||
getDiscount(): number;
|
||||
getAllTaskNames(): string[];
|
||||
getUpgradeCost(upg: GangMemberUpgrade): number;
|
||||
toJSON(): any;
|
||||
toJSON(): IReviverValue;
|
||||
}
|
||||
|
@ -2,17 +2,17 @@ import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||
import { GangMember } from "../GangMember";
|
||||
import { GangMemberTask } from "../GangMemberTask";
|
||||
|
||||
interface Gang {
|
||||
export interface FormulaGang {
|
||||
respect: number;
|
||||
territory: number;
|
||||
wantedLevel: number;
|
||||
}
|
||||
|
||||
export function calculateWantedPenalty(gang: Gang): number {
|
||||
export function calculateWantedPenalty(gang: FormulaGang): number {
|
||||
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;
|
||||
let statWeight =
|
||||
(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);
|
||||
}
|
||||
|
||||
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;
|
||||
let statWeight =
|
||||
(task.hackWeight / 100) * member.hack +
|
||||
@ -53,7 +53,7 @@ export function calculateWantedLevelGain(gang: Gang, member: GangMember, task: G
|
||||
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;
|
||||
let statWeight =
|
||||
(task.hackWeight / 100) * member.hack +
|
||||
|
@ -12,7 +12,7 @@ export function calculateHackingChance(server: Server, player: IPlayer): number
|
||||
const skillMult = hackFactor * player.hacking;
|
||||
const skillChance = (skillMult - server.requiredHackingSkill) / skillMult;
|
||||
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) {
|
||||
return 1;
|
||||
}
|
||||
@ -36,7 +36,7 @@ export function calculateHackingExpGain(server: Server, player: IPlayer): number
|
||||
let expGain = baseExpGain;
|
||||
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 skillMult = (player.hacking - (server.requiredHackingSkill - 1)) / player.hacking;
|
||||
const percentMoneyHacked =
|
||||
(difficultyMult * skillMult * player.hacking_money_mult * BitNodeMultipliers.ScriptHackMoney) / balanceFactor;
|
||||
(difficultyMult * skillMult * player.mults.hacking_money * BitNodeMultipliers.ScriptHackMoney) / balanceFactor;
|
||||
if (percentMoneyHacked < 0) {
|
||||
return 0;
|
||||
}
|
||||
@ -77,7 +77,7 @@ export function calculateHackingTime(server: Server, player: IPlayer): number {
|
||||
const hackTimeMultiplier = 5;
|
||||
const hackingTime =
|
||||
(hackTimeMultiplier * skillFactor) /
|
||||
(player.hacking_speed_mult * calculateIntelligenceBonus(player.intelligence, 1));
|
||||
(player.mults.hacking_speed * calculateIntelligenceBonus(player.intelligence, 1));
|
||||
|
||||
return hackingTime;
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ export function purchaseHacknet(player: IPlayer): number {
|
||||
|
||||
// Auto generate a name for the Node
|
||||
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.hacknetNodes.push(node);
|
||||
@ -80,11 +80,11 @@ export function hasMaxNumberHacknetServers(player: IPlayer): boolean {
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
@ -97,14 +97,14 @@ export function getMaxNumberLevelUpgrades(
|
||||
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;
|
||||
}
|
||||
|
||||
let min = 1;
|
||||
let max = maxLevel - 1;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -112,13 +112,13 @@ export function getMaxNumberLevelUpgrades(
|
||||
const curr = ((min + max) / 2) | 0;
|
||||
if (
|
||||
curr !== maxLevel &&
|
||||
player.money > nodeObj.calculateLevelUpgradeCost(curr, player.hacknet_node_level_cost_mult) &&
|
||||
player.money < nodeObj.calculateLevelUpgradeCost(curr + 1, player.hacknet_node_level_cost_mult)
|
||||
player.money > nodeObj.calculateLevelUpgradeCost(curr, player.mults.hacknet_node_level_cost) &&
|
||||
player.money < nodeObj.calculateLevelUpgradeCost(curr + 1, player.mults.hacknet_node_level_cost)
|
||||
) {
|
||||
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;
|
||||
} 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;
|
||||
} else {
|
||||
return Math.min(levelsToMax, curr);
|
||||
@ -137,7 +137,7 @@ export function getMaxNumberRamUpgrades(
|
||||
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;
|
||||
}
|
||||
|
||||
@ -147,13 +147,13 @@ export function getMaxNumberRamUpgrades(
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
//We'll just loop until we find the max
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -170,14 +170,14 @@ export function getMaxNumberCoreUpgrades(
|
||||
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;
|
||||
}
|
||||
|
||||
let min = 1;
|
||||
let max = maxLevel - 1;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -186,13 +186,13 @@ export function getMaxNumberCoreUpgrades(
|
||||
const curr = ((min + max) / 2) | 0;
|
||||
if (
|
||||
curr != maxLevel &&
|
||||
player.money > nodeObj.calculateCoreUpgradeCost(curr, player.hacknet_node_core_cost_mult) &&
|
||||
player.money < nodeObj.calculateCoreUpgradeCost(curr + 1, player.hacknet_node_core_cost_mult)
|
||||
player.money > nodeObj.calculateCoreUpgradeCost(curr, player.mults.hacknet_node_core_cost) &&
|
||||
player.money < nodeObj.calculateCoreUpgradeCost(curr + 1, player.mults.hacknet_node_core_cost)
|
||||
) {
|
||||
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;
|
||||
} 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;
|
||||
} else {
|
||||
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 {
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
@ -266,14 +266,14 @@ export function purchaseLevelUpgrade(player: IPlayer, node: HacknetNode | Hackne
|
||||
}
|
||||
|
||||
player.loseMoney(cost, "hacknet_expenses");
|
||||
node.upgradeLevel(sanitizedLevels, player.hacknet_node_money_mult);
|
||||
node.upgradeLevel(sanitizedLevels, player.mults.hacknet_node_money);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function purchaseRamUpgrade(player: IPlayer, node: HacknetNode | HacknetServer, levels = 1): boolean {
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
@ -305,14 +305,14 @@ export function purchaseRamUpgrade(player: IPlayer, node: HacknetNode | HacknetS
|
||||
}
|
||||
|
||||
player.loseMoney(cost, "hacknet_expenses");
|
||||
node.upgradeRam(sanitizedLevels, player.hacknet_node_money_mult);
|
||||
node.upgradeRam(sanitizedLevels, player.mults.hacknet_node_money);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function purchaseCoreUpgrade(player: IPlayer, node: HacknetNode | HacknetServer, levels = 1): boolean {
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
@ -336,7 +336,7 @@ export function purchaseCoreUpgrade(player: IPlayer, node: HacknetNode | Hacknet
|
||||
}
|
||||
|
||||
player.loseMoney(cost, "hacknet_expenses");
|
||||
node.upgradeCore(sanitizedLevels, player.hacknet_node_money_mult);
|
||||
node.upgradeCore(sanitizedLevels, player.mults.hacknet_node_money);
|
||||
|
||||
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`);
|
||||
const hserver = GetServer(ip);
|
||||
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);
|
||||
hashes += h;
|
||||
}
|
||||
@ -467,7 +467,7 @@ export function updateHashManagerCapacity(player: IPlayer): void {
|
||||
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)) {
|
||||
console.error(`Player does not have a HashManager`);
|
||||
return false;
|
||||
@ -475,21 +475,21 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
||||
|
||||
// HashManager handles the transaction. This just needs to actually implement
|
||||
// the effects of the upgrade
|
||||
if (player.hashManager.upgrade(upgName)) {
|
||||
if (player.hashManager.upgrade(upgName, count)) {
|
||||
const upg = HashUpgrades[upgName];
|
||||
|
||||
switch (upgName) {
|
||||
case "Sell for Money": {
|
||||
player.gainMoney(upg.value, "hacknet");
|
||||
player.gainMoney(upg.value * count, "hacknet");
|
||||
break;
|
||||
}
|
||||
case "Sell for Corporation Funds": {
|
||||
const corp = player.corporation;
|
||||
if (corp === null) {
|
||||
player.hashManager.refundUpgrade(upgName);
|
||||
player.hashManager.refundUpgrade(upgName, count);
|
||||
return false;
|
||||
}
|
||||
corp.funds = corp.funds + upg.value;
|
||||
corp.funds = corp.funds + upg.value * count;
|
||||
break;
|
||||
}
|
||||
case "Reduce Minimum Security": {
|
||||
@ -497,13 +497,13 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
||||
const target = GetServer(upgTarget);
|
||||
if (target == null) {
|
||||
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.`);
|
||||
|
||||
target.changeMinimumSecurity(upg.value, true);
|
||||
target.changeMinimumSecurity(upg.value ** count, true);
|
||||
} catch (e) {
|
||||
player.hashManager.refundUpgrade(upgName);
|
||||
player.hashManager.refundUpgrade(upgName, count);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@ -513,13 +513,16 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
||||
const target = GetServer(upgTarget);
|
||||
if (target == null) {
|
||||
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.`);
|
||||
|
||||
//Manually loop the change so as to properly handle the softcap
|
||||
for (let i = 0; i < count; i++) {
|
||||
target.changeMaximumMoney(upg.value);
|
||||
}
|
||||
} catch (e) {
|
||||
player.hashManager.refundUpgrade(upgName);
|
||||
player.hashManager.refundUpgrade(upgName, count);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@ -536,11 +539,11 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
||||
// This will throw if player doesn't have a corporation
|
||||
const corp = player.corporation;
|
||||
if (corp === null) {
|
||||
player.hashManager.refundUpgrade(upgName);
|
||||
player.hashManager.refundUpgrade(upgName, count);
|
||||
return false;
|
||||
}
|
||||
for (const division of corp.divisions) {
|
||||
division.sciResearch.qty += upg.value;
|
||||
division.sciResearch.qty += upg.value * count;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -548,30 +551,31 @@ export function purchaseHashUpgrade(player: IPlayer, upgName: string, upgTarget:
|
||||
// This will throw if player isnt in Bladeburner
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) {
|
||||
player.hashManager.refundUpgrade(upgName);
|
||||
player.hashManager.refundUpgrade(upgName, count);
|
||||
return false;
|
||||
}
|
||||
bladeburner.changeRank(player, upg.value);
|
||||
bladeburner.changeRank(player, upg.value * count);
|
||||
break;
|
||||
}
|
||||
case "Exchange for Bladeburner SP": {
|
||||
// This will throw if player isnt in Bladeburner
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) {
|
||||
player.hashManager.refundUpgrade(upgName);
|
||||
player.hashManager.refundUpgrade(upgName, count);
|
||||
return false;
|
||||
}
|
||||
|
||||
bladeburner.skillPoints += upg.value;
|
||||
bladeburner.skillPoints += upg.value * count;
|
||||
break;
|
||||
}
|
||||
case "Generate Coding Contract": {
|
||||
for (let i = 0; i < count; i++) {
|
||||
generateRandomContract();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
console.warn(`Unrecognized upgrade name ${upgName}. Upgrade has no effect`);
|
||||
player.hashManager.refundUpgrade(upgName);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ import {
|
||||
import { HacknetNodeConstants } from "./data/Constants";
|
||||
|
||||
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";
|
||||
|
||||
export class HacknetNode implements IHacknetNode {
|
||||
@ -123,15 +123,14 @@ export class HacknetNode implements IHacknetNode {
|
||||
/**
|
||||
* Serialize the current object to a JSON save state.
|
||||
*/
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("HacknetNode", this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiatizes a HacknetNode object from a JSON save state.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): HacknetNode {
|
||||
static fromJSON(value: IReviverValue): HacknetNode {
|
||||
return Generic_fromJSON(HacknetNode, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
|
||||
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";
|
||||
|
||||
interface IConstructorParams {
|
||||
@ -125,7 +125,7 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
|
||||
|
||||
updateRamUsed(ram: number, player: IPlayer): void {
|
||||
super.updateRamUsed(ram, player);
|
||||
this.updateHashRate(player.hacknet_node_money_mult);
|
||||
this.updateHashRate(player.mults.hacknet_node_money);
|
||||
}
|
||||
|
||||
updateHashCapacity(): void {
|
||||
@ -145,13 +145,12 @@ export class HacknetServer extends BaseServer implements IHacknetNode {
|
||||
}
|
||||
|
||||
// Serialize the current object to a JSON save state
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("HacknetServer", this);
|
||||
}
|
||||
|
||||
// Initializes a HacknetServer Object from a JSON save state
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): HacknetServer {
|
||||
static fromJSON(value: IReviverValue): HacknetServer {
|
||||
return Generic_fromJSON(HacknetServer, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import { HashUpgrades } from "./HashUpgrades";
|
||||
import { HashUpgrade } from "./HashUpgrade";
|
||||
|
||||
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 {
|
||||
// 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
|
||||
*/
|
||||
getUpgradeCost(upgName: string): number {
|
||||
getUpgradeCost(upgName: string, count = 1): number {
|
||||
const upg = this.getUpgrade(upgName);
|
||||
const currLevel = this.upgrades[upgName];
|
||||
if (upg == null || currLevel == null) {
|
||||
@ -81,7 +81,7 @@ export class HashManager {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
return upg.getCost(currLevel);
|
||||
return upg.getCost(currLevel, count);
|
||||
}
|
||||
|
||||
prestige(): void {
|
||||
@ -97,11 +97,11 @@ export class HashManager {
|
||||
/**
|
||||
* 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];
|
||||
|
||||
// Reduce the level first, so we get the right cost
|
||||
--this.upgrades[upgName];
|
||||
this.upgrades[upgName] -= count;
|
||||
|
||||
const currLevel = this.upgrades[upgName];
|
||||
if (upg == null || currLevel == null || currLevel < 0) {
|
||||
@ -109,7 +109,7 @@ export class HashManager {
|
||||
return;
|
||||
}
|
||||
|
||||
const cost = upg.getCost(currLevel);
|
||||
const cost = upg.getCost(currLevel, count);
|
||||
this.hashes += cost;
|
||||
}
|
||||
|
||||
@ -137,33 +137,32 @@ export class HashManager {
|
||||
* Returns boolean indicating whether or not the upgrade was successfully purchased
|
||||
* Note that this does NOT actually implement the effect
|
||||
*/
|
||||
upgrade(upgName: string): boolean {
|
||||
upgrade(upgName: string, count = 1): boolean {
|
||||
const upg = HashUpgrades[upgName];
|
||||
if (upg == null) {
|
||||
console.error(`Invalid Upgrade Name given to HashManager.upgrade(): ${upgName}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const cost = this.getUpgradeCost(upgName);
|
||||
const cost = this.getUpgradeCost(upgName, count);
|
||||
|
||||
if (this.hashes < cost) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.hashes -= cost;
|
||||
++this.upgrades[upgName];
|
||||
this.upgrades[upgName] += count;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//Serialize the current object to a JSON save state.
|
||||
toJSON(): any {
|
||||
toJSON(): IReviverValue {
|
||||
return Generic_toJSON("HashManager", this);
|
||||
}
|
||||
|
||||
// Initiatizes a HashManager object from a JSON save state.
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
static fromJSON(value: any): HashManager {
|
||||
static fromJSON(value: IReviverValue): HashManager {
|
||||
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.
|
||||
effectText: (level: number) => JSX.Element | null = () => null;
|
||||
|
||||
getCost(levels: number): number {
|
||||
getCost(currentLevel: number, count = 1): 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 =
|
||||
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;
|
||||
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 = (
|
||||
<Tooltip
|
||||
title={
|
||||
@ -102,9 +102,9 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
|
||||
node.level,
|
||||
node.ram * Math.pow(2, multiplier),
|
||||
node.cores,
|
||||
props.player.hacknet_node_money_mult,
|
||||
props.player.mults.hacknet_node_money,
|
||||
) - 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 = (
|
||||
<Tooltip
|
||||
title={
|
||||
@ -148,9 +148,9 @@ export function HacknetNodeElem(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
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;
|
||||
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 = (
|
||||
<Tooltip
|
||||
title={
|
||||
|
@ -61,11 +61,16 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
const base_increase =
|
||||
calculateHashGainRate(node.level + multiplier, 0, node.maxRam, node.cores, props.player.hacknet_node_money_mult) -
|
||||
calculateHashGainRate(node.level, 0, node.maxRam, node.cores, props.player.hacknet_node_money_mult);
|
||||
calculateHashGainRate(
|
||||
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 upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, props.player.hacknet_node_level_cost_mult);
|
||||
const upgradeLevelCost = node.calculateLevelUpgradeCost(multiplier, props.player.mults.hacknet_node_level_cost);
|
||||
upgradeLevelButton = (
|
||||
<Tooltip
|
||||
title={
|
||||
@ -122,8 +127,8 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
0,
|
||||
node.maxRam * Math.pow(2, multiplier),
|
||||
node.cores,
|
||||
props.player.hacknet_node_money_mult,
|
||||
) - calculateHashGainRate(node.level, 0, node.maxRam, node.cores, props.player.hacknet_node_money_mult);
|
||||
props.player.mults.hacknet_node_money,
|
||||
) - calculateHashGainRate(node.level, 0, node.maxRam, node.cores, props.player.mults.hacknet_node_money);
|
||||
|
||||
const modded_increase =
|
||||
calculateHashGainRate(
|
||||
@ -131,11 +136,11 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
node.ramUsed,
|
||||
node.maxRam * Math.pow(2, multiplier),
|
||||
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 = (
|
||||
<Tooltip
|
||||
title={
|
||||
@ -179,11 +184,16 @@ export function HacknetServerElem(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
const base_increase =
|
||||
calculateHashGainRate(node.level, 0, node.maxRam, node.cores + multiplier, props.player.hacknet_node_money_mult) -
|
||||
calculateHashGainRate(node.level, 0, node.maxRam, node.cores, props.player.hacknet_node_money_mult);
|
||||
calculateHashGainRate(
|
||||
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 upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, props.player.hacknet_node_core_cost_mult);
|
||||
const upgradeCoreCost = node.calculateCoreUpgradeCost(multiplier, props.player.mults.hacknet_node_core_cost);
|
||||
upgradeCoresButton = (
|
||||
<Tooltip
|
||||
title={
|
||||
|
@ -16,10 +16,10 @@ export function calculateDifficulty(player: IPlayer, startingSecurityLevel: numb
|
||||
export function calculateReward(player: IPlayer, startingSecurityLevel: number): number {
|
||||
const xpMult = 10 * 60 * 15;
|
||||
const total =
|
||||
calculateSkill(player.strength_exp_mult * xpMult, player.strength_mult) +
|
||||
calculateSkill(player.defense_exp_mult * xpMult, player.defense_mult) +
|
||||
calculateSkill(player.agility_exp_mult * xpMult, player.agility_mult) +
|
||||
calculateSkill(player.dexterity_exp_mult * xpMult, player.dexterity_mult) +
|
||||
calculateSkill(player.charisma_exp_mult * xpMult, player.charisma_mult);
|
||||
calculateSkill(player.mults.strength_exp * xpMult, player.mults.strength) +
|
||||
calculateSkill(player.mults.defense_exp * xpMult, player.mults.defense) +
|
||||
calculateSkill(player.mults.agility_exp * xpMult, player.mults.agility) +
|
||||
calculateSkill(player.mults.dexterity_exp * xpMult, player.mults.dexterity) +
|
||||
calculateSkill(player.mults.charisma_exp * xpMult, player.mults.charisma);
|
||||
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 colorNames: any = {
|
||||
const colorNames: Record<string, string> = {
|
||||
red: "red",
|
||||
"#FFC107": "yellow",
|
||||
blue: "blue",
|
||||
|
@ -77,7 +77,9 @@ function LocationLetter(location: Location): React.ReactElement {
|
||||
|
||||
function ASCIICity(props: IProps): React.ReactElement {
|
||||
const locationLettersRegex = /[A-Z]/g;
|
||||
const letterMap: any = {
|
||||
const letterMap: {
|
||||
[key: string]: number;
|
||||
} = {
|
||||
A: 0,
|
||||
B: 1,
|
||||
C: 2,
|
||||
@ -106,10 +108,10 @@ function ASCIICity(props: IProps): React.ReactElement {
|
||||
Z: 25,
|
||||
};
|
||||
|
||||
const lineElems = (s: string): JSX.Element[] => {
|
||||
const elems: any[] = [];
|
||||
const matches: any[] = [];
|
||||
let match: any;
|
||||
const lineElems = (s: string): (string | React.ReactElement)[] => {
|
||||
const elems: (string | React.ReactElement)[] = [];
|
||||
const matches: RegExpExecArray[] = [];
|
||||
let match: RegExpExecArray | null = null;
|
||||
while ((match = locationLettersRegex.exec(s)) !== null) {
|
||||
matches.push(match);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import { Reputation } from "../../ui/React/Reputation";
|
||||
import { Favor } from "../../ui/React/Favor";
|
||||
import { use } from "../../ui/Context";
|
||||
import { QuitJobModal } from "../../Company/ui/QuitJobModal";
|
||||
import { CompanyWork } from "../../Work/CompanyWork";
|
||||
|
||||
type IProps = {
|
||||
locName: LocationName;
|
||||
@ -175,11 +176,12 @@ export function CompanyLocation(props: IProps): React.ReactElement {
|
||||
|
||||
const pos = companyPosition;
|
||||
if (pos instanceof CompanyPosition) {
|
||||
if (pos.isPartTimeJob() || pos.isSoftwareConsultantJob() || pos.isBusinessConsultantJob()) {
|
||||
p.startWorkPartTime(props.locName);
|
||||
} else {
|
||||
p.startWork(props.locName);
|
||||
}
|
||||
p.startWork(
|
||||
new CompanyWork({
|
||||
singularity: false,
|
||||
companyName: props.locName,
|
||||
}),
|
||||
);
|
||||
p.startFocusing();
|
||||
router.toWork();
|
||||
}
|
||||
|
@ -8,16 +8,13 @@ import Button from "@mui/material/Button";
|
||||
|
||||
import { Location } from "../Location";
|
||||
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { GetServer } from "../../Server/AllServers";
|
||||
import { Server } from "../../Server/Server";
|
||||
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { IRouter } from "../../ui/Router";
|
||||
import { serverMetadata } from "../../Server/data/servers";
|
||||
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 = {
|
||||
loc: Location;
|
||||
@ -26,51 +23,32 @@ type IProps = {
|
||||
};
|
||||
|
||||
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 {
|
||||
const loc = props.loc;
|
||||
props.p.startClass(calculateCost(), loc.expMult, stat);
|
||||
props.p.startWork(
|
||||
new ClassWork({
|
||||
classType: stat,
|
||||
location: props.loc.name,
|
||||
singularity: false,
|
||||
}),
|
||||
);
|
||||
props.p.startFocusing();
|
||||
props.router.toWork();
|
||||
}
|
||||
|
||||
function trainStrength(): void {
|
||||
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();
|
||||
const cost = calculateCost(Classes[ClassType.GymStrength], props.loc);
|
||||
|
||||
return (
|
||||
<Box sx={{ display: "grid", width: "fit-content" }}>
|
||||
<Button onClick={trainStrength}>
|
||||
<Button onClick={() => train(ClassType.GymStrength)}>
|
||||
Train Strength (<Money money={cost} player={props.p} /> / sec)
|
||||
</Button>
|
||||
<Button onClick={trainDefense}>
|
||||
<Button onClick={() => train(ClassType.GymDefense)}>
|
||||
Train Defense (<Money money={cost} player={props.p} /> / sec)
|
||||
</Button>
|
||||
<Button onClick={trainDexterity}>
|
||||
<Button onClick={() => train(ClassType.GymDexterity)}>
|
||||
Train Dexterity (<Money money={cost} player={props.p} /> / sec)
|
||||
</Button>
|
||||
<Button onClick={trainAgility}>
|
||||
<Button onClick={() => train(ClassType.GymAgility)}>
|
||||
Train Agility (<Money money={cost} player={props.p} /> / sec)
|
||||
</Button>
|
||||
</Box>
|
||||
|
@ -25,13 +25,11 @@ export class HospitalLocation extends React.Component<IProps, IState> {
|
||||
/**
|
||||
* Stores button styling that sets them all to block display
|
||||
*/
|
||||
btnStyle: any;
|
||||
btnStyle = { display: "block" };
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.btnStyle = { display: "block" };
|
||||
|
||||
this.getCost = this.getCost.bind(this);
|
||||
this.getHealed = this.getHealed.bind(this);
|
||||
|
||||
|
@ -20,84 +20,108 @@ export function SlumsLocation(): React.ReactElement {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.Shoplift.commit(router, player);
|
||||
Crimes.Shoplift.commit(player);
|
||||
router.toWork();
|
||||
player.focus = true;
|
||||
}
|
||||
|
||||
function robStore(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.RobStore.commit(router, player);
|
||||
Crimes.RobStore.commit(player);
|
||||
router.toWork();
|
||||
player.focus = true;
|
||||
}
|
||||
|
||||
function mug(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.Mug.commit(router, player);
|
||||
Crimes.Mug.commit(player);
|
||||
router.toWork();
|
||||
player.focus = true;
|
||||
}
|
||||
|
||||
function larceny(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.Larceny.commit(router, player);
|
||||
Crimes.Larceny.commit(player);
|
||||
router.toWork();
|
||||
player.focus = true;
|
||||
}
|
||||
|
||||
function dealDrugs(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.DealDrugs.commit(router, player);
|
||||
Crimes.DealDrugs.commit(player);
|
||||
router.toWork();
|
||||
player.focus = true;
|
||||
}
|
||||
|
||||
function bondForgery(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.BondForgery.commit(router, player);
|
||||
Crimes.BondForgery.commit(player);
|
||||
router.toWork();
|
||||
player.focus = true;
|
||||
}
|
||||
|
||||
function traffickArms(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.TraffickArms.commit(router, player);
|
||||
Crimes.TraffickArms.commit(player);
|
||||
router.toWork();
|
||||
player.focus = true;
|
||||
}
|
||||
|
||||
function homicide(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.Homicide.commit(router, player);
|
||||
Crimes.Homicide.commit(player);
|
||||
router.toWork();
|
||||
player.focus = true;
|
||||
}
|
||||
|
||||
function grandTheftAuto(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.GrandTheftAuto.commit(router, player);
|
||||
Crimes.GrandTheftAuto.commit(player);
|
||||
router.toWork();
|
||||
player.focus = true;
|
||||
}
|
||||
|
||||
function kidnap(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.Kidnap.commit(router, player);
|
||||
Crimes.Kidnap.commit(player);
|
||||
router.toWork();
|
||||
player.focus = true;
|
||||
}
|
||||
|
||||
function assassinate(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.Assassination.commit(router, player);
|
||||
Crimes.Assassination.commit(player);
|
||||
router.toWork();
|
||||
player.focus = true;
|
||||
}
|
||||
|
||||
function heist(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Crimes.Heist.commit(router, player);
|
||||
Crimes.Heist.commit(player);
|
||||
router.toWork();
|
||||
player.focus = true;
|
||||
}
|
||||
|
||||
const shopliftChance = Crimes.Shoplift.successRate(player);
|
||||
|
@ -56,7 +56,7 @@ export function SpecialLocation(props: IProps): React.ReactElement {
|
||||
router.toBladeburner();
|
||||
} else if (p.strength >= 100 && p.defense >= 100 && p.dexterity >= 100 && p.agility >= 100) {
|
||||
// Apply for Bladeburner division
|
||||
p.startBladeburner({ new: true });
|
||||
p.startBladeburner();
|
||||
dialogBoxCreate("You have been accepted into the Bladeburner division!");
|
||||
setRerender((old) => !old);
|
||||
|
||||
|
@ -9,15 +9,12 @@ import Button from "@mui/material/Button";
|
||||
|
||||
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 { use } from "../../ui/Context";
|
||||
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 = {
|
||||
loc: Location;
|
||||
@ -27,51 +24,23 @@ export function UniversityLocation(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const router = use.Router();
|
||||
|
||||
function calculateCost(): number {
|
||||
const server = GetServer(props.loc.name);
|
||||
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 take(stat: ClassType): void {
|
||||
const loc = props.loc;
|
||||
player.startClass(calculateCost(), loc.expMult, stat);
|
||||
function take(classType: ClassType): void {
|
||||
player.startWork(
|
||||
new ClassWork({
|
||||
classType: classType,
|
||||
location: props.loc.name,
|
||||
singularity: false,
|
||||
}),
|
||||
);
|
||||
player.startFocusing();
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
function study(): void {
|
||||
take(ClassType.StudyComputerScience);
|
||||
}
|
||||
|
||||
function dataStructures(): void {
|
||||
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 dataStructuresCost = calculateCost(Classes[ClassType.DataStructures], props.loc);
|
||||
const networksCost = calculateCost(Classes[ClassType.Networks], props.loc);
|
||||
const algorithmsCost = calculateCost(Classes[ClassType.Algorithms], props.loc);
|
||||
const managementCost = calculateCost(Classes[ClassType.Management], props.loc);
|
||||
const leadershipCost = calculateCost(Classes[ClassType.Leadership], props.loc);
|
||||
|
||||
const earnHackingExpTooltip = `Gain hacking experience!`;
|
||||
const earnCharismaExpTooltip = `Gain charisma experience!`;
|
||||
@ -79,34 +48,34 @@ export function UniversityLocation(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<Box sx={{ display: "grid", width: "fit-content" }}>
|
||||
<Tooltip title={earnHackingExpTooltip}>
|
||||
<Button onClick={study}>Study Computer Science (free)</Button>
|
||||
<Button onClick={() => take(ClassType.StudyComputerScience)}>Study Computer Science (free)</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title={earnHackingExpTooltip}>
|
||||
<Button onClick={dataStructures}>
|
||||
<Button onClick={() => take(ClassType.DataStructures)}>
|
||||
Take Data Structures course (
|
||||
<Money money={dataStructuresCost} player={player} /> / sec)
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title={earnHackingExpTooltip}>
|
||||
<Button onClick={networks}>
|
||||
<Button onClick={() => take(ClassType.Networks)}>
|
||||
Take Networks course (
|
||||
<Money money={networksCost} player={player} /> / sec)
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title={earnHackingExpTooltip}>
|
||||
<Button onClick={algorithms}>
|
||||
<Button onClick={() => take(ClassType.Algorithms)}>
|
||||
Take Algorithms course (
|
||||
<Money money={algorithmsCost} player={player} /> / sec)
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title={earnCharismaExpTooltip}>
|
||||
<Button onClick={management}>
|
||||
<Button onClick={() => take(ClassType.Management)}>
|
||||
Take Management course (
|
||||
<Money money={managementCost} player={player} /> / sec)
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title={earnCharismaExpTooltip}>
|
||||
<Button onClick={leadership}>
|
||||
<Button onClick={() => take(ClassType.Leadership)}>
|
||||
Take Leadership course (
|
||||
<Money money={leadershipCost} player={player} /> / sec)
|
||||
</Button>
|
||||
|
@ -4,6 +4,7 @@ import { Factions } from "../Faction/Factions";
|
||||
import { Faction } from "../Faction/Faction";
|
||||
import { GetServer } from "../Server/AllServers";
|
||||
import { FactionNames } from "../Faction/data/FactionNames";
|
||||
import { Server } from "../Server/Server";
|
||||
|
||||
function allFactionAugs(p: IPlayer, f: Faction): boolean {
|
||||
const factionAugs = f.augmentations.slice().filter((aug) => aug !== "NeuroFlux Governor");
|
||||
@ -24,7 +25,7 @@ export const Milestones: Milestone[] = [
|
||||
fulfilled: (): boolean => {
|
||||
const server = GetServer("CSEC");
|
||||
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 => {
|
||||
const server = GetServer("CSEC");
|
||||
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 { makeRuntimeRejectMsg } from "../NetscriptEvaluator";
|
||||
import { Player } from "../Player";
|
||||
import { CityName } from "src/Locations/data/CityNames";
|
||||
import { Settings } from "../Settings/Settings";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { CityName } from "../Locations/data/CityNames";
|
||||
import { BasicHGWOptions } from "../ScriptEditor/NetscriptDefinitions";
|
||||
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 = {
|
||||
[string: string]: ExternalAPI | ExternalFunction;
|
||||
};
|
||||
@ -36,39 +42,30 @@ export type NetscriptContext = {
|
||||
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 = {
|
||||
makeRuntimeErrorMsg: (msg: string) => string;
|
||||
string: (argName: string, v: unknown) => string;
|
||||
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;
|
||||
boolean: (v: unknown) => boolean;
|
||||
getServer: (hostname: string) => BaseServer;
|
||||
checkSingularityAccess: () => void;
|
||||
hack: (hostname: any, manual: any, { threads: requestedThreads, stock }?: any) => Promise<number>;
|
||||
getValidPort: (port: any) => IPort;
|
||||
hack: (hostname: string, manual: boolean, { threads: requestedThreads, stock }?: BasicHGWOptions) => Promise<number>;
|
||||
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(
|
||||
helpers: NetscriptHelpers,
|
||||
wrappedAPI: any,
|
||||
helpers: INetscriptHelper,
|
||||
wrappedAPI: ExternalAPI,
|
||||
workerScript: WorkerScript,
|
||||
func: (_ctx: NetscriptContext) => (...args: unknown[]) => unknown,
|
||||
...tree: string[]
|
||||
@ -91,12 +88,22 @@ function wrapFunction(
|
||||
makeRuntimeErrorMsg: (msg: string) => helpers.makeRuntimeErrorMsg(functionPath, msg),
|
||||
string: (argName: string, v: unknown) => helpers.string(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),
|
||||
boolean: helpers.boolean,
|
||||
getServer: (hostname: string) => helpers.getServer(hostname, ctx),
|
||||
checkSingularityAccess: () => helpers.checkSingularityAccess(functionName),
|
||||
hack: (hostname: any, manual: any, extra?: any) => helpers.hack(ctx, hostname, manual, extra),
|
||||
getValidPort: (port: any) => helpers.getValidPort(functionPath, port),
|
||||
hack: (hostname: string, manual: boolean, extra?: BasicHGWOptions) => helpers.hack(ctx, hostname, manual, extra),
|
||||
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 {
|
||||
@ -112,48 +119,43 @@ function wrapFunction(
|
||||
}
|
||||
|
||||
export function wrapAPI(
|
||||
helpers: NetscriptHelpers,
|
||||
helpers: INetscriptHelper,
|
||||
wrappedAPI: ExternalAPI,
|
||||
workerScript: WorkerScript,
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
namespace: any,
|
||||
namespace: object,
|
||||
...tree: string[]
|
||||
): WrappedNetscriptAPI {
|
||||
if (typeof namespace !== "object") throw new Error("Invalid namespace?");
|
||||
for (const property of Object.getOwnPropertyNames(namespace)) {
|
||||
switch (typeof namespace[property]) {
|
||||
case "function": {
|
||||
wrapFunction(helpers, wrappedAPI, workerScript, namespace[property], ...tree, property);
|
||||
break;
|
||||
}
|
||||
case "object": {
|
||||
wrapAPI(helpers, wrappedAPI, workerScript, namespace[property], ...tree, property);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
setNestedProperty(wrappedAPI, namespace[property], ...tree, property);
|
||||
}
|
||||
for (const [key, value] of Object.entries(namespace)) {
|
||||
if (typeof value === "function") {
|
||||
wrapFunction(helpers, wrappedAPI, workerScript, value, ...tree, key);
|
||||
} else if (Array.isArray(value)) {
|
||||
setNestedProperty(wrappedAPI, value, key);
|
||||
} else if (typeof value === "object") {
|
||||
wrapAPI(helpers, wrappedAPI, workerScript, value, ...tree, key);
|
||||
} else {
|
||||
setNestedProperty(wrappedAPI, value, ...tree, key);
|
||||
}
|
||||
}
|
||||
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;
|
||||
const key = tree.pop();
|
||||
if (typeof key !== "string") {
|
||||
if (!key) {
|
||||
throw new Error("Failure occured while wrapping netscript api (setNestedProperty)");
|
||||
}
|
||||
for (const branch of tree) {
|
||||
if (target[branch] === undefined) {
|
||||
target[branch] = {};
|
||||
for (let branch of Object.values(target)) {
|
||||
if (branch === undefined) {
|
||||
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;
|
||||
for (const branch of tree) {
|
||||
if (target[branch] === undefined) {
|
||||
|
@ -1,16 +1,10 @@
|
||||
import { NS } from "../ScriptEditor/NetscriptDefinitions";
|
||||
|
||||
/**
|
||||
* The environment in which a script runs. The environment holds
|
||||
* Netscript functions and arguments for that script.
|
||||
*/
|
||||
import { NS } from "src/ScriptEditor/NetscriptDefinitions";
|
||||
import { IMap } from "../types";
|
||||
|
||||
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
|
||||
*/
|
||||
@ -19,58 +13,5 @@ export class Environment {
|
||||
/**
|
||||
* Environment variables (currently only Netscript functions)
|
||||
*/
|
||||
vars: any = {};
|
||||
|
||||
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);
|
||||
}
|
||||
vars: NS | null = null;
|
||||
}
|
||||
|
@ -62,7 +62,6 @@ export const RamCostConstants: IMap<number> = {
|
||||
ScriptGetFavorToDonate: 0.1,
|
||||
ScriptCodingContractBaseRamCost: 10,
|
||||
ScriptSleeveBaseRamCost: 4,
|
||||
ScriptGetOwnedSourceFiles: 5,
|
||||
ScriptClearTerminalCost: 0.2,
|
||||
|
||||
ScriptSingularityFn1RamCost: 2,
|
||||
@ -135,8 +134,8 @@ const stock = {
|
||||
getMaxShares: RamCostConstants.ScriptGetStockRamCost,
|
||||
getPurchaseCost: RamCostConstants.ScriptGetStockRamCost,
|
||||
getSaleGain: RamCostConstants.ScriptGetStockRamCost,
|
||||
buy: RamCostConstants.ScriptBuySellStockRamCost,
|
||||
sell: RamCostConstants.ScriptBuySellStockRamCost,
|
||||
buyStock: RamCostConstants.ScriptBuySellStockRamCost,
|
||||
sellStock: RamCostConstants.ScriptBuySellStockRamCost,
|
||||
short: RamCostConstants.ScriptBuySellStockRamCost,
|
||||
sellShort: RamCostConstants.ScriptBuySellStockRamCost,
|
||||
placeOrder: RamCostConstants.ScriptBuySellStockRamCost,
|
||||
@ -191,10 +190,12 @@ const singularity = {
|
||||
getCrimeChance: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
getCrimeStats: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
getOwnedAugmentations: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
getOwnedSourceFiles: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
getAugmentationsFromFaction: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
getAugmentationCost: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
getAugmentationPrereq: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
getAugmentationPrice: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost / 2),
|
||||
getAugmentationBasePrice: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost / 2),
|
||||
getAugmentationRepReq: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost / 2),
|
||||
getAugmentationStats: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
purchaseAugmentation: SF4Cost(RamCostConstants.ScriptSingularityFn3RamCost),
|
||||
@ -505,7 +506,9 @@ const SourceRamCosts = {
|
||||
getHackTime: RamCostConstants.ScriptGetHackTimeRamCost,
|
||||
getGrowTime: RamCostConstants.ScriptGetHackTimeRamCost,
|
||||
getWeakenTime: RamCostConstants.ScriptGetHackTimeRamCost,
|
||||
getTotalScriptIncome: RamCostConstants.ScriptGetScriptRamCost,
|
||||
getScriptIncome: RamCostConstants.ScriptGetScriptRamCost,
|
||||
getTotalScriptExpGain: RamCostConstants.ScriptGetScriptRamCost,
|
||||
getScriptExpGain: RamCostConstants.ScriptGetScriptRamCost,
|
||||
getRunningScript: RamCostConstants.ScriptGetRunningScriptRamCost,
|
||||
nFormat: 0,
|
||||
@ -516,7 +519,6 @@ const SourceRamCosts = {
|
||||
getFavorToDonate: RamCostConstants.ScriptGetFavorToDonate,
|
||||
getPlayer: RamCostConstants.ScriptSingularityFn1RamCost / 4,
|
||||
mv: 0,
|
||||
getOwnedSourceFiles: RamCostConstants.ScriptGetOwnedSourceFiles,
|
||||
tail: 0,
|
||||
toast: 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 { IMap } from "../types";
|
||||
import { NS } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { ScriptDeath } from "./ScriptDeath";
|
||||
import { ScriptArg } from "./ScriptArg";
|
||||
|
||||
export class WorkerScript {
|
||||
/**
|
||||
* Script's arguments
|
||||
*/
|
||||
args: any[];
|
||||
args: ScriptArg[];
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
delayReject?: (reason?: any) => void;
|
||||
delayReject?: (reason?: ScriptDeath) => void;
|
||||
|
||||
/**
|
||||
* Stores names of all functions that have logging disabled
|
||||
@ -110,7 +112,7 @@ export class WorkerScript {
|
||||
/**
|
||||
* Function called when the script ends.
|
||||
*/
|
||||
atExit: any;
|
||||
atExit?: () => void;
|
||||
|
||||
constructor(runningScriptObj: RunningScript, pid: number, nsFuncsGenerator?: (ws: WorkerScript) => NS) {
|
||||
this.name = runningScriptObj.filename;
|
||||
@ -140,11 +142,10 @@ export class WorkerScript {
|
||||
}
|
||||
this.scriptRef = runningScriptObj;
|
||||
this.args = runningScriptObj.args.slice();
|
||||
this.env = new Environment(null);
|
||||
this.env = new Environment();
|
||||
if (typeof nsFuncsGenerator === "function") {
|
||||
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 { Player } from "../Player";
|
||||
|
||||
export function killWorkerScript(runningScriptObj: RunningScript, hostname: string, rerenderUi?: boolean): boolean;
|
||||
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;
|
||||
}
|
||||
export type killScriptParams = WorkerScript | number | { runningScript: RunningScript; hostname: string };
|
||||
|
||||
if (script instanceof WorkerScript) {
|
||||
stopAndCleanUpWorkerScript(script);
|
||||
export function killWorkerScript(params: killScriptParams): boolean {
|
||||
if (params instanceof WorkerScript) {
|
||||
stopAndCleanUpWorkerScript(params);
|
||||
|
||||
return true;
|
||||
} else if (script instanceof RunningScript && typeof hostname === "string") {
|
||||
} else if (typeof params === "number") {
|
||||
return killWorkerScriptByPid(params);
|
||||
} else {
|
||||
// Try to kill by PID
|
||||
const res = killWorkerScriptByPid(script.pid, rerenderUi);
|
||||
const res = killWorkerScriptByPid(params.runningScript.pid);
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
|
||||
// If for some reason that doesn't work, we'll try the old way
|
||||
for (const ws of workerScripts.values()) {
|
||||
if (ws.name == script.filename && ws.hostname == hostname && compareArrays(ws.args, script.args)) {
|
||||
stopAndCleanUpWorkerScript(ws, rerenderUi);
|
||||
if (
|
||||
ws.name == params.runningScript.filename &&
|
||||
ws.hostname == params.hostname &&
|
||||
compareArrays(ws.args, params.runningScript.args)
|
||||
) {
|
||||
stopAndCleanUpWorkerScript(ws);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
function killWorkerScriptByPid(pid: number, rerenderUi = true): boolean {
|
||||
function killWorkerScriptByPid(pid: number): boolean {
|
||||
const ws = workerScripts.get(pid);
|
||||
if (ws instanceof WorkerScript) {
|
||||
stopAndCleanUpWorkerScript(ws, rerenderUi);
|
||||
stopAndCleanUpWorkerScript(ws);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -68,20 +59,22 @@ function killWorkerScriptByPid(pid: number, rerenderUi = true): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
function stopAndCleanUpWorkerScript(workerScript: WorkerScript, rerenderUi = true): void {
|
||||
function stopAndCleanUpWorkerScript(workerScript: WorkerScript): void {
|
||||
if (typeof workerScript.atExit === "function") {
|
||||
try {
|
||||
workerScript.atExit();
|
||||
} catch (e: any) {
|
||||
} catch (e: unknown) {
|
||||
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.env.stopFlag = true;
|
||||
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
|
||||
* its index in the global workerScripts array
|
||||
*/
|
||||
function removeWorkerScript(workerScript: WorkerScript, rerenderUi = true): void {
|
||||
function removeWorkerScript(workerScript: WorkerScript): void {
|
||||
const ip = workerScript.hostname;
|
||||
const name = workerScript.name;
|
||||
|
||||
@ -125,10 +118,8 @@ function removeWorkerScript(workerScript: WorkerScript, rerenderUi = true): void
|
||||
// }
|
||||
AddRecentScript(workerScript);
|
||||
|
||||
if (rerenderUi) {
|
||||
WorkerScriptStartStopEventEmitter.emit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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