mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-11 10:13:52 +01:00
commit
b7f1572288
@ -4,3 +4,4 @@ dist/
|
||||
tests/*.bundle.*
|
||||
src/ThirdParty/*
|
||||
src/JSInterpreter.js
|
||||
main.bundle.js
|
@ -100,6 +100,7 @@
|
||||
flex: row nowrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.log-box-log-container {
|
||||
|
40
dist/vendor.bundle.js
vendored
40
dist/vendor.bundle.js
vendored
File diff suppressed because one or more lines are too long
@ -23,7 +23,7 @@ function createWindow() {
|
||||
|
||||
win.webContents.on("new-window", function (e, url) {
|
||||
// make sure local urls stay in electron perimeter
|
||||
if ("file://" === url.substr(0, "file://".length)) {
|
||||
if (url.substr(0, "file://".length) === "file://") {
|
||||
return;
|
||||
}
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
main.css
3
main.css
@ -2178,7 +2178,8 @@ input[type="checkbox"] {
|
||||
display: flex;
|
||||
flex: row nowrap;
|
||||
align-items: center;
|
||||
justify-content: space-between; }
|
||||
justify-content: space-between;
|
||||
cursor: grab; }
|
||||
|
||||
.log-box-log-container {
|
||||
overflow-y: auto; }
|
||||
|
File diff suppressed because one or more lines are too long
@ -2,25 +2,25 @@ const numSpaces = 4;
|
||||
const maxLineLength = 160;
|
||||
|
||||
module.exports = {
|
||||
env: {
|
||||
es6: true,
|
||||
node: true,
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
extends: "eslint:recommended",
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
experimentalObjectRestSpread: true,
|
||||
"extends": "eslint:recommended",
|
||||
"parserOptions": {
|
||||
"ecmaFeatures": {
|
||||
"experimentalObjectRestSpread": true
|
||||
},
|
||||
ecmaVersion: 8,
|
||||
sourceType: "module",
|
||||
"ecmaVersion": 8,
|
||||
"sourceType": "module"
|
||||
},
|
||||
rules: {
|
||||
"rules": {
|
||||
"accessor-pairs": [
|
||||
"error",
|
||||
{
|
||||
getWithoutSet: false,
|
||||
setWithoutGet: true,
|
||||
},
|
||||
"getWithoutSet": false,
|
||||
"setWithoutGet": true
|
||||
}
|
||||
],
|
||||
"array-bracket-newline": ["error"],
|
||||
"array-bracket-spacing": ["error"],
|
||||
@ -33,35 +33,50 @@ module.exports = {
|
||||
"block-spacing": ["error"],
|
||||
"brace-style": ["error"],
|
||||
"callback-return": ["error"],
|
||||
camelcase: ["error"],
|
||||
"camelcase": ["error"],
|
||||
"capitalized-comments": ["error"],
|
||||
"class-methods-use-this": ["error"],
|
||||
"comma-dangle": ["error"],
|
||||
"comma-spacing": ["error"],
|
||||
"comma-style": ["error", "last"],
|
||||
complexity: ["error"],
|
||||
"computed-property-spacing": ["error", "never"],
|
||||
"comma-style": [
|
||||
"error",
|
||||
"last"
|
||||
],
|
||||
"complexity": ["error"],
|
||||
"computed-property-spacing": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"consistent-return": ["error"],
|
||||
"consistent-this": ["error"],
|
||||
"constructor-super": ["error"],
|
||||
curly: ["error"],
|
||||
"curly": ["error"],
|
||||
"default-case": ["error"],
|
||||
"dot-location": ["error", "property"],
|
||||
"dot-location": [
|
||||
"error",
|
||||
"property"
|
||||
],
|
||||
"dot-notation": ["error"],
|
||||
"eol-last": ["error"],
|
||||
eqeqeq: ["error"],
|
||||
"eqeqeq": ["error"],
|
||||
"for-direction": ["error"],
|
||||
"func-call-spacing": ["error"],
|
||||
"func-name-matching": ["error"],
|
||||
"func-names": ["error", "never"],
|
||||
"func-names": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"func-style": ["error"],
|
||||
"function-paren-newline": ["error"],
|
||||
"generator-star-spacing": ["error", "before"],
|
||||
"generator-star-spacing": [
|
||||
"error",
|
||||
"before"
|
||||
],
|
||||
"getter-return": [
|
||||
"error",
|
||||
{
|
||||
allowImplicit: false,
|
||||
},
|
||||
"allowImplicit": false
|
||||
}
|
||||
],
|
||||
"global-require": ["error"],
|
||||
"guard-for-in": ["error"],
|
||||
@ -69,37 +84,52 @@ module.exports = {
|
||||
"id-blacklist": ["error"],
|
||||
"id-length": ["error"],
|
||||
"id-match": ["error"],
|
||||
"implicit-arrow-linebreak": ["error", "beside"],
|
||||
indent: [
|
||||
"implicit-arrow-linebreak": [
|
||||
"error",
|
||||
"beside"
|
||||
],
|
||||
"indent": [
|
||||
"error",
|
||||
numSpaces,
|
||||
{
|
||||
SwitchCase: 1,
|
||||
},
|
||||
"SwitchCase": 1
|
||||
}
|
||||
],
|
||||
"init-declarations": ["error"],
|
||||
"jsx-quotes": ["error"],
|
||||
"key-spacing": ["error"],
|
||||
"keyword-spacing": ["error"],
|
||||
"line-comment-position": ["error"],
|
||||
"linebreak-style": ["error", "windows"],
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"windows"
|
||||
],
|
||||
"lines-around-comment": ["error"],
|
||||
"lines-between-class-members": ["error"],
|
||||
"max-depth": ["error"],
|
||||
"max-len": ["error", maxLineLength],
|
||||
"max-len": [
|
||||
"error",
|
||||
maxLineLength
|
||||
],
|
||||
"max-lines": [
|
||||
"error",
|
||||
{
|
||||
skipBlankLines: true,
|
||||
skipComments: true,
|
||||
},
|
||||
"skipBlankLines": true,
|
||||
"skipComments": true
|
||||
}
|
||||
],
|
||||
"max-nested-callbacks": ["error"],
|
||||
"max-params": ["error"],
|
||||
"max-statements": ["error"],
|
||||
"max-statements-per-line": ["error"],
|
||||
"multiline-comment-style": ["off", "starred-block"],
|
||||
"multiline-ternary": ["error", "never"],
|
||||
"multiline-comment-style": [
|
||||
"off",
|
||||
"starred-block"
|
||||
],
|
||||
"multiline-ternary": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"new-cap": ["error"],
|
||||
"new-parens": ["error"],
|
||||
// TODO: configure this...
|
||||
@ -115,15 +145,18 @@ module.exports = {
|
||||
"no-catch-shadow": ["error"],
|
||||
"no-class-assign": ["error"],
|
||||
"no-compare-neg-zero": ["error"],
|
||||
"no-cond-assign": ["error", "except-parens"],
|
||||
"no-cond-assign": [
|
||||
"error",
|
||||
"except-parens"
|
||||
],
|
||||
"no-confusing-arrow": ["error"],
|
||||
"no-console": ["error"],
|
||||
"no-const-assign": ["error"],
|
||||
"no-constant-condition": [
|
||||
"error",
|
||||
{
|
||||
checkLoops: false,
|
||||
},
|
||||
"checkLoops": false
|
||||
}
|
||||
],
|
||||
"no-continue": ["off"],
|
||||
"no-control-regex": ["error"],
|
||||
@ -137,15 +170,15 @@ module.exports = {
|
||||
"no-duplicate-imports": [
|
||||
"error",
|
||||
{
|
||||
includeExports: true,
|
||||
},
|
||||
"includeExports": true
|
||||
}
|
||||
],
|
||||
"no-else-return": ["error"],
|
||||
"no-empty": [
|
||||
"error",
|
||||
{
|
||||
allowEmptyCatch: false,
|
||||
},
|
||||
"allowEmptyCatch": false
|
||||
}
|
||||
],
|
||||
"no-empty-character-class": ["error"],
|
||||
"no-empty-function": ["error"],
|
||||
@ -161,8 +194,8 @@ module.exports = {
|
||||
"error",
|
||||
"all",
|
||||
{
|
||||
conditionalAssign: false,
|
||||
},
|
||||
"conditionalAssign": false
|
||||
}
|
||||
],
|
||||
"no-extra-semi": ["error"],
|
||||
"no-fallthrough": ["error"],
|
||||
@ -173,17 +206,20 @@ module.exports = {
|
||||
"no-implicit-globals": ["error"],
|
||||
"no-implied-eval": ["error"],
|
||||
"no-inline-comments": ["error"],
|
||||
"no-inner-declarations": ["error", "both"],
|
||||
"no-inner-declarations": [
|
||||
"error",
|
||||
"both"
|
||||
],
|
||||
"no-invalid-regexp": ["error"],
|
||||
"no-invalid-this": ["error"],
|
||||
"no-irregular-whitespace": [
|
||||
"error",
|
||||
{
|
||||
skipComments: false,
|
||||
skipRegExps: false,
|
||||
skipStrings: false,
|
||||
skipTemplates: false,
|
||||
},
|
||||
"skipComments": false,
|
||||
"skipRegExps": false,
|
||||
"skipStrings": false,
|
||||
"skipTemplates": false
|
||||
}
|
||||
],
|
||||
"no-iterator": ["error"],
|
||||
"no-label-var": ["error"],
|
||||
@ -194,9 +230,13 @@ module.exports = {
|
||||
"no-magic-numbers": [
|
||||
"error",
|
||||
{
|
||||
ignore: [-1, 0, 1],
|
||||
ignoreArrayIndexes: true,
|
||||
},
|
||||
"ignore": [
|
||||
-1,
|
||||
0,
|
||||
1
|
||||
],
|
||||
"ignoreArrayIndexes": true
|
||||
}
|
||||
],
|
||||
"no-mixed-operators": ["error"],
|
||||
"no-mixed-requires": ["error"],
|
||||
@ -207,8 +247,8 @@ module.exports = {
|
||||
"no-multiple-empty-lines": [
|
||||
"error",
|
||||
{
|
||||
max: 1,
|
||||
},
|
||||
"max": 1
|
||||
}
|
||||
],
|
||||
"no-native-reassign": ["error"],
|
||||
"no-negated-condition": ["error"],
|
||||
@ -228,8 +268,8 @@ module.exports = {
|
||||
"no-plusplus": [
|
||||
"error",
|
||||
{
|
||||
allowForLoopAfterthoughts: true,
|
||||
},
|
||||
"allowForLoopAfterthoughts": true
|
||||
}
|
||||
],
|
||||
"no-process-env": ["error"],
|
||||
"no-process-exit": ["error"],
|
||||
@ -243,10 +283,10 @@ module.exports = {
|
||||
"no-restricted-properties": [
|
||||
"error",
|
||||
{
|
||||
message: "'log' is too general, use an appropriate level when logging.",
|
||||
object: "console",
|
||||
property: "log",
|
||||
},
|
||||
"message": "'log' is too general, use an appropriate level when logging.",
|
||||
"object": "console",
|
||||
"property": "log"
|
||||
}
|
||||
],
|
||||
"no-restricted-syntax": ["error"],
|
||||
"no-return-assign": ["error"],
|
||||
@ -255,8 +295,8 @@ module.exports = {
|
||||
"no-self-assign": [
|
||||
"error",
|
||||
{
|
||||
props: false,
|
||||
},
|
||||
"props": false
|
||||
}
|
||||
],
|
||||
"no-self-compare": ["error"],
|
||||
"no-sequences": ["error"],
|
||||
@ -293,10 +333,10 @@ module.exports = {
|
||||
"no-useless-rename": [
|
||||
"error",
|
||||
{
|
||||
ignoreDestructuring: false,
|
||||
ignoreExport: false,
|
||||
ignoreImport: false,
|
||||
},
|
||||
"ignoreDestructuring": false,
|
||||
"ignoreExport": false,
|
||||
"ignoreImport": false
|
||||
}
|
||||
],
|
||||
"no-useless-return": ["error"],
|
||||
"no-var": ["error"],
|
||||
@ -304,7 +344,10 @@ module.exports = {
|
||||
"no-warning-comments": ["error"],
|
||||
"no-whitespace-before-property": ["error"],
|
||||
"no-with": ["error"],
|
||||
"nonblock-statement-body-position": ["error", "below"],
|
||||
"nonblock-statement-body-position": [
|
||||
"error",
|
||||
"below"
|
||||
],
|
||||
"object-curly-newline": ["error"],
|
||||
"object-curly-spacing": ["error"],
|
||||
"object-property-newline": ["error"],
|
||||
@ -312,7 +355,10 @@ module.exports = {
|
||||
"one-var": ["off"],
|
||||
"one-var-declaration-per-line": ["error"],
|
||||
"operator-assignment": ["error"],
|
||||
"operator-linebreak": ["error", "none"],
|
||||
"operator-linebreak": [
|
||||
"error",
|
||||
"none"
|
||||
],
|
||||
"padded-blocks": ["off"],
|
||||
"padding-line-between-statements": ["error"],
|
||||
"prefer-arrow-callback": ["error"],
|
||||
@ -325,15 +371,24 @@ module.exports = {
|
||||
"prefer-spread": ["error"],
|
||||
"prefer-template": ["error"],
|
||||
"quote-props": ["error"],
|
||||
quotes: ["error"],
|
||||
radix: ["error", "as-needed"],
|
||||
"quotes": ["error"],
|
||||
"radix": [
|
||||
"error",
|
||||
"as-needed"
|
||||
],
|
||||
"require-await": ["error"],
|
||||
"require-jsdoc": ["off"],
|
||||
"require-yield": ["error"],
|
||||
"rest-spread-spacing": ["error", "never"],
|
||||
semi: ["error"],
|
||||
"rest-spread-spacing": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"semi": ["error"],
|
||||
"semi-spacing": ["error"],
|
||||
"semi-style": ["error", "last"],
|
||||
"semi-style": [
|
||||
"error",
|
||||
"last"
|
||||
],
|
||||
"sort-imports": ["error"],
|
||||
"sort-keys": ["error"],
|
||||
"sort-vars": ["error"],
|
||||
@ -343,25 +398,37 @@ module.exports = {
|
||||
"space-infix-ops": ["error"],
|
||||
"space-unary-ops": ["error"],
|
||||
"spaced-comment": ["error"],
|
||||
strict: ["error"],
|
||||
"strict": ["error"],
|
||||
"switch-colon-spacing": [
|
||||
"error",
|
||||
{
|
||||
after: true,
|
||||
before: false,
|
||||
},
|
||||
"after": true,
|
||||
"before": false
|
||||
}
|
||||
],
|
||||
"symbol-description": ["error"],
|
||||
"template-curly-spacing": ["error"],
|
||||
"template-tag-spacing": ["error"],
|
||||
"unicode-bom": ["error", "never"],
|
||||
"unicode-bom": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"use-isnan": ["error"],
|
||||
"valid-jsdoc": ["error"],
|
||||
"valid-typeof": ["error"],
|
||||
"vars-on-top": ["error"],
|
||||
"wrap-iife": ["error", "any"],
|
||||
"wrap-iife": [
|
||||
"error",
|
||||
"any"
|
||||
],
|
||||
"wrap-regex": ["error"],
|
||||
"yield-star-spacing": ["error", "before"],
|
||||
yoda: ["error", "never"],
|
||||
},
|
||||
"yield-star-spacing": [
|
||||
"error",
|
||||
"before"
|
||||
],
|
||||
"yoda": [
|
||||
"error",
|
||||
"never"
|
||||
]
|
||||
}
|
||||
};
|
||||
|
@ -8,8 +8,7 @@ const path = require("path");
|
||||
const exec = require("child_process").exec;
|
||||
const semver = require("./semver");
|
||||
|
||||
const getPackageJson = () =>
|
||||
new Promise((resolve, reject) => {
|
||||
const getPackageJson = () => new Promise((resolve, reject) => {
|
||||
try {
|
||||
/* eslint-disable-next-line global-require */
|
||||
resolve(require(path.resolve(process.cwd(), "package.json")));
|
||||
@ -18,8 +17,7 @@ const getPackageJson = () =>
|
||||
}
|
||||
});
|
||||
|
||||
const getEngines = (data) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const getEngines = (data) => new Promise((resolve, reject) => {
|
||||
let versions = null;
|
||||
|
||||
if (data.engines) {
|
||||
@ -33,8 +31,7 @@ const getEngines = (data) =>
|
||||
}
|
||||
});
|
||||
|
||||
const checkNpmVersion = (engines) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const checkNpmVersion = (engines) => new Promise((resolve, reject) => {
|
||||
exec("npm -v", (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
reject(`Unable to find NPM version\n${stderr}`);
|
||||
@ -46,23 +43,18 @@ const checkNpmVersion = (engines) =>
|
||||
if (semver.satisfies(npmVersion, engineVersion)) {
|
||||
resolve();
|
||||
} else {
|
||||
reject(
|
||||
`Incorrect npm version\n'package.json' specifies "${engineVersion}", you are currently running "${npmVersion}".`,
|
||||
);
|
||||
reject(`Incorrect npm version\n'package.json' specifies "${engineVersion}", you are currently running "${npmVersion}".`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const checkNodeVersion = (engines) =>
|
||||
new Promise((resolve, reject) => {
|
||||
const checkNodeVersion = (engines) => new Promise((resolve, reject) => {
|
||||
const nodeVersion = process.version.substring(1);
|
||||
|
||||
if (semver.satisfies(nodeVersion, engines.node)) {
|
||||
resolve(engines);
|
||||
} else {
|
||||
reject(
|
||||
`Incorrect node version\n'package.json' specifies "${engines.node}", you are currently running "${process.version}".`,
|
||||
);
|
||||
reject(`Incorrect node version\n'package.json' specifies "${engines.node}", you are currently running "${process.version}".`);
|
||||
}
|
||||
});
|
||||
|
||||
@ -77,5 +69,5 @@ getPackageJson()
|
||||
/* eslint-disable no-console, no-process-exit */
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
@ -444,6 +444,7 @@ function parseComparator(comp, loose) {
|
||||
}
|
||||
|
||||
class SemVer {
|
||||
|
||||
/**
|
||||
* A semantic version.
|
||||
* @param {string} version The version.
|
||||
@ -487,7 +488,7 @@ class SemVer {
|
||||
// Numberify any prerelease numeric ids
|
||||
if (matches[4]) {
|
||||
this.prerelease = matches[4].split(".").map((id) => {
|
||||
if (/^[0-9]+$/.test(id)) {
|
||||
if ((/^[0-9]+$/).test(id)) {
|
||||
const num = Number(id);
|
||||
if (num >= 0 && num < MAX_SAFE_INTEGER) {
|
||||
return num;
|
||||
@ -531,9 +532,7 @@ class SemVer {
|
||||
}
|
||||
|
||||
return (
|
||||
compareIdentifiers(this.major, other.major) ||
|
||||
compareIdentifiers(this.minor, other.minor) ||
|
||||
compareIdentifiers(this.patch, other.patch)
|
||||
compareIdentifiers(this.major, other.major) || compareIdentifiers(this.minor, other.minor) || compareIdentifiers(this.patch, other.patch)
|
||||
);
|
||||
}
|
||||
|
||||
@ -573,8 +572,7 @@ class SemVer {
|
||||
}
|
||||
}
|
||||
|
||||
const compare = (leftVersion, rightVersion, loose) =>
|
||||
new SemVer(leftVersion, loose).compare(new SemVer(rightVersion, loose));
|
||||
const compare = (leftVersion, rightVersion, loose) => new SemVer(leftVersion, loose).compare(new SemVer(rightVersion, loose));
|
||||
const gt = (leftVersion, rightVersion, loose) => compare(leftVersion, rightVersion, loose) > 0;
|
||||
const lt = (leftVersion, rightVersion, loose) => compare(leftVersion, rightVersion, loose) < 0;
|
||||
const eq = (leftVersion, rightVersion, loose) => compare(leftVersion, rightVersion, loose) === 0;
|
||||
|
@ -12,7 +12,7 @@ import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviv
|
||||
|
||||
export interface IConstructorParams {
|
||||
info: string | JSX.Element;
|
||||
stats?: JSX.Element;
|
||||
stats?: JSX.Element | null;
|
||||
isSpecial?: boolean;
|
||||
moneyCost: number;
|
||||
name: string;
|
||||
@ -369,7 +369,7 @@ export class Augmentation {
|
||||
info: string | JSX.Element;
|
||||
|
||||
// Description of the stats, often autogenerated, sometimes manually written.
|
||||
stats: JSX.Element;
|
||||
stats: JSX.Element | null;
|
||||
|
||||
// Any Augmentation not immediately available in BitNode-1 is special (e.g. Bladeburner augs)
|
||||
isSpecial = false;
|
||||
@ -507,8 +507,9 @@ export class Augmentation {
|
||||
this.mults.bladeburner_success_chance_mult = params.bladeburner_success_chance_mult;
|
||||
}
|
||||
|
||||
if (params.stats) this.stats = params.stats;
|
||||
else this.stats = generateStatsDescription(this.mults, params.programs, params.startingMoney);
|
||||
if (params.stats === undefined)
|
||||
this.stats = generateStatsDescription(this.mults, params.programs, params.startingMoney);
|
||||
else this.stats = params.stats;
|
||||
}
|
||||
|
||||
// Adds this Augmentation to the specified Factions
|
||||
|
@ -111,8 +111,8 @@ function getRandomBonus(): any {
|
||||
return bonuses[Math.floor(bonuses.length * randomNumber.random())];
|
||||
}
|
||||
|
||||
function initAugmentations() {
|
||||
for (var name in Factions) {
|
||||
function initAugmentations(): void {
|
||||
for (const name in Factions) {
|
||||
if (Factions.hasOwnProperty(name)) {
|
||||
Factions[name].augmentations = [];
|
||||
}
|
||||
@ -1555,7 +1555,7 @@ function initAugmentations() {
|
||||
repCost: 2.5e6,
|
||||
moneyCost: 0,
|
||||
info: "It's time to leave the cave.",
|
||||
stats: <></>,
|
||||
stats: null,
|
||||
});
|
||||
RedPill.addToFactions(["Daedalus"]);
|
||||
if (augmentationExists(AugmentationNames.TheRedPill)) {
|
||||
@ -1595,7 +1595,7 @@ function initAugmentations() {
|
||||
"exactly the implant does, but they promise that it will greatly " +
|
||||
"enhance your abilities.",
|
||||
hacking_grow_mult: 3,
|
||||
stats: <></>,
|
||||
stats: null,
|
||||
});
|
||||
HiveMind.addToFactions(["ECorp"]);
|
||||
if (augmentationExists(AugmentationNames.HiveMind)) {
|
||||
@ -2349,7 +2349,7 @@ function initAugmentations() {
|
||||
CONSTANTS.MultipleAugMultiplier * [1, 0.96, 0.94, 0.93][SourceFileFlags[11]],
|
||||
Player.queuedAugmentations.length,
|
||||
);
|
||||
for (var name in Augmentations) {
|
||||
for (const name in Augmentations) {
|
||||
if (Augmentations.hasOwnProperty(name)) {
|
||||
Augmentations[name].baseCost *= mult;
|
||||
}
|
||||
@ -2363,7 +2363,7 @@ function resetAugmentation(newAugObject: Augmentation): void {
|
||||
if (!(newAugObject instanceof Augmentation)) {
|
||||
throw new Error("Invalid argument 'newAugObject' passed into resetAugmentation");
|
||||
}
|
||||
var name = newAugObject.name;
|
||||
const name = newAugObject.name;
|
||||
if (augmentationExists(name)) {
|
||||
delete Augmentations[name];
|
||||
}
|
||||
@ -2397,12 +2397,12 @@ function applyAugmentation(aug: IPlayerOwnedAugmentation, reapply = false): void
|
||||
|
||||
// Push onto Player's Augmentation list
|
||||
if (!reapply) {
|
||||
var ownedAug = new PlayerOwnedAugmentation(aug.name);
|
||||
const ownedAug = new PlayerOwnedAugmentation(aug.name);
|
||||
Player.augmentations.push(ownedAug);
|
||||
}
|
||||
}
|
||||
|
||||
function installAugmentations() {
|
||||
function installAugmentations(): boolean {
|
||||
if (Player.queuedAugmentations.length == 0) {
|
||||
dialogBoxCreate("You have not purchased any Augmentations to install!");
|
||||
return false;
|
||||
@ -2440,9 +2440,10 @@ function installAugmentations() {
|
||||
"<br>You wake up in your home...you feel different...",
|
||||
);
|
||||
prestigeAugmentation();
|
||||
return true;
|
||||
}
|
||||
|
||||
function augmentationExists(name: string) {
|
||||
function augmentationExists(name: string): boolean {
|
||||
return Augmentations.hasOwnProperty(name);
|
||||
}
|
||||
|
||||
|
@ -2,42 +2,33 @@
|
||||
* Root React component for the Augmentations UI page that display all of your
|
||||
* owned and purchased Augmentations and Source-Files.
|
||||
*/
|
||||
import * as React from "react";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { InstalledAugmentationsAndSourceFiles } from "./InstalledAugmentationsAndSourceFiles";
|
||||
import { InstalledAugmentations } from "./InstalledAugmentations";
|
||||
import { PlayerMultipliers } from "./PlayerMultipliers";
|
||||
import { PurchasedAugmentations } from "./PurchasedAugmentations";
|
||||
import { SourceFiles } from "./SourceFiles";
|
||||
|
||||
import { Player } from "../../Player";
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { canGetBonus } from "../../ExportBonus";
|
||||
|
||||
type IProps = {
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Box from "@mui/material/Box";
|
||||
|
||||
interface IProps {
|
||||
exportGameFn: () => void;
|
||||
installAugmentationsFn: () => void;
|
||||
};
|
||||
|
||||
type IState = {
|
||||
rerender: boolean;
|
||||
};
|
||||
|
||||
export class AugmentationsRoot extends React.Component<IProps, IState> {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
this.state = {
|
||||
rerender: false,
|
||||
};
|
||||
this.export = this.export.bind(this);
|
||||
}
|
||||
|
||||
export(): void {
|
||||
this.props.exportGameFn();
|
||||
this.setState({
|
||||
rerender: !this.state.rerender,
|
||||
});
|
||||
export function AugmentationsRoot(props: IProps): React.ReactElement {
|
||||
const setRerender = useState(false)[1];
|
||||
|
||||
function doExport(): void {
|
||||
props.exportGameFn();
|
||||
setRerender((o) => !o);
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
function exportBonusStr(): string {
|
||||
if (canGetBonus()) return "(+1 favor to all factions)";
|
||||
return "";
|
||||
@ -45,49 +36,53 @@ export class AugmentationsRoot extends React.Component<IProps, IState> {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="augmentations-content">
|
||||
<h1>Purchased Augmentations</h1>
|
||||
<p>
|
||||
<Typography variant="h4">Augmentations</Typography>
|
||||
<Box mx={2}>
|
||||
<Typography>
|
||||
Below is a list of all Augmentations you have purchased but not yet installed. Click the button below to
|
||||
install them.
|
||||
</p>
|
||||
<p>WARNING: Installing your Augmentations resets most of your progress, including:</p>
|
||||
</Typography>
|
||||
<Typography>WARNING: Installing your Augmentations resets most of your progress, including:</Typography>
|
||||
<br />
|
||||
<p>- Stats/Skill levels and Experience</p>
|
||||
<p>- Money</p>
|
||||
<p>- Scripts on every computer but your home computer</p>
|
||||
<p>- Purchased servers</p>
|
||||
<p>- Hacknet Nodes</p>
|
||||
<p>- Faction/Company reputation</p>
|
||||
<p>- Stocks</p>
|
||||
<Typography>- Stats/Skill levels and Experience</Typography>
|
||||
<Typography>- Money</Typography>
|
||||
<Typography>- Scripts on every computer but your home computer</Typography>
|
||||
<Typography>- Purchased servers</Typography>
|
||||
<Typography>- Hacknet Nodes</Typography>
|
||||
<Typography>- Faction/Company reputation</Typography>
|
||||
<Typography>- Stocks</Typography>
|
||||
<br />
|
||||
<p>
|
||||
<Typography>
|
||||
Installing Augmentations lets you start over with the perks and benefits granted by all of the Augmentations
|
||||
you have ever installed. Also, you will keep any scripts and RAM/Core upgrades on your home computer (but
|
||||
you will lose all programs besides NUKE.exe)
|
||||
</p>
|
||||
<StdButton
|
||||
onClick={this.props.installAugmentationsFn}
|
||||
text="Install Augmentations"
|
||||
tooltip="'I never asked for this'"
|
||||
/>
|
||||
<StdButton
|
||||
addClasses="flashing-button"
|
||||
onClick={this.export}
|
||||
text={`Backup Save ${exportBonusStr()}`}
|
||||
tooltip="It's always a good idea to backup/export your save!"
|
||||
/>
|
||||
you have ever installed. Also, you will keep any scripts and RAM/Core upgrades on your home computer (but you
|
||||
will lose all programs besides NUKE.exe)
|
||||
</Typography>
|
||||
</Box>
|
||||
<Typography variant="h4" color="primary">
|
||||
Purchased Augmentations
|
||||
</Typography>
|
||||
<Box mx={2}>
|
||||
<Tooltip title={"'I never asked for this'"}>
|
||||
<Button onClick={props.installAugmentationsFn}>
|
||||
<Typography>Install Augmentations</Typography>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title={"It's always a good idea to backup/export your save!"}>
|
||||
<Button sx={{ mx: 2 }} onClick={doExport}>
|
||||
<Typography color="error">Backup Save {exportBonusStr()}</Typography>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<PurchasedAugmentations />
|
||||
<h1>Installed Augmentations</h1>
|
||||
<p>
|
||||
{`List of all Augmentations ${Player.sourceFiles.length > 0 ? "and Source Files " : ""} ` +
|
||||
`that have been installed. You have gained the effects of these.`}
|
||||
</p>
|
||||
<InstalledAugmentationsAndSourceFiles />
|
||||
<br /> <br />
|
||||
</Box>
|
||||
<Typography variant="h4">Installed Augmentations</Typography>
|
||||
<Box mx={2}>
|
||||
<Typography>
|
||||
List of all Augmentations that have been installed. You have gained the effects of these.
|
||||
</Typography>
|
||||
<InstalledAugmentations />
|
||||
</Box>
|
||||
<PlayerMultipliers />
|
||||
</div>
|
||||
<SourceFiles />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,28 @@
|
||||
/**
|
||||
* React Component for displaying a list of the player's installed Augmentations
|
||||
* on the Augmentations UI
|
||||
* React Component for displaying all of the player's installed Augmentations and
|
||||
* Source-Files.
|
||||
*
|
||||
* It also contains 'configuration' buttons that allow you to change how the
|
||||
* Augs/SF's are displayed
|
||||
*/
|
||||
import * as React from "react";
|
||||
|
||||
import { Player } from "../../Player";
|
||||
import { Augmentations } from "../../Augmentation/Augmentations";
|
||||
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { AugmentationAccordion } from "../../ui/React/AugmentationAccordion";
|
||||
import { Augmentations } from "../../Augmentation/Augmentations";
|
||||
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
||||
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { use } from "../../ui/Context";
|
||||
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
|
||||
import Button from "@mui/material/Button";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import List from "@mui/material/List";
|
||||
|
||||
export function InstalledAugmentations(): React.ReactElement {
|
||||
const sourceAugs = Player.augmentations.slice();
|
||||
const setRerender = useState(true)[1];
|
||||
const player = use.Player();
|
||||
|
||||
const sourceAugs = player.augmentations.slice();
|
||||
|
||||
if (Settings.OwnedAugmentationsOrder === OwnedAugmentationsOrderSetting.Alphabetically) {
|
||||
sourceAugs.sort((aug1, aug2) => {
|
||||
@ -21,7 +30,32 @@ export function InstalledAugmentations(): React.ReactElement {
|
||||
});
|
||||
}
|
||||
|
||||
const augs = sourceAugs.map((e) => {
|
||||
function rerender(): void {
|
||||
setRerender((old) => !old);
|
||||
}
|
||||
|
||||
function sortByAcquirementTime(): void {
|
||||
Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.AcquirementTime;
|
||||
rerender();
|
||||
}
|
||||
|
||||
function sortInOrder(): void {
|
||||
Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.Alphabetically;
|
||||
rerender();
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip title={"Sorts the Augmentations alphabetically in numeral order"}>
|
||||
<Button onClick={sortInOrder}>Sort in Order</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title={"Sorts the Augmentations based on when you acquired them (same as default)"}>
|
||||
<Button sx={{ mx: 2 }} onClick={sortByAcquirementTime}>
|
||||
Sort by Acquirement Time
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<List dense>
|
||||
{sourceAugs.map((e) => {
|
||||
const aug = Augmentations[e.name];
|
||||
|
||||
let level = null;
|
||||
@ -29,12 +63,9 @@ export function InstalledAugmentations(): React.ReactElement {
|
||||
level = e.level;
|
||||
}
|
||||
|
||||
return (
|
||||
<li key={e.name}>
|
||||
<AugmentationAccordion aug={aug} level={level} />
|
||||
</li>
|
||||
return <AugmentationAccordion key={aug.name} aug={aug} level={level} />;
|
||||
})}
|
||||
</List>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
return <>{augs}</>;
|
||||
}
|
||||
|
@ -1,115 +0,0 @@
|
||||
/**
|
||||
* React Component for displaying all of the player's installed Augmentations and
|
||||
* Source-Files.
|
||||
*
|
||||
* It also contains 'configuration' buttons that allow you to change how the
|
||||
* Augs/SF's are displayed
|
||||
*/
|
||||
import * as React from "react";
|
||||
|
||||
import { InstalledAugmentations } from "./InstalledAugmentations";
|
||||
import { ListConfiguration } from "./ListConfiguration";
|
||||
import { OwnedSourceFiles } from "./OwnedSourceFiles";
|
||||
import { SourceFileMinus1 } from "./SourceFileMinus1";
|
||||
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
|
||||
|
||||
type IProps = {
|
||||
// nothing special.
|
||||
};
|
||||
|
||||
type IState = {
|
||||
rerenderFlag: boolean;
|
||||
};
|
||||
|
||||
export class InstalledAugmentationsAndSourceFiles extends React.Component<IProps, IState> {
|
||||
listRef: React.RefObject<HTMLUListElement>;
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
rerenderFlag: false,
|
||||
};
|
||||
|
||||
this.collapseAllHeaders = this.collapseAllHeaders.bind(this);
|
||||
this.expandAllHeaders = this.expandAllHeaders.bind(this);
|
||||
this.sortByAcquirementTime = this.sortByAcquirementTime.bind(this);
|
||||
this.sortInOrder = this.sortInOrder.bind(this);
|
||||
|
||||
this.listRef = React.createRef();
|
||||
}
|
||||
|
||||
collapseAllHeaders(): void {
|
||||
const ul = this.listRef.current;
|
||||
if (ul == null) {
|
||||
return;
|
||||
}
|
||||
const tickers = ul.getElementsByClassName("accordion-header");
|
||||
for (let i = 0; i < tickers.length; ++i) {
|
||||
const ticker = tickers[i];
|
||||
if (!(ticker instanceof HTMLButtonElement)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ticker.classList.contains("active")) {
|
||||
ticker.click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expandAllHeaders(): void {
|
||||
const ul = this.listRef.current;
|
||||
if (ul == null) {
|
||||
return;
|
||||
}
|
||||
const tickers = ul.getElementsByClassName("accordion-header");
|
||||
for (let i = 0; i < tickers.length; ++i) {
|
||||
const ticker = tickers[i];
|
||||
if (!(ticker instanceof HTMLButtonElement)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ticker.classList.contains("active")) {
|
||||
ticker.click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rerender(): void {
|
||||
this.setState((prevState) => {
|
||||
return {
|
||||
rerenderFlag: !prevState.rerenderFlag,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
sortByAcquirementTime(): void {
|
||||
Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.AcquirementTime;
|
||||
this.rerender();
|
||||
}
|
||||
|
||||
sortInOrder(): void {
|
||||
Settings.OwnedAugmentationsOrder = OwnedAugmentationsOrderSetting.Alphabetically;
|
||||
this.rerender();
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
return (
|
||||
<>
|
||||
<ListConfiguration
|
||||
collapseAllButtonsFn={this.collapseAllHeaders}
|
||||
expandAllButtonsFn={this.expandAllHeaders}
|
||||
sortByAcquirementTimeFn={this.sortByAcquirementTime}
|
||||
sortInOrderFn={this.sortInOrder}
|
||||
/>
|
||||
<ul className="augmentations-list" ref={this.listRef}>
|
||||
<SourceFileMinus1 />
|
||||
<OwnedSourceFiles />
|
||||
<InstalledAugmentations />
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
/**
|
||||
* React Component for configuring the way installed augmentations and
|
||||
* Source-Files are displayed in the Augmentations UI
|
||||
*/
|
||||
import * as React from "react";
|
||||
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
|
||||
type IProps = {
|
||||
collapseAllButtonsFn: () => void;
|
||||
expandAllButtonsFn: () => void;
|
||||
sortByAcquirementTimeFn: () => void;
|
||||
sortInOrderFn: () => void;
|
||||
};
|
||||
|
||||
export function ListConfiguration(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
<StdButton onClick={props.expandAllButtonsFn} text="Expand All" />
|
||||
<StdButton onClick={props.collapseAllButtonsFn} text="Collapse All" />
|
||||
<StdButton
|
||||
onClick={props.sortInOrderFn}
|
||||
text="Sort in Order"
|
||||
tooltip="Sorts the Augmentations alphabetically and Source-Files in numeral order"
|
||||
/>
|
||||
<StdButton
|
||||
onClick={props.sortByAcquirementTimeFn}
|
||||
text="Sort by Acquirement Time"
|
||||
tooltip="Sorts the Augmentations and Source-Files based on when you acquired them (same as default)"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
@ -20,7 +20,9 @@ export function OwnedSourceFiles(): React.ReactElement {
|
||||
});
|
||||
}
|
||||
|
||||
const sfs = sourceSfs.map((e) => {
|
||||
return (
|
||||
<>
|
||||
{sourceSfs.map((e) => {
|
||||
const srcFileKey = "SourceFile" + e.n;
|
||||
const sfObj = SourceFiles[srcFileKey];
|
||||
if (sfObj == null) {
|
||||
@ -28,12 +30,8 @@ export function OwnedSourceFiles(): React.ReactElement {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<li key={e.n}>
|
||||
<SourceFileAccordion level={e.lvl} sf={sfObj} />
|
||||
</li>
|
||||
return <SourceFileAccordion key={e.n} level={e.lvl} sf={sfObj} />;
|
||||
})}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
return <>{sfs}</>;
|
||||
}
|
||||
|
@ -6,6 +6,11 @@ import * as React from "react";
|
||||
import { Player } from "../../Player";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { Augmentations } from "../Augmentations";
|
||||
import { Table, TableCell } from "../../ui/React/Table";
|
||||
import TableBody from "@mui/material/TableBody";
|
||||
import TableRow from "@mui/material/TableRow";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Box from "@mui/material/Box";
|
||||
|
||||
function calculateAugmentedStats(): any {
|
||||
const augP: any = {};
|
||||
@ -19,41 +24,51 @@ function calculateAugmentedStats(): any {
|
||||
return augP;
|
||||
}
|
||||
|
||||
export function PlayerMultipliers(): React.ReactElement {
|
||||
const mults = calculateAugmentedStats();
|
||||
function MultiplierTable(rows: any[]): React.ReactElement {
|
||||
function improvements(r: number): JSX.Element[] {
|
||||
let elems: JSX.Element[] = [];
|
||||
function Improvements({ r }: { r: number }): React.ReactElement {
|
||||
if (r) {
|
||||
elems = [<td key="2"> {"=>"} </td>, <td key="3">{numeralWrapper.formatPercentage(r)}</td>];
|
||||
}
|
||||
return elems;
|
||||
}
|
||||
|
||||
return (
|
||||
<table>
|
||||
<tbody>
|
||||
{rows.map((r: any) => (
|
||||
<tr key={r[0]}>
|
||||
<td key="0">
|
||||
<span>{r[0]} multiplier: </span>
|
||||
</td>
|
||||
<td key="1" style={{ textAlign: "right" }}>
|
||||
{numeralWrapper.formatPercentage(r[1])}
|
||||
</td>
|
||||
{improvements(r[2])}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<>
|
||||
<TableCell key="2">
|
||||
<Typography> {"=>"} </Typography>
|
||||
</TableCell>
|
||||
<TableCell key="3">
|
||||
<Typography>{numeralWrapper.formatPercentage(r)}</Typography>
|
||||
</TableCell>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return <></>;
|
||||
}
|
||||
|
||||
function MultiplierTable({ rows }: { rows: [string, number, number][] }): React.ReactElement {
|
||||
return (
|
||||
<Table size="small" padding="none">
|
||||
<TableBody>
|
||||
{rows.map((r: any) => (
|
||||
<TableRow key={r[0]}>
|
||||
<TableCell key="0">
|
||||
<Typography noWrap>{r[0]} multiplier: </Typography>
|
||||
</TableCell>
|
||||
<TableCell key="1" style={{ textAlign: "right" }}>
|
||||
<Typography noWrap>{numeralWrapper.formatPercentage(r[1])}</Typography>
|
||||
</TableCell>
|
||||
<Improvements r={r[2]} />
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
);
|
||||
}
|
||||
|
||||
export function PlayerMultipliers(): React.ReactElement {
|
||||
const mults = calculateAugmentedStats();
|
||||
|
||||
function BladeburnerMults(): React.ReactElement {
|
||||
if (!Player.canAccessBladeburner()) return <></>;
|
||||
return (
|
||||
<>
|
||||
{MultiplierTable([
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
[
|
||||
"Bladeburner Success Chance",
|
||||
Player.bladeburner_success_chance_mult,
|
||||
@ -74,7 +89,8 @@ export function PlayerMultipliers(): React.ReactElement {
|
||||
Player.bladeburner_analysis_mult,
|
||||
Player.bladeburner_analysis_mult * mults.bladeburner_analysis_mult,
|
||||
],
|
||||
])}
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
@ -82,57 +98,68 @@ export function PlayerMultipliers(): React.ReactElement {
|
||||
|
||||
return (
|
||||
<>
|
||||
<p>
|
||||
<strong>
|
||||
<u>Multipliers:</u>
|
||||
</strong>
|
||||
</p>
|
||||
<br />
|
||||
{MultiplierTable([
|
||||
<Typography variant="h4">Multipliers</Typography>
|
||||
<Box mx={2}>
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Hacking Chance ", Player.hacking_chance_mult, Player.hacking_chance_mult * mults.hacking_chance_mult],
|
||||
["Hacking Speed ", Player.hacking_speed_mult, Player.hacking_speed_mult * mults.hacking_speed_mult],
|
||||
["Hacking Money ", Player.hacking_money_mult, Player.hacking_money_mult * mults.hacking_money_mult],
|
||||
["Hacking Growth ", Player.hacking_grow_mult, Player.hacking_grow_mult * mults.hacking_grow_mult],
|
||||
])}
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
{MultiplierTable([
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Hacking Level ", Player.hacking_mult, Player.hacking_mult * mults.hacking_mult],
|
||||
["Hacking Experience ", Player.hacking_exp_mult, Player.hacking_exp_mult * mults.hacking_exp_mult],
|
||||
])}
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
{MultiplierTable([
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Strength Level ", Player.strength_mult, Player.strength_mult * mults.strength_mult],
|
||||
["Strength Experience ", Player.strength_exp_mult, Player.strength_exp_mult * mults.strength_exp_mult],
|
||||
])}
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
{MultiplierTable([
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Defense Level ", Player.defense_mult, Player.defense_mult * mults.defense_mult],
|
||||
["Defense Experience ", Player.defense_exp_mult, Player.defense_exp_mult * mults.defense_exp_mult],
|
||||
])}
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
{MultiplierTable([
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Dexterity Level ", Player.dexterity_mult, Player.dexterity_mult * mults.dexterity_mult],
|
||||
["Dexterity Experience ", Player.dexterity_exp_mult, Player.dexterity_exp_mult * mults.dexterity_exp_mult],
|
||||
])}
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
{MultiplierTable([
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Agility Level ", Player.agility_mult, Player.agility_mult * mults.agility_mult],
|
||||
["Agility Experience ", Player.agility_exp_mult, Player.agility_exp_mult * mults.agility_exp_mult],
|
||||
])}
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
{MultiplierTable([
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Charisma Level ", Player.charisma_mult, Player.charisma_mult * mults.charisma_mult],
|
||||
["Charisma Experience ", Player.charisma_exp_mult, Player.charisma_exp_mult * mults.charisma_exp_mult],
|
||||
])}
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
{MultiplierTable([
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
[
|
||||
"Hacknet Node production ",
|
||||
Player.hacknet_node_money_mult,
|
||||
@ -158,23 +185,29 @@ export function PlayerMultipliers(): React.ReactElement {
|
||||
Player.hacknet_node_level_cost_mult,
|
||||
Player.hacknet_node_level_cost_mult * mults.hacknet_node_level_cost_mult,
|
||||
],
|
||||
])}
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
{MultiplierTable([
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Company reputation gain ", Player.company_rep_mult, Player.company_rep_mult * mults.company_rep_mult],
|
||||
["Faction reputation gain ", Player.faction_rep_mult, Player.faction_rep_mult * mults.faction_rep_mult],
|
||||
["Salary ", Player.work_money_mult, Player.work_money_mult * mults.work_money_mult],
|
||||
])}
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
{MultiplierTable([
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
["Crime success ", Player.crime_success_mult, Player.crime_success_mult * mults.crime_success_mult],
|
||||
["Crime money ", Player.crime_money_mult, Player.crime_money_mult * mults.crime_money_mult],
|
||||
])}
|
||||
]}
|
||||
/>
|
||||
<br />
|
||||
|
||||
<BladeburnerMults />
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
||||
import { Player } from "../../Player";
|
||||
|
||||
import { AugmentationAccordion } from "../../ui/React/AugmentationAccordion";
|
||||
import List from "@mui/material/List";
|
||||
|
||||
export function PurchasedAugmentations(): React.ReactElement {
|
||||
const augs: React.ReactElement[] = [];
|
||||
@ -29,12 +30,8 @@ export function PurchasedAugmentations(): React.ReactElement {
|
||||
level = ownedAug.level;
|
||||
}
|
||||
|
||||
augs.push(
|
||||
<li key={`${ownedAug.name}${ownedAug.level}`}>
|
||||
<AugmentationAccordion aug={aug} level={level} />
|
||||
</li>,
|
||||
);
|
||||
augs.push(<AugmentationAccordion key={aug.name} aug={aug} level={level} />);
|
||||
}
|
||||
|
||||
return <ul className="augmentations-list">{augs}</ul>;
|
||||
return <List dense>{augs}</List>;
|
||||
}
|
||||
|
@ -2,14 +2,22 @@
|
||||
* React Component for displaying a list of the player's Source-Files
|
||||
* on the Augmentations UI
|
||||
*/
|
||||
import * as React from "react";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { Player } from "../../Player";
|
||||
import { Exploit, ExploitName } from "../../Exploits/Exploit";
|
||||
|
||||
import { BBAccordion } from "../../ui/React/BBAccordion";
|
||||
import ListItemButton from "@mui/material/ListItemButton";
|
||||
import ListItemText from "@mui/material/ListItemText";
|
||||
import Box from "@mui/material/Box";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import Collapse from "@mui/material/Collapse";
|
||||
import ExpandMore from "@mui/icons-material/ExpandMore";
|
||||
import ExpandLess from "@mui/icons-material/ExpandLess";
|
||||
|
||||
export function SourceFileMinus1(): React.ReactElement {
|
||||
const [open, setOpen] = useState(false);
|
||||
const exploits = Player.exploits;
|
||||
|
||||
if (exploits.length === 0) {
|
||||
@ -17,33 +25,35 @@ export function SourceFileMinus1(): React.ReactElement {
|
||||
}
|
||||
|
||||
return (
|
||||
<li key={-1}>
|
||||
<BBAccordion
|
||||
headerContent={
|
||||
<>
|
||||
<Box component={Paper}>
|
||||
<ListItemButton onClick={() => setOpen((old) => !old)}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography style={{ whiteSpace: "pre-wrap" }}>
|
||||
Source-File -1: Exploits in the BitNodes
|
||||
<br />
|
||||
Level {exploits.length} / ?
|
||||
</>
|
||||
}
|
||||
panelContent={
|
||||
<>
|
||||
<p>
|
||||
This Source-File can only be acquired with obscure knowledge of the game, javascript, and the web
|
||||
ecosystem.
|
||||
</p>
|
||||
<p>It increases all of the player's multipliers by 0.1%</p>
|
||||
<br />
|
||||
|
||||
<p>You have found the following exploits:</p>
|
||||
<ul>
|
||||
{exploits.map((c: Exploit) => (
|
||||
<li key={c}>* {ExploitName(c)}</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</li>
|
||||
{open ? <ExpandLess color="primary" /> : <ExpandMore color="primary" />}
|
||||
</ListItemButton>
|
||||
<Collapse in={open} unmountOnExit>
|
||||
<Box m={4}>
|
||||
<Typography>
|
||||
This Source-File can only be acquired with obscure knowledge of the game, javascript, and the web ecosystem.
|
||||
</Typography>
|
||||
<Typography>It increases all of the player's multipliers by 0.1%</Typography>
|
||||
<br />
|
||||
|
||||
<Typography>You have found the following exploits:</Typography>
|
||||
<Box mx={2}>
|
||||
{exploits.map((c: Exploit) => (
|
||||
<Typography key={c}>* {ExploitName(c)}</Typography>
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
</Collapse>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
21
src/Augmentation/ui/SourceFiles.tsx
Normal file
21
src/Augmentation/ui/SourceFiles.tsx
Normal file
@ -0,0 +1,21 @@
|
||||
import React from "react";
|
||||
import { SourceFileMinus1 } from "./SourceFileMinus1";
|
||||
import { OwnedSourceFiles } from "./OwnedSourceFiles";
|
||||
import List from "@mui/material/List";
|
||||
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Box from "@mui/material/Box";
|
||||
|
||||
export function SourceFiles(): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
<Typography variant="h4">Source Files</Typography>
|
||||
<Box mx={2}>
|
||||
<List dense>
|
||||
<SourceFileMinus1 />
|
||||
<OwnedSourceFiles />
|
||||
</List>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
}
|
@ -4,7 +4,6 @@ import { Console } from "./Console";
|
||||
import { AllPages } from "./AllPages";
|
||||
|
||||
import { use } from "../../ui/Context";
|
||||
import { IBladeburner } from "../IBladeburner";
|
||||
|
||||
export function BladeburnerRoot(): React.ReactElement {
|
||||
const player = use.Player();
|
||||
|
@ -7,7 +7,6 @@ import { IIndustry } from "../IIndustry";
|
||||
import { NewIndustryPopup } from "./NewIndustryPopup";
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
import { ICorporation } from "../ICorporation";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { MainPanel } from "./MainPanel";
|
||||
import { Industries } from "../IndustryData";
|
||||
import { use } from "../../ui/Context";
|
||||
|
@ -47,7 +47,7 @@ export function joinFaction(faction: Faction): void {
|
||||
Factions[enemy].isBanned = true;
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < Player.factionInvitations.length; ++i) {
|
||||
for (let i = 0; i < Player.factionInvitations.length; ++i) {
|
||||
if (Player.factionInvitations[i] == faction.name || Factions[Player.factionInvitations[i]].isBanned) {
|
||||
Player.factionInvitations.splice(i, 1);
|
||||
i--;
|
||||
@ -91,28 +91,29 @@ export function hasAugmentationPrereqs(aug: Augmentation): boolean {
|
||||
|
||||
export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = false): string {
|
||||
const factionInfo = fac.getInfo();
|
||||
var hasPrereqs = hasAugmentationPrereqs(aug);
|
||||
const hasPrereqs = hasAugmentationPrereqs(aug);
|
||||
if (!hasPrereqs) {
|
||||
var txt = "You must first purchase or install " + aug.prereqs.join(",") + " before you can " + "purchase this one.";
|
||||
const txt =
|
||||
"You must first purchase or install " + aug.prereqs.join(",") + " before you can " + "purchase this one.";
|
||||
if (sing) {
|
||||
return txt;
|
||||
} else {
|
||||
dialogBoxCreate(txt);
|
||||
}
|
||||
} else if (aug.baseCost !== 0 && Player.money.lt(aug.baseCost * factionInfo.augmentationPriceMult)) {
|
||||
let txt = "You don't have enough money to purchase " + aug.name;
|
||||
const txt = "You don't have enough money to purchase " + aug.name;
|
||||
if (sing) {
|
||||
return txt;
|
||||
}
|
||||
dialogBoxCreate(txt);
|
||||
} else if (fac.playerReputation < aug.baseRepRequirement) {
|
||||
let txt = "You don't have enough faction reputation to purchase " + aug.name;
|
||||
const txt = "You don't have enough faction reputation to purchase " + aug.name;
|
||||
if (sing) {
|
||||
return txt;
|
||||
}
|
||||
dialogBoxCreate(txt);
|
||||
} else if (aug.baseCost === 0 || Player.money.gte(aug.baseCost * factionInfo.augmentationPriceMult)) {
|
||||
var queuedAugmentation = new PlayerOwnedAugmentation(aug.name);
|
||||
const queuedAugmentation = new PlayerOwnedAugmentation(aug.name);
|
||||
if (aug.name == AugmentationNames.NeuroFluxGovernor) {
|
||||
queuedAugmentation.level = getNextNeurofluxLevel();
|
||||
}
|
||||
@ -122,18 +123,18 @@ export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = fal
|
||||
|
||||
// If you just purchased Neuroflux Governor, recalculate the cost
|
||||
if (aug.name == AugmentationNames.NeuroFluxGovernor) {
|
||||
var nextLevel = getNextNeurofluxLevel();
|
||||
let nextLevel = getNextNeurofluxLevel();
|
||||
--nextLevel;
|
||||
var mult = Math.pow(CONSTANTS.NeuroFluxGovernorLevelMult, nextLevel);
|
||||
const mult = Math.pow(CONSTANTS.NeuroFluxGovernorLevelMult, nextLevel);
|
||||
aug.baseRepRequirement = 500 * mult * BitNodeMultipliers.AugmentationRepCost;
|
||||
aug.baseCost = 750e3 * mult * BitNodeMultipliers.AugmentationMoneyCost;
|
||||
|
||||
for (var i = 0; i < Player.queuedAugmentations.length - 1; ++i) {
|
||||
for (let i = 0; i < Player.queuedAugmentations.length - 1; ++i) {
|
||||
aug.baseCost *= CONSTANTS.MultipleAugMultiplier * [1, 0.96, 0.94, 0.93][SourceFileFlags[11]];
|
||||
}
|
||||
}
|
||||
|
||||
for (var name in Augmentations) {
|
||||
for (const name in Augmentations) {
|
||||
if (Augmentations.hasOwnProperty(name)) {
|
||||
Augmentations[name].baseCost *= CONSTANTS.MultipleAugMultiplier * [1, 0.96, 0.94, 0.93][SourceFileFlags[11]];
|
||||
}
|
||||
@ -166,14 +167,14 @@ export function purchaseAugmentation(aug: Augmentation, fac: Faction, sing = fal
|
||||
export function getNextNeurofluxLevel(): number {
|
||||
// Get current Neuroflux level based on Player's augmentations
|
||||
let currLevel = 0;
|
||||
for (var i = 0; i < Player.augmentations.length; ++i) {
|
||||
for (let i = 0; i < Player.augmentations.length; ++i) {
|
||||
if (Player.augmentations[i].name === AugmentationNames.NeuroFluxGovernor) {
|
||||
currLevel = Player.augmentations[i].level;
|
||||
}
|
||||
}
|
||||
|
||||
// Account for purchased but uninstalled Augmentations
|
||||
for (var i = 0; i < Player.queuedAugmentations.length; ++i) {
|
||||
for (let i = 0; i < Player.queuedAugmentations.length; ++i) {
|
||||
if (Player.queuedAugmentations[i].name == AugmentationNames.NeuroFluxGovernor) {
|
||||
++currLevel;
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ import { PurchaseAugmentationsOrderSetting } from "../../Settings/SettingEnums";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { hasAugmentationPrereqs } from "../FactionHelpers";
|
||||
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { use } from "../../ui/Context";
|
||||
|
||||
import Button from "@mui/material/Button";
|
||||
@ -87,7 +86,6 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
|
||||
const augs = getAugs();
|
||||
function canBuy(augName: string): boolean {
|
||||
const aug = Augmentations[augName];
|
||||
const moneyCost = aug.baseCost * props.faction.getInfo().augmentationPriceMult;
|
||||
const repCost = aug.baseRepRequirement * props.faction.getInfo().augmentationRepRequirementMult;
|
||||
const hasReq = props.faction.playerReputation >= repCost;
|
||||
const hasRep = hasAugmentationPrereqs(aug);
|
||||
|
@ -12,8 +12,6 @@ import { Favor } from "../../ui/React/Favor";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { Reputation } from "../../ui/React/Reputation";
|
||||
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
@ -32,11 +30,6 @@ type IProps = {
|
||||
rerender: () => void;
|
||||
};
|
||||
|
||||
const inputStyleMarkup = {
|
||||
margin: "5px",
|
||||
height: "26px",
|
||||
};
|
||||
|
||||
export function DonateOption(props: IProps): React.ReactElement {
|
||||
const [donateAmt, setDonateAmt] = useState<number | null>(null);
|
||||
const digits = (CONSTANTS.DonateMoneyToRepDivisor + "").length - 1;
|
||||
@ -52,7 +45,6 @@ export function DonateOption(props: IProps): React.ReactElement {
|
||||
const amt = numeralWrapper.parseMoney(event.target.value);
|
||||
if (event.target.value === "" || isNaN(amt)) setDonateAmt(null);
|
||||
else setDonateAmt(amt);
|
||||
console.log("set");
|
||||
}
|
||||
|
||||
function donate(): void {
|
||||
|
@ -3,7 +3,7 @@
|
||||
* This is the component for displaying a single faction's UI, not the list of all
|
||||
* accessible factions
|
||||
*/
|
||||
import React, { useState, useEffect } from "react";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { AugmentationsPage } from "./AugmentationsPage";
|
||||
import { DonateOption } from "./DonateOption";
|
||||
|
@ -39,9 +39,7 @@ export function FactionsRoot(props: IProps): React.ReactElement {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography variant="h5" color="primary">
|
||||
Factions
|
||||
</Typography>
|
||||
<Typography variant="h4">Factions</Typography>
|
||||
<Typography>Lists all factions you have joined</Typography>
|
||||
<br />
|
||||
<Box display="flex" flexDirection="column">
|
||||
|
@ -7,13 +7,10 @@ import React, { useState, useEffect } from "react";
|
||||
import { Faction } from "../../Faction/Faction";
|
||||
import { FactionInfo } from "../../Faction/FactionInfo";
|
||||
|
||||
import { AutoupdatingParagraph } from "../../ui/React/AutoupdatingParagraph";
|
||||
import { ParagraphWithTooltip } from "../../ui/React/ParagraphWithTooltip";
|
||||
import { Reputation } from "../../ui/React/Reputation";
|
||||
import { Favor } from "../../ui/React/Favor";
|
||||
import { MathComponent } from "mathjax-react";
|
||||
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import Typography from "@mui/material/Typography";
|
||||
@ -25,10 +22,11 @@ type IProps = {
|
||||
factionInfo: FactionInfo;
|
||||
};
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
const useStyles = makeStyles(() =>
|
||||
createStyles({
|
||||
noformat: {
|
||||
whiteSpace: "pre-wrap",
|
||||
lineHeight: "1em",
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
@ -5,8 +5,6 @@
|
||||
*/
|
||||
import * as React from "react";
|
||||
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import Paper from "@mui/material/Paper";
|
||||
|
@ -15,9 +15,7 @@ import { Settings } from "../../Settings/Settings";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { Reputation } from "../../ui/React/Reputation";
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
import { IMap } from "../../types";
|
||||
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { Augmentation as AugFormat } from "../../ui/React/Augmentation";
|
||||
import Button from "@mui/material/Button";
|
||||
import Typography from "@mui/material/Typography";
|
||||
@ -51,7 +49,6 @@ function Requirements(props: IReqProps): React.ReactElement {
|
||||
);
|
||||
}
|
||||
|
||||
let color = !props.hasRep || !props.hasCost ? "error" : "primary";
|
||||
return (
|
||||
<React.Fragment key="f">
|
||||
<TableCell key={1}>
|
||||
@ -80,26 +77,6 @@ export function PurchaseableAugmentation(props: IProps): React.ReactElement {
|
||||
const aug = Augmentations[props.augName];
|
||||
if (aug == null) throw new Error(`aug ${props.augName} does not exists`);
|
||||
|
||||
// Whether the player has this augmentations (purchased OR installed)
|
||||
function owned(): boolean {
|
||||
let owned = false;
|
||||
for (const queuedAug of props.p.queuedAugmentations) {
|
||||
if (queuedAug.name === props.augName) {
|
||||
owned = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (const installedAug of props.p.augmentations) {
|
||||
if (installedAug.name === props.augName) {
|
||||
owned = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return owned;
|
||||
}
|
||||
|
||||
if (aug == null) {
|
||||
console.error(
|
||||
`Invalid Augmentation when trying to create PurchaseableAugmentation display element: ${props.augName}`,
|
||||
@ -175,10 +152,7 @@ export function PurchaseableAugmentation(props: IProps): React.ReactElement {
|
||||
placement="top"
|
||||
disableFocusListener
|
||||
disableTouchListener
|
||||
enterNextDelay={1000}
|
||||
enterDelay={500}
|
||||
leaveDelay={0}
|
||||
leaveTouchDelay={0}
|
||||
disableInteractive
|
||||
>
|
||||
<Typography>{btnTxt}</Typography>
|
||||
</Tooltip>
|
||||
|
@ -6,7 +6,6 @@ import { ManagementSubpage } from "./ManagementSubpage";
|
||||
import { TerritorySubpage } from "./TerritorySubpage";
|
||||
import { use } from "../../ui/Context";
|
||||
import { Factions } from "../../Faction/Factions";
|
||||
import { Gang } from "../Gang";
|
||||
|
||||
export function GangRoot(): React.ReactElement {
|
||||
const player = use.Player();
|
||||
|
@ -33,7 +33,7 @@ export function BackwardGame(props: IMinigameProps): React.ReactElement {
|
||||
const [answer] = useState(makeAnswer(difficulty));
|
||||
const [guess, setGuess] = useState("");
|
||||
|
||||
function press(event: React.KeyboardEvent<HTMLElement>): void {
|
||||
function press(this: Document, event: KeyboardEvent): void {
|
||||
event.preventDefault();
|
||||
if (event.keyCode === 16) return;
|
||||
const nextGuess = guess + event.key.toUpperCase();
|
||||
|
@ -36,7 +36,7 @@ function generateLeftSide(difficulty: Difficulty): string {
|
||||
return str;
|
||||
}
|
||||
|
||||
function getChar(event: React.KeyboardEvent<HTMLElement>): string {
|
||||
function getChar(event: KeyboardEvent): string {
|
||||
if (event.keyCode == 48 && event.shiftKey) return ")";
|
||||
if (event.keyCode == 221 && !event.shiftKey) return "]";
|
||||
if (event.keyCode == 221 && event.shiftKey) return "}";
|
||||
@ -60,7 +60,7 @@ export function BracketGame(props: IMinigameProps): React.ReactElement {
|
||||
const [right, setRight] = useState("");
|
||||
const [left] = useState(generateLeftSide(difficulty));
|
||||
|
||||
function press(event: React.KeyboardEvent<HTMLElement>): void {
|
||||
function press(this: Document, event: KeyboardEvent): void {
|
||||
event.preventDefault();
|
||||
const char = getChar(event);
|
||||
if (!char) return;
|
||||
|
@ -30,7 +30,7 @@ export function BribeGame(props: IMinigameProps): React.ReactElement {
|
||||
const [choices] = useState(makeChoices(difficulty));
|
||||
const [index, setIndex] = useState(0);
|
||||
|
||||
function press(event: React.KeyboardEvent<HTMLElement>): void {
|
||||
function press(this: Document, event: KeyboardEvent): void {
|
||||
event.preventDefault();
|
||||
const k = event.keyCode;
|
||||
if (k === 32) {
|
||||
|
@ -32,7 +32,7 @@ export function CheatCodeGame(props: IMinigameProps): React.ReactElement {
|
||||
const [code] = useState(generateCode(difficulty));
|
||||
const [index, setIndex] = useState(0);
|
||||
|
||||
function press(event: React.KeyboardEvent<HTMLElement>): void {
|
||||
function press(this: Document, event: KeyboardEvent): void {
|
||||
event.preventDefault();
|
||||
if (code[index] !== getArrow(event)) {
|
||||
props.onFailure();
|
||||
|
@ -35,7 +35,7 @@ export function Cyberpunk2077Game(props: IMinigameProps): React.ReactElement {
|
||||
const [index, setIndex] = useState(0);
|
||||
const [pos, setPos] = useState([0, 0]);
|
||||
|
||||
function press(event: React.KeyboardEvent<HTMLElement>): void {
|
||||
function press(this: Document, event: KeyboardEvent): void {
|
||||
event.preventDefault();
|
||||
const move = [0, 0];
|
||||
const arrow = getArrow(event);
|
||||
|
@ -1,22 +1,20 @@
|
||||
import React, { useEffect } from "react";
|
||||
|
||||
interface IProps {
|
||||
onKeyDown: (event: React.KeyboardEvent<HTMLElement>) => void;
|
||||
onKeyDown: (this: Document, event: KeyboardEvent) => void;
|
||||
onFailure: (options?: { automated: boolean }) => void;
|
||||
}
|
||||
|
||||
export function KeyHandler(props: IProps): React.ReactElement {
|
||||
let elem: any;
|
||||
useEffect(() => elem.focus());
|
||||
|
||||
function onKeyDown(event: React.KeyboardEvent<HTMLElement>): void {
|
||||
if (!event.isTrusted) {
|
||||
props.onFailure({ automated: true });
|
||||
return;
|
||||
}
|
||||
props.onKeyDown(event);
|
||||
useEffect(() => {
|
||||
function press(this: Document, event: KeyboardEvent): void {
|
||||
const f = props.onKeyDown.bind(this);
|
||||
f(event);
|
||||
}
|
||||
document.addEventListener("keydown", press);
|
||||
return () => document.removeEventListener("keydown", press);
|
||||
});
|
||||
|
||||
// invisible autofocused element that eats all the keypress for the minigames.
|
||||
return <div tabIndex={1} ref={(c) => (elem = c)} onKeyDown={onKeyDown} />;
|
||||
return <></>;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ export function MinesweeperGame(props: IMinigameProps): React.ReactElement {
|
||||
const [pos, setPos] = useState([0, 0]);
|
||||
const [memoryPhase, setMemoryPhase] = useState(true);
|
||||
|
||||
function press(event: React.KeyboardEvent<HTMLElement>): void {
|
||||
function press(this: Document, event: KeyboardEvent): void {
|
||||
event.preventDefault();
|
||||
if (memoryPhase) return;
|
||||
const move = [0, 0];
|
||||
|
@ -27,7 +27,7 @@ export function SlashGame(props: IMinigameProps): React.ReactElement {
|
||||
interpolate(difficulties, props.difficulty, difficulty);
|
||||
const [guarding, setGuarding] = useState(true);
|
||||
|
||||
function press(event: React.KeyboardEvent<HTMLElement>): void {
|
||||
function press(this: Document, event: KeyboardEvent): void {
|
||||
event.preventDefault();
|
||||
if (event.keyCode !== 32) return;
|
||||
if (guarding) {
|
||||
|
@ -60,7 +60,7 @@ export function WireCuttingGame(props: IMinigameProps): React.ReactElement {
|
||||
const [cutWires, setCutWires] = useState(new Array(wires.length).fill(false));
|
||||
const [questions] = useState(generateQuestion(wires, difficulty));
|
||||
|
||||
function press(event: React.KeyboardEvent<HTMLElement>): void {
|
||||
function press(this: Document, event: KeyboardEvent): void {
|
||||
event.preventDefault();
|
||||
const wireNum = parseInt(event.key);
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
import React from "react";
|
||||
|
||||
export function random(min: number, max: number): number {
|
||||
return Math.random() * (max - min) + min;
|
||||
}
|
||||
|
||||
export function getArrow(event: React.KeyboardEvent<HTMLElement>): string {
|
||||
export function getArrow(event: KeyboardEvent): string {
|
||||
switch (event.keyCode) {
|
||||
case 38:
|
||||
case 87:
|
||||
|
@ -3,10 +3,10 @@
|
||||
*
|
||||
* TThis subcomponent renders all of the buttons for traveling to different cities
|
||||
*/
|
||||
import * as React from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import { CityName } from "../data/CityNames";
|
||||
import { TravelConfirmationPopup } from "./TravelConfirmationPopup";
|
||||
import { TravelConfirmationModal } from "./TravelConfirmationModal";
|
||||
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
@ -14,11 +14,15 @@ import { IRouter } from "../../ui/Router";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
import { use } from "../../ui/Context";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { WorldMap } from "../../ui/React/WorldMap";
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Box from "@mui/material/Box";
|
||||
import Button from "@mui/material/Button";
|
||||
|
||||
type IProps = {
|
||||
p: IPlayer;
|
||||
router: IRouter;
|
||||
@ -27,7 +31,6 @@ type IProps = {
|
||||
function travel(p: IPlayer, router: IRouter, to: CityName): void {
|
||||
const cost = CONSTANTS.TravelCost;
|
||||
if (!p.canAfford(cost)) {
|
||||
dialogBoxCreate(`You cannot afford to travel to ${to}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -37,69 +40,69 @@ function travel(p: IPlayer, router: IRouter, to: CityName): void {
|
||||
router.toCity();
|
||||
}
|
||||
|
||||
function createTravelPopup(p: IPlayer, router: IRouter, city: CityName): void {
|
||||
if (Settings.SuppressTravelConfirmation) {
|
||||
travel(p, router, city);
|
||||
export function TravelAgencyRoot(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const router = use.Router();
|
||||
const setRerender = useState(false)[1];
|
||||
const [open, setOpen] = useState(false);
|
||||
const [destination, setDestination] = useState(CityName.Sector12);
|
||||
function rerender(): void {
|
||||
setRerender((o) => !o);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(rerender, 1000);
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
|
||||
function startTravel(city: CityName): void {
|
||||
const cost = CONSTANTS.TravelCost;
|
||||
if (!player.canAfford(cost)) {
|
||||
return;
|
||||
}
|
||||
const popupId = `travel-confirmation`;
|
||||
createPopup(popupId, TravelConfirmationPopup, {
|
||||
player: p,
|
||||
city: city,
|
||||
travel: () => travel(p, router, city),
|
||||
popupId: popupId,
|
||||
});
|
||||
if (Settings.SuppressTravelConfirmation) {
|
||||
travel(player, router, city);
|
||||
return;
|
||||
}
|
||||
setOpen(true);
|
||||
setDestination(city);
|
||||
}
|
||||
|
||||
function ASCIIWorldMap(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<div className="noselect">
|
||||
<p>
|
||||
<>
|
||||
<Typography variant="h4">Travel Agency</Typography>
|
||||
<Box mx={2}>
|
||||
<Typography>
|
||||
From here, you can travel to any other city! A ticket costs{" "}
|
||||
<Money money={CONSTANTS.TravelCost} player={props.p} />.
|
||||
</p>
|
||||
<WorldMap
|
||||
currentCity={props.p.city}
|
||||
onTravel={(city: CityName) => createTravelPopup(props.p, props.router, city)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ListWorldMap(props: IProps): React.ReactElement {
|
||||
return (
|
||||
</Typography>
|
||||
{Settings.DisableASCIIArt ? (
|
||||
<div>
|
||||
<p>
|
||||
From here, you can travel to any other city! A ticket costs{" "}
|
||||
<Money money={CONSTANTS.TravelCost} player={props.p} />.
|
||||
</p>
|
||||
{Object.values(CityName)
|
||||
.filter((city: string) => city != props.p.city)
|
||||
.map((city: string) => {
|
||||
const match = Object.entries(CityName).find((entry) => entry[1] === city);
|
||||
if (match === undefined) throw new Error(`could not find key for city '${city}'`);
|
||||
return (
|
||||
<StdButton
|
||||
key={city}
|
||||
onClick={() => createTravelPopup(props.p, props.router, city as CityName)}
|
||||
style={{ display: "block" }}
|
||||
text={`Travel to ${city}`}
|
||||
/>
|
||||
<React.Fragment key={city}>
|
||||
<Button onClick={() => startTravel(city as CityName)} sx={{ m: 2 }}>
|
||||
<Typography>Travel to {city}</Typography>
|
||||
</Button>
|
||||
<br />
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function TravelAgencyRoot(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
<h1>Travel Agency</h1>
|
||||
{Settings.DisableASCIIArt ? (
|
||||
<ListWorldMap p={props.p} router={props.router} />
|
||||
) : (
|
||||
<ASCIIWorldMap p={props.p} router={props.router} />
|
||||
<WorldMap currentCity={props.p.city} onTravel={(city: CityName) => startTravel(city)} />
|
||||
)}
|
||||
</Box>
|
||||
<TravelConfirmationModal
|
||||
city={destination}
|
||||
travel={() => travel(player, router, destination)}
|
||||
open={open}
|
||||
onClose={() => setOpen(false)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
37
src/Locations/ui/TravelConfirmationModal.tsx
Normal file
37
src/Locations/ui/TravelConfirmationModal.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import React from "react";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { Modal } from "../../ui/React/Modal";
|
||||
import { use } from "../../ui/Context";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
|
||||
interface IProps {
|
||||
city: string;
|
||||
travel: () => void;
|
||||
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export function TravelConfirmationModal(props: IProps): React.ReactElement {
|
||||
const player = use.Player();
|
||||
const cost = CONSTANTS.TravelCost;
|
||||
function travel(): void {
|
||||
props.travel();
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal open={props.open} onClose={props.onClose}>
|
||||
<Typography>
|
||||
Would you like to travel to {props.city}? The trip will cost <Money money={cost} player={player} />.
|
||||
</Typography>
|
||||
<br />
|
||||
<br />
|
||||
<Button onClick={travel}>
|
||||
<Typography>Travel</Typography>
|
||||
</Button>
|
||||
</Modal>
|
||||
);
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
import React from "react";
|
||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { Money } from "../../ui/React/Money";
|
||||
import { removePopup } from "../../ui/React/createPopup";
|
||||
|
||||
interface IProps {
|
||||
player: IPlayer;
|
||||
city: string;
|
||||
travel: () => void;
|
||||
popupId: string;
|
||||
}
|
||||
|
||||
export function TravelConfirmationPopup(props: IProps): React.ReactElement {
|
||||
const cost = CONSTANTS.TravelCost;
|
||||
function travel(): void {
|
||||
props.travel();
|
||||
removePopup(props.popupId);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<span>
|
||||
Would you like to travel to {props.city}? The trip will cost <Money money={cost} player={props.player} />.
|
||||
</span>
|
||||
<br />
|
||||
<br />
|
||||
<button className="std-button" onClick={travel}>
|
||||
Travel
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
}
|
@ -20,7 +20,7 @@ function sendMessage(msg: Message, forced = false): void {
|
||||
}
|
||||
|
||||
function showMessage(msg: Message): void {
|
||||
var txt =
|
||||
const txt =
|
||||
"Message received from unknown sender: <br><br>" +
|
||||
"<i>" +
|
||||
msg.msg +
|
||||
@ -33,15 +33,15 @@ function showMessage(msg: Message): void {
|
||||
|
||||
//Adds a message to a server
|
||||
function addMessageToServer(msg: Message, serverHostname: string): void {
|
||||
var server = GetServerByHostname(serverHostname);
|
||||
const server = GetServerByHostname(serverHostname);
|
||||
if (server == null) {
|
||||
console.warn(`Could not find server ${serverHostname}`);
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < server.messages.length; ++i) {
|
||||
const msg = server.messages[i];
|
||||
if (typeof msg === "string") continue;
|
||||
if (msg.filename === msg.filename) {
|
||||
for (let i = 0; i < server.messages.length; ++i) {
|
||||
const other = server.messages[i];
|
||||
if (typeof other === "string") continue;
|
||||
if (msg.filename === other.filename) {
|
||||
return; //Already exists
|
||||
}
|
||||
}
|
||||
@ -49,7 +49,7 @@ function addMessageToServer(msg: Message, serverHostname: string): void {
|
||||
}
|
||||
|
||||
//Checks if any of the 'timed' messages should be sent
|
||||
function checkForMessagesToSend() {
|
||||
function checkForMessagesToSend(): void {
|
||||
if (redPillFlag) return;
|
||||
const jumper0 = Messages[MessageFilenames.Jumper0];
|
||||
const jumper1 = Messages[MessageFilenames.Jumper1];
|
||||
@ -107,7 +107,7 @@ function loadMessages(saveString: string): void {
|
||||
Messages = JSON.parse(saveString, Reviver);
|
||||
}
|
||||
|
||||
let MessageFilenames = {
|
||||
const MessageFilenames = {
|
||||
Jumper0: "j0.msg",
|
||||
Jumper1: "j1.msg",
|
||||
Jumper2: "j2.msg",
|
||||
@ -119,7 +119,7 @@ let MessageFilenames = {
|
||||
RedPill: "icarus.msg",
|
||||
};
|
||||
|
||||
function initMessages() {
|
||||
function initMessages(): void {
|
||||
//Reset
|
||||
Messages = {};
|
||||
|
||||
|
@ -40,14 +40,14 @@ export class WorkerScript {
|
||||
/**
|
||||
* Stores names of all functions that have logging disabled
|
||||
*/
|
||||
disableLogs: IMap<string> = {};
|
||||
disableLogs: IMap<boolean> = {};
|
||||
|
||||
/**
|
||||
* Used for dynamic RAM calculation. Stores names of all functions that have
|
||||
* already been checked by this script.
|
||||
* TODO: Could probably just combine this with loadedFns?
|
||||
*/
|
||||
dynamicLoadedFns: IMap<string> = {};
|
||||
dynamicLoadedFns: IMap<boolean> = {};
|
||||
|
||||
/**
|
||||
* Tracks dynamic RAM usage
|
||||
|
@ -12,7 +12,7 @@ import { AllServers } from "../Server/AllServers";
|
||||
import { compareArrays } from "../../utils/helpers/compareArrays";
|
||||
import { roundToTwo } from "../../utils/helpers/roundToTwo";
|
||||
|
||||
export function killWorkerScript(runningScriptObj: RunningScript, serverIp: string, rerenderUi: boolean): boolean;
|
||||
export function killWorkerScript(runningScriptObj: RunningScript, serverIp: string, rerenderUi?: boolean): boolean;
|
||||
export function killWorkerScript(workerScript: WorkerScript): boolean;
|
||||
export function killWorkerScript(pid: number): boolean;
|
||||
export function killWorkerScript(
|
||||
|
@ -14,12 +14,8 @@ export function netscriptDelay(time: number, workerScript: WorkerScript): Promis
|
||||
});
|
||||
}
|
||||
|
||||
export function makeRuntimeRejectMsg(workerScript: WorkerScript, msg: string, exp: any = null) {
|
||||
var lineNum = "";
|
||||
if (exp != null) {
|
||||
var num = getErrorLineNumber(exp, workerScript);
|
||||
lineNum = " (Line " + num + ")";
|
||||
}
|
||||
export function makeRuntimeRejectMsg(workerScript: WorkerScript, msg: string): string {
|
||||
const lineNum = "";
|
||||
const server = AllServers[workerScript.serverIp];
|
||||
if (server == null) {
|
||||
throw new Error(`WorkerScript constructed with invalid server ip: ${workerScript.serverIp}`);
|
||||
@ -32,7 +28,7 @@ export function resolveNetscriptRequestedThreads(
|
||||
workerScript: WorkerScript,
|
||||
functionName: string,
|
||||
requestedThreads: number,
|
||||
) {
|
||||
): number {
|
||||
const threads = workerScript.scriptRef.threads;
|
||||
if (!requestedThreads) {
|
||||
return isNaN(threads) || threads < 1 ? 1 : threads;
|
||||
@ -53,26 +49,11 @@ export function resolveNetscriptRequestedThreads(
|
||||
return requestedThreadsAsInt;
|
||||
}
|
||||
|
||||
export function getErrorLineNumber(exp: any, workerScript: WorkerScript): number {
|
||||
return -1;
|
||||
// TODO wtf is codeCode?
|
||||
|
||||
// var code = workerScript.scriptRef.codeCode();
|
||||
|
||||
// //Split code up to the start of the node
|
||||
// try {
|
||||
// code = code.substring(0, exp.start);
|
||||
// return (code.match(/\n/g) || []).length + 1;
|
||||
// } catch (e) {
|
||||
// return -1;
|
||||
// }
|
||||
}
|
||||
|
||||
export function isScriptErrorMessage(msg: string): boolean {
|
||||
if (!isString(msg)) {
|
||||
return false;
|
||||
}
|
||||
let splitMsg = msg.split("|");
|
||||
const splitMsg = msg.split("|");
|
||||
if (splitMsg.length != 4) {
|
||||
return false;
|
||||
}
|
||||
|
2
src/NetscriptFunctions.d.ts
vendored
2
src/NetscriptFunctions.d.ts
vendored
@ -1,2 +0,0 @@
|
||||
import { WorkerScript } from "./Netscript/WorkerScript";
|
||||
export declare function NetscriptFunctions(workerScript: WorkerScript): any;
|
File diff suppressed because it is too large
Load Diff
@ -16,10 +16,9 @@ function makeScriptBlob(code: string): Blob {
|
||||
// (i.e. hack, grow, etc.).
|
||||
// When the promise returned by this resolves, we'll have finished
|
||||
// running the main function of the script.
|
||||
export async function executeJSScript(scripts: Script[] = [], workerScript: WorkerScript) {
|
||||
let loadedModule;
|
||||
export async function executeJSScript(scripts: Script[] = [], workerScript: WorkerScript): Promise<void> {
|
||||
let uurls: ScriptUrl[] = [];
|
||||
let script = workerScript.getScript();
|
||||
const script = workerScript.getScript();
|
||||
if (script === null) throw new Error("script is null");
|
||||
if (shouldCompile(script, scripts)) {
|
||||
// The URL at the top is the one we want to import. It will
|
||||
@ -35,9 +34,9 @@ export async function executeJSScript(scripts: Script[] = [], workerScript: Work
|
||||
script.module = new Promise((resolve) => resolve(eval("import(uurls[uurls.length - 1].url)")));
|
||||
script.dependencies = uurls;
|
||||
}
|
||||
loadedModule = await script.module;
|
||||
const loadedModule = await script.module;
|
||||
|
||||
let ns = workerScript.env.vars;
|
||||
const ns = workerScript.env.vars;
|
||||
|
||||
// TODO: putting await in a non-async function yields unhelpful
|
||||
// "SyntaxError: unexpected reserved word" with no line number information.
|
||||
|
@ -14,13 +14,11 @@ import { isScriptErrorMessage, makeRuntimeRejectMsg } from "./NetscriptEvaluator
|
||||
import { NetscriptFunctions } from "./NetscriptFunctions";
|
||||
import { executeJSScript } from "./NetscriptJSEvaluator";
|
||||
import { NetscriptPort, IPort } from "./NetscriptPort";
|
||||
import { Player } from "./Player";
|
||||
import { RunningScript } from "./Script/RunningScript";
|
||||
import { getRamUsageFromRunningScript } from "./Script/RunningScriptHelpers";
|
||||
import { scriptCalculateOfflineProduction } from "./Script/ScriptHelpers";
|
||||
import { Script } from "./Script/Script";
|
||||
import { AllServers } from "./Server/AllServers";
|
||||
import { Server } from "./Server/Server";
|
||||
import { BaseServer } from "./Server/BaseServer";
|
||||
import { Settings } from "./Settings/Settings";
|
||||
import { setTimeoutRef } from "./utils/SetTimeoutRef";
|
||||
@ -38,11 +36,11 @@ import { simple as walksimple } from "acorn-walk";
|
||||
|
||||
// Netscript Ports are instantiated here
|
||||
export const NetscriptPorts: IPort[] = [];
|
||||
for (var i = 0; i < CONSTANTS.NumNetscriptPorts; ++i) {
|
||||
for (let i = 0; i < CONSTANTS.NumNetscriptPorts; ++i) {
|
||||
NetscriptPorts.push(NetscriptPort());
|
||||
}
|
||||
|
||||
export function prestigeWorkerScripts() {
|
||||
export function prestigeWorkerScripts(): void {
|
||||
for (const ws of workerScripts.values()) {
|
||||
ws.env.stopFlag = true;
|
||||
killWorkerScript(ws);
|
||||
@ -65,7 +63,7 @@ function startNetscript2Script(workerScript: WorkerScript): Promise<WorkerScript
|
||||
// We need to go through the environment and wrap each function in such a way that it
|
||||
// can be called at most once at a time. This will prevent situations where multiple
|
||||
// hack promises are outstanding, for example.
|
||||
function wrap(propName: string, f: Function): Function {
|
||||
function wrap(propName: string, f: (...args: any[]) => Promise<void>): (...args: any[]) => Promise<void> {
|
||||
// This function unfortunately cannot be an async function, because we don't
|
||||
// know if the original one was, and there's no way to tell.
|
||||
return function (...args: any[]) {
|
||||
@ -85,7 +83,7 @@ function startNetscript2Script(workerScript: WorkerScript): Promise<WorkerScript
|
||||
"Did you forget to await hack(), grow(), or some other " +
|
||||
"promise-returning function? (Currently running: %s tried to run: %s)";
|
||||
if (runningFn) {
|
||||
workerScript.errorMessage = makeRuntimeRejectMsg(workerScript, sprintf(msg, runningFn, propName), null);
|
||||
workerScript.errorMessage = makeRuntimeRejectMsg(workerScript, sprintf(msg, runningFn, propName));
|
||||
throw workerScript;
|
||||
}
|
||||
runningFn = propName;
|
||||
@ -112,7 +110,7 @@ function startNetscript2Script(workerScript: WorkerScript): Promise<WorkerScript
|
||||
};
|
||||
}
|
||||
|
||||
for (let prop in workerScript.env.vars) {
|
||||
for (const prop in workerScript.env.vars) {
|
||||
if (typeof workerScript.env.vars[prop] !== "function") continue;
|
||||
workerScript.env.vars[prop] = wrap(prop, workerScript.env.vars[prop]);
|
||||
}
|
||||
@ -145,9 +143,9 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<WorkerScript
|
||||
workerScript.running = true;
|
||||
|
||||
//Process imports
|
||||
var codeWithImports, codeLineOffset;
|
||||
let codeWithImports, codeLineOffset;
|
||||
try {
|
||||
let importProcessingRes = processNetscript1Imports(code, workerScript);
|
||||
const importProcessingRes = processNetscript1Imports(code, workerScript);
|
||||
codeWithImports = importProcessingRes.code;
|
||||
codeLineOffset = importProcessingRes.lineOffset;
|
||||
} catch (e) {
|
||||
@ -158,11 +156,11 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<WorkerScript
|
||||
return Promise.resolve(workerScript);
|
||||
}
|
||||
|
||||
var interpreterInitialization = function (int: any, scope: any) {
|
||||
const interpreterInitialization = function (int: any, scope: any): void {
|
||||
//Add the Netscript environment
|
||||
var ns = NetscriptFunctions(workerScript);
|
||||
for (let name in ns) {
|
||||
let entry = ns[name];
|
||||
const ns = NetscriptFunctions(workerScript);
|
||||
for (const name in ns) {
|
||||
const entry = ns[name];
|
||||
if (typeof entry === "function") {
|
||||
//Async functions need to be wrapped. See JS-Interpreter documentation
|
||||
if (
|
||||
@ -173,20 +171,20 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<WorkerScript
|
||||
name === "prompt" ||
|
||||
name === "manualHack"
|
||||
) {
|
||||
let tempWrapper = function () {
|
||||
let fnArgs = [];
|
||||
const tempWrapper = function (...args: any[]): void {
|
||||
const fnArgs = [];
|
||||
|
||||
//All of the Object/array elements are in JSInterpreter format, so
|
||||
//we have to convert them back to native format to pass them to these fns
|
||||
for (let i = 0; i < arguments.length - 1; ++i) {
|
||||
if (typeof arguments[i] === "object" || arguments[i].constructor === Array) {
|
||||
fnArgs.push(int.pseudoToNative(arguments[i]));
|
||||
for (let i = 0; i < args.length - 1; ++i) {
|
||||
if (typeof args[i] === "object" || args[i].constructor === Array) {
|
||||
fnArgs.push(int.pseudoToNative(args[i]));
|
||||
} else {
|
||||
fnArgs.push(arguments[i]);
|
||||
fnArgs.push(args[i]);
|
||||
}
|
||||
}
|
||||
let cb = arguments[arguments.length - 1];
|
||||
let fnPromise = entry.apply(null, fnArgs);
|
||||
const cb = args[args.length - 1];
|
||||
const fnPromise = entry(...fnArgs);
|
||||
fnPromise
|
||||
.then(function (res: any) {
|
||||
cb(res);
|
||||
@ -206,25 +204,25 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<WorkerScript
|
||||
name === "run" ||
|
||||
name === "exec"
|
||||
) {
|
||||
let tempWrapper = function () {
|
||||
let fnArgs = [];
|
||||
const tempWrapper = function (...args: any[]): void {
|
||||
const fnArgs = [];
|
||||
|
||||
//All of the Object/array elements are in JSInterpreter format, so
|
||||
//we have to convert them back to native format to pass them to these fns
|
||||
for (let i = 0; i < arguments.length; ++i) {
|
||||
if (typeof arguments[i] === "object" || arguments[i].constructor === Array) {
|
||||
fnArgs.push(int.pseudoToNative(arguments[i]));
|
||||
for (let i = 0; i < args.length; ++i) {
|
||||
if (typeof args[i] === "object" || args[i].constructor === Array) {
|
||||
fnArgs.push(int.pseudoToNative(args[i]));
|
||||
} else {
|
||||
fnArgs.push(arguments[i]);
|
||||
fnArgs.push(args[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return entry.apply(null, fnArgs);
|
||||
return entry(...fnArgs);
|
||||
};
|
||||
int.setProperty(scope, name, int.createNativeFunction(tempWrapper));
|
||||
} else {
|
||||
let tempWrapper = function () {
|
||||
let res = entry.apply(null, arguments);
|
||||
const tempWrapper = function (...args: any[]): any {
|
||||
const res = entry(...args);
|
||||
|
||||
if (res == null) {
|
||||
return res;
|
||||
@ -247,7 +245,7 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<WorkerScript
|
||||
int.setProperty(scope, "args", int.nativeToPseudo(workerScript.args));
|
||||
};
|
||||
|
||||
var interpreter: any;
|
||||
let interpreter: any;
|
||||
try {
|
||||
interpreter = new Interpreter(codeWithImports, interpreterInitialization, codeLineOffset);
|
||||
} catch (e) {
|
||||
@ -259,7 +257,7 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<WorkerScript
|
||||
}
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
function runInterpreter() {
|
||||
function runInterpreter(): void {
|
||||
try {
|
||||
if (workerScript.env.stopFlag) {
|
||||
return reject(workerScript);
|
||||
@ -314,7 +312,7 @@ function processNetscript1Imports(code: string, workerScript: WorkerScript): any
|
||||
sourceType: "module",
|
||||
});
|
||||
|
||||
var server = workerScript.getServer();
|
||||
const server = workerScript.getServer();
|
||||
if (server == null) {
|
||||
throw new Error("Failed to find underlying Server object for script");
|
||||
}
|
||||
@ -339,11 +337,11 @@ function processNetscript1Imports(code: string, workerScript: WorkerScript): any
|
||||
if (scriptName.startsWith("./")) {
|
||||
scriptName = scriptName.slice(2);
|
||||
}
|
||||
let script = getScript(scriptName);
|
||||
const script = getScript(scriptName);
|
||||
if (script == null) {
|
||||
throw new Error("'Import' failed due to invalid script: " + scriptName);
|
||||
}
|
||||
let scriptAst = parse(script.code, {
|
||||
const scriptAst = parse(script.code, {
|
||||
ecmaVersion: 9,
|
||||
allowReserved: true,
|
||||
sourceType: "module",
|
||||
@ -351,9 +349,9 @@ function processNetscript1Imports(code: string, workerScript: WorkerScript): any
|
||||
|
||||
if (node.specifiers.length === 1 && node.specifiers[0].type === "ImportNamespaceSpecifier") {
|
||||
// import * as namespace from script
|
||||
let namespace = node.specifiers[0].local.name;
|
||||
let fnNames: string[] = []; //Names only
|
||||
let fnDeclarations: any[] = []; //FunctionDeclaration Node objects
|
||||
const namespace = node.specifiers[0].local.name;
|
||||
const fnNames: string[] = []; //Names only
|
||||
const fnDeclarations: any[] = []; //FunctionDeclaration Node objects
|
||||
walksimple(scriptAst, {
|
||||
FunctionDeclaration: (node: any) => {
|
||||
fnNames.push(node.id.name);
|
||||
@ -382,13 +380,13 @@ function processNetscript1Imports(code: string, workerScript: WorkerScript): any
|
||||
//import {...} from script
|
||||
|
||||
//Get array of all fns to import
|
||||
let fnsToImport: string[] = [];
|
||||
const fnsToImport: string[] = [];
|
||||
node.specifiers.forEach((e: any) => {
|
||||
fnsToImport.push(e.local.name);
|
||||
});
|
||||
|
||||
//Walk through script and get FunctionDeclaration code for all specified fns
|
||||
let fnDeclarations: any[] = [];
|
||||
const fnDeclarations: any[] = [];
|
||||
walksimple(scriptAst, {
|
||||
FunctionDeclaration: (node: any) => {
|
||||
if (fnsToImport.includes(node.id.name)) {
|
||||
@ -412,7 +410,7 @@ function processNetscript1Imports(code: string, workerScript: WorkerScript): any
|
||||
}
|
||||
|
||||
//Remove ImportDeclarations from AST. These ImportDeclarations must be in top-level
|
||||
var linesRemoved = 0;
|
||||
let linesRemoved = 0;
|
||||
if (ast.type !== "Program" || ast.body == null) {
|
||||
throw new Error("Code could not be properly parsed");
|
||||
}
|
||||
@ -424,7 +422,7 @@ function processNetscript1Imports(code: string, workerScript: WorkerScript): any
|
||||
}
|
||||
|
||||
//Calculated line offset
|
||||
var lineOffset = (generatedCode.match(/\n/g) || []).length - linesRemoved;
|
||||
const lineOffset = (generatedCode.match(/\n/g) || []).length - linesRemoved;
|
||||
|
||||
//Convert the AST back into code
|
||||
code = generate(ast);
|
||||
@ -432,7 +430,7 @@ function processNetscript1Imports(code: string, workerScript: WorkerScript): any
|
||||
//Add the imported code and re-generate in ES5 (JS Interpreter for NS1 only supports ES5);
|
||||
code = generatedCode + code;
|
||||
|
||||
var res = {
|
||||
const res = {
|
||||
code: code,
|
||||
lineOffset: lineOffset,
|
||||
};
|
||||
@ -595,8 +593,8 @@ export function createAndAddWorkerScript(
|
||||
/**
|
||||
* Updates the online running time stat of all running scripts
|
||||
*/
|
||||
export function updateOnlineScriptTimes(numCycles = 1) {
|
||||
var time = (numCycles * CONSTANTS._idleSpeed) / 1000; //seconds
|
||||
export function updateOnlineScriptTimes(numCycles = 1): void {
|
||||
const time = (numCycles * CONSTANTS._idleSpeed) / 1000; //seconds
|
||||
for (const ws of workerScripts.values()) {
|
||||
ws.scriptRef.onlineRunningTime += time;
|
||||
}
|
||||
@ -606,8 +604,8 @@ export function updateOnlineScriptTimes(numCycles = 1) {
|
||||
* Called when the game is loaded. Loads all running scripts (from all servers)
|
||||
* into worker scripts so that they will start running
|
||||
*/
|
||||
export function loadAllRunningScripts() {
|
||||
let skipScriptLoad = window.location.href.toLowerCase().indexOf("?noscripts") !== -1;
|
||||
export function loadAllRunningScripts(): void {
|
||||
const skipScriptLoad = window.location.href.toLowerCase().indexOf("?noscripts") !== -1;
|
||||
if (skipScriptLoad) {
|
||||
console.info("Skipping the load of any scripts during startup");
|
||||
}
|
||||
@ -661,7 +659,7 @@ export function runScriptFromScript(
|
||||
}
|
||||
|
||||
// Check if the script is already running
|
||||
let runningScriptObj = server.getRunningScript(scriptname, args);
|
||||
const runningScriptObj = server.getRunningScript(scriptname, args);
|
||||
if (runningScriptObj != null) {
|
||||
workerScript.log(caller, `'${scriptname}' is already running on '${server.hostname}'`);
|
||||
return 0;
|
||||
@ -703,7 +701,7 @@ export function runScriptFromScript(
|
||||
caller,
|
||||
`'${scriptname}' on '${server.hostname}' with ${threads} threads and args: ${arrayToString(args)}.`,
|
||||
);
|
||||
let runningScriptObj = new RunningScript(script, args);
|
||||
const runningScriptObj = new RunningScript(script, args);
|
||||
runningScriptObj.threads = threads;
|
||||
|
||||
return startWorkerScript(runningScriptObj, server, workerScript);
|
||||
|
@ -206,7 +206,7 @@ export interface IPlayer {
|
||||
regenerateHp(amt: number): void;
|
||||
recordMoneySource(amt: number, source: string): void;
|
||||
setMoney(amt: number): void;
|
||||
singularityStopWork(): void;
|
||||
singularityStopWork(): string;
|
||||
startBladeburner(p: any): void;
|
||||
startFactionWork(router: IRouter, faction: Faction): void;
|
||||
startClass(router: IRouter, costMult: number, expMult: number, className: string): void;
|
||||
|
@ -213,7 +213,7 @@ export class PlayerObject implements IPlayer {
|
||||
regenerateHp: (amt: number) => void;
|
||||
recordMoneySource: (amt: number, source: string) => void;
|
||||
setMoney: (amt: number) => void;
|
||||
singularityStopWork: () => void;
|
||||
singularityStopWork: () => string;
|
||||
startBladeburner: (p: any) => void;
|
||||
startFactionWork: (router: IRouter, faction: Faction) => void;
|
||||
startClass: (router: IRouter, costMult: number, expMult: number, className: string) => void;
|
||||
@ -409,8 +409,8 @@ export class PlayerObject implements IPlayer {
|
||||
|
||||
this.crimeType = "";
|
||||
|
||||
(this.timeWorked = 0), //in m;
|
||||
(this.timeWorkedCreateProgram = 0);
|
||||
this.timeWorked = 0; //in m;
|
||||
this.timeWorkedCreateProgram = 0;
|
||||
this.timeNeededToCompleteWork = 0;
|
||||
|
||||
this.work_money_mult = 1;
|
||||
@ -438,15 +438,15 @@ export class PlayerObject implements IPlayer {
|
||||
this.bladeburner = null;
|
||||
this.bladeburner_max_stamina_mult = 1;
|
||||
this.bladeburner_stamina_gain_mult = 1;
|
||||
(this.bladeburner_analysis_mult = 1), //Field Analysis Onl;
|
||||
(this.bladeburner_success_chance_mult = 1);
|
||||
this.bladeburner_analysis_mult = 1; //Field Analysis Onl;
|
||||
this.bladeburner_success_chance_mult = 1;
|
||||
|
||||
// Sleeves & Re-sleeving
|
||||
this.sleeves = [];
|
||||
this.resleeves = [];
|
||||
(this.sleevesFromCovenant = 0), // # of Duplicate sleeves purchased from the covenan;
|
||||
this.sleevesFromCovenant = 0; // # of Duplicate sleeves purchased from the covenan;
|
||||
//bitnode
|
||||
(this.bitNodeN = 1);
|
||||
this.bitNodeN = 1;
|
||||
|
||||
//Used to store the last update time.
|
||||
this.lastUpdate = 0;
|
||||
@ -455,10 +455,10 @@ export class PlayerObject implements IPlayer {
|
||||
this.playtimeSinceLastBitnode = 0;
|
||||
|
||||
// Keep track of where money comes from
|
||||
(this.moneySourceA = new MoneySourceTracker()), // Where money comes from since last-installed Augmentatio;
|
||||
(this.moneySourceB = new MoneySourceTracker()), // Where money comes from for this entire BitNode ru;
|
||||
this.moneySourceA = new MoneySourceTracker(); // Where money comes from since last-installed Augmentatio;
|
||||
this.moneySourceB = new MoneySourceTracker(); // Where money comes from for this entire BitNode ru;
|
||||
// Production since last Augmentation installation
|
||||
(this.scriptProdSinceLastAug = 0);
|
||||
this.scriptProdSinceLastAug = 0;
|
||||
|
||||
this.exploits = [];
|
||||
|
||||
|
@ -2,7 +2,7 @@ import { Bladeburner } from "../../Bladeburner/Bladeburner";
|
||||
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
|
||||
import { IPlayer } from "../IPlayer";
|
||||
|
||||
export function canAccessBladeburner(this: IPlayer) {
|
||||
export function canAccessBladeburner(this: IPlayer): boolean {
|
||||
if (this.bitNodeN === 8) {
|
||||
return false;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import { applyAugmentation } from "../../Augmentation/AugmentationHelpers";
|
||||
import { PlayerOwnedAugmentation } from "../../Augmentation/PlayerOwnedAugmentation";
|
||||
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
||||
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
|
||||
import { CodingContractRewardType } from "../../CodingContracts";
|
||||
import { CodingContractRewardType, ICodingContractReward } from "../../CodingContracts";
|
||||
import { Company } from "../../Company/Company";
|
||||
import { Companies } from "../../Company/Companies";
|
||||
import { getNextCompanyPositionHelper } from "../../Company/GetNextCompanyPosition";
|
||||
@ -15,13 +15,11 @@ import * as posNames from "../../Company/data/companypositionnames";
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { Programs } from "../../Programs/Programs";
|
||||
import { determineCrimeSuccess } from "../../Crime/CrimeHelpers";
|
||||
import { ICodingContractReward } from "../../CodingContracts";
|
||||
import { Crimes } from "../../Crime/Crimes";
|
||||
import { Exploit } from "../../Exploits/Exploit";
|
||||
import { Faction } from "../../Faction/Faction";
|
||||
import { Factions } from "../../Faction/Factions";
|
||||
import { resetGangs } from "../../Gang/AllGangs";
|
||||
import { hasHacknetServers } from "../../Hacknet/HacknetHelpers";
|
||||
import { Cities } from "../../Locations/Cities";
|
||||
import { Locations } from "../../Locations/Locations";
|
||||
import { CityName } from "../../Locations/data/CityNames";
|
||||
@ -60,9 +58,9 @@ import { Money } from "../../ui/React/Money";
|
||||
|
||||
import React from "react";
|
||||
|
||||
export function init(this: IPlayer) {
|
||||
export function init(this: IPlayer): void {
|
||||
/* Initialize Player's home computer */
|
||||
var t_homeComp = safetlyCreateUniqueServer({
|
||||
const t_homeComp = safetlyCreateUniqueServer({
|
||||
adminRights: true,
|
||||
hostname: "home",
|
||||
ip: createUniqueRandomIp(),
|
||||
@ -78,8 +76,8 @@ export function init(this: IPlayer) {
|
||||
this.getHomeComputer().programs.push(Programs.NukeProgram.name);
|
||||
}
|
||||
|
||||
export function prestigeAugmentation(this: IPlayer) {
|
||||
var homeComp = this.getHomeComputer();
|
||||
export function prestigeAugmentation(this: IPlayer): void {
|
||||
const homeComp = this.getHomeComputer();
|
||||
this.currentServer = homeComp.ip;
|
||||
this.homeComputer = homeComp.ip;
|
||||
|
||||
@ -178,7 +176,7 @@ export function prestigeAugmentation(this: IPlayer) {
|
||||
this.hp = this.max_hp;
|
||||
}
|
||||
|
||||
export function prestigeSourceFile(this: IPlayer) {
|
||||
export function prestigeSourceFile(this: IPlayer): void {
|
||||
this.prestigeAugmentation();
|
||||
// Duplicate sleeves are reset to level 1 every Bit Node (but the number of sleeves you have persists)
|
||||
for (let i = 0; i < this.sleeves.length; ++i) {
|
||||
@ -262,7 +260,7 @@ export function updateSkillLevels(this: IPlayer): void {
|
||||
this.intelligence = 0;
|
||||
}
|
||||
|
||||
var ratio = this.hp / this.max_hp;
|
||||
const ratio = this.hp / this.max_hp;
|
||||
this.max_hp = Math.floor(10 + this.defense / 10);
|
||||
this.hp = Math.round(this.max_hp * ratio);
|
||||
}
|
||||
@ -313,7 +311,7 @@ export function hasProgram(this: IPlayer, programName: string): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < home.programs.length; ++i) {
|
||||
for (let i = 0; i < home.programs.length; ++i) {
|
||||
if (programName.toLowerCase() == home.programs[i].toLowerCase()) {
|
||||
return true;
|
||||
}
|
||||
@ -354,7 +352,7 @@ export function canAfford(this: IPlayer, cost: number): boolean {
|
||||
return this.money.gte(cost);
|
||||
}
|
||||
|
||||
export function recordMoneySource(this: IPlayer, amt: number, source: string) {
|
||||
export function recordMoneySource(this: IPlayer, amt: number, source: string): void {
|
||||
if (!(this.moneySourceA instanceof MoneySourceTracker)) {
|
||||
console.warn(`Player.moneySourceA was not properly initialized. Resetting`);
|
||||
this.moneySourceA = new MoneySourceTracker();
|
||||
@ -367,7 +365,7 @@ export function recordMoneySource(this: IPlayer, amt: number, source: string) {
|
||||
this.moneySourceB.record(amt, source);
|
||||
}
|
||||
|
||||
export function gainHackingExp(this: IPlayer, exp: number) {
|
||||
export function gainHackingExp(this: IPlayer, exp: number): void {
|
||||
if (isNaN(exp)) {
|
||||
console.error("ERR: NaN passed into Player.gainHackingExp()");
|
||||
return;
|
||||
@ -380,7 +378,7 @@ export function gainHackingExp(this: IPlayer, exp: number) {
|
||||
this.hacking_skill = calculateSkillF(this.hacking_exp, this.hacking_mult * BitNodeMultipliers.HackingLevelMultiplier);
|
||||
}
|
||||
|
||||
export function gainStrengthExp(this: IPlayer, exp: number) {
|
||||
export function gainStrengthExp(this: IPlayer, exp: number): void {
|
||||
if (isNaN(exp)) {
|
||||
console.error("ERR: NaN passed into Player.gainStrengthExp()");
|
||||
return;
|
||||
@ -393,7 +391,7 @@ export function gainStrengthExp(this: IPlayer, exp: number) {
|
||||
this.strength = calculateSkillF(this.strength_exp, this.strength_mult * BitNodeMultipliers.StrengthLevelMultiplier);
|
||||
}
|
||||
|
||||
export function gainDefenseExp(this: IPlayer, exp: number) {
|
||||
export function gainDefenseExp(this: IPlayer, exp: number): void {
|
||||
if (isNaN(exp)) {
|
||||
console.error("ERR: NaN passed into player.gainDefenseExp()");
|
||||
return;
|
||||
@ -406,7 +404,7 @@ export function gainDefenseExp(this: IPlayer, exp: number) {
|
||||
this.defense = calculateSkillF(this.defense_exp, this.defense_mult * BitNodeMultipliers.DefenseLevelMultiplier);
|
||||
}
|
||||
|
||||
export function gainDexterityExp(this: IPlayer, exp: number) {
|
||||
export function gainDexterityExp(this: IPlayer, exp: number): void {
|
||||
if (isNaN(exp)) {
|
||||
console.error("ERR: NaN passed into Player.gainDexterityExp()");
|
||||
return;
|
||||
@ -520,7 +518,7 @@ export function resetWorkStatus(this: IPlayer, generalType?: string, group?: str
|
||||
this.className = "";
|
||||
}
|
||||
|
||||
export function processWorkEarnings(this: IPlayer, numCycles = 1) {
|
||||
export function processWorkEarnings(this: IPlayer, numCycles = 1): void {
|
||||
const focusBonus = this.focus ? 1 : 0.8;
|
||||
const hackExpGain = focusBonus * this.workHackExpGainRate * numCycles;
|
||||
const strExpGain = focusBonus * this.workStrExpGainRate * numCycles;
|
||||
@ -574,7 +572,7 @@ export function startWork(this: IPlayer, router: IRouter, companyName: string):
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
export function cancelationPenalty(this: IPlayer) {
|
||||
export function cancelationPenalty(this: IPlayer): number {
|
||||
const specialIp = SpecialServerIps[this.companyName];
|
||||
if (typeof specialIp === "string" && specialIp !== "") {
|
||||
const server = AllServers[specialIp];
|
||||
@ -588,7 +586,7 @@ export function cancelationPenalty(this: IPlayer) {
|
||||
export function work(this: IPlayer, numCycles: number): boolean {
|
||||
// Cap the number of cycles being processed to whatever would put you at
|
||||
// the work time limit (8 hours)
|
||||
var overMax = false;
|
||||
let overMax = false;
|
||||
if (this.timeWorked + CONSTANTS._idleSpeed * numCycles >= CONSTANTS.MillisecondsPer8Hours) {
|
||||
overMax = true;
|
||||
numCycles = Math.round((CONSTANTS.MillisecondsPer8Hours - this.timeWorked) / CONSTANTS._idleSpeed);
|
||||
@ -714,7 +712,7 @@ export function startWorkPartTime(this: IPlayer, router: IRouter, companyName: s
|
||||
export function workPartTime(this: IPlayer, numCycles: number): boolean {
|
||||
//Cap the number of cycles being processed to whatever would put you at the
|
||||
//work time limit (8 hours)
|
||||
var overMax = false;
|
||||
let overMax = false;
|
||||
if (this.timeWorked + CONSTANTS._idleSpeed * numCycles >= CONSTANTS.MillisecondsPer8Hours) {
|
||||
overMax = true;
|
||||
numCycles = Math.round((CONSTANTS.MillisecondsPer8Hours - this.timeWorked) / CONSTANTS._idleSpeed);
|
||||
@ -733,7 +731,7 @@ export function workPartTime(this: IPlayer, numCycles: number): boolean {
|
||||
}
|
||||
|
||||
export function finishWorkPartTime(this: IPlayer, sing = false): string {
|
||||
var company = Companies[this.companyName];
|
||||
const company = Companies[this.companyName];
|
||||
company.playerReputation += this.workRepGained;
|
||||
|
||||
this.updateSkillLevels();
|
||||
@ -764,7 +762,7 @@ export function finishWorkPartTime(this: IPlayer, sing = false): string {
|
||||
this.resetWorkStatus();
|
||||
|
||||
if (sing) {
|
||||
var res =
|
||||
const res =
|
||||
"You worked for " +
|
||||
convertTimeMsToTimeElapsedString(this.timeWorked) +
|
||||
" and " +
|
||||
@ -802,7 +800,7 @@ export function stopFocusing(this: IPlayer): void {
|
||||
/* Working for Faction */
|
||||
export function startFactionWork(this: IPlayer, router: IRouter, faction: Faction): void {
|
||||
//Update reputation gain rate to account for faction favor
|
||||
var favorMult = 1 + faction.favor / 100;
|
||||
let favorMult = 1 + faction.favor / 100;
|
||||
if (isNaN(favorMult)) {
|
||||
favorMult = 1;
|
||||
}
|
||||
@ -818,7 +816,7 @@ export function startFactionWork(this: IPlayer, router: IRouter, faction: Factio
|
||||
router.toWork();
|
||||
}
|
||||
|
||||
export function startFactionHackWork(this: IPlayer, router: IRouter, faction: Faction) {
|
||||
export function startFactionHackWork(this: IPlayer, router: IRouter, faction: Faction): void {
|
||||
this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkHacking);
|
||||
|
||||
this.workHackExpGainRate = 0.15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
@ -833,7 +831,7 @@ export function startFactionHackWork(this: IPlayer, router: IRouter, faction: Fa
|
||||
this.startFactionWork(router, faction);
|
||||
}
|
||||
|
||||
export function startFactionFieldWork(this: IPlayer, router: IRouter, faction: Faction) {
|
||||
export function startFactionFieldWork(this: IPlayer, router: IRouter, faction: Faction): void {
|
||||
this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkField);
|
||||
|
||||
this.workHackExpGainRate = 0.1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
@ -850,7 +848,7 @@ export function startFactionFieldWork(this: IPlayer, router: IRouter, faction: F
|
||||
this.startFactionWork(router, faction);
|
||||
}
|
||||
|
||||
export function startFactionSecurityWork(this: IPlayer, router: IRouter, faction: Faction) {
|
||||
export function startFactionSecurityWork(this: IPlayer, router: IRouter, faction: Faction): void {
|
||||
this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkSecurity);
|
||||
|
||||
this.workHackExpGainRate = 0.05 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
|
||||
@ -867,7 +865,7 @@ export function startFactionSecurityWork(this: IPlayer, router: IRouter, faction
|
||||
this.startFactionWork(router, faction);
|
||||
}
|
||||
|
||||
export function workForFaction(this: IPlayer, numCycles: number) {
|
||||
export function workForFaction(this: IPlayer, numCycles: number): boolean {
|
||||
const faction = Factions[this.currentWorkFactionName];
|
||||
|
||||
//Constantly update the rep gain rate
|
||||
@ -933,7 +931,7 @@ export function finishFactionWork(this: IPlayer, cancelled: boolean, sing = fals
|
||||
this.isWorking = false;
|
||||
this.resetWorkStatus();
|
||||
if (sing) {
|
||||
var res =
|
||||
const res =
|
||||
"You worked for your faction " +
|
||||
faction.name +
|
||||
" for a total of " +
|
||||
@ -1146,7 +1144,7 @@ export function getWorkRepGain(this: IPlayer): number {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var jobPerformance = companyPosition.calculateJobPerformance(
|
||||
let jobPerformance = companyPosition.calculateJobPerformance(
|
||||
this.hacking_skill,
|
||||
this.strength,
|
||||
this.defense,
|
||||
@ -1159,7 +1157,7 @@ export function getWorkRepGain(this: IPlayer): number {
|
||||
jobPerformance += this.intelligence / CONSTANTS.MaxSkillLevel;
|
||||
|
||||
//Update reputation gain rate to account for company favor
|
||||
var favorMult = 1 + company.favor / 100;
|
||||
let favorMult = 1 + company.favor / 100;
|
||||
if (isNaN(favorMult)) {
|
||||
favorMult = 1;
|
||||
}
|
||||
@ -1208,14 +1206,14 @@ export function startCreateProgramWork(
|
||||
|
||||
this.timeNeededToCompleteWork = time;
|
||||
//Check for incomplete program
|
||||
for (var i = 0; i < this.getHomeComputer().programs.length; ++i) {
|
||||
var programFile = this.getHomeComputer().programs[i];
|
||||
for (let i = 0; i < this.getHomeComputer().programs.length; ++i) {
|
||||
const programFile = this.getHomeComputer().programs[i];
|
||||
if (programFile.startsWith(programName) && programFile.endsWith("%-INC")) {
|
||||
var res = programFile.split("-");
|
||||
const res = programFile.split("-");
|
||||
if (res.length != 3) {
|
||||
break;
|
||||
}
|
||||
var percComplete = Number(res[1].slice(0, -1));
|
||||
const percComplete = Number(res[1].slice(0, -1));
|
||||
if (isNaN(percComplete) || percComplete < 0 || percComplete >= 100) {
|
||||
break;
|
||||
}
|
||||
@ -1230,8 +1228,8 @@ export function startCreateProgramWork(
|
||||
|
||||
export function createProgramWork(this: IPlayer, numCycles: number): boolean {
|
||||
//Higher hacking skill will allow you to create programs faster
|
||||
var reqLvl = this.createProgramReqLvl;
|
||||
var skillMult = (this.hacking_skill / reqLvl) * this.getIntelligenceBonus(3); //This should always be greater than 1;
|
||||
const reqLvl = this.createProgramReqLvl;
|
||||
let skillMult = (this.hacking_skill / reqLvl) * this.getIntelligenceBonus(3); //This should always be greater than 1;
|
||||
skillMult = 1 + (skillMult - 1) / 5; //The divider constant can be adjusted as necessary
|
||||
|
||||
//Skill multiplier directly applied to "time worked"
|
||||
@ -1246,7 +1244,7 @@ export function createProgramWork(this: IPlayer, numCycles: number): boolean {
|
||||
}
|
||||
|
||||
export function finishCreateProgramWork(this: IPlayer, cancelled: boolean): string {
|
||||
var programName = this.createProgramName;
|
||||
const programName = this.createProgramName;
|
||||
if (cancelled === false) {
|
||||
dialogBoxCreate(
|
||||
"You've finished creating " + programName + "!<br>" + "The new program can be found on your home computer.",
|
||||
@ -1254,8 +1252,8 @@ export function finishCreateProgramWork(this: IPlayer, cancelled: boolean): stri
|
||||
|
||||
this.getHomeComputer().programs.push(programName);
|
||||
} else {
|
||||
var perc = (Math.floor((this.timeWorkedCreateProgram / this.timeNeededToCompleteWork) * 10000) / 100).toString();
|
||||
var incompleteName = programName + "-" + perc + "%-INC";
|
||||
const perc = (Math.floor((this.timeWorkedCreateProgram / this.timeNeededToCompleteWork) * 10000) / 100).toString();
|
||||
const incompleteName = programName + "-" + perc + "%-INC";
|
||||
this.getHomeComputer().programs.push(incompleteName);
|
||||
}
|
||||
|
||||
@ -1281,8 +1279,8 @@ export function startClass(this: IPlayer, router: IRouter, costMult: number, exp
|
||||
const gameCPS = 1000 / CONSTANTS._idleSpeed;
|
||||
|
||||
//Find cost and exp gain per game cycle
|
||||
var cost = 0;
|
||||
var hackExp = 0,
|
||||
let cost = 0;
|
||||
let hackExp = 0,
|
||||
strExp = 0,
|
||||
defExp = 0,
|
||||
dexExp = 0,
|
||||
@ -1381,7 +1379,7 @@ export function finishClass(this: IPlayer, sing = false): string {
|
||||
this.isWorking = false;
|
||||
|
||||
if (sing) {
|
||||
var res =
|
||||
const res =
|
||||
"After " +
|
||||
this.className +
|
||||
" for " +
|
||||
@ -1709,7 +1707,7 @@ export function applyForJob(this: IPlayer, entryPosType: CompanyPosition, sing =
|
||||
}
|
||||
|
||||
while (true) {
|
||||
let newPos = getNextCompanyPositionHelper(pos);
|
||||
const newPos = getNextCompanyPositionHelper(pos);
|
||||
if (newPos == null) {
|
||||
break;
|
||||
}
|
||||
@ -1737,7 +1735,7 @@ export function applyForJob(this: IPlayer, entryPosType: CompanyPosition, sing =
|
||||
return false;
|
||||
} else if (company.hasPosition(nextPos)) {
|
||||
if (!sing) {
|
||||
var reqText = getJobRequirementText(company, nextPos);
|
||||
const reqText = getJobRequirementText(company, nextPos);
|
||||
dialogBoxCreate("Unfortunately, you do not qualify for a promotion<br>" + reqText);
|
||||
}
|
||||
return false;
|
||||
@ -1766,7 +1764,7 @@ export function getNextCompanyPosition(
|
||||
company: Company,
|
||||
entryPosType: CompanyPosition,
|
||||
): CompanyPosition | null {
|
||||
var currCompany = null;
|
||||
let currCompany = null;
|
||||
if (this.companyName !== "") {
|
||||
currCompany = Companies[this.companyName];
|
||||
}
|
||||
@ -1818,7 +1816,7 @@ export function applyForItJob(this: IPlayer, sing = false): boolean {
|
||||
}
|
||||
|
||||
export function applyForSecurityEngineerJob(this: IPlayer, sing = false): boolean {
|
||||
var company = Companies[this.location]; //Company being applied to
|
||||
const company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions[posNames.SecurityEngineerCompanyPositions[0]])) {
|
||||
return this.applyForJob(CompanyPositions[posNames.SecurityEngineerCompanyPositions[0]], sing);
|
||||
} else {
|
||||
@ -1830,7 +1828,7 @@ export function applyForSecurityEngineerJob(this: IPlayer, sing = false): boolea
|
||||
}
|
||||
|
||||
export function applyForNetworkEngineerJob(this: IPlayer, sing = false): boolean {
|
||||
var company = Companies[this.location]; //Company being applied to
|
||||
const company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions[posNames.NetworkEngineerCompanyPositions[0]])) {
|
||||
const pos = CompanyPositions[posNames.NetworkEngineerCompanyPositions[0]];
|
||||
return this.applyForJob(pos, sing);
|
||||
@ -1857,7 +1855,7 @@ export function applyForSecurityJob(this: IPlayer, sing = false): boolean {
|
||||
}
|
||||
|
||||
export function applyForAgentJob(this: IPlayer, sing = false): boolean {
|
||||
var company = Companies[this.location]; //Company being applied to
|
||||
const company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions[posNames.AgentCompanyPositions[0]])) {
|
||||
const pos = CompanyPositions[posNames.AgentCompanyPositions[0]];
|
||||
return this.applyForJob(pos, sing);
|
||||
@ -1870,7 +1868,7 @@ export function applyForAgentJob(this: IPlayer, sing = false): boolean {
|
||||
}
|
||||
|
||||
export function applyForEmployeeJob(this: IPlayer, sing = false): boolean {
|
||||
var company = Companies[this.location]; //Company being applied to
|
||||
const company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions[posNames.MiscCompanyPositions[1]])) {
|
||||
this.companyName = company.name;
|
||||
this.jobs[company.name] = posNames.MiscCompanyPositions[1];
|
||||
@ -1889,7 +1887,7 @@ export function applyForEmployeeJob(this: IPlayer, sing = false): boolean {
|
||||
}
|
||||
|
||||
export function applyForPartTimeEmployeeJob(this: IPlayer, sing = false): boolean {
|
||||
var company = Companies[this.location]; //Company being applied to
|
||||
const company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions[posNames.PartTimeCompanyPositions[1]])) {
|
||||
this.jobs[company.name] = posNames.PartTimeCompanyPositions[1];
|
||||
if (!sing) {
|
||||
@ -1907,7 +1905,7 @@ export function applyForPartTimeEmployeeJob(this: IPlayer, sing = false): boolea
|
||||
}
|
||||
|
||||
export function applyForWaiterJob(this: IPlayer, sing = false): boolean {
|
||||
var company = Companies[this.location]; //Company being applied to
|
||||
const company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions[posNames.MiscCompanyPositions[0]])) {
|
||||
this.companyName = company.name;
|
||||
this.jobs[company.name] = posNames.MiscCompanyPositions[0];
|
||||
@ -1924,7 +1922,7 @@ export function applyForWaiterJob(this: IPlayer, sing = false): boolean {
|
||||
}
|
||||
|
||||
export function applyForPartTimeWaiterJob(this: IPlayer, sing = false): boolean {
|
||||
var company = Companies[this.location]; //Company being applied to
|
||||
const company = Companies[this.location]; //Company being applied to
|
||||
if (this.isQualified(company, CompanyPositions[posNames.PartTimeCompanyPositions[0]])) {
|
||||
this.companyName = company.name;
|
||||
this.jobs[company.name] = posNames.PartTimeCompanyPositions[0];
|
||||
@ -1942,13 +1940,13 @@ export function applyForPartTimeWaiterJob(this: IPlayer, sing = false): boolean
|
||||
|
||||
//Checks if the Player is qualified for a certain position
|
||||
export function isQualified(this: IPlayer, company: Company, position: CompanyPosition): boolean {
|
||||
var offset = company.jobStatReqOffset;
|
||||
var reqHacking = position.requiredHacking > 0 ? position.requiredHacking + offset : 0;
|
||||
var reqStrength = position.requiredStrength > 0 ? position.requiredStrength + offset : 0;
|
||||
var reqDefense = position.requiredDefense > 0 ? position.requiredDefense + offset : 0;
|
||||
var reqDexterity = position.requiredDexterity > 0 ? position.requiredDexterity + offset : 0;
|
||||
var reqAgility = position.requiredDexterity > 0 ? position.requiredDexterity + offset : 0;
|
||||
var reqCharisma = position.requiredCharisma > 0 ? position.requiredCharisma + offset : 0;
|
||||
const offset = company.jobStatReqOffset;
|
||||
const reqHacking = position.requiredHacking > 0 ? position.requiredHacking + offset : 0;
|
||||
const reqStrength = position.requiredStrength > 0 ? position.requiredStrength + offset : 0;
|
||||
const reqDefense = position.requiredDefense > 0 ? position.requiredDefense + offset : 0;
|
||||
const reqDexterity = position.requiredDexterity > 0 ? position.requiredDexterity + offset : 0;
|
||||
const reqAgility = position.requiredDexterity > 0 ? position.requiredDexterity + offset : 0;
|
||||
const reqCharisma = position.requiredCharisma > 0 ? position.requiredCharisma + offset : 0;
|
||||
|
||||
if (
|
||||
this.hacking_skill >= reqHacking &&
|
||||
@ -1977,7 +1975,7 @@ export function reapplyAllAugmentations(this: IPlayer, resetMultipliers = true):
|
||||
}
|
||||
|
||||
const augName = this.augmentations[i].name;
|
||||
var aug = Augmentations[augName];
|
||||
const aug = Augmentations[augName];
|
||||
if (aug == null) {
|
||||
console.warn(`Invalid augmentation name in Player.reapplyAllAugmentations(). Aug ${augName} will be skipped`);
|
||||
continue;
|
||||
@ -2000,8 +1998,8 @@ export function reapplyAllSourceFiles(this: IPlayer): void {
|
||||
//this.resetMultipliers();
|
||||
|
||||
for (let i = 0; i < this.sourceFiles.length; ++i) {
|
||||
var srcFileKey = "SourceFile" + this.sourceFiles[i].n;
|
||||
var sourceFileObject = SourceFiles[srcFileKey];
|
||||
const srcFileKey = "SourceFile" + this.sourceFiles[i].n;
|
||||
const sourceFileObject = SourceFiles[srcFileKey];
|
||||
if (sourceFileObject == null) {
|
||||
console.error(`Invalid source file number: ${this.sourceFiles[i].n}`);
|
||||
continue;
|
||||
@ -2016,9 +2014,9 @@ export function reapplyAllSourceFiles(this: IPlayer): void {
|
||||
//those requirements and will return an array of all factions that the Player should
|
||||
//receive an invitation to
|
||||
export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
let invitedFactions: Faction[] = []; //Array which will hold all Factions the player should be invited to
|
||||
const invitedFactions: Faction[] = []; //Array which will hold all Factions the player should be invited to
|
||||
|
||||
var numAugmentations = this.augmentations.length;
|
||||
const numAugmentations = this.augmentations.length;
|
||||
|
||||
const allCompanies = Object.keys(this.jobs);
|
||||
const allPositions = Object.values(this.jobs);
|
||||
@ -2042,7 +2040,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//Illuminati
|
||||
var illuminatiFac = Factions["Illuminati"];
|
||||
const illuminatiFac = Factions["Illuminati"];
|
||||
if (
|
||||
!illuminatiFac.isBanned &&
|
||||
!illuminatiFac.isMember &&
|
||||
@ -2059,7 +2057,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//Daedalus
|
||||
var daedalusFac = Factions["Daedalus"];
|
||||
const daedalusFac = Factions["Daedalus"];
|
||||
if (
|
||||
!daedalusFac.isBanned &&
|
||||
!daedalusFac.isMember &&
|
||||
@ -2073,7 +2071,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//The Covenant
|
||||
var covenantFac = Factions["The Covenant"];
|
||||
const covenantFac = Factions["The Covenant"];
|
||||
if (
|
||||
!covenantFac.isBanned &&
|
||||
!covenantFac.isMember &&
|
||||
@ -2090,7 +2088,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//ECorp
|
||||
var ecorpFac = Factions["ECorp"];
|
||||
const ecorpFac = Factions["ECorp"];
|
||||
if (
|
||||
!ecorpFac.isBanned &&
|
||||
!ecorpFac.isMember &&
|
||||
@ -2101,7 +2099,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//MegaCorp
|
||||
var megacorpFac = Factions["MegaCorp"];
|
||||
const megacorpFac = Factions["MegaCorp"];
|
||||
if (
|
||||
!megacorpFac.isBanned &&
|
||||
!megacorpFac.isMember &&
|
||||
@ -2112,7 +2110,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//Bachman & Associates
|
||||
var bachmanandassociatesFac = Factions["Bachman & Associates"];
|
||||
const bachmanandassociatesFac = Factions["Bachman & Associates"];
|
||||
if (
|
||||
!bachmanandassociatesFac.isBanned &&
|
||||
!bachmanandassociatesFac.isMember &&
|
||||
@ -2123,7 +2121,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//Blade Industries
|
||||
var bladeindustriesFac = Factions["Blade Industries"];
|
||||
const bladeindustriesFac = Factions["Blade Industries"];
|
||||
if (
|
||||
!bladeindustriesFac.isBanned &&
|
||||
!bladeindustriesFac.isMember &&
|
||||
@ -2134,7 +2132,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//NWO
|
||||
var nwoFac = Factions["NWO"];
|
||||
const nwoFac = Factions["NWO"];
|
||||
if (
|
||||
!nwoFac.isBanned &&
|
||||
!nwoFac.isMember &&
|
||||
@ -2145,7 +2143,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//Clarke Incorporated
|
||||
var clarkeincorporatedFac = Factions["Clarke Incorporated"];
|
||||
const clarkeincorporatedFac = Factions["Clarke Incorporated"];
|
||||
if (
|
||||
!clarkeincorporatedFac.isBanned &&
|
||||
!clarkeincorporatedFac.isMember &&
|
||||
@ -2156,7 +2154,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//OmniTek Incorporated
|
||||
var omnitekincorporatedFac = Factions["OmniTek Incorporated"];
|
||||
const omnitekincorporatedFac = Factions["OmniTek Incorporated"];
|
||||
if (
|
||||
!omnitekincorporatedFac.isBanned &&
|
||||
!omnitekincorporatedFac.isMember &&
|
||||
@ -2167,7 +2165,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//Four Sigma
|
||||
var foursigmaFac = Factions["Four Sigma"];
|
||||
const foursigmaFac = Factions["Four Sigma"];
|
||||
if (
|
||||
!foursigmaFac.isBanned &&
|
||||
!foursigmaFac.isMember &&
|
||||
@ -2178,7 +2176,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//KuaiGong International
|
||||
var kuaigonginternationalFac = Factions["KuaiGong International"];
|
||||
const kuaigonginternationalFac = Factions["KuaiGong International"];
|
||||
if (
|
||||
!kuaigonginternationalFac.isBanned &&
|
||||
!kuaigonginternationalFac.isMember &&
|
||||
@ -2261,7 +2259,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//Chongqing
|
||||
var chongqingFac = Factions["Chongqing"];
|
||||
const chongqingFac = Factions["Chongqing"];
|
||||
if (
|
||||
!chongqingFac.isBanned &&
|
||||
!chongqingFac.isMember &&
|
||||
@ -2273,7 +2271,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//Sector-12
|
||||
var sector12Fac = Factions["Sector-12"];
|
||||
const sector12Fac = Factions["Sector-12"];
|
||||
if (
|
||||
!sector12Fac.isBanned &&
|
||||
!sector12Fac.isMember &&
|
||||
@ -2285,7 +2283,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//New Tokyo
|
||||
var newtokyoFac = Factions["New Tokyo"];
|
||||
const newtokyoFac = Factions["New Tokyo"];
|
||||
if (
|
||||
!newtokyoFac.isBanned &&
|
||||
!newtokyoFac.isMember &&
|
||||
@ -2297,7 +2295,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//Aevum
|
||||
var aevumFac = Factions["Aevum"];
|
||||
const aevumFac = Factions["Aevum"];
|
||||
if (
|
||||
!aevumFac.isBanned &&
|
||||
!aevumFac.isMember &&
|
||||
@ -2309,7 +2307,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//Ishima
|
||||
var ishimaFac = Factions["Ishima"];
|
||||
const ishimaFac = Factions["Ishima"];
|
||||
if (
|
||||
!ishimaFac.isBanned &&
|
||||
!ishimaFac.isMember &&
|
||||
@ -2321,7 +2319,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//Volhaven
|
||||
var volhavenFac = Factions["Volhaven"];
|
||||
const volhavenFac = Factions["Volhaven"];
|
||||
if (
|
||||
!volhavenFac.isBanned &&
|
||||
!volhavenFac.isMember &&
|
||||
@ -2333,7 +2331,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//Speakers for the Dead
|
||||
var speakersforthedeadFac = Factions["Speakers for the Dead"];
|
||||
const speakersforthedeadFac = Factions["Speakers for the Dead"];
|
||||
if (
|
||||
!speakersforthedeadFac.isBanned &&
|
||||
!speakersforthedeadFac.isMember &&
|
||||
@ -2352,7 +2350,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//The Dark Army
|
||||
var thedarkarmyFac = Factions["The Dark Army"];
|
||||
const thedarkarmyFac = Factions["The Dark Army"];
|
||||
if (
|
||||
!thedarkarmyFac.isBanned &&
|
||||
!thedarkarmyFac.isMember &&
|
||||
@ -2372,7 +2370,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//The Syndicate
|
||||
var thesyndicateFac = Factions["The Syndicate"];
|
||||
const thesyndicateFac = Factions["The Syndicate"];
|
||||
if (
|
||||
!thesyndicateFac.isBanned &&
|
||||
!thesyndicateFac.isMember &&
|
||||
@ -2392,7 +2390,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//Silhouette
|
||||
var silhouetteFac = Factions["Silhouette"];
|
||||
const silhouetteFac = Factions["Silhouette"];
|
||||
if (
|
||||
!silhouetteFac.isBanned &&
|
||||
!silhouetteFac.isMember &&
|
||||
@ -2407,7 +2405,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//Tetrads
|
||||
var tetradsFac = Factions["Tetrads"];
|
||||
const tetradsFac = Factions["Tetrads"];
|
||||
if (
|
||||
!tetradsFac.isBanned &&
|
||||
!tetradsFac.isMember &&
|
||||
@ -2423,7 +2421,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//SlumSnakes
|
||||
var slumsnakesFac = Factions["Slum Snakes"];
|
||||
const slumsnakesFac = Factions["Slum Snakes"];
|
||||
if (
|
||||
!slumsnakesFac.isBanned &&
|
||||
!slumsnakesFac.isMember &&
|
||||
@ -2439,10 +2437,10 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//Netburners
|
||||
var netburnersFac = Factions["Netburners"];
|
||||
var totalHacknetRam = 0;
|
||||
var totalHacknetCores = 0;
|
||||
var totalHacknetLevels = 0;
|
||||
const netburnersFac = Factions["Netburners"];
|
||||
let totalHacknetRam = 0;
|
||||
let totalHacknetCores = 0;
|
||||
let totalHacknetLevels = 0;
|
||||
for (let i = 0; i < this.hacknetNodes.length; ++i) {
|
||||
const v = this.hacknetNodes[i];
|
||||
if (typeof v === "string") {
|
||||
@ -2470,7 +2468,7 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
//Tian Di Hui
|
||||
var tiandihuiFac = Factions["Tian Di Hui"];
|
||||
const tiandihuiFac = Factions["Tian Di Hui"];
|
||||
if (
|
||||
!tiandihuiFac.isBanned &&
|
||||
!tiandihuiFac.isMember &&
|
||||
@ -2503,11 +2501,11 @@ export function checkForFactionInvitations(this: IPlayer): Faction[] {
|
||||
}
|
||||
|
||||
/************* BitNodes **************/
|
||||
export function setBitNodeNumber(this: IPlayer, n: number) {
|
||||
export function setBitNodeNumber(this: IPlayer, n: number): void {
|
||||
this.bitNodeN = n;
|
||||
}
|
||||
|
||||
export function queueAugmentation(this: IPlayer, name: string) {
|
||||
export function queueAugmentation(this: IPlayer, name: string): void {
|
||||
for (const i in this.queuedAugmentations) {
|
||||
if (this.queuedAugmentations[i].name == name) {
|
||||
console.warn(`tried to queue ${name} twice, this may be a bug`);
|
||||
@ -2526,7 +2524,7 @@ export function queueAugmentation(this: IPlayer, name: string) {
|
||||
}
|
||||
|
||||
/************* Coding Contracts **************/
|
||||
export function gainCodingContractReward(this: IPlayer, reward: ICodingContractReward, difficulty = 1) {
|
||||
export function gainCodingContractReward(this: IPlayer, reward: ICodingContractReward, difficulty = 1): string {
|
||||
if (reward == null || reward.type == null || reward == null) {
|
||||
return `No reward for this contract`;
|
||||
}
|
||||
@ -2539,7 +2537,7 @@ export function gainCodingContractReward(this: IPlayer, reward: ICodingContractR
|
||||
reward.type = CodingContractRewardType.FactionReputationAll;
|
||||
return this.gainCodingContractReward(reward);
|
||||
}
|
||||
var repGain = CONSTANTS.CodingContractBaseFactionRepGain * difficulty;
|
||||
const repGain = CONSTANTS.CodingContractBaseFactionRepGain * difficulty;
|
||||
Factions[reward.name].playerReputation += repGain;
|
||||
return `Gained ${repGain} faction reputation for ${reward.name}`;
|
||||
case CodingContractRewardType.FactionReputationAll:
|
||||
@ -2547,8 +2545,7 @@ export function gainCodingContractReward(this: IPlayer, reward: ICodingContractR
|
||||
|
||||
// Ignore Bladeburners and other special factions for this calculation
|
||||
const specialFactions = ["Bladeburners"];
|
||||
var factions = this.factions.slice();
|
||||
factions = factions.filter((f) => {
|
||||
const factions = this.factions.slice().filter((f) => {
|
||||
return !specialFactions.includes(f);
|
||||
});
|
||||
|
||||
@ -2567,28 +2564,28 @@ export function gainCodingContractReward(this: IPlayer, reward: ICodingContractR
|
||||
}
|
||||
return `Gained ${gainPerFaction} reputation for each of the following factions: ${factions.toString()}`;
|
||||
break;
|
||||
case CodingContractRewardType.CompanyReputation:
|
||||
case CodingContractRewardType.CompanyReputation: {
|
||||
if (reward.name == null || !(Companies[reward.name] instanceof Company)) {
|
||||
//If no/invalid company was designated, just give rewards to all factions
|
||||
reward.type = CodingContractRewardType.FactionReputationAll;
|
||||
return this.gainCodingContractReward(reward);
|
||||
}
|
||||
var repGain = CONSTANTS.CodingContractBaseCompanyRepGain * difficulty;
|
||||
const repGain = CONSTANTS.CodingContractBaseCompanyRepGain * difficulty;
|
||||
Companies[reward.name].playerReputation += repGain;
|
||||
return `Gained ${repGain} company reputation for ${reward.name}`;
|
||||
break;
|
||||
}
|
||||
case CodingContractRewardType.Money:
|
||||
default:
|
||||
var moneyGain = CONSTANTS.CodingContractBaseMoneyGain * difficulty * BitNodeMultipliers.CodingContractMoney;
|
||||
default: {
|
||||
const moneyGain = CONSTANTS.CodingContractBaseMoneyGain * difficulty * BitNodeMultipliers.CodingContractMoney;
|
||||
this.gainMoney(moneyGain);
|
||||
this.recordMoneySource(moneyGain, "codingcontract");
|
||||
return `Gained ${numeralWrapper.formatMoney(moneyGain)}`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* eslint-enable no-case-declarations */
|
||||
}
|
||||
|
||||
export function travel(this: IPlayer, to: CityName) {
|
||||
export function travel(this: IPlayer, to: CityName): boolean {
|
||||
if (Cities[to] == null) {
|
||||
console.warn(`Player.travel() called with invalid city: ${to}`);
|
||||
return false;
|
||||
@ -2598,7 +2595,7 @@ export function travel(this: IPlayer, to: CityName) {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function gotoLocation(this: IPlayer, to: LocationName) {
|
||||
export function gotoLocation(this: IPlayer, to: LocationName): boolean {
|
||||
if (Locations[to] == null) {
|
||||
console.warn(`Player.gotoLocation() called with invalid location: ${to}`);
|
||||
return false;
|
||||
@ -2608,21 +2605,21 @@ export function gotoLocation(this: IPlayer, to: LocationName) {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function canAccessResleeving(this: IPlayer) {
|
||||
export function canAccessResleeving(this: IPlayer): boolean {
|
||||
return this.bitNodeN === 10 || SourceFileFlags[10] > 0;
|
||||
}
|
||||
|
||||
export function giveExploit(this: IPlayer, exploit: Exploit) {
|
||||
export function giveExploit(this: IPlayer, exploit: Exploit): void {
|
||||
if (!this.exploits.includes(exploit)) {
|
||||
this.exploits.push(exploit);
|
||||
}
|
||||
}
|
||||
|
||||
export function getIntelligenceBonus(this: IPlayer, weight: number) {
|
||||
export function getIntelligenceBonus(this: IPlayer, weight: number): number {
|
||||
return calculateIntelligenceBonus(this.intelligence, weight);
|
||||
}
|
||||
|
||||
export function getCasinoWinnings(this: IPlayer) {
|
||||
export function getCasinoWinnings(this: IPlayer): number {
|
||||
return this.moneySourceA.casino;
|
||||
}
|
||||
|
||||
|
@ -479,6 +479,7 @@ export class Sleeve extends Person {
|
||||
|
||||
let time = this.storedCycles * CONSTANTS.MilliPerCycle;
|
||||
let cyclesUsed = this.storedCycles;
|
||||
cyclesUsed = Math.min(cyclesUsed, 15);
|
||||
if (this.currentTaskMaxTime !== 0 && this.currentTaskTime + time > this.currentTaskMaxTime) {
|
||||
time = this.currentTaskMaxTime - this.currentTaskTime;
|
||||
cyclesUsed = Math.floor(time / CONSTANTS.MilliPerCycle);
|
||||
|
@ -47,7 +47,7 @@ export function SleeveAugmentationsPopup(props: IProps): React.ReactElement {
|
||||
tooltip = renderToStaticMarkup(tooltip);
|
||||
}
|
||||
tooltip += "<br /><br />";
|
||||
tooltip += renderToStaticMarkup(aug.stats);
|
||||
tooltip += renderToStaticMarkup(aug.stats || <></>);
|
||||
return (
|
||||
<div key={augName} className="gang-owned-upgrade tooltip">
|
||||
{augName}
|
||||
@ -70,7 +70,7 @@ export function SleeveAugmentationsPopup(props: IProps): React.ReactElement {
|
||||
info = renderToStaticMarkup(info);
|
||||
}
|
||||
info += "<br /><br />";
|
||||
info += renderToStaticMarkup(aug.stats);
|
||||
info += renderToStaticMarkup(aug.stats || <></>);
|
||||
|
||||
return (
|
||||
<div key={aug.name} className="cmpy-mgmt-upgrade-div" onClick={() => purchaseAugmentation(aug)}>
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { Sleeve } from "../Sleeve";
|
||||
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||
import * as React from "react";
|
||||
import { convertTimeMsToTimeElapsedString } from "../../../../utils/StringHelperFunctions";
|
||||
import { CONSTANTS } from "../../../Constants";
|
||||
|
||||
interface IProps {
|
||||
sleeve: Sleeve;
|
||||
@ -77,6 +79,14 @@ export function StatsElement(props: IProps): React.ReactElement {
|
||||
{numeralWrapper.formatSleeveMemory(props.sleeve.memory)}
|
||||
</td>
|
||||
</tr>
|
||||
{props.sleeve.storedCycles > 15 && (
|
||||
<tr>
|
||||
<td>Bonus time: </td>
|
||||
<td style={style}>
|
||||
{convertTimeMsToTimeElapsedString((props.sleeve.storedCycles / (1000 / CONSTANTS._idleSpeed)) * 1000)}
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
</>
|
||||
|
@ -6,7 +6,6 @@ import { Bladeburner } from "./Bladeburner/Bladeburner";
|
||||
import { Companies, initCompanies } from "./Company/Companies";
|
||||
import { resetIndustryResearchTrees } from "./Corporation/IndustryData";
|
||||
import { Programs } from "./Programs/Programs";
|
||||
import { Engine } from "./engine";
|
||||
import { Faction } from "./Faction/Faction";
|
||||
import { Factions, initFactions } from "./Faction/Factions";
|
||||
import { joinFaction } from "./Faction/FactionHelpers";
|
||||
@ -155,7 +154,7 @@ function prestigeSourceFile(flume: boolean): void {
|
||||
Player.prestigeSourceFile();
|
||||
prestigeWorkerScripts(); // Delete all Worker Scripts objects
|
||||
|
||||
var homeComp = Player.getHomeComputer();
|
||||
const homeComp = Player.getHomeComputer();
|
||||
|
||||
// Delete all servers except home computer
|
||||
prestigeAllServers(); // Must be done before initForeignServers()
|
||||
@ -180,14 +179,14 @@ function prestigeSourceFile(flume: boolean): void {
|
||||
homeComp.cpuCores = 1;
|
||||
|
||||
// Reset favor for Companies
|
||||
for (var member in Companies) {
|
||||
for (const member in Companies) {
|
||||
if (Companies.hasOwnProperty(member)) {
|
||||
Companies[member].favor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset favor for factions
|
||||
for (var member in Factions) {
|
||||
for (const member in Factions) {
|
||||
if (Factions.hasOwnProperty(member)) {
|
||||
Factions[member].favor = 0;
|
||||
}
|
||||
@ -199,7 +198,7 @@ function prestigeSourceFile(flume: boolean): void {
|
||||
}
|
||||
|
||||
// Delete all Augmentations
|
||||
for (var name in Augmentations) {
|
||||
for (const name in Augmentations) {
|
||||
if (Augmentations.hasOwnProperty(name)) {
|
||||
delete Augmentations[name];
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react";
|
||||
import { use } from "../../ui/Context";
|
||||
import { getAvailableCreatePrograms } from "../ProgramHelpers";
|
||||
|
||||
import { Box, ButtonGroup, Tooltip, Typography } from "@mui/material";
|
||||
import { Box, Tooltip, Typography } from "@mui/material";
|
||||
import Button from "@mui/material/Button";
|
||||
|
||||
export function ProgramsRoot(): React.ReactElement {
|
||||
@ -20,33 +20,34 @@ export function ProgramsRoot(): React.ReactElement {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<Box>
|
||||
<Typography variant="h4">Create program</Typography>
|
||||
<Typography>
|
||||
This page displays any programs that you are able to create. Writing the code for a program takes time,
|
||||
which can vary based on how complex the program is. If you are working on creating a program you can cancel
|
||||
at any time. Your progress will be saved and you can continue later.
|
||||
This page displays any programs that you are able to create. Writing the code for a program takes time, which
|
||||
can vary based on how complex the program is. If you are working on creating a program you can cancel at any
|
||||
time. Your progress will be saved and you can continue later.
|
||||
</Typography>
|
||||
</Box>
|
||||
<ButtonGroup>
|
||||
|
||||
{getAvailableCreatePrograms(player).map((program) => {
|
||||
const create = program.create;
|
||||
if (create === null) return <></>;
|
||||
|
||||
return (
|
||||
<Tooltip key={program.name} title={create.tooltip}>
|
||||
<React.Fragment key={program.name}>
|
||||
<Tooltip title={create.tooltip}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
sx={{ my: 1 }}
|
||||
onClick={(event) => {
|
||||
if (!event.isTrusted) return;
|
||||
player.startCreateProgramWork(router, program.name, create.time, create.level);
|
||||
}}
|
||||
>
|
||||
{program.name}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<br />
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -17,17 +17,17 @@ export function setRedPillFlag(b: boolean): void {
|
||||
}
|
||||
|
||||
function giveSourceFile(bitNodeNumber: number): void {
|
||||
var sourceFileKey = "SourceFile" + bitNodeNumber.toString();
|
||||
var sourceFile = SourceFiles[sourceFileKey];
|
||||
const sourceFileKey = "SourceFile" + bitNodeNumber.toString();
|
||||
const sourceFile = SourceFiles[sourceFileKey];
|
||||
if (sourceFile == null) {
|
||||
console.error(`Could not find source file for Bit node: ${bitNodeNumber}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if player already has this source file
|
||||
var alreadyOwned = false;
|
||||
var ownedSourceFile = null;
|
||||
for (var i = 0; i < Player.sourceFiles.length; ++i) {
|
||||
let alreadyOwned = false;
|
||||
let ownedSourceFile = null;
|
||||
for (let i = 0; i < Player.sourceFiles.length; ++i) {
|
||||
if (Player.sourceFiles[i].n === bitNodeNumber) {
|
||||
alreadyOwned = true;
|
||||
ownedSourceFile = Player.sourceFiles[i];
|
||||
@ -51,7 +51,7 @@ function giveSourceFile(bitNodeNumber: number): void {
|
||||
);
|
||||
}
|
||||
} else {
|
||||
var playerSrcFile = new PlayerOwnedSourceFile(bitNodeNumber, 1);
|
||||
const playerSrcFile = new PlayerOwnedSourceFile(bitNodeNumber, 1);
|
||||
Player.sourceFiles.push(playerSrcFile);
|
||||
if (bitNodeNumber === 5 && Player.intelligence === 0) {
|
||||
// Artificial Intelligence
|
||||
|
6
src/SaveObject.d.ts
vendored
6
src/SaveObject.d.ts
vendored
@ -1,6 +0,0 @@
|
||||
export declare const saveObject: {
|
||||
getSaveString: () => string;
|
||||
saveGame: () => void;
|
||||
exportGame: () => void;
|
||||
};
|
||||
export declare function loadGame(s: string): boolean;
|
@ -1,7 +1,6 @@
|
||||
import { loadAliases, loadGlobalAliases, Aliases, GlobalAliases } from "./Alias";
|
||||
import { Companies, loadCompanies } from "./Company/Companies";
|
||||
import { CONSTANTS } from "./Constants";
|
||||
import { Engine } from "./engine";
|
||||
import { Factions, loadFactions } from "./Faction/Factions";
|
||||
import { loadAllGangs, AllGangs } from "./Gang/AllGangs";
|
||||
import { loadMessages, initMessages, Messages } from "./Message/MessageHelpers";
|
||||
@ -18,12 +17,9 @@ import { setTimeoutRef } from "./utils/SetTimeoutRef";
|
||||
import * as ExportBonus from "./ExportBonus";
|
||||
|
||||
import { dialogBoxCreate } from "../utils/DialogBox";
|
||||
import { clearEventListeners } from "../utils/uiHelpers/clearEventListeners";
|
||||
import { Reviver, Generic_toJSON, Generic_fromJSON } from "../utils/JSONReviver";
|
||||
import { save } from "./db";
|
||||
|
||||
import Decimal from "decimal.js";
|
||||
|
||||
/* SaveObject.js
|
||||
* Defines the object used to save/load games
|
||||
*/
|
||||
@ -47,14 +43,14 @@ class BitburnerSaveObject {
|
||||
this.PlayerSave = JSON.stringify(Player);
|
||||
|
||||
// Delete all logs from all running scripts
|
||||
var TempAllServers = JSON.parse(JSON.stringify(AllServers), Reviver);
|
||||
for (var ip in TempAllServers) {
|
||||
var server = TempAllServers[ip];
|
||||
const TempAllServers = JSON.parse(JSON.stringify(AllServers), Reviver);
|
||||
for (const ip in TempAllServers) {
|
||||
const server = TempAllServers[ip];
|
||||
if (server == null) {
|
||||
continue;
|
||||
}
|
||||
for (var i = 0; i < server.runningScripts.length; ++i) {
|
||||
var runningScriptObj = server.runningScripts[i];
|
||||
for (let i = 0; i < server.runningScripts.length; ++i) {
|
||||
const runningScriptObj = server.runningScripts[i];
|
||||
runningScriptObj.logs.length = 0;
|
||||
runningScriptObj.logs = [];
|
||||
}
|
||||
@ -74,7 +70,7 @@ class BitburnerSaveObject {
|
||||
if (Player.inGang()) {
|
||||
this.AllGangsSave = JSON.stringify(AllGangs);
|
||||
}
|
||||
var saveString = btoa(unescape(encodeURIComponent(JSON.stringify(this))));
|
||||
const saveString = btoa(unescape(encodeURIComponent(JSON.stringify(this))));
|
||||
|
||||
return saveString;
|
||||
}
|
||||
@ -94,13 +90,13 @@ class BitburnerSaveObject {
|
||||
const epochTime = Math.round(Date.now() / 1000);
|
||||
const bn = Player.bitNodeN;
|
||||
const filename = `bitburnerSave_BN${bn}x${SourceFileFlags[bn]}_${epochTime}.json`;
|
||||
var file = new Blob([saveString], { type: "text/plain" });
|
||||
const file = new Blob([saveString], { type: "text/plain" });
|
||||
if (window.navigator.msSaveOrOpenBlob) {
|
||||
// IE10+
|
||||
window.navigator.msSaveOrOpenBlob(file, filename);
|
||||
} else {
|
||||
// Others
|
||||
var a = document.createElement("a"),
|
||||
const a = document.createElement("a"),
|
||||
url = URL.createObjectURL(file);
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
@ -124,7 +120,7 @@ class BitburnerSaveObject {
|
||||
|
||||
// Makes necessary changes to the loaded/imported data to ensure
|
||||
// the game stills works with new versions
|
||||
function evaluateVersionCompatibility(ver: string) {
|
||||
function evaluateVersionCompatibility(ver: string): void {
|
||||
// We have to do this because ts won't let us otherwise
|
||||
const anyPlayer = Player as any;
|
||||
// This version refactored the Company/job-related code
|
||||
@ -239,7 +235,7 @@ function loadGame(saveString: string): boolean {
|
||||
}
|
||||
if (saveObj.hasOwnProperty("VersionSave")) {
|
||||
try {
|
||||
var ver = JSON.parse(saveObj.VersionSave, Reviver);
|
||||
const ver = JSON.parse(saveObj.VersionSave, Reviver);
|
||||
evaluateVersionCompatibility(ver);
|
||||
|
||||
if (window.location.href.toLowerCase().includes("bitburner-beta")) {
|
||||
@ -265,7 +261,7 @@ function loadGame(saveString: string): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
function createNewUpdateText() {
|
||||
function createNewUpdateText(): void {
|
||||
dialogBoxCreate(
|
||||
"New update!<br>" +
|
||||
"Please report any bugs/issues through the github repository " +
|
||||
@ -274,7 +270,7 @@ function createNewUpdateText() {
|
||||
);
|
||||
}
|
||||
|
||||
function createBetaUpdateText() {
|
||||
function createBetaUpdateText(): void {
|
||||
dialogBoxCreate(
|
||||
"You are playing on the beta environment! This branch of the game " +
|
||||
"features the latest developments in the game. This version may be unstable.<br>" +
|
||||
@ -288,4 +284,4 @@ Reviver.constructors.BitburnerSaveObject = BitburnerSaveObject;
|
||||
|
||||
export { saveObject, loadGame };
|
||||
|
||||
let saveObject = new BitburnerSaveObject();
|
||||
const saveObject = new BitburnerSaveObject();
|
||||
|
@ -104,7 +104,7 @@ async function parseOnlyRamCalculate(
|
||||
}
|
||||
|
||||
let script = null;
|
||||
let fn = nextModule.startsWith("./") ? nextModule.slice(2) : nextModule;
|
||||
const fn = nextModule.startsWith("./") ? nextModule.slice(2) : nextModule;
|
||||
for (const s of otherScripts) {
|
||||
if (s.filename === fn) {
|
||||
script = s;
|
||||
@ -147,14 +147,14 @@ async function parseOnlyRamCalculate(
|
||||
if (ref.endsWith(".*")) {
|
||||
// A prefix reference. We need to find all matching identifiers.
|
||||
const prefix = ref.slice(0, ref.length - 2);
|
||||
for (let ident of Object.keys(dependencyMap).filter((k) => k.startsWith(prefix))) {
|
||||
for (let dep of dependencyMap[ident] || []) {
|
||||
for (const ident of Object.keys(dependencyMap).filter((k) => k.startsWith(prefix))) {
|
||||
for (const dep of dependencyMap[ident] || []) {
|
||||
if (!resolvedRefs.has(dep)) unresolvedRefs.push(dep);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// An exact reference. Add all dependencies of this ref.
|
||||
for (let dep of dependencyMap[ref] || []) {
|
||||
for (const dep of dependencyMap[ref] || []) {
|
||||
if (!resolvedRefs.has(dep)) unresolvedRefs.push(dep);
|
||||
}
|
||||
}
|
||||
@ -162,7 +162,7 @@ async function parseOnlyRamCalculate(
|
||||
// Check if this identifier is a function in the workerScript environment.
|
||||
// If it is, then we need to get its RAM cost.
|
||||
try {
|
||||
function applyFuncRam(func: any) {
|
||||
function applyFuncRam(func: any): number {
|
||||
if (typeof func === "function") {
|
||||
try {
|
||||
let res;
|
||||
@ -235,9 +235,9 @@ function parseOnlyCalculateDeps(code: string, currentModule: string): any {
|
||||
|
||||
// If we reference this internal name, we're really referencing that external name.
|
||||
// Filled when we import names from other modules.
|
||||
let internalToExternal: { [key: string]: string | undefined } = {};
|
||||
const internalToExternal: { [key: string]: string | undefined } = {};
|
||||
|
||||
let additionalModules: string[] = [];
|
||||
const additionalModules: string[] = [];
|
||||
|
||||
// References get added pessimistically. They are added for thisModule.name, name, and for
|
||||
// any aliases.
|
||||
@ -256,7 +256,7 @@ function parseOnlyCalculateDeps(code: string, currentModule: string): any {
|
||||
|
||||
// If we discover a dependency identifier, state.key is the dependent identifier.
|
||||
// walkDeeper is for doing recursive walks of expressions in composites that we handle.
|
||||
function commonVisitors() {
|
||||
function commonVisitors(): any {
|
||||
return {
|
||||
Identifier: (node: any, st: any) => {
|
||||
if (objectPrototypeProperties.includes(node.name)) {
|
||||
|
@ -91,16 +91,11 @@ export class Script {
|
||||
* @param {string} code - The new contents of the script
|
||||
* @param {Script[]} otherScripts - Other scripts on the server. Used to process imports
|
||||
*/
|
||||
saveScript(code: string, serverIp: string, otherScripts: Script[]): void {
|
||||
saveScript(filename: string, code: string, serverIp: string, otherScripts: Script[]): void {
|
||||
// Update code and filename
|
||||
this.code = code.replace(/^\s+|\s+$/g, "");
|
||||
|
||||
const filenameElem: HTMLInputElement | null = document.getElementById("script-editor-filename") as HTMLInputElement;
|
||||
if (filenameElem == null) {
|
||||
console.error(`Failed to get Script filename DOM element`);
|
||||
return;
|
||||
}
|
||||
this.filename = filenameElem.value;
|
||||
this.filename = filename;
|
||||
this.server = serverIp;
|
||||
this.updateRamUsage(otherScripts);
|
||||
this.markUpdated();
|
||||
|
@ -10,7 +10,7 @@ import { numeralWrapper } from "../ui/numeralFormat";
|
||||
|
||||
import { compareArrays } from "../../utils/helpers/compareArrays";
|
||||
|
||||
export function scriptCalculateOfflineProduction(runningScript: RunningScript) {
|
||||
export function scriptCalculateOfflineProduction(runningScript: RunningScript): void {
|
||||
//The Player object stores the last update time from when we were online
|
||||
const thisUpdate = new Date().getTime();
|
||||
const lastUpdate = Player.lastUpdate;
|
||||
@ -83,8 +83,12 @@ export function scriptCalculateOfflineProduction(runningScript: RunningScript) {
|
||||
|
||||
//Returns a RunningScript object matching the filename and arguments on the
|
||||
//designated server, and false otherwise
|
||||
export function findRunningScript(filename: string, args: (string | number)[], server: BaseServer) {
|
||||
for (var i = 0; i < server.runningScripts.length; ++i) {
|
||||
export function findRunningScript(
|
||||
filename: string,
|
||||
args: (string | number)[],
|
||||
server: BaseServer,
|
||||
): RunningScript | null {
|
||||
for (let i = 0; i < server.runningScripts.length; ++i) {
|
||||
if (server.runningScripts[i].filename === filename && compareArrays(server.runningScripts[i].args, args)) {
|
||||
return server.runningScripts[i];
|
||||
}
|
||||
@ -94,8 +98,8 @@ export function findRunningScript(filename: string, args: (string | number)[], s
|
||||
|
||||
//Returns a RunningScript object matching the pid on the
|
||||
//designated server, and false otherwise
|
||||
export function findRunningScriptByPid(pid: number, server: BaseServer) {
|
||||
for (var i = 0; i < server.runningScripts.length; ++i) {
|
||||
export function findRunningScriptByPid(pid: number, server: BaseServer): RunningScript | null {
|
||||
for (let i = 0; i < server.runningScripts.length; ++i) {
|
||||
if (server.runningScripts[i].pid === pid) {
|
||||
return server.runningScripts[i];
|
||||
}
|
||||
|
54
src/ScriptEditor/ui/OptionsModal.tsx
Normal file
54
src/ScriptEditor/ui/OptionsModal.tsx
Normal file
@ -0,0 +1,54 @@
|
||||
import React, { useState } from "react";
|
||||
import { Options } from "./Options";
|
||||
import { Modal } from "../../ui/React/Modal";
|
||||
|
||||
import Button from "@mui/material/Button";
|
||||
import Box from "@mui/material/Box";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Select from "@mui/material/Select";
|
||||
import Switch from "@mui/material/Switch";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
|
||||
interface IProps {
|
||||
options: Options;
|
||||
save: (options: Options) => void;
|
||||
onClose: () => void;
|
||||
open: boolean;
|
||||
}
|
||||
|
||||
export function OptionsModal(props: IProps): React.ReactElement {
|
||||
const [theme, setTheme] = useState(props.options.theme);
|
||||
const [insertSpaces, setInsertSpaces] = useState(props.options.insertSpaces);
|
||||
|
||||
function save(): void {
|
||||
props.save({
|
||||
theme: theme,
|
||||
insertSpaces: insertSpaces,
|
||||
});
|
||||
props.onClose();
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal open={props.open} onClose={props.onClose}>
|
||||
<Box display="flex" flexDirection="row" alignItems="center">
|
||||
<Typography>Theme: </Typography>
|
||||
<Select
|
||||
variant="standard"
|
||||
color="primary"
|
||||
onChange={(event) => setTheme(event.target.value)}
|
||||
defaultValue={props.options.theme}
|
||||
>
|
||||
<MenuItem value="vs-dark">dark</MenuItem>
|
||||
<MenuItem value="light">light</MenuItem>
|
||||
</Select>
|
||||
</Box>
|
||||
|
||||
<Box display="flex" flexDirection="row" alignItems="center">
|
||||
<Typography>Use whitespace over tabs: </Typography>
|
||||
<Switch onChange={(event) => setInsertSpaces(event.target.checked)} checked={insertSpaces} />
|
||||
</Box>
|
||||
<br />
|
||||
<Button onClick={save}>Save</Button>
|
||||
</Modal>
|
||||
);
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
import { Options } from "./Options";
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import { removePopup } from "../../ui/React/createPopup";
|
||||
|
||||
interface IProps {
|
||||
id: string;
|
||||
options: Options;
|
||||
save: (options: Options) => void;
|
||||
}
|
||||
|
||||
export function OptionsPopup(props: IProps): React.ReactElement {
|
||||
const [theme, setTheme] = useState(props.options.theme);
|
||||
const [insertSpaces, setInsertSpaces] = useState(props.options.insertSpaces);
|
||||
|
||||
function save(): void {
|
||||
props.save({
|
||||
theme: theme,
|
||||
insertSpaces: insertSpaces,
|
||||
});
|
||||
removePopup(props.id);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="editor-options-container noselect">
|
||||
<div className="editor-options-line">
|
||||
<p>Theme: </p>
|
||||
<select className="dropdown" onChange={(event) => setTheme(event.target.value)} defaultValue={theme}>
|
||||
<option value="vs-dark">vs-dark</option>
|
||||
<option value="light">light</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="editor-options-line">
|
||||
<p>Use whitespace over tabs: </p>
|
||||
<input type="checkbox" onChange={(event) => setInsertSpaces(event.target.checked)} checked={insertSpaces} />
|
||||
</div>
|
||||
<br />
|
||||
<StdButton style={{ width: "50px" }} text={"Save"} onClick={save} />
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,10 +1,8 @@
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import { StdButton } from "../../ui/React/StdButton";
|
||||
import Editor from "@monaco-editor/react";
|
||||
import * as monaco from "monaco-editor";
|
||||
type IStandaloneCodeEditor = monaco.editor.IStandaloneCodeEditor;
|
||||
import { createPopup } from "../../ui/React/createPopup";
|
||||
import { OptionsPopup } from "./OptionsPopup";
|
||||
import { OptionsModal } from "./OptionsModal";
|
||||
import { Options } from "./Options";
|
||||
import { js_beautify as beautifyCode } from "js-beautify";
|
||||
import { isValidFilePath } from "../../Terminal/DirectoryHelpers";
|
||||
@ -24,7 +22,14 @@ import { WorkerScript } from "../../Netscript/WorkerScript";
|
||||
import { Settings } from "../../Settings/Settings";
|
||||
import { iTutorialNextStep, ITutorial, iTutorialSteps } from "../../InteractiveTutorial";
|
||||
|
||||
let loaded = false;
|
||||
import Button from "@mui/material/Button";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Link from "@mui/material/Link";
|
||||
import Box from "@mui/material/Box";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import SettingsIcon from "@mui/icons-material/Settings";
|
||||
|
||||
let symbols: string[] = [];
|
||||
(function () {
|
||||
const ns = NetscriptFunctions({} as WorkerScript);
|
||||
@ -78,6 +83,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
const [filename, setFilename] = useState(props.filename ? props.filename : lastFilename);
|
||||
const [code, setCode] = useState<string>(props.filename ? props.code : lastCode);
|
||||
const [ram, setRAM] = useState("RAM: ???");
|
||||
const [optionsOpen, setOptionsOpen] = useState(false);
|
||||
const [options, setOptions] = useState<Options>({
|
||||
theme: Settings.MonacoTheme,
|
||||
insertSpaces: Settings.MonacoInsertSpaces,
|
||||
@ -121,14 +127,14 @@ export function Root(props: IProps): React.ReactElement {
|
||||
let found = false;
|
||||
for (let i = 0; i < server.scripts.length; i++) {
|
||||
if (filename == server.scripts[i].filename) {
|
||||
server.scripts[i].saveScript(code, props.player.currentServer, server.scripts);
|
||||
server.scripts[i].saveScript(filename, code, props.player.currentServer, server.scripts);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
const script = new Script();
|
||||
script.saveScript(code, props.player.currentServer, server.scripts);
|
||||
script.saveScript(filename, code, props.player.currentServer, server.scripts);
|
||||
server.scripts.push(script);
|
||||
}
|
||||
|
||||
@ -156,7 +162,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
//If the current script already exists on the server, overwrite it
|
||||
for (let i = 0; i < server.scripts.length; i++) {
|
||||
if (filename == server.scripts[i].filename) {
|
||||
server.scripts[i].saveScript(code, props.player.currentServer, server.scripts);
|
||||
server.scripts[i].saveScript(filename, code, props.player.currentServer, server.scripts);
|
||||
props.router.toTerminal();
|
||||
return;
|
||||
}
|
||||
@ -164,7 +170,7 @@ export function Root(props: IProps): React.ReactElement {
|
||||
|
||||
//If the current script does NOT exist, create a new one
|
||||
const script = new Script();
|
||||
script.saveScript(code, props.player.currentServer, server.scripts);
|
||||
script.saveScript(filename, code, props.player.currentServer, server.scripts);
|
||||
server.scripts.push(script);
|
||||
} else if (filename.endsWith(".txt")) {
|
||||
for (let i = 0; i < server.textFiles.length; ++i) {
|
||||
@ -198,24 +204,6 @@ export function Root(props: IProps): React.ReactElement {
|
||||
setFilename(event.target.value);
|
||||
}
|
||||
|
||||
function openOptions(): void {
|
||||
const id = "script-editor-options-popup";
|
||||
const newOptions = {
|
||||
theme: "",
|
||||
insertSpaces: false,
|
||||
};
|
||||
Object.assign(newOptions, options);
|
||||
createPopup(id, OptionsPopup, {
|
||||
id: id,
|
||||
options: newOptions,
|
||||
save: (options: Options) => {
|
||||
setOptions(options);
|
||||
Settings.MonacoTheme = options.theme;
|
||||
Settings.MonacoInsertSpaces = options.insertSpaces;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function updateCode(newCode?: string): void {
|
||||
if (newCode === undefined) return;
|
||||
lastCode = newCode;
|
||||
@ -302,26 +290,20 @@ export function Root(props: IProps): React.ReactElement {
|
||||
});
|
||||
monaco.languages.typescript.javascriptDefaults.addExtraLib(libSource, "netscript.d.ts");
|
||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(libSource, "netscript.d.ts");
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id="script-editor-filename-wrapper">
|
||||
<p id="script-editor-filename-tag" className="noselect">
|
||||
{" "}
|
||||
<strong style={{ backgroundColor: "#555" }}>Script name: </strong>
|
||||
</p>
|
||||
<input
|
||||
id="script-editor-filename"
|
||||
type="text"
|
||||
maxLength={100}
|
||||
tabIndex={1}
|
||||
value={filename}
|
||||
onChange={onFilenameChange}
|
||||
/>
|
||||
<StdButton text={"options"} onClick={openOptions} />
|
||||
</div>
|
||||
<Box display="flex" flexDirection="row" alignItems="center">
|
||||
<Typography>Script name: </Typography>
|
||||
<TextField variant="standard" type="text" tabIndex={1} value={filename} onChange={onFilenameChange} />
|
||||
<IconButton onClick={() => setOptionsOpen(true)}>
|
||||
<>
|
||||
<SettingsIcon />
|
||||
options
|
||||
</>
|
||||
</IconButton>
|
||||
</Box>
|
||||
<Editor
|
||||
beforeMount={beforeMount}
|
||||
onMount={onMount}
|
||||
@ -333,23 +315,27 @@ export function Root(props: IProps): React.ReactElement {
|
||||
theme={options.theme}
|
||||
options={options}
|
||||
/>
|
||||
<div id="script-editor-buttons-wrapper">
|
||||
<StdButton text={"Beautify"} onClick={beautify} />
|
||||
<p id="script-editor-status-text" style={{ display: "inline-block", margin: "10px" }}>
|
||||
{ram}
|
||||
</p>
|
||||
<button className="std-button" style={{ display: "inline-block" }} onClick={save}>
|
||||
Save & Close (Ctrl/Cmd + b)
|
||||
</button>
|
||||
<a
|
||||
className="std-button"
|
||||
style={{ display: "inline-block" }}
|
||||
target="_blank"
|
||||
href="https://bitburner.readthedocs.io/en/latest/index.html"
|
||||
>
|
||||
<Box display="flex" flexDirection="row" sx={{ m: 1 }} alignItems="center">
|
||||
<Button onClick={beautify}>Beautify</Button>
|
||||
<Typography sx={{ mx: 1 }}>{ram}</Typography>
|
||||
<Button onClick={save}>Save & Close (Ctrl/Cmd + b)</Button>
|
||||
<Link sx={{ mx: 1 }} target="_blank" href="https://bitburner.readthedocs.io/en/latest/index.html">
|
||||
Netscript Documentation
|
||||
</a>
|
||||
</div>
|
||||
</Link>
|
||||
</Box>
|
||||
<OptionsModal
|
||||
open={optionsOpen}
|
||||
onClose={() => setOptionsOpen(false)}
|
||||
options={{
|
||||
theme: Settings.MonacoTheme,
|
||||
insertSpaces: Settings.MonacoInsertSpaces,
|
||||
}}
|
||||
save={(options: Options) => {
|
||||
setOptions(options);
|
||||
Settings.MonacoTheme = options.theme;
|
||||
Settings.MonacoInsertSpaces = options.insertSpaces;
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,94 +1,5 @@
|
||||
// Enums that defined allowed values for setting configuration
|
||||
|
||||
/**
|
||||
* Allowed values for 'Keybinding/Keymap' setting in Ace editor
|
||||
*/
|
||||
export enum AceKeybindingSetting {
|
||||
Ace = "ace",
|
||||
Emacs = "emacs",
|
||||
Vim = "vim",
|
||||
}
|
||||
|
||||
/**
|
||||
* Allowed values for 'Keybinding/Keymap' setting in Code Mirror editor
|
||||
*/
|
||||
export enum CodeMirrorKeybindingSetting {
|
||||
Default = "default",
|
||||
Emacs = "emacs",
|
||||
Sublime = "sublime",
|
||||
Vim = "vim",
|
||||
}
|
||||
|
||||
/**
|
||||
* Allowed values for 'Theme' setting in Code Mirror editor
|
||||
*/
|
||||
export enum CodeMirrorThemeSetting {
|
||||
Monokai = "monokai",
|
||||
Day_3024 = "3024-day",
|
||||
Night_3024 = "3024-night",
|
||||
abcdef = "abcdef",
|
||||
Ambiance_mobile = "ambiance-mobile",
|
||||
Ambiance = "ambiance",
|
||||
Base16_dark = "base16-dark",
|
||||
Base16_light = "base16-light",
|
||||
Bespin = "bespin",
|
||||
Blackboard = "blackboard",
|
||||
Cobalt = "cobalt",
|
||||
Colorforth = "colorforth",
|
||||
Darcula = "darcula",
|
||||
Dracula = "dracula",
|
||||
Duotone_dark = "duotone-dark",
|
||||
Duotone_light = "duotone-light",
|
||||
Eclipse = "eclipse",
|
||||
Elegant = "elegant",
|
||||
Erlang_dark = "erlang-dark",
|
||||
Gruvbox_dark = "gruvbox-dark",
|
||||
Hopscotch = "hopscotch",
|
||||
Icecoder = "icecoder",
|
||||
Idea = "idea",
|
||||
Isotope = "isotope",
|
||||
Lesser_dark = "lesser-dark",
|
||||
Liquibyte = "liquibyte",
|
||||
Lucario = "lucario",
|
||||
Material = "material",
|
||||
Mbo = "mbo",
|
||||
Mdn_like = "mdn-like",
|
||||
Midnight = "midnight",
|
||||
Neat = "neat",
|
||||
Neo = "neo",
|
||||
Night = "night",
|
||||
Oceanic_next = "oceanic-next",
|
||||
Panda_syntax = "panda-syntax",
|
||||
Paraiso_dark = "paraiso-dark",
|
||||
Paraiso_light = "paraiso-light",
|
||||
Pastel_on_dark = "pastel-on-dark",
|
||||
Railscasts = "railscasts",
|
||||
Rubyblue = "rubyblue",
|
||||
Seti = "seti",
|
||||
Shadowfox = "shadowfox",
|
||||
Solarized = "solarized",
|
||||
SolarizedDark = "solarized dark",
|
||||
ssms = "ssms",
|
||||
The_matrix = "the-matrix",
|
||||
Tomorrow_night_bright = "tomorrow-night-bright",
|
||||
Tomorrow_night_eighties = "tomorrow-night-eighties",
|
||||
Ttcn = "ttcn",
|
||||
Twilight = "twilight",
|
||||
Vibrant_ink = "vibrant-ink",
|
||||
xq_dark = "xq-dark",
|
||||
xq_light = "xq-light",
|
||||
Yeti = "yeti",
|
||||
Zenburn = "zenburn",
|
||||
}
|
||||
|
||||
/**
|
||||
* Allowed values for the "Editor" setting
|
||||
*/
|
||||
export enum EditorSetting {
|
||||
Ace = "Ace",
|
||||
CodeMirror = "CodeMirror",
|
||||
}
|
||||
|
||||
/**
|
||||
* Allowed values for the 'OwnedAugmentationsOrder' setting
|
||||
*/
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { BitNodes } from "../BitNode/BitNode";
|
||||
|
||||
export class SourceFile {
|
||||
info: string;
|
||||
info: JSX.Element;
|
||||
lvl = 1;
|
||||
n: number;
|
||||
name: string;
|
||||
owned = false;
|
||||
|
||||
constructor(number: number, info = "") {
|
||||
constructor(number: number, info: JSX.Element) {
|
||||
const bitnodeKey = "BitNode" + number;
|
||||
const bitnode = BitNodes[bitnodeKey];
|
||||
if (bitnode == null) {
|
||||
|
@ -1,104 +0,0 @@
|
||||
import { SourceFile } from "./SourceFile";
|
||||
import { IMap } from "../types";
|
||||
|
||||
export const SourceFiles: IMap<SourceFile> = {};
|
||||
|
||||
SourceFiles["SourceFile1"] = new SourceFile(
|
||||
1,
|
||||
"This Source-File lets the player start with 32GB of RAM on his/her " +
|
||||
"home computer. It also increases all of the player's multipliers by:<br><br>" +
|
||||
"Level 1: 16%<br>" +
|
||||
"Level 2: 24%<br>" +
|
||||
"Level 3: 28%",
|
||||
);
|
||||
SourceFiles["SourceFile2"] = new SourceFile(
|
||||
2,
|
||||
"This Source-File allows you to form gangs in other BitNodes " +
|
||||
"once your karma decreases to a certain value. It also increases the player's " +
|
||||
"crime success rate, crime money, and charisma multipliers by:<br><br>" +
|
||||
"Level 1: 24%<br>" +
|
||||
"Level 2: 36%<br>" +
|
||||
"Level 3: 42%",
|
||||
);
|
||||
SourceFiles["SourceFile3"] = new SourceFile(
|
||||
3,
|
||||
"This Source-File lets you create corporations on other BitNodes (although " +
|
||||
"some BitNodes will disable this mechanic). This Source-File also increases your charisma and company salary multipliers by:<br>" +
|
||||
"Level 1: 8%<br>" +
|
||||
"Level 2: 12%<br>" +
|
||||
"Level 3: 14%",
|
||||
);
|
||||
SourceFiles["SourceFile4"] = new SourceFile(
|
||||
4,
|
||||
"This Source-File lets you access and use the Singularity Functions in every BitNode. Every " +
|
||||
"level of this Source-File opens up more of the Singularity Functions you can use.",
|
||||
);
|
||||
SourceFiles["SourceFile5"] = new SourceFile(
|
||||
5,
|
||||
"This Source-File grants a special new stat called Intelligence. Intelligence " +
|
||||
"is unique because it is permanent and persistent (it never gets reset back to 1). However, " +
|
||||
"gaining Intelligence experience is much slower than other stats, and it is also hidden (you won't " +
|
||||
"know when you gain experience and how much). Higher Intelligence levels will boost your production " +
|
||||
"for many actions in the game. In addition, this Source-File will unlock the getBitNodeMultipliers() " +
|
||||
"and getServer() Netscript functions, as well as the formulas API, and will raise all of your " +
|
||||
"hacking-related multipliers by:<br><br> " +
|
||||
"Level 1: 8%<br>" +
|
||||
"Level 2: 12%<br>" +
|
||||
"Level 3: 14%",
|
||||
);
|
||||
SourceFiles["SourceFile6"] = new SourceFile(
|
||||
6,
|
||||
"This Source-File allows you to access the NSA's Bladeburner Division in other " +
|
||||
"BitNodes. In addition, this Source-File will raise both the level and experience gain rate of all your combat stats by:<br><br>" +
|
||||
"Level 1: 8%<br>" +
|
||||
"Level 2: 12%<br>" +
|
||||
"Level 3: 14%",
|
||||
);
|
||||
SourceFiles["SourceFile7"] = new SourceFile(
|
||||
7,
|
||||
"This Source-File allows you to access the Bladeburner Netscript API in other " +
|
||||
"BitNodes. In addition, this Source-File will increase all of your Bladeburner multipliers by:<br><br>" +
|
||||
"Level 1: 8%<br>" +
|
||||
"Level 2: 12%<br>" +
|
||||
"Level 3: 14%",
|
||||
);
|
||||
SourceFiles["SourceFile8"] = new SourceFile(
|
||||
8,
|
||||
"This Source-File grants the following benefits:<br><br>" +
|
||||
"Level 1: Permanent access to WSE and TIX API<br>" +
|
||||
"Level 2: Ability to short stocks in other BitNodes<br>" +
|
||||
"Level 3: Ability to use limit/stop orders in other BitNodes<br><br>" +
|
||||
"This Source-File also increases your hacking growth multipliers by: " +
|
||||
"<br>Level 1: 12%<br>Level 2: 18%<br>Level 3: 21%",
|
||||
);
|
||||
SourceFiles["SourceFile9"] = new SourceFile(
|
||||
9,
|
||||
"This Source-File grants the following benefits:<br><br>" +
|
||||
"Level 1: Permanently unlocks the Hacknet Server in other BitNodes<br>" +
|
||||
"Level 2: You start with 128GB of RAM on your home computer when entering a new BitNode<br>" +
|
||||
"Level 3: Grants a highly-upgraded Hacknet Server when entering a new BitNode<br><br>" +
|
||||
"(Note that the Level 3 effect of this Source-File only applies when entering a new BitNode, NOT " +
|
||||
"when installing Augmentations)",
|
||||
);
|
||||
SourceFiles["SourceFile10"] = new SourceFile(
|
||||
10,
|
||||
"This Source-File unlocks Sleeve technology in other BitNodes. Each level of this " +
|
||||
"Source-File also grants you a Duplicate Sleeve",
|
||||
);
|
||||
SourceFiles["SourceFile11"] = new SourceFile(
|
||||
11,
|
||||
"This Source-File makes it so that company favor increases BOTH the player's salary and reputation gain rate " +
|
||||
"at that company by 1% per favor (rather than just the reputation gain). This Source-File also " +
|
||||
" increases the player's company salary and reputation gain multipliers by:<br><br>" +
|
||||
"Level 1: 32%<br>" +
|
||||
"Level 2: 48%<br>" +
|
||||
"Level 3: 56%<br><br>" +
|
||||
"It also reduces the price increase for every aug bought by:<br><br>" +
|
||||
"Level 1: 4%<br>" +
|
||||
"Level 2: 6%<br>" +
|
||||
"Level 3: 7%",
|
||||
);
|
||||
SourceFiles["SourceFile12"] = new SourceFile(
|
||||
12,
|
||||
"This Source-File lets the player start with Neuroflux Governor equal to the level of this Source-File.",
|
||||
);
|
197
src/SourceFile/SourceFiles.tsx
Normal file
197
src/SourceFile/SourceFiles.tsx
Normal file
@ -0,0 +1,197 @@
|
||||
import React from "react";
|
||||
import { SourceFile } from "./SourceFile";
|
||||
import { IMap } from "../types";
|
||||
|
||||
export const SourceFiles: IMap<SourceFile> = {};
|
||||
|
||||
SourceFiles["SourceFile1"] = new SourceFile(
|
||||
1,
|
||||
(
|
||||
<>
|
||||
This Source-File lets the player start with 32GB of RAM on his/her home computer. It also increases all of the
|
||||
player's multipliers by:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: 16%
|
||||
<br />
|
||||
Level 2: 24%
|
||||
<br />
|
||||
Level 3: 28%
|
||||
</>
|
||||
),
|
||||
);
|
||||
SourceFiles["SourceFile2"] = new SourceFile(
|
||||
2,
|
||||
(
|
||||
<>
|
||||
This Source-File allows you to form gangs in other BitNodes once your karma decreases to a certain value. It also
|
||||
increases the player's crime success rate, crime money, and charisma multipliers by:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: 24%
|
||||
<br />
|
||||
Level 2: 36%
|
||||
<br />
|
||||
Level 3: 42%
|
||||
</>
|
||||
),
|
||||
);
|
||||
SourceFiles["SourceFile3"] = new SourceFile(
|
||||
3,
|
||||
(
|
||||
<>
|
||||
This Source-File lets you create corporations on other BitNodes (although some BitNodes will disable this
|
||||
mechanic). This Source-File also increases your charisma and company salary multipliers by:
|
||||
<br />
|
||||
Level 1: 8%
|
||||
<br />
|
||||
Level 2: 12%
|
||||
<br />
|
||||
Level 3: 14%
|
||||
</>
|
||||
),
|
||||
);
|
||||
SourceFiles["SourceFile4"] = new SourceFile(
|
||||
4,
|
||||
(
|
||||
<>
|
||||
This Source-File lets you access and use the Singularity Functions in every BitNode. Every level of this
|
||||
Source-File opens up more of the Singularity Functions you can use.
|
||||
</>
|
||||
),
|
||||
);
|
||||
SourceFiles["SourceFile5"] = new SourceFile(
|
||||
5,
|
||||
(
|
||||
<>
|
||||
This Source-File grants a special new stat called Intelligence. Intelligence is unique because it is permanent and
|
||||
persistent (it never gets reset back to 1). However, gaining Intelligence experience is much slower than other
|
||||
stats, and it is also hidden (you won't know when you gain experience and how much). Higher Intelligence levels
|
||||
will boost your production for many actions in the game. In addition, this Source-File will unlock the
|
||||
getBitNodeMultipliers() and getServer() Netscript functions, as well as the formulas API, and will raise all of
|
||||
your hacking-related multipliers by:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: 8%
|
||||
<br />
|
||||
Level 2: 12%
|
||||
<br />
|
||||
Level 3: 14%
|
||||
</>
|
||||
),
|
||||
);
|
||||
SourceFiles["SourceFile6"] = new SourceFile(
|
||||
6,
|
||||
(
|
||||
<>
|
||||
This Source-File allows you to access the NSA's Bladeburner Division in other BitNodes. In addition, this
|
||||
Source-File will raise both the level and experience gain rate of all your combat stats by:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: 8%
|
||||
<br />
|
||||
Level 2: 12%
|
||||
<br />
|
||||
Level 3: 14%
|
||||
</>
|
||||
),
|
||||
);
|
||||
SourceFiles["SourceFile7"] = new SourceFile(
|
||||
7,
|
||||
(
|
||||
<>
|
||||
This Source-File allows you to access the Bladeburner Netscript API in other BitNodes. In addition, this
|
||||
Source-File will increase all of your Bladeburner multipliers by:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: 8%
|
||||
<br />
|
||||
Level 2: 12%
|
||||
<br />
|
||||
Level 3: 14%
|
||||
</>
|
||||
),
|
||||
);
|
||||
SourceFiles["SourceFile8"] = new SourceFile(
|
||||
8,
|
||||
(
|
||||
<>
|
||||
This Source-File grants the following benefits:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: Permanent access to WSE and TIX API
|
||||
<br />
|
||||
Level 2: Ability to short stocks in other BitNodes
|
||||
<br />
|
||||
Level 3: Ability to use limit/stop orders in other BitNodes
|
||||
<br />
|
||||
<br />
|
||||
This Source-File also increases your hacking growth multipliers by:
|
||||
<br />
|
||||
Level 1: 12%
|
||||
<br />
|
||||
Level 2: 18%
|
||||
<br />
|
||||
Level 3: 21%
|
||||
</>
|
||||
),
|
||||
);
|
||||
SourceFiles["SourceFile9"] = new SourceFile(
|
||||
9,
|
||||
(
|
||||
<>
|
||||
This Source-File grants the following benefits:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: Permanently unlocks the Hacknet Server in other BitNodes
|
||||
<br />
|
||||
Level 2: You start with 128GB of RAM on your home computer when entering a new BitNode
|
||||
<br />
|
||||
Level 3: Grants a highly-upgraded Hacknet Server when entering a new BitNode
|
||||
<br />
|
||||
<br />
|
||||
(Note that the Level 3 effect of this Source-File only applies when entering a new BitNode, NOT when installing
|
||||
Augmentations)
|
||||
</>
|
||||
),
|
||||
);
|
||||
SourceFiles["SourceFile10"] = new SourceFile(
|
||||
10,
|
||||
(
|
||||
<>
|
||||
This Source-File unlocks Sleeve technology in other BitNodes. Each level of this Source-File also grants you a
|
||||
Duplicate Sleeve
|
||||
</>
|
||||
),
|
||||
);
|
||||
SourceFiles["SourceFile11"] = new SourceFile(
|
||||
11,
|
||||
(
|
||||
<>
|
||||
This Source-File makes it so that company favor increases BOTH the player's salary and reputation gain rate at
|
||||
that company by 1% per favor (rather than just the reputation gain). This Source-File also increases the player's
|
||||
company salary and reputation gain multipliers by:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: 32%
|
||||
<br />
|
||||
Level 2: 48%
|
||||
<br />
|
||||
Level 3: 56%
|
||||
<br />
|
||||
<br />
|
||||
It also reduces the price increase for every aug bought by:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: 4%
|
||||
<br />
|
||||
Level 2: 6%
|
||||
<br />
|
||||
Level 3: 7%
|
||||
</>
|
||||
),
|
||||
);
|
||||
SourceFiles["SourceFile12"] = new SourceFile(
|
||||
12,
|
||||
<>This Source-File lets the player start with Neuroflux Governor equal to the level of this Source-File.</>,
|
||||
);
|
@ -6,7 +6,7 @@ import Box from "@mui/material/Box";
|
||||
export function TutorialRoot(): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
<Typography variant="h4">Tutorial (AKA Links to Documentation)</Typography>
|
||||
<Typography variant="h4">Tutorial / Documentation</Typography>
|
||||
<Box m={2}>
|
||||
<Link
|
||||
color="primary"
|
||||
|
15
src/db.tsx
15
src/db.tsx
@ -1,6 +1,3 @@
|
||||
import { Engine } from "./engine";
|
||||
import { createStatusText } from "./ui/createStatusText";
|
||||
|
||||
function getDB(): Promise<IDBObjectStore> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!window.indexedDB) {
|
||||
@ -24,7 +21,7 @@ function getDB(): Promise<IDBObjectStore> {
|
||||
reject(`Failed to get IDB ${ev}`);
|
||||
};
|
||||
|
||||
indexedDbRequest.onsuccess = function (this: IDBRequest<IDBDatabase>, ev: Event) {
|
||||
indexedDbRequest.onsuccess = function (this: IDBRequest<IDBDatabase>) {
|
||||
const db = this.result;
|
||||
if (!db) {
|
||||
reject("database loadign result was undefined");
|
||||
@ -35,11 +32,6 @@ function getDB(): Promise<IDBObjectStore> {
|
||||
});
|
||||
}
|
||||
|
||||
interface ILoadCallback {
|
||||
success: (s: string) => void;
|
||||
error?: () => void;
|
||||
}
|
||||
|
||||
export function load(): Promise<string> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
await getDB()
|
||||
@ -59,11 +51,6 @@ export function load(): Promise<string> {
|
||||
});
|
||||
}
|
||||
|
||||
interface ISaveCallback {
|
||||
success: () => void;
|
||||
error?: () => void;
|
||||
}
|
||||
|
||||
export function save(saveString: string): Promise<void> {
|
||||
return getDB().then((db) => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
|
1
src/engine.d.ts
vendored
1
src/engine.d.ts
vendored
@ -1 +0,0 @@
|
||||
export declare const Engine: IEngine;
|
@ -231,7 +231,7 @@ const Engine: {
|
||||
}
|
||||
|
||||
if (Engine.Counters.passiveFactionGrowth <= 0) {
|
||||
var adjustedCycles = Math.floor(5 - Engine.Counters.passiveFactionGrowth);
|
||||
const adjustedCycles = Math.floor(5 - Engine.Counters.passiveFactionGrowth);
|
||||
processPassiveFactionRepGain(adjustedCycles);
|
||||
Engine.Counters.passiveFactionGrowth = 5;
|
||||
}
|
||||
@ -334,7 +334,7 @@ const Engine: {
|
||||
}
|
||||
|
||||
// Hacknet Nodes offline progress
|
||||
var offlineProductionFromHacknetNodes = processHacknetEarnings(Player, numCyclesOffline);
|
||||
const offlineProductionFromHacknetNodes = processHacknetEarnings(Player, numCyclesOffline);
|
||||
const hacknetProdInfo = hasHacknetServers(Player) ? (
|
||||
<>{Hashes(offlineProductionFromHacknetNodes)} hashes</>
|
||||
) : (
|
||||
@ -384,7 +384,7 @@ const Engine: {
|
||||
}
|
||||
|
||||
// Update total playtime
|
||||
var time = numCyclesOffline * CONSTANTS._idleSpeed;
|
||||
const time = numCyclesOffline * CONSTANTS._idleSpeed;
|
||||
if (Player.totalPlaytime == null) {
|
||||
Player.totalPlaytime = 0;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ ReactDOM.render(
|
||||
document.getElementById("mainmenu-container"),
|
||||
);
|
||||
|
||||
function rerender() {
|
||||
function rerender(): void {
|
||||
refreshTheme();
|
||||
ReactDOM.render(
|
||||
<Theme>
|
||||
|
@ -28,6 +28,7 @@ export function ActiveScriptsRoot(props: IProps): React.ReactElement {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography variant="h4">Active Scripts</Typography>
|
||||
<Typography>
|
||||
This page displays a list of all of your scripts that are currently running across every machine. It also
|
||||
provides information about each script's production. The scripts are categorized by the hostname of the servers
|
||||
|
@ -145,7 +145,7 @@ function CurrentBitNode(): React.ReactElement {
|
||||
const index = "BitNode" + player.bitNodeN;
|
||||
return (
|
||||
<>
|
||||
<Typography variant="h5" color="primary">
|
||||
<Typography variant="h4">
|
||||
BitNode {player.bitNodeN}: {BitNodes[index].name}
|
||||
</Typography>
|
||||
<Typography sx={{ mx: 2 }} style={{ whiteSpace: "pre-wrap", overflowWrap: "break-word" }}>
|
||||
@ -270,9 +270,7 @@ export function CharacterStats(): React.ReactElement {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography variant="h5" color="primary">
|
||||
General
|
||||
</Typography>
|
||||
<Typography variant="h4">General</Typography>
|
||||
<Box sx={{ mx: 2 }}>
|
||||
<Typography>Current City: {player.city}</Typography>
|
||||
<LastEmployer />
|
||||
@ -287,9 +285,7 @@ export function CharacterStats(): React.ReactElement {
|
||||
</Typography>
|
||||
</Box>
|
||||
<br />
|
||||
<Typography variant="h5" color="primary">
|
||||
Stats
|
||||
</Typography>
|
||||
<Typography variant="h4">Stats</Typography>
|
||||
<Box sx={{ mx: 2 }}>
|
||||
<Table size="small" padding="none">
|
||||
<TableBody>
|
||||
@ -365,9 +361,7 @@ export function CharacterStats(): React.ReactElement {
|
||||
<br />
|
||||
</Box>
|
||||
<br />
|
||||
<Typography variant="h5" color="primary">
|
||||
Multipliers
|
||||
</Typography>
|
||||
<Typography variant="h4">Multipliers</Typography>
|
||||
<Box sx={{ mx: 2 }}>
|
||||
<MultiplierTable
|
||||
rows={[
|
||||
@ -477,9 +471,7 @@ export function CharacterStats(): React.ReactElement {
|
||||
</Box>
|
||||
<br />
|
||||
|
||||
<Typography variant="h5" color="primary">
|
||||
Misc
|
||||
</Typography>
|
||||
<Typography variant="h4">Misc</Typography>
|
||||
<Box sx={{ mx: 2 }}>
|
||||
<Typography>{`Servers owned: ${player.purchasedServers.length} / ${getPurchaseServerLimit()}`}</Typography>
|
||||
<Hacknet />
|
||||
|
@ -23,7 +23,7 @@ export function LoadingScreen(): React.ReactElement {
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
async function doLoad() {
|
||||
async function doLoad(): Promise<void> {
|
||||
await load()
|
||||
.then((saveString) => {
|
||||
Engine.load(saveString);
|
||||
|
@ -4,12 +4,18 @@
|
||||
* The header of the accordion contains the Augmentation's name (and level, if
|
||||
* applicable), and the accordion's panel contains the Augmentation's description.
|
||||
*/
|
||||
import * as React from "react";
|
||||
|
||||
import { BBAccordion } from "./BBAccordion";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { Augmentation } from "../../Augmentation/Augmentation";
|
||||
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
|
||||
import ListItemButton from "@mui/material/ListItemButton";
|
||||
import ListItemText from "@mui/material/ListItemText";
|
||||
import Box from "@mui/material/Box";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import Collapse from "@mui/material/Collapse";
|
||||
import ExpandMore from "@mui/icons-material/ExpandMore";
|
||||
import ExpandLess from "@mui/icons-material/ExpandLess";
|
||||
|
||||
type IProps = {
|
||||
aug: Augmentation;
|
||||
@ -17,6 +23,7 @@ type IProps = {
|
||||
};
|
||||
|
||||
export function AugmentationAccordion(props: IProps): React.ReactElement {
|
||||
const [open, setOpen] = useState(false);
|
||||
let displayName = props.aug.name;
|
||||
if (props.level != null) {
|
||||
if (props.aug.name === AugmentationNames.NeuroFluxGovernor) {
|
||||
@ -26,31 +33,47 @@ export function AugmentationAccordion(props: IProps): React.ReactElement {
|
||||
|
||||
if (typeof props.aug.info === "string") {
|
||||
return (
|
||||
<BBAccordion
|
||||
headerContent={<>{displayName}</>}
|
||||
panelContent={
|
||||
<p>
|
||||
<span dangerouslySetInnerHTML={{ __html: props.aug.info }} />
|
||||
<Box component={Paper}>
|
||||
<ListItemButton onClick={() => setOpen((old) => !old)}>
|
||||
<ListItemText primary={<Typography style={{ whiteSpace: "pre-wrap" }}>{displayName}</Typography>} />
|
||||
{open ? <ExpandLess color="primary" /> : <ExpandMore color="primary" />}
|
||||
</ListItemButton>
|
||||
<Collapse in={open} unmountOnExit>
|
||||
<Box m={4}>
|
||||
<Typography dangerouslySetInnerHTML={{ __html: props.aug.info }} />
|
||||
{props.aug.stats && (
|
||||
<>
|
||||
<br />
|
||||
<br />
|
||||
{props.aug.stats}
|
||||
</p>
|
||||
}
|
||||
/>
|
||||
<Typography>{props.aug.stats}</Typography>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
</Collapse>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<BBAccordion
|
||||
headerContent={<>{displayName}</>}
|
||||
panelContent={
|
||||
<p>
|
||||
<Box component={Paper}>
|
||||
<ListItemButton onClick={() => setOpen((old) => !old)}>
|
||||
<ListItemText primary={<Typography style={{ whiteSpace: "pre-wrap" }}>{displayName}</Typography>} />
|
||||
{open ? <ExpandLess color="primary" /> : <ExpandMore color="primary" />}
|
||||
</ListItemButton>
|
||||
<Collapse in={open} unmountOnExit>
|
||||
<Box m={4}>
|
||||
<Typography>
|
||||
{props.aug.info}
|
||||
{props.aug.stats && (
|
||||
<>
|
||||
<br />
|
||||
<br />
|
||||
{props.aug.stats}
|
||||
</p>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Collapse>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
@ -4,30 +4,47 @@
|
||||
* The header of the accordion contains the Source-Files's name and level,
|
||||
* and the accordion's panel contains the Source-File's description.
|
||||
*/
|
||||
import * as React from "react";
|
||||
|
||||
import { BBAccordion } from "./BBAccordion";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { SourceFile } from "../../SourceFile/SourceFile";
|
||||
|
||||
import ListItemButton from "@mui/material/ListItemButton";
|
||||
import ListItemText from "@mui/material/ListItemText";
|
||||
import Box from "@mui/material/Box";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import Collapse from "@mui/material/Collapse";
|
||||
import ExpandMore from "@mui/icons-material/ExpandMore";
|
||||
import ExpandLess from "@mui/icons-material/ExpandLess";
|
||||
|
||||
type IProps = {
|
||||
level: number;
|
||||
sf: SourceFile;
|
||||
};
|
||||
|
||||
export function SourceFileAccordion(props: IProps): React.ReactElement {
|
||||
const [open, setOpen] = useState(false);
|
||||
const maxLevel = props.sf.n === 12 ? "∞" : "3";
|
||||
|
||||
return (
|
||||
<BBAccordion
|
||||
headerContent={
|
||||
<>
|
||||
<Box component={Paper}>
|
||||
<ListItemButton onClick={() => setOpen((old) => !old)}>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography style={{ whiteSpace: "pre-wrap" }}>
|
||||
{props.sf.name}
|
||||
<br />
|
||||
{`Level ${props.level} / ${maxLevel}`}
|
||||
</>
|
||||
</Typography>
|
||||
}
|
||||
panelContent={<p dangerouslySetInnerHTML={{ __html: props.sf.info }}></p>}
|
||||
/>
|
||||
{open ? <ExpandLess color="primary" /> : <ExpandMore color="primary" />}
|
||||
</ListItemButton>
|
||||
<Collapse in={open} unmountOnExit>
|
||||
<Box m={4}>
|
||||
<Typography>{props.sf.info}</Typography>
|
||||
</Box>
|
||||
</Collapse>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ declare module "@mui/material/styles" {
|
||||
|
||||
let theme: Theme;
|
||||
|
||||
export function refreshTheme() {
|
||||
export function refreshTheme(): void {
|
||||
theme = createTheme({
|
||||
colors: {
|
||||
hp: Settings.theme.hp,
|
||||
|
@ -3,7 +3,6 @@ import { Modal } from "./Modal";
|
||||
import Button from "@mui/material/Button";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import DoneIcon from "@mui/icons-material/Done";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import ReplyIcon from "@mui/icons-material/Reply";
|
||||
import { Color, ColorPicker } from "material-ui-color";
|
||||
@ -15,30 +14,15 @@ interface IProps {
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
function ColorEditor({ name }: { name: string }): React.ReactElement {
|
||||
const [color, setColor] = useState(Settings.theme[name]);
|
||||
if (color === undefined) return <></>;
|
||||
const valid = color.match(/#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})/g);
|
||||
|
||||
function set(): void {
|
||||
if (!valid) return;
|
||||
Settings.theme[name] = color;
|
||||
ThemeEvents.emit();
|
||||
interface IColorEditorProps {
|
||||
name: string;
|
||||
color: string | undefined;
|
||||
onColorChange: (name: string, value: string) => void;
|
||||
defaultColor: string;
|
||||
}
|
||||
|
||||
function revert(): void {
|
||||
Settings.theme[name] = defaultSettings.theme[name];
|
||||
setColor(defaultSettings.theme[name]);
|
||||
ThemeEvents.emit();
|
||||
}
|
||||
|
||||
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
setColor(event.target.value);
|
||||
}
|
||||
|
||||
function onColorPickerChange(newValue: Color): void {
|
||||
setColor("#" + newValue.hex.toLowerCase());
|
||||
}
|
||||
function ColorEditor({ name, onColorChange, color, defaultColor }: IColorEditorProps): React.ReactElement {
|
||||
if (color === undefined) throw new Error("should not happen");
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -46,20 +30,20 @@ function ColorEditor({ name }: { name: string }): React.ReactElement {
|
||||
sx={{ mx: 1 }}
|
||||
label={name}
|
||||
value={color}
|
||||
onChange={onChange}
|
||||
variant="standard"
|
||||
InputProps={{
|
||||
startAdornment: (
|
||||
<>
|
||||
<ColorPicker hideTextfield value={color} onChange={onColorPickerChange} />
|
||||
<ColorPicker
|
||||
hideTextfield
|
||||
value={color}
|
||||
onChange={(newColor: Color) => onColorChange(name, "#" + newColor.hex)}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
endAdornment: (
|
||||
<>
|
||||
<IconButton onClick={set} disabled={!valid}>
|
||||
<DoneIcon color={valid ? "primary" : "error"} />
|
||||
</IconButton>
|
||||
<IconButton onClick={revert}>
|
||||
<IconButton onClick={() => onColorChange(name, defaultColor)}>
|
||||
<ReplyIcon color="primary" />
|
||||
</IconButton>
|
||||
</>
|
||||
@ -71,6 +55,34 @@ function ColorEditor({ name }: { name: string }): React.ReactElement {
|
||||
}
|
||||
|
||||
export function ThemeEditorModal(props: IProps): React.ReactElement {
|
||||
const [customTheme, setCustomTheme] = useState<{ [key: string]: string | undefined }>({
|
||||
...Settings.theme,
|
||||
});
|
||||
|
||||
function onThemeChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
try {
|
||||
const importedTheme = JSON.parse(event.target.value);
|
||||
if (typeof importedTheme !== "object") return;
|
||||
setCustomTheme(importedTheme);
|
||||
for (const key of Object.keys(importedTheme)) {
|
||||
Settings.theme[key] = importedTheme[key];
|
||||
}
|
||||
ThemeEvents.emit();
|
||||
} catch (err) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
function onColorChange(name: string, value: string): void {
|
||||
setCustomTheme((old: any) => {
|
||||
old[name] = value;
|
||||
return old;
|
||||
});
|
||||
|
||||
Settings.theme[name] = value;
|
||||
ThemeEvents.emit();
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal open={props.open} onClose={props.onClose}>
|
||||
<Button color="primary">primary</Button>
|
||||
@ -84,44 +96,177 @@ export function ThemeEditorModal(props: IProps): React.ReactElement {
|
||||
<Typography color="info">info</Typography>
|
||||
<Typography color="error">error</Typography>
|
||||
<br />
|
||||
<ColorEditor name="primarylight" />
|
||||
<ColorEditor name="primary" />
|
||||
<ColorEditor name="primarydark" />
|
||||
<ColorEditor
|
||||
name="primarylight"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["primarylight"]}
|
||||
defaultColor={defaultSettings.theme["primarylight"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="primary"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["primary"]}
|
||||
defaultColor={defaultSettings.theme["primary"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="primarydark"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["primarydark"]}
|
||||
defaultColor={defaultSettings.theme["primarydark"]}
|
||||
/>
|
||||
|
||||
<br />
|
||||
<ColorEditor name="errorlight" />
|
||||
<ColorEditor name="error" />
|
||||
<ColorEditor name="errordark" />
|
||||
<ColorEditor
|
||||
name="errorlight"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["errorlight"]}
|
||||
defaultColor={defaultSettings.theme["errorlight"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="error"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["error"]}
|
||||
defaultColor={defaultSettings.theme["error"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="errordark"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["errordark"]}
|
||||
defaultColor={defaultSettings.theme["errordark"]}
|
||||
/>
|
||||
|
||||
<br />
|
||||
<ColorEditor name="secondarylight" />
|
||||
<ColorEditor name="secondary" />
|
||||
<ColorEditor name="secondarydark" />
|
||||
<ColorEditor
|
||||
name="secondarylight"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["secondarylight"]}
|
||||
defaultColor={defaultSettings.theme["secondarylight"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="secondary"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["secondary"]}
|
||||
defaultColor={defaultSettings.theme["secondary"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="secondarydark"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["secondarydark"]}
|
||||
defaultColor={defaultSettings.theme["secondarydark"]}
|
||||
/>
|
||||
|
||||
<br />
|
||||
<ColorEditor name="warninglight" />
|
||||
<ColorEditor name="warning" />
|
||||
<ColorEditor name="warningdark" />
|
||||
<ColorEditor
|
||||
name="warninglight"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["warninglight"]}
|
||||
defaultColor={defaultSettings.theme["warninglight"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="warning"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["warning"]}
|
||||
defaultColor={defaultSettings.theme["warning"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="warningdark"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["warningdark"]}
|
||||
defaultColor={defaultSettings.theme["warningdark"]}
|
||||
/>
|
||||
|
||||
<br />
|
||||
<ColorEditor name="infolight" />
|
||||
<ColorEditor name="info" />
|
||||
<ColorEditor name="infodark" />
|
||||
<ColorEditor
|
||||
name="infolight"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["infolight"]}
|
||||
defaultColor={defaultSettings.theme["infolight"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="info"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["info"]}
|
||||
defaultColor={defaultSettings.theme["info"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="infodark"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["infodark"]}
|
||||
defaultColor={defaultSettings.theme["infodark"]}
|
||||
/>
|
||||
|
||||
<br />
|
||||
<ColorEditor name="welllight" />
|
||||
<ColorEditor name="well" />
|
||||
<ColorEditor name="white" />
|
||||
<ColorEditor name="black" />
|
||||
<ColorEditor
|
||||
name="welllight"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["welllight"]}
|
||||
defaultColor={defaultSettings.theme["welllight"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="well"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["well"]}
|
||||
defaultColor={defaultSettings.theme["well"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="white"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["white"]}
|
||||
defaultColor={defaultSettings.theme["white"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="black"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["black"]}
|
||||
defaultColor={defaultSettings.theme["black"]}
|
||||
/>
|
||||
|
||||
<br />
|
||||
<ColorEditor name="hp" />
|
||||
<ColorEditor name="money" />
|
||||
<ColorEditor name="hack" />
|
||||
<ColorEditor name="combat" />
|
||||
<ColorEditor name="cha" />
|
||||
<ColorEditor name="int" />
|
||||
<ColorEditor name="rep" />
|
||||
<ColorEditor
|
||||
name="hp"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["hp"]}
|
||||
defaultColor={defaultSettings.theme["hp"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="money"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["money"]}
|
||||
defaultColor={defaultSettings.theme["money"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="hack"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["hack"]}
|
||||
defaultColor={defaultSettings.theme["hack"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="combat"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["combat"]}
|
||||
defaultColor={defaultSettings.theme["combat"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="cha"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["cha"]}
|
||||
defaultColor={defaultSettings.theme["cha"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="int"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["int"]}
|
||||
defaultColor={defaultSettings.theme["int"]}
|
||||
/>
|
||||
<ColorEditor
|
||||
name="rep"
|
||||
onColorChange={onColorChange}
|
||||
color={customTheme["rep"]}
|
||||
defaultColor={defaultSettings.theme["rep"]}
|
||||
/>
|
||||
<br />
|
||||
<br />
|
||||
<TextField label={"import / export theme"} value={JSON.stringify(customTheme)} onChange={onThemeChange} />
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
import React from "react";
|
||||
import { CityName } from "../../Locations/data/CityNames";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
|
||||
interface ICityProps {
|
||||
currentCity: CityName;
|
||||
@ -10,19 +12,14 @@ interface ICityProps {
|
||||
function City(props: ICityProps): React.ReactElement {
|
||||
if (props.city !== props.currentCity) {
|
||||
return (
|
||||
<Tooltip title={props.city}>
|
||||
<span
|
||||
className="tooltip"
|
||||
style={{
|
||||
color: "white",
|
||||
whiteSpace: "nowrap",
|
||||
margin: "0px",
|
||||
padding: "0px",
|
||||
}}
|
||||
onClick={() => props.onTravel(props.city)}
|
||||
style={{ color: "white", lineHeight: "1em", whiteSpace: "pre" }}
|
||||
>
|
||||
<span className="tooltiptext">{props.city}</span>
|
||||
<b>{props.city[0]}</b>
|
||||
{props.city[0]}
|
||||
</span>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
return <span>{props.city[0]}</span>;
|
||||
@ -37,28 +34,28 @@ export function WorldMap(props: IProps): React.ReactElement {
|
||||
// prettier-ignore
|
||||
return (
|
||||
<div className="noselect">
|
||||
<pre> ,_ . ._. _. .</pre>
|
||||
<pre> , _-\','|~\~ ~/ ;-'_ _-' ,;_;_, ~~-</pre>
|
||||
<pre> /~~-\_/-'~'--' \~~| ', ,' / / ~|-_\_/~/~ ~~--~~~~'--_</pre>
|
||||
<pre> / ,/'-/~ '\ ,' _ , '<City onTravel={props.onTravel} currentCity={props.currentCity} city={CityName.Volhaven} />,'|~ ._/-, /~</pre>
|
||||
<pre> ~/-'~\_, '-,| '|. ' ~ ,\ /'~ / /_ /~</pre>
|
||||
<pre>.-~ '| '',\~|\ _\~ ,_ , <City onTravel={props.onTravel} currentCity={props.currentCity} city={CityName.Chongqing} /> /,</pre>
|
||||
<pre> '\ <City onTravel={props.onTravel} currentCity={props.currentCity} city={CityName.Sector12} /> /'~ |_/~\\,-,~ \ " ,_,/ |</pre>
|
||||
<pre> | / ._-~'\_ _~| \ ) <City onTravel={props.onTravel} currentCity={props.currentCity} city={CityName.NewTokyo} /></pre>
|
||||
<pre> \ __-\ '/ ~ |\ \_ / ~</pre>
|
||||
<pre> ., '\ |, ~-_ - | \\_' ~| /\ \~ ,</pre>
|
||||
<pre> ~-_' _; '\ '-, \,' /\/ |</pre>
|
||||
<pre> '\_,~'\_ \_ _, /' ' |, /|'</pre>
|
||||
<pre> / \_ ~ | / \ ~'; -,_.</pre>
|
||||
<pre> | ~\ | | , '-_, ,; ~ ~\</pre>
|
||||
<pre> \, <City onTravel={props.onTravel} currentCity={props.currentCity} city={CityName.Aevum} /> / \ / /| ,-, , -,</pre>
|
||||
<pre> | ,/ | |' |/ ,- ~ \ '.</pre>
|
||||
<pre> ,| ,/ \ ,/ \ <City onTravel={props.onTravel} currentCity={props.currentCity} city={CityName.Ishima} /> |</pre>
|
||||
<pre> / | ~ -~~-, / _</pre>
|
||||
<pre> | ,-' ~ /</pre>
|
||||
<pre> / ,' ~</pre>
|
||||
<pre> ',| ~</pre>
|
||||
<pre> ~'</pre>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> ,_ . ._. _. .</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> , _-\','|~\~ ~/ ;-'_ _-' ,;_;_, ~~-</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> /~~-\_/-'~'--' \~~| ', ,' / / ~|-_\_/~/~ ~~--~~~~'--_</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> / ,/'-/~ '\ ,' _ , '<City onTravel={props.onTravel} currentCity={props.currentCity} city={CityName.Volhaven} />,'|~ ._/-, /~</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> ~/-'~\_, '-,| '|. ' ~ ,\ /'~ / /_ /~</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}>.-~ '| '',\~|\ _\~ ,_ , <City onTravel={props.onTravel} currentCity={props.currentCity} city={CityName.Chongqing} /> /,</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> '\ <City onTravel={props.onTravel} currentCity={props.currentCity} city={CityName.Sector12} /> /'~ |_/~\\,-,~ \ " ,_,/ |</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | / ._-~'\_ _~| \ ) <City onTravel={props.onTravel} currentCity={props.currentCity} city={CityName.NewTokyo} /></Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \ __-\ '/ ~ |\ \_ / ~</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> ., '\ |, ~-_ - | \\_' ~| /\ \~ ,</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> ~-_' _; '\ '-, \,' /\/ |</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> '\_,~'\_ \_ _, /' ' |, /|'</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> / \_ ~ | / \ ~'; -,_.</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | ~\ | | , '-_, ,; ~ ~\</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> \, <City onTravel={props.onTravel} currentCity={props.currentCity} city={CityName.Aevum} /> / \ / /| ,-, , -,</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | ,/ | |' |/ ,- ~ \ '.</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> ,| ,/ \ ,/ \ <City onTravel={props.onTravel} currentCity={props.currentCity} city={CityName.Ishima} /> |</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> / | ~ -~~-, / _</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> | ,-' ~ /</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> / ,' ~</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> ',| ~</Typography>
|
||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> ~'</Typography>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -97,10 +97,6 @@ export function WorkInProgressRoot(): React.ReactElement {
|
||||
player.finishClass(true);
|
||||
router.toCity();
|
||||
}
|
||||
function unfocus(): void {
|
||||
player.stopFocusing();
|
||||
router.toCity();
|
||||
}
|
||||
|
||||
let stopText = "";
|
||||
if (
|
||||
|
10
utils/JSONReviver.d.ts
vendored
10
utils/JSONReviver.d.ts
vendored
@ -1,10 +0,0 @@
|
||||
interface IReviverValue {
|
||||
ctor: string;
|
||||
data: any;
|
||||
}
|
||||
export function Generic_fromJSON<T>(ctor: new () => T, data: any): T;
|
||||
export function Generic_toJSON(ctorName: string, obj: any, keys?: string[]): string;
|
||||
export function Reviver(key, value: IReviverValue);
|
||||
export namespace Reviver {
|
||||
export let constructors: any;
|
||||
}
|
@ -1,12 +1,16 @@
|
||||
/* Generic Reviver, toJSON, and fromJSON functions used for saving and loading objects */
|
||||
|
||||
export interface IReviverValue {
|
||||
ctor: string;
|
||||
data: any;
|
||||
}
|
||||
|
||||
// A generic "smart reviver" function.
|
||||
// Looks for object values with a `ctor` property and
|
||||
// a `data` property. If it finds them, and finds a matching
|
||||
// constructor that has a `fromJSON` property on it, it hands
|
||||
// off to that `fromJSON` fuunction, passing in the value.
|
||||
function Reviver(key, value) {
|
||||
var ctor;
|
||||
export function Reviver(key: string, value: IReviverValue | null): any {
|
||||
if (value == null) {
|
||||
console.log("Reviver WRONGLY called with key: " + key + ", and value: " + value);
|
||||
return 0;
|
||||
@ -20,7 +24,7 @@ function Reviver(key, value) {
|
||||
return value.data;
|
||||
}
|
||||
|
||||
ctor = Reviver.constructors[value.ctor] || window[value.ctor];
|
||||
const ctor = Reviver.constructors[value.ctor];
|
||||
|
||||
if (typeof ctor === "function" && typeof ctor.fromJSON === "function") {
|
||||
return ctor.fromJSON(value);
|
||||
@ -28,7 +32,11 @@ function Reviver(key, value) {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
Reviver.constructors = {}; // A list of constructors the smart reviver should know about
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
export namespace Reviver {
|
||||
export const constructors: { [key: string]: any } = {};
|
||||
}
|
||||
|
||||
// A generic "toJSON" function that creates the data expected
|
||||
// by Reviver.
|
||||
@ -41,16 +49,15 @@ Reviver.constructors = {}; // A list of constructors the smart reviver should kn
|
||||
// regardless of whether it's an "own" property.)
|
||||
// Returns: The structure (which will then be turned into a string
|
||||
// as part of the JSON.stringify algorithm)
|
||||
function Generic_toJSON(ctorName, obj, keys) {
|
||||
var data, key;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
export function Generic_toJSON(ctorName: string, obj: any, keys?: string[]): IReviverValue {
|
||||
if (!keys) {
|
||||
keys = Object.keys(obj); // Only "own" properties are included
|
||||
}
|
||||
|
||||
data = {};
|
||||
const data: any = {};
|
||||
for (let index = 0; index < keys.length; ++index) {
|
||||
key = keys[index];
|
||||
const key = keys[index];
|
||||
data[key] = obj[key];
|
||||
}
|
||||
return { ctor: ctorName, data: data };
|
||||
@ -63,14 +70,11 @@ function Generic_toJSON(ctorName, obj, keys) {
|
||||
// `ctor` The constructor to call
|
||||
// `data` The data to apply
|
||||
// Returns: The object
|
||||
function Generic_fromJSON(ctor, data) {
|
||||
var obj, name;
|
||||
|
||||
obj = new ctor();
|
||||
for (name in data) {
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
export function Generic_fromJSON<T>(ctor: new () => T, data: any): T {
|
||||
const obj: any = new ctor();
|
||||
for (const name in data) {
|
||||
obj[name] = data[name];
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
export { Reviver, Generic_toJSON, Generic_fromJSON };
|
Loading…
Reference in New Issue
Block a user