From f40d4f8e92c6cc812a6eeb0078b33fea8175cddf Mon Sep 17 00:00:00 2001 From: Caldwell <115591472+Caldwell-74@users.noreply.github.com> Date: Mon, 3 Jun 2024 02:38:01 +0200 Subject: [PATCH 01/43] BUGFIX: fix relative imports (#1305) Relative paths work in imports, at last. --- src/NetscriptJSEvaluator.ts | 4 +- src/Script/RamCalculations.ts | 59 ++++-- src/Script/Script.ts | 8 +- src/ScriptEditor/ui/ScriptEditorContext.tsx | 11 +- src/ScriptEditor/ui/ScriptEditorRoot.tsx | 1 + test/jest/Netscript/RamCalculation.test.ts | 5 +- .../StaticRamParsingCalculation.test.ts | 182 ++++++++++++++++-- 7 files changed, 219 insertions(+), 51 deletions(-) diff --git a/src/NetscriptJSEvaluator.ts b/src/NetscriptJSEvaluator.ts index 22532ec2a..1f6e98b33 100644 --- a/src/NetscriptJSEvaluator.ts +++ b/src/NetscriptJSEvaluator.ts @@ -8,7 +8,6 @@ import { parse } from "acorn"; import { LoadedModule, ScriptURL, ScriptModule } from "./Script/LoadedModule"; import { Script } from "./Script/Script"; import { ScriptFilePath, resolveScriptFilePath } from "./Paths/ScriptFilePath"; -import { root } from "./Paths/Directory"; // Acorn type def is straight up incomplete so we have to fill with our own. export type Node = any; @@ -125,7 +124,7 @@ function generateLoadedModule(script: Script, scripts: Map { script.invalidateModule(); diff --git a/src/Script/RamCalculations.ts b/src/Script/RamCalculations.ts index 1a5222f49..a9b0abc32 100644 --- a/src/Script/RamCalculations.ts +++ b/src/Script/RamCalculations.ts @@ -14,7 +14,7 @@ import { RamCosts, RamCostConstants } from "../Netscript/RamCostGenerator"; import { Script } from "./Script"; import { Node } from "../NetscriptJSEvaluator"; import { ScriptFilePath, resolveScriptFilePath } from "../Paths/ScriptFilePath"; -import { root } from "../Paths/Directory"; +import { ServerName } from "../Types/strings"; export interface RamUsageEntry { type: "ns" | "dom" | "fn" | "misc"; @@ -56,12 +56,21 @@ function getNumericCost(cost: number | (() => number)): number { * Parses code into an AST and walks through it recursively to calculate * RAM usage. Also accounts for imported modules. * @param otherScripts - All other scripts on the server. Used to account for imported scripts - * @param code - The code being parsed */ -function parseOnlyRamCalculate(otherScripts: Map, code: string, ns1?: boolean): RamCalculation { + * @param code - The code being parsed + * @param scriptname - The name of the script that ram needs to be added to + * @param server - Servername of the scripts for Error Message + * */ +function parseOnlyRamCalculate( + otherScripts: Map, + code: string, + scriptname: ScriptFilePath, + server: ServerName, + ns1?: boolean, +): RamCalculation { /** * Maps dependent identifiers to their dependencies. * - * The initial identifier is __SPECIAL_INITIAL_MODULE__.__GLOBAL__. + * The initial identifier is .__GLOBAL__. * It depends on all the functions declared in the module, all the global scopes * of its imports, and any identifiers referenced in this global scope. Each * function depends on all the identifiers referenced internally. @@ -74,10 +83,10 @@ function parseOnlyRamCalculate(otherScripts: Map, code: const completedParses = new Set(); // Scripts we've discovered that need to be parsed. - const parseQueue: string[] = []; + const parseQueue: ScriptFilePath[] = []; // Parses a chunk of code with a given module name, and updates parseQueue and dependencyMap. - function parseCode(code: string, moduleName: string): void { - const result = parseOnlyCalculateDeps(code, moduleName); + function parseCode(code: string, moduleName: ScriptFilePath): void { + const result = parseOnlyCalculateDeps(code, moduleName, ns1); completedParses.add(moduleName); // Add any additional modules to the parse queue; @@ -92,7 +101,7 @@ function parseOnlyRamCalculate(otherScripts: Map, code: } // Parse the initial module, which is the "main" script that is being run - const initialModule = "__SPECIAL_INITIAL_MODULE__"; + const initialModule = scriptname; parseCode(code, initialModule); // Process additional modules, which occurs if the "main" script has any imports @@ -101,21 +110,19 @@ function parseOnlyRamCalculate(otherScripts: Map, code: if (nextModule === undefined) throw new Error("nextModule should not be undefined"); if (nextModule.startsWith("https://") || nextModule.startsWith("http://")) continue; - // Using root as the path base right now. Difficult to implement - const filename = resolveScriptFilePath(nextModule, root, ns1 ? ".script" : ".js"); - if (!filename) { - return { errorCode: RamCalculationErrorCode.ImportError, errorMessage: `Invalid import path: "${nextModule}"` }; - } - const script = otherScripts.get(filename); + const script = otherScripts.get(nextModule); if (!script) { - return { errorCode: RamCalculationErrorCode.ImportError, errorMessage: `No such file on server: "${filename}"` }; + return { + errorCode: RamCalculationErrorCode.ImportError, + errorMessage: `File: "${nextModule}" not found on server: ${server}`, + }; } parseCode(script.code, nextModule); } // Finally, walk the reference map and generate a ram cost. The initial set of keys to scan - // are those that start with __SPECIAL_INITIAL_MODULE__. + // are those that start with the name of the main script. let ram = RamCostConstants.Base; const detailedCosts: RamUsageEntry[] = [{ type: "misc", name: "baseCost", cost: RamCostConstants.Base }]; const unresolvedRefs = Object.keys(dependencyMap).filter((s) => s.startsWith(initialModule)); @@ -250,7 +257,7 @@ export function checkInfiniteLoop(code: string): number[] { interface ParseDepsResult { dependencyMap: Record | undefined>; - additionalModules: string[]; + additionalModules: ScriptFilePath[]; } /** @@ -259,7 +266,7 @@ interface ParseDepsResult { * for RAM usage calculations. It also returns an array of additional modules * that need to be parsed (i.e. are 'import'ed scripts). */ -function parseOnlyCalculateDeps(code: string, currentModule: string): ParseDepsResult { +function parseOnlyCalculateDeps(code: string, currentModule: ScriptFilePath, ns1?: boolean): ParseDepsResult { const ast = parse(code, { sourceType: "module", ecmaVersion: "latest" }); // Everything from the global scope goes in ".". Everything else goes in ".function", where only // the outermost layer of functions counts. @@ -271,7 +278,7 @@ function parseOnlyCalculateDeps(code: string, currentModule: string): ParseDepsR // Filled when we import names from other modules. const internalToExternal: Record = {}; - const additionalModules: string[] = []; + const additionalModules: ScriptFilePath[] = []; // References get added pessimistically. They are added for thisModule.name, name, and for // any aliases. @@ -338,7 +345,12 @@ function parseOnlyCalculateDeps(code: string, currentModule: string): ParseDepsR Object.assign( { ImportDeclaration: (node: Node, st: State) => { - const importModuleName = node.source.value; + const importModuleName = resolveScriptFilePath(node.source.value, currentModule, ns1 ? ".script" : ".js"); + if (!importModuleName) + throw new Error( + `ScriptFilePath couldnt be resolved in ImportDeclaration. Value: ${node.source.value} ScriptFilePath: ${currentModule}`, + ); + additionalModules.push(importModuleName); // This module's global scope refers to that module's global scope, no matter how we @@ -397,16 +409,21 @@ function parseOnlyCalculateDeps(code: string, currentModule: string): ParseDepsR /** * Calculate's a scripts RAM Usage * @param {string} code - The script's code + * @param {ScriptFilePath} scriptname - The script's name. Used to resolve relative paths * @param {Script[]} otherScripts - All other scripts on the server. * Used to account for imported scripts + * @param {ServerName} server - Servername of the scripts for Error Message + * @param {boolean} ns1 - Deprecated: is the fileExtension .script or .js */ export function calculateRamUsage( code: string, + scriptname: ScriptFilePath, otherScripts: Map, + server: ServerName, ns1?: boolean, ): RamCalculation { try { - return parseOnlyRamCalculate(otherScripts, code, ns1); + return parseOnlyRamCalculate(otherScripts, code, scriptname, server, ns1); } catch (e) { return { errorCode: RamCalculationErrorCode.SyntaxError, diff --git a/src/Script/Script.ts b/src/Script/Script.ts index 9e6139f0b..45384c9c6 100644 --- a/src/Script/Script.ts +++ b/src/Script/Script.ts @@ -73,7 +73,13 @@ export class Script implements ContentFile { * @param {Script[]} otherScripts - Other scripts on the server. Used to process imports */ updateRamUsage(otherScripts: Map): void { - const ramCalc = calculateRamUsage(this.code, otherScripts, this.filename.endsWith(".script")); + const ramCalc = calculateRamUsage( + this.code, + this.filename, + otherScripts, + this.server, + this.filename.endsWith(".script"), + ); if (ramCalc.cost && ramCalc.cost >= RamCostConstants.Base) { this.ramUsage = roundToTwo(ramCalc.cost); this.ramUsageEntries = ramCalc.entries as RamUsageEntry[]; diff --git a/src/ScriptEditor/ui/ScriptEditorContext.tsx b/src/ScriptEditor/ui/ScriptEditorContext.tsx index e23465ca3..9453cc214 100644 --- a/src/ScriptEditor/ui/ScriptEditorContext.tsx +++ b/src/ScriptEditor/ui/ScriptEditorContext.tsx @@ -8,11 +8,13 @@ import { useBoolean } from "../../ui/React/hooks"; import { BaseServer } from "../../Server/BaseServer"; import { Options } from "./Options"; +import { FilePath } from "../../Paths/FilePath"; +import { hasScriptExtension } from "../../Paths/ScriptFilePath"; export interface ScriptEditorContextShape { ram: string; ramEntries: string[][]; - updateRAM: (newCode: string | null, server: BaseServer | null) => void; + updateRAM: (newCode: string | null, filename: FilePath | null, server: BaseServer | null) => void; isUpdatingRAM: boolean; startUpdatingRAM: () => void; @@ -28,14 +30,13 @@ export function ScriptEditorContextProvider({ children, vim }: { children: React const [ram, setRAM] = useState("RAM: ???"); const [ramEntries, setRamEntries] = useState([["???", ""]]); - const updateRAM: ScriptEditorContextShape["updateRAM"] = (newCode, server) => { - if (newCode === null || server === null) { + const updateRAM: ScriptEditorContextShape["updateRAM"] = (newCode, filename, server) => { + if (newCode == null || filename == null || server == null || !hasScriptExtension(filename)) { setRAM("N/A"); setRamEntries([["N/A", ""]]); return; } - - const ramUsage = calculateRamUsage(newCode, server.scripts); + const ramUsage = calculateRamUsage(newCode, filename, server.scripts, server.hostname); if (ramUsage.cost && ramUsage.cost > 0) { const entries = ramUsage.entries?.sort((a, b) => b.cost - a.cost) ?? []; const entriesDisp = []; diff --git a/src/ScriptEditor/ui/ScriptEditorRoot.tsx b/src/ScriptEditor/ui/ScriptEditorRoot.tsx index 5e0cc21ad..202599703 100644 --- a/src/ScriptEditor/ui/ScriptEditorRoot.tsx +++ b/src/ScriptEditor/ui/ScriptEditorRoot.tsx @@ -143,6 +143,7 @@ function Root(props: IProps): React.ReactElement { infLoop(newCode); updateRAM( !currentScript || currentScript.isTxt ? null : newCode, + currentScript && currentScript.path, currentScript && GetServer(currentScript.hostname), ); finishUpdatingRAM(); diff --git a/test/jest/Netscript/RamCalculation.test.ts b/test/jest/Netscript/RamCalculation.test.ts index 452ae036e..e505ac233 100644 --- a/test/jest/Netscript/RamCalculation.test.ts +++ b/test/jest/Netscript/RamCalculation.test.ts @@ -9,6 +9,7 @@ import { calculateRamUsage } from "../../../src/Script/RamCalculations"; import { ns } from "../../../src/NetscriptFunctions"; import { InternalAPI } from "src/Netscript/APIWrapper"; import { Singularity } from "@nsdefs"; +import { ScriptFilePath } from "src/Paths/ScriptFilePath"; type PotentiallyAsyncFunction = (arg?: unknown) => { catch?: PotentiallyAsyncFunction }; @@ -71,13 +72,15 @@ describe("Netscript RAM Calculation/Generation Tests", function () { extraLayerCost = 0, ) { const code = `${fnPath.join(".")}();\n`.repeat(3); + const filename = "testfile.js" as ScriptFilePath; const fnName = fnPath[fnPath.length - 1]; + const server = "testserver"; //check imported getRamCost fn vs. expected ram from test expect(getRamCost(fnPath, true)).toEqual(expectedRamCost); // Static ram check - const staticCost = calculateRamUsage(code, new Map()).cost; + const staticCost = calculateRamUsage(code, filename, new Map(), server).cost; expect(staticCost).toBeCloseTo(Math.min(baseCost + expectedRamCost + extraLayerCost, maxCost)); // reset workerScript for dynamic check diff --git a/test/jest/Netscript/StaticRamParsingCalculation.test.ts b/test/jest/Netscript/StaticRamParsingCalculation.test.ts index db1d83fac..ebe3a0997 100644 --- a/test/jest/Netscript/StaticRamParsingCalculation.test.ts +++ b/test/jest/Netscript/StaticRamParsingCalculation.test.ts @@ -10,6 +10,10 @@ const GrowCost = 0.15; const SleeveGetTaskCost = 4; const HacknetCost = 4; const MaxCost = 1024; + +const filename = "testfile.js" as ScriptFilePath; +const folderFilename = "test/testfile.js" as ScriptFilePath; +const server = "testserver"; describe("Parsing NetScript code to work out static RAM costs", function () { jest.spyOn(console, "error").mockImplementation(() => {}); /** Tests numeric equality, allowing for floating point imprecision - and includes script base cost */ @@ -24,7 +28,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () { const code = ` export async function main(ns) { } `; - const calculated = calculateRamUsage(code, new Map()).cost; + const calculated = calculateRamUsage(code, filename, new Map(), server).cost; expectCost(calculated, 0); }); @@ -34,7 +38,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () { ns.print("Slum snakes r00l!"); } `; - const calculated = calculateRamUsage(code, new Map()).cost; + const calculated = calculateRamUsage(code, filename, new Map(), server).cost; expectCost(calculated, 0); }); @@ -44,7 +48,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () { await ns.hack("joesguns"); } `; - const calculated = calculateRamUsage(code, new Map()).cost; + const calculated = calculateRamUsage(code, filename, new Map(), server).cost; expectCost(calculated, HackCost); }); @@ -54,7 +58,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () { await X.hack("joesguns"); } `; - const calculated = calculateRamUsage(code, new Map()).cost; + const calculated = calculateRamUsage(code, filename, new Map(), server).cost; expectCost(calculated, HackCost); }); @@ -65,7 +69,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () { await ns.hack("joesguns"); } `; - const calculated = calculateRamUsage(code, new Map()).cost; + const calculated = calculateRamUsage(code, filename, new Map(), server).cost; expectCost(calculated, HackCost); }); @@ -76,7 +80,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () { await ns.grow("joesguns"); } `; - const calculated = calculateRamUsage(code, new Map()).cost; + const calculated = calculateRamUsage(code, filename, new Map(), server).cost; expectCost(calculated, HackCost + GrowCost); }); @@ -89,7 +93,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () { await ns.hack("joesguns"); } `; - const calculated = calculateRamUsage(code, new Map()).cost; + const calculated = calculateRamUsage(code, filename, new Map(), server).cost; expectCost(calculated, HackCost); }); @@ -104,7 +108,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () { async doHacking() { await this.ns.hack("joesguns"); } } `; - const calculated = calculateRamUsage(code, new Map()).cost; + const calculated = calculateRamUsage(code, filename, new Map(), server).cost; expectCost(calculated, HackCost); }); @@ -119,7 +123,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () { async doHacking() { await this.#ns.hack("joesguns"); } } `; - const calculated = calculateRamUsage(code, new Map()).cost; + const calculated = calculateRamUsage(code, filename, new Map(), server).cost; expectCost(calculated, HackCost); }); }); @@ -132,7 +136,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () { } function get() { return 0; } `; - const calculated = calculateRamUsage(code, new Map()).cost; + const calculated = calculateRamUsage(code, filename, new Map(), server).cost; expectCost(calculated, 0); }); @@ -143,7 +147,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () { } function purchaseNode() { return 0; } `; - const calculated = calculateRamUsage(code, new Map()).cost; + const calculated = calculateRamUsage(code, filename, new Map(), server).cost; // Works at present, because the parser checks the namespace only, not the function name expectCost(calculated, 0); }); @@ -156,7 +160,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () { } function getTask() { return 0; } `; - const calculated = calculateRamUsage(code, new Map()).cost; + const calculated = calculateRamUsage(code, filename, new Map(), server).cost; expectCost(calculated, 0); }); }); @@ -168,7 +172,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () { ns.hacknet.purchaseNode(0); } `; - const calculated = calculateRamUsage(code, new Map()).cost; + const calculated = calculateRamUsage(code, filename, new Map(), server).cost; expectCost(calculated, HacknetCost); }); @@ -178,7 +182,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () { ns.sleeve.getTask(3); } `; - const calculated = calculateRamUsage(code, new Map()).cost; + const calculated = calculateRamUsage(code, filename, new Map(), server).cost; expectCost(calculated, SleeveGetTaskCost); }); }); @@ -196,7 +200,12 @@ describe("Parsing NetScript code to work out static RAM costs", function () { dummy(); } `; - const calculated = calculateRamUsage(code, new Map([["libTest.js" as ScriptFilePath, lib]])).cost; + const calculated = calculateRamUsage( + code, + filename, + new Map([["libTest.js" as ScriptFilePath, lib]]), + server, + ).cost; expectCost(calculated, 0); }); @@ -212,7 +221,12 @@ describe("Parsing NetScript code to work out static RAM costs", function () { await doHack(ns); } `; - const calculated = calculateRamUsage(code, new Map([["libTest.js" as ScriptFilePath, lib]])).cost; + const calculated = calculateRamUsage( + code, + filename, + new Map([["libTest.js" as ScriptFilePath, lib]]), + server, + ).cost; expectCost(calculated, HackCost); }); @@ -229,7 +243,12 @@ describe("Parsing NetScript code to work out static RAM costs", function () { await doHack(ns); } `; - const calculated = calculateRamUsage(code, new Map([["libTest.js" as ScriptFilePath, lib]])).cost; + const calculated = calculateRamUsage( + code, + filename, + new Map([["libTest.js" as ScriptFilePath, lib]]), + server, + ).cost; expectCost(calculated, HackCost); }); @@ -246,7 +265,12 @@ describe("Parsing NetScript code to work out static RAM costs", function () { await test.doHack(ns); } `; - const calculated = calculateRamUsage(code, new Map([["libTest.js" as ScriptFilePath, lib]])).cost; + const calculated = calculateRamUsage( + code, + filename, + new Map([["libTest.js" as ScriptFilePath, lib]]), + server, + ).cost; expectCost(calculated, HackCost + GrowCost); }); @@ -267,7 +291,7 @@ describe("Parsing NetScript code to work out static RAM costs", function () { ${lines.join("\n")}; } `; - const calculated = calculateRamUsage(code, new Map()).cost; + const calculated = calculateRamUsage(code, filename, new Map(), server).cost; expectCost(calculated, MaxCost); }); @@ -289,7 +313,12 @@ describe("Parsing NetScript code to work out static RAM costs", function () { await test.doHack(ns); } `; - const calculated = calculateRamUsage(code, new Map([["libTest.js" as ScriptFilePath, lib]])).cost; + const calculated = calculateRamUsage( + code, + filename, + new Map([["libTest.js" as ScriptFilePath, lib]]), + server, + ).cost; expectCost(calculated, HackCost); }); @@ -315,8 +344,119 @@ describe("Parsing NetScript code to work out static RAM costs", function () { await growerInstance.doGrow(); } `; - const calculated = calculateRamUsage(code, new Map([["libTest.js" as ScriptFilePath, lib]])).cost; + const calculated = calculateRamUsage( + code, + filename, + new Map([["libTest.js" as ScriptFilePath, lib]]), + server, + ).cost; expectCost(calculated, GrowCost); }); + + it("Importing with a relative path - One Layer Deep", async function () { + const libCode = ` + export async function testRelative(ns) { + await ns.hack("n00dles") + } + `; + const lib = new Script("test/libTest.js" as ScriptFilePath, libCode); + const code = ` + import { testRelative } from "./libTest"; + + export async function main(ns) { + await testRelative(ns) + } + `; + const calculated = calculateRamUsage( + code, + folderFilename, + new Map([["test/libTest.js" as ScriptFilePath, lib]]), + server, + ).cost; + expectCost(calculated, HackCost); + }); + it("Importing with a relative path - Two Layer Deep", async function () { + const libNameOne = "test/libTestOne.js" as ScriptFilePath; + const libNameTwo = "test/libTestTwo.js" as ScriptFilePath; + + const libCodeOne = ` + import { testRelativeAgain } from "./libTestTwo"; + export function testRelative(ns) { + return testRelativeAgain(ns) + } + `; + const libScriptOne = new Script(libNameOne, libCodeOne); + + const libCodeTwo = ` + export function testRelativeAgain(ns) { + return ns.hack("n00dles") + } + `; + const libScriptTwo = new Script(libNameTwo, libCodeTwo); + + const code = ` + import { testRelative } from "./libTestOne"; + + export async function main(ns) { + await testRelative(ns) + } + `; + const calculated = calculateRamUsage( + code, + folderFilename, + new Map([ + [libNameOne, libScriptOne], + [libNameTwo, libScriptTwo], + ]), + server, + ).cost; + expectCost(calculated, HackCost); + }); + it("Importing with a relative path - possible path conflict", async function () { + const libNameOne = "foo/libTestOne.js" as ScriptFilePath; + const libNameTwo = "foo/libTestTwo.js" as ScriptFilePath; + const incorrect_libNameTwo = "test/libTestTwo.js" as ScriptFilePath; + + const libCodeOne = ` + import { testRelativeAgain } from "./libTestTwo"; + export function testRelative(ns) { + return testRelativeAgain(ns) + } + `; + const libScriptOne = new Script(libNameOne, libCodeOne); + + const libCodeTwo = ` + export function testRelativeAgain(ns) { + return ns.hack("n00dles") + } + `; + const libScriptTwo = new Script(libNameTwo, libCodeTwo); + + const incorrect_libCodeTwo = ` + export function testRelativeAgain(ns) { + return ns.grow("n00dles") + } + `; + const incorrect_libScriptTwo = new Script(incorrect_libNameTwo, incorrect_libCodeTwo); + + const code = ` + import { testRelative } from "foo/libTestOne"; + + export async function main(ns) { + await testRelative(ns) + } + `; + const calculated = calculateRamUsage( + code, + folderFilename, + new Map([ + [libNameOne, libScriptOne], + [libNameTwo, libScriptTwo], + [incorrect_libNameTwo, incorrect_libScriptTwo], + ]), + server, + ).cost; + expectCost(calculated, HackCost); + }); }); }); From a28bb4bd993d9e2d64feca9025ff9ade65abd1e8 Mon Sep 17 00:00:00 2001 From: Michael Ficocelli Date: Sun, 2 Jun 2024 20:41:31 -0400 Subject: [PATCH 02/43] IPVGO: Support playing manually as white against your scripts using the No AI type board (#1296) --- markdown/bitburner.go.md | 2 +- markdown/bitburner.go.resetboardstate.md | 2 +- src/Go/Constants.ts | 3 +- src/Go/boardAnalysis/boardAnalysis.ts | 24 +++++++++++- src/Go/boardAnalysis/goAI.ts | 45 +++++++++++++++++----- src/Go/ui/GoGameboardWrapper.tsx | 26 ++++++++----- src/ScriptEditor/NetscriptDefinitions.d.ts | 2 +- 7 files changed, 80 insertions(+), 24 deletions(-) diff --git a/markdown/bitburner.go.md b/markdown/bitburner.go.md index 02e57f9e3..d477706a5 100644 --- a/markdown/bitburner.go.md +++ b/markdown/bitburner.go.md @@ -30,5 +30,5 @@ export interface Go | [makeMove(x, y)](./bitburner.go.makemove.md) | Make a move on the IPvGO subnet gameboard, and await the opponent's response. x:0 y:0 represents the bottom-left corner of the board in the UI. | | [opponentNextTurn(logOpponentMove)](./bitburner.go.opponentnextturn.md) | Returns a promise that resolves with the success or failure state of your last move, and the AI's response, if applicable. x:0 y:0 represents the bottom-left corner of the board in the UI. | | [passTurn()](./bitburner.go.passturn.md) |

Pass the player's turn rather than making a move, and await the opponent's response. This ends the game if the opponent passed on the previous turn, or if the opponent passes on their following turn.

This can also be used if you pick up the game in a state where the opponent needs to play next. For example: if BitBurner was closed while waiting for the opponent to make a move, you may need to call passTurn() to get them to play their move on game start.

| -| [resetBoardState(opponent, boardSize)](./bitburner.go.resetboardstate.md) |

Gets new IPvGO subnet with the specified size owned by the listed faction, ready for the player to make a move. This will reset your win streak if the current game is not complete and you have already made moves.

Note that some factions will have a few routers on the subnet at this state.

opponent is "Netburners" or "Slum Snakes" or "The Black Hand" or "Tetrads" or "Daedalus" or "Illuminati" or "????????????",

| +| [resetBoardState(opponent, boardSize)](./bitburner.go.resetboardstate.md) |

Gets new IPvGO subnet with the specified size owned by the listed faction, ready for the player to make a move. This will reset your win streak if the current game is not complete and you have already made moves.

Note that some factions will have a few routers on the subnet at this state.

opponent is "Netburners" or "Slum Snakes" or "The Black Hand" or "Tetrads" or "Daedalus" or "Illuminati" or "????????????" or "No AI",

| diff --git a/markdown/bitburner.go.resetboardstate.md b/markdown/bitburner.go.resetboardstate.md index afec085ef..b00ec5ac7 100644 --- a/markdown/bitburner.go.resetboardstate.md +++ b/markdown/bitburner.go.resetboardstate.md @@ -8,7 +8,7 @@ Gets new IPvGO subnet with the specified size owned by the listed faction, ready Note that some factions will have a few routers on the subnet at this state. -opponent is "Netburners" or "Slum Snakes" or "The Black Hand" or "Tetrads" or "Daedalus" or "Illuminati" or "????????????", +opponent is "Netburners" or "Slum Snakes" or "The Black Hand" or "Tetrads" or "Daedalus" or "Illuminati" or "????????????" or "No AI", **Signature:** diff --git a/src/Go/Constants.ts b/src/Go/Constants.ts index b434f6793..ff6a4e0a7 100644 --- a/src/Go/Constants.ts +++ b/src/Go/Constants.ts @@ -6,7 +6,8 @@ export const opponentDetails = { [GoOpponent.none]: { komi: 5.5, description: "Practice Board", - flavorText: "Practice on a subnet where you place both colors of routers.", + flavorText: + "Practice on a subnet where you place both colors of routers, or play as white against your IPvGO script.", bonusDescription: "", bonusPower: 0, }, diff --git a/src/Go/boardAnalysis/boardAnalysis.ts b/src/Go/boardAnalysis/boardAnalysis.ts index 9a3fee8b1..5fd6c2c5d 100644 --- a/src/Go/boardAnalysis/boardAnalysis.ts +++ b/src/Go/boardAnalysis/boardAnalysis.ts @@ -1,6 +1,6 @@ -import type { Board, BoardState, Neighbor, PointState, SimpleBoard } from "../Types"; +import type { Board, BoardState, Neighbor, Play, PointState, SimpleBoard } from "../Types"; -import { GoValidity, GoOpponent, GoColor } from "@enums"; +import { GoValidity, GoOpponent, GoColor, GoPlayType } from "@enums"; import { Go } from "../Go"; import { findAdjacentPointsInChain, @@ -655,3 +655,23 @@ export function getPreviousMove(): [number, number] | null { return null; } + +/** + * Gets the last move, if it was made by the specified color and is present + */ +export function getPreviousMoveDetails(): Play { + const priorMove = getPreviousMove(); + if (priorMove) { + return { + type: GoPlayType.move, + x: priorMove[0], + y: priorMove[1], + }; + } + + return { + type: !priorMove && Go.currentGame?.passCount ? GoPlayType.pass : GoPlayType.gameOver, + x: null, + y: null, + }; +} diff --git a/src/Go/boardAnalysis/goAI.ts b/src/Go/boardAnalysis/goAI.ts index 885ab716d..e4d0198fb 100644 --- a/src/Go/boardAnalysis/goAI.ts +++ b/src/Go/boardAnalysis/goAI.ts @@ -1,7 +1,7 @@ import type { Board, BoardState, EyeMove, Move, MoveOptions, Play, PointState } from "../Types"; import { Player } from "@player"; -import { AugmentationName, GoOpponent, GoColor, GoPlayType } from "@enums"; +import { AugmentationName, GoColor, GoOpponent, GoPlayType } from "@enums"; import { opponentDetails } from "../Constants"; import { findNeighbors, isNotNullish, makeMove, passTurn } from "../boardState/boardState"; import { @@ -15,22 +15,35 @@ import { getAllEyesByChainId, getAllNeighboringChains, getAllValidMoves, + getPreviousMoveDetails, } from "./boardAnalysis"; import { findDisputedTerritory } from "./controlledTerritory"; import { findAnyMatchedPatterns } from "./patternMatching"; import { WHRNG } from "../../Casino/RNG"; import { Go, GoEvents } from "../Go"; -let currentAITurn: Promise | null = null; +let isAiThinking: boolean = false; +let currentTurnResolver: (() => void) | null = null; /** * Retrieves a move from the current faction in response to the player's move */ export function makeAIMove(boardState: BoardState): Promise { // If AI is already taking their turn, return the existing turn. - if (currentAITurn) return currentAITurn; - currentAITurn = Go.nextTurn = getMove(boardState, GoColor.white, Go.currentGame.ai) - .then(async (play): Promise => { + if (isAiThinking) { + return Go.nextTurn; + } + isAiThinking = true; + + // If the AI is disabled, simply make a promise to be resolved once the player makes a move as white + if (boardState.ai === GoOpponent.none) { + GoEvents.emit(); + // Update currentTurnResolver to call Go.nextTurn's resolve function with the last played move's details + Go.nextTurn = new Promise((resolve) => (currentTurnResolver = () => resolve(getPreviousMoveDetails()))); + } + // If an AI is in use, find the faction's move in response, and resolve the Go.nextTurn promise once it is found and played. + else { + Go.nextTurn = getMove(boardState, GoColor.white, Go.currentGame.ai).then(async (play): Promise => { if (boardState !== Go.currentGame) return play; //Stale game // Handle AI passing @@ -54,15 +67,29 @@ export function makeAIMove(boardState: BoardState): Promise { } return play; - }) - .finally(() => { - currentAITurn = null; - GoEvents.emit(); }); + } + + // Once the AI moves (or the player playing as white with No AI moves), + // clear the isAiThinking semaphore and update the board UI. + Go.nextTurn = Go.nextTurn.finally(() => { + isAiThinking = false; + GoEvents.emit(); + }); return Go.nextTurn; } +/** + * Resolves the current turn. + * This is used for players manually playing against their script on the no-ai board. + */ +export function resolveCurrentTurn() { + // Call the resolve function on Go.nextTurn, if it exists + currentTurnResolver?.(); + currentTurnResolver = null; +} + /* Basic GO AIs, each with some personality and weaknesses diff --git a/src/Go/ui/GoGameboardWrapper.tsx b/src/Go/ui/GoGameboardWrapper.tsx index 4b8bb6de2..466f1e5c5 100644 --- a/src/Go/ui/GoGameboardWrapper.tsx +++ b/src/Go/ui/GoGameboardWrapper.tsx @@ -18,7 +18,7 @@ import { GoScoreModal } from "./GoScoreModal"; import { GoGameboard } from "./GoGameboard"; import { GoSubnetSearch } from "./GoSubnetSearch"; import { CorruptableText } from "../../ui/React/CorruptableText"; -import { makeAIMove } from "../boardAnalysis/goAI"; +import { makeAIMove, resolveCurrentTurn } from "../boardAnalysis/goAI"; interface GoGameboardWrapperProps { showInstructions: () => void; @@ -85,7 +85,7 @@ export function GoGameboardWrapper({ showInstructions }: GoGameboardWrapperProps const didUpdateBoard = makeMove(boardState, x, y, currentPlayer); if (didUpdateBoard) { rerender(); - Go.currentGame.ai !== GoOpponent.none && takeAiTurn(boardState); + takeAiTurn(boardState); } } @@ -104,11 +104,17 @@ export function GoGameboardWrapper({ showInstructions }: GoGameboardWrapperProps } setTimeout(() => { - Go.currentGame.ai !== GoOpponent.none && takeAiTurn(boardState); + takeAiTurn(boardState); }, 100); } async function takeAiTurn(boardState: BoardState) { + // If white is being played manually, halt and notify any scripts playing as black if present, instead of making an AI move + if (Go.currentGame.ai === GoOpponent.none) { + Go.currentGame.previousPlayer && resolveCurrentTurn(); + return; + } + const move = await makeAIMove(boardState); if (move.type === GoPlayType.pass) { @@ -137,6 +143,7 @@ export function GoGameboardWrapper({ showInstructions }: GoGameboardWrapperProps Go.currentGame = getNewBoardState(newBoardSize, newOpponent, true); rerender(); + resolveCurrentTurn(); } function getPriorMove() { @@ -159,17 +166,19 @@ export function GoGameboardWrapper({ showInstructions }: GoGameboardWrapperProps rerender(); } - const endGameAvailable = boardState.previousPlayer === GoColor.white && boardState.passCount; - const noLegalMoves = - boardState.previousPlayer === GoColor.white && !getAllValidMoves(boardState, GoColor.black).length; + const ongoingNoAiGame = boardState.ai === GoOpponent.none && boardState.previousPlayer; + const manualTurnAvailable = ongoingNoAiGame || boardState.previousPlayer === GoColor.white; + const endGameAvailable = manualTurnAvailable && boardState.passCount; + const noLegalMoves = manualTurnAvailable && !getAllValidMoves(boardState, currentPlayer).length; const scoreBoxText = boardState.previousBoards.length ? `Score: Black: ${score[GoColor.black].sum} White: ${score[GoColor.white].sum}` : "Place a router to begin!"; const getPassButtonLabel = () => { + const playerString = boardState.ai === GoOpponent.none ? ` (${currentPlayer})` : ""; if (endGameAvailable) { - return "End Game"; + return `End Game${playerString}`; } if (boardState.previousPlayer === null) { return "View Final Score"; @@ -177,8 +186,7 @@ export function GoGameboardWrapper({ showInstructions }: GoGameboardWrapperProps if (waitingOnAI) { return "Waiting for opponent"; } - const currentPlayer = boardState.previousPlayer === GoColor.black ? GoColor.white : GoColor.black; - return `Pass Turn${boardState.ai === GoOpponent.none ? ` (${currentPlayer})` : ""}`; + return `Pass Turn${playerString}`; }; return ( diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index bf9263925..c8145c8c1 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -4079,7 +4079,7 @@ export interface Go { * * Note that some factions will have a few routers on the subnet at this state. * - * opponent is "Netburners" or "Slum Snakes" or "The Black Hand" or "Tetrads" or "Daedalus" or "Illuminati" or "????????????", + * opponent is "Netburners" or "Slum Snakes" or "The Black Hand" or "Tetrads" or "Daedalus" or "Illuminati" or "????????????" or "No AI", * * @returns a simplified version of the board state as an array of strings representing the board columns. See ns.Go.getBoardState() for full details * From 1f08724fea5413d4166b144c7cd0621f1f6fc675 Mon Sep 17 00:00:00 2001 From: gmcew <97335456+gmcew@users.noreply.github.com> Date: Mon, 3 Jun 2024 02:01:03 +0100 Subject: [PATCH 03/43] CORP: Products sell all at price of 0 (#1330) Match material behaviour - price of 0 discards stored products --- src/Corporation/Division.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Corporation/Division.ts b/src/Corporation/Division.ts index ccc6e6d45..ebf00a409 100644 --- a/src/Corporation/Division.ts +++ b/src/Corporation/Division.ts @@ -925,6 +925,8 @@ export class Division { if (sCost - product.cityData[city].productionCost > markupLimit) { markup = markupLimit / (sCost - product.cityData[city].productionCost); } + } else if (sCost <= 0) { + markup = 1e12; //Sell everything, essentially discard - as materials } product.maxSellAmount = @@ -939,7 +941,7 @@ export class Division { sellAmt = Math.min(product.maxSellAmount, sellAmt); sellAmt = sellAmt * corpConstants.secondsPerMarketCycle * marketCycles; sellAmt = Math.min(product.cityData[city].stored, sellAmt); //data[0] is qty - if (sellAmt && sCost) { + if (sellAmt && sCost >= 0) { product.cityData[city].stored -= sellAmt; //data[0] is qty totalProfit += sellAmt * sCost; product.cityData[city].actualSellAmount = sellAmt / (corpConstants.secondsPerMarketCycle * marketCycles); //data[2] is sell property From 2f7950b49c82fc87d3c372435782edfce352a46d Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Mon, 3 Jun 2024 10:14:18 +0700 Subject: [PATCH 04/43] DOCUMENTATION: Clarify server's minimum security level (#1337) --- src/Documentation/doc/basic/hacking.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Documentation/doc/basic/hacking.md b/src/Documentation/doc/basic/hacking.md index da3a0936e..aaaa0d2a4 100644 --- a/src/Documentation/doc/basic/hacking.md +++ b/src/Documentation/doc/basic/hacking.md @@ -75,7 +75,7 @@ Calling the `grow` function in a script will also increase security level of the These actions will make it harder for you to hack the [server](servers.md), and decrease the amount of money you can steal. You can lower a [server](servers.md)'s security level in a script using the `weaken` function. -This means that a [server](servers.md)'s security level will not fall below this value if you are trying to `weaken` it. +Each server has a minimum security level. The [server](servers.md)'s security level will not fall below this value if you try to `weaken` it. You can get this value with the `getServerMinSecurityLevel` function. ## Backdoors From d9f04203cfd71f8f236f3ec3c4c7c9dbe2e6e1e4 Mon Sep 17 00:00:00 2001 From: Michael Ficocelli Date: Sun, 2 Jun 2024 23:19:26 -0400 Subject: [PATCH 05/43] IPVGO: Record full history to avoid infinite ko capture loops on larger boards (#1299) --- src/Go/Types.ts | 2 +- src/Go/boardAnalysis/boardAnalysis.ts | 56 ++++++++++++++++++++++----- src/Go/boardState/boardState.ts | 11 ++---- src/Go/ui/GoGameboardWrapper.tsx | 4 +- src/Go/ui/GoPoint.tsx | 4 +- test/jest/Go/NetscriptGo.test.ts | 4 +- test/jest/Go/boardAnalysis.test.ts | 8 ++-- 7 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/Go/Types.ts b/src/Go/Types.ts index 1697e20ae..c765c6aec 100644 --- a/src/Go/Types.ts +++ b/src/Go/Types.ts @@ -37,7 +37,7 @@ export type BoardState = { board: Board; previousPlayer: GoColor | null; /** The previous board positions as a SimpleBoard */ - previousBoards: SimpleBoard[]; + previousBoards: string[]; ai: GoOpponent; passCount: number; cheatCount: number; diff --git a/src/Go/boardAnalysis/boardAnalysis.ts b/src/Go/boardAnalysis/boardAnalysis.ts index 5fd6c2c5d..c3d8b097c 100644 --- a/src/Go/boardAnalysis/boardAnalysis.ts +++ b/src/Go/boardAnalysis/boardAnalysis.ts @@ -44,7 +44,7 @@ export function evaluateIfMoveIsValid(boardState: BoardState, x: number, y: numb } // Detect if the move might be an immediate repeat (only one board of history is saved to check) - const possibleRepeat = boardState.previousBoards.find((board) => getColorOnSimpleBoard(board, x, y) === player); + const possibleRepeat = boardState.previousBoards.find((board) => getColorOnBoardString(board, x, y) === player); if (shortcut) { // If the current point has some adjacent open spaces, it is not suicide. If the move is not repeated, it is legal @@ -86,8 +86,8 @@ export function evaluateIfMoveIsValid(boardState: BoardState, x: number, y: numb return GoValidity.noSuicide; } if (possibleRepeat && boardState.previousBoards.length) { - const simpleEvalBoard = simpleBoardFromBoard(evaluationBoard); - if (boardState.previousBoards.find((board) => areSimpleBoardsIdentical(simpleEvalBoard, board))) { + const simpleEvalBoard = boardStringFromBoard(evaluationBoard); + if (boardState.previousBoards.includes(simpleEvalBoard)) { return GoValidity.boardRepeated; } } @@ -548,7 +548,8 @@ export function findAdjacentLibertiesAndAlliesForPoint( } /** - * Retrieves a simplified version of the board state. "X" represents black pieces, "O" white, and "." empty points. + * Retrieves a simplified version of the board state. + * "X" represents black pieces, "O" white, "." empty points, and "#" offline nodes. * * For example, a 5x5 board might look like this: * ``` @@ -563,14 +564,15 @@ export function findAdjacentLibertiesAndAlliesForPoint( * * Each string represents a vertical column on the board, and each character in the string represents a point. * - * Traditional notation for Go is e.g. "B,1" referring to second ("B") column, first rank. This is the equivalent of index [1][0]. + * Traditional notation for Go is e.g. "B,1" referring to second ("B") column, first rank. This is the equivalent of + * index (1 * N) + 0 , where N is the size of the board. * - * Note that the [0][0] point is shown on the bottom-left on the visual board (as is traditional), and each + * Note that index 0 (the [0][0] point) is shown on the bottom-left on the visual board (as is traditional), and each * string represents a vertical column on the board. In other words, the printed example above can be understood to * be rotated 90 degrees clockwise compared to the board UI as shown in the IPvGO game. * */ -export function simpleBoardFromBoard(board: Board): string[] { +export function simpleBoardFromBoard(board: Board): SimpleBoard { return board.map((column) => column.reduce((str, point) => { if (!point) { @@ -587,6 +589,39 @@ export function simpleBoardFromBoard(board: Board): string[] { ); } +/** + * Returns a string representation of the given board. + * The string representation is the same as simpleBoardFromBoard() but concatenated into a single string + * + * For example, a 5x5 board might look like this: + * ``` + * "XX.O.X..OO.XO..XXO...XOO." + * ``` + */ +export function boardStringFromBoard(board: Board): string { + return simpleBoardFromBoard(board).join(""); +} + +/** + * Returns a full board object from a string representation of the board. + * The string representation is the same as simpleBoardFromBoard() but concatenated into a single string + * + * For example, a 5x5 board might look like this: + * ``` + * "XX.O.X..OO.XO..XXO...XOO." + * ``` + */ +export function boardFromBoardString(boardString: string): Board { + // Turn the SimpleBoard string into a string array, allowing access of each point via indexes e.g. [0][1] + const boardSize = Math.round(Math.sqrt(boardString.length)); + const boardTiles = boardString.split(""); + const simpleBoardArray = Array(boardSize).map((_, index) => + boardTiles.slice(index * boardSize, (index + 1) * boardSize).join(""), + ); + + return boardFromSimpleBoard(simpleBoardArray); +} + /** Creates a board object from a simple board. The resulting board has no analytics (liberties/chains) */ export function boardFromSimpleBoard(simpleBoard: SimpleBoard): Board { return simpleBoard.map((column, x) => @@ -624,8 +659,9 @@ export function areSimpleBoardsIdentical(simpleBoard1: SimpleBoard, simpleBoard2 return simpleBoard1.every((column, x) => column === simpleBoard2[x]); } -export function getColorOnSimpleBoard(simpleBoard: SimpleBoard, x: number, y: number): GoColor | null { - const char = simpleBoard[x]?.[y]; +export function getColorOnBoardString(boardString: string, x: number, y: number): GoColor | null { + const boardSize = Math.round(Math.sqrt(boardString.length)); + const char = boardString[x * boardSize + y]; if (char === "X") return GoColor.black; if (char === "O") return GoColor.white; if (char === ".") return GoColor.empty; @@ -643,7 +679,7 @@ export function getPreviousMove(): [number, number] | null { const row = Go.currentGame.board[+rowIndexString] ?? []; for (const pointIndexString in row) { const point = row[+pointIndexString]; - const priorColor = point && priorBoard && getColorOnSimpleBoard(priorBoard, point.x, point.y); + const priorColor = point && priorBoard && getColorOnBoardString(priorBoard, point.x, point.y); const currentColor = point?.color; const isPreviousPlayer = currentColor === Go.currentGame.previousPlayer; const isChanged = priorColor !== currentColor; diff --git a/src/Go/boardState/boardState.ts b/src/Go/boardState/boardState.ts index 3eb80e841..808cdd634 100644 --- a/src/Go/boardState/boardState.ts +++ b/src/Go/boardState/boardState.ts @@ -9,7 +9,7 @@ import { findLibertiesForChain, getAllChains, boardFromSimpleBoard, - simpleBoardFromBoard, + boardStringFromBoard, } from "../boardAnalysis/boardAnalysis"; import { endGoGame } from "../boardAnalysis/scoring"; import { addObstacles, resetCoordinates, rotate90Degrees } from "./offlineNodes"; @@ -89,15 +89,12 @@ export function makeMove(boardState: BoardState, x: number, y: number, player: G return false; } - // Only maintain last 7 moves - boardState.previousBoards.unshift(simpleBoardFromBoard(boardState.board)); - if (boardState.previousBoards.length > 7) { - boardState.previousBoards.pop(); - } - const point = boardState.board[x][y]; if (!point) return false; + // Add move to board history + boardState.previousBoards.unshift(boardStringFromBoard(boardState.board)); + point.color = player; boardState.previousPlayer = player; boardState.passCount = 0; diff --git a/src/Go/ui/GoGameboardWrapper.tsx b/src/Go/ui/GoGameboardWrapper.tsx index 466f1e5c5..6c2e76072 100644 --- a/src/Go/ui/GoGameboardWrapper.tsx +++ b/src/Go/ui/GoGameboardWrapper.tsx @@ -9,7 +9,7 @@ import { SnackbarEvents } from "../../ui/React/Snackbar"; import { getNewBoardState, getStateCopy, makeMove, passTurn, updateCaptures } from "../boardState/boardState"; import { bitverseArt, weiArt } from "../boardState/asciiArt"; import { getScore, resetWinstreak } from "../boardAnalysis/scoring"; -import { boardFromSimpleBoard, evaluateIfMoveIsValid, getAllValidMoves } from "../boardAnalysis/boardAnalysis"; +import { boardFromBoardString, evaluateIfMoveIsValid, getAllValidMoves } from "../boardAnalysis/boardAnalysis"; import { useRerender } from "../../ui/React/hooks"; import { OptionSwitch } from "../../ui/React/OptionSwitch"; import { boardStyles } from "../boardState/goStyles"; @@ -150,7 +150,7 @@ export function GoGameboardWrapper({ showInstructions }: GoGameboardWrapperProps if (!boardState.previousBoards.length) return boardState; const priorState = getStateCopy(boardState); priorState.previousPlayer = boardState.previousPlayer === GoColor.black ? GoColor.white : GoColor.black; - priorState.board = boardFromSimpleBoard(boardState.previousBoards[0]); + priorState.board = boardFromBoardString(boardState.previousBoards[0]); updateCaptures(priorState.board, priorState.previousPlayer); return priorState; } diff --git a/src/Go/ui/GoPoint.tsx b/src/Go/ui/GoPoint.tsx index 5c1c6217b..5e67346e9 100644 --- a/src/Go/ui/GoPoint.tsx +++ b/src/Go/ui/GoPoint.tsx @@ -7,7 +7,7 @@ import { GoColor } from "@enums"; import { columnIndexes } from "../Constants"; import { findNeighbors } from "../boardState/boardState"; import { pointStyle } from "../boardState/goStyles"; -import { findAdjacentLibertiesAndAlliesForPoint, getColorOnSimpleBoard } from "../boardAnalysis/boardAnalysis"; +import { findAdjacentLibertiesAndAlliesForPoint, getColorOnBoardString } from "../boardAnalysis/boardAnalysis"; interface GoPointProps { state: BoardState; @@ -42,7 +42,7 @@ export function GoPoint({ state, x, y, traditional, hover, valid, emptyPointOwne const sizeClass = getSizeClass(state.board[0].length, classes); const isNewStone = - state.previousBoards.length && getColorOnSimpleBoard(state.previousBoards[0], x, y) === GoColor.empty; + state.previousBoards.length && getColorOnBoardString(state.previousBoards[0], x, y) === GoColor.empty; const isPriorMove = player === state.previousPlayer && isNewStone; const emptyPointColorClass = diff --git a/test/jest/Go/NetscriptGo.test.ts b/test/jest/Go/NetscriptGo.test.ts index 85a6174ee..28d05d896 100644 --- a/test/jest/Go/NetscriptGo.test.ts +++ b/test/jest/Go/NetscriptGo.test.ts @@ -92,9 +92,9 @@ describe("Netscript Go API unit tests", () => { describe("getGameState() tests", () => { it("should correctly retrieve the current game state", async () => { - const board = ["OXX..", ".....", ".....", "...XX", "...X."]; + const board = ["OXX..", ".....", "..#..", "...XX", "...X."]; const boardState = boardStateFromSimpleBoard(board, GoOpponent.Daedalus, GoColor.black); - boardState.previousBoards = [["OX..", ".....", ".....", "...XX", "...X."]]; + boardState.previousBoards = ["OX.........#.....XX...X."]; Go.currentGame = boardState; const result = getGameState(); diff --git a/test/jest/Go/boardAnalysis.test.ts b/test/jest/Go/boardAnalysis.test.ts index 805ebff94..97df6b678 100644 --- a/test/jest/Go/boardAnalysis.test.ts +++ b/test/jest/Go/boardAnalysis.test.ts @@ -57,10 +57,10 @@ describe("Go board analysis tests", () => { it("identifies invalid moves from repeat", async () => { const board = [".X...", ".....", ".....", ".....", "....."]; const boardState = boardStateFromSimpleBoard(board); - boardState.previousBoards.push([".X...", ".....", ".....", ".....", "....."]); - boardState.previousBoards.push([".X...", ".....", ".....", ".....", "....."]); - boardState.previousBoards.push([".X...", ".....", ".....", ".....", "....."]); - boardState.previousBoards.push(["OX...", ".....", ".....", ".....", "....."]); + boardState.previousBoards.push(".X......................."); + boardState.previousBoards.push(".X......................."); + boardState.previousBoards.push(".X......................."); + boardState.previousBoards.push("OX......................."); const validity = evaluateIfMoveIsValid(boardState, 0, 0, GoColor.white, false); expect(validity).toEqual(GoValidity.boardRepeated); From e622b9b9042049aa87ddbf82844bd41e27fbcabe Mon Sep 17 00:00:00 2001 From: TheAimMan <147098375+TheAimMan@users.noreply.github.com> Date: Sun, 2 Jun 2024 23:51:21 -0400 Subject: [PATCH 06/43] UI: change time elapsed to time remaining for programs and grafting (#1328) --- src/Work/CreateProgramWork.ts | 6 ++++-- src/Work/GraftingWork.tsx | 6 ++++-- src/ui/WorkInProgressRoot.tsx | 9 +++++---- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Work/CreateProgramWork.ts b/src/Work/CreateProgramWork.ts index c4b3d1e6e..56a25d9c7 100644 --- a/src/Work/CreateProgramWork.ts +++ b/src/Work/CreateProgramWork.ts @@ -21,10 +21,11 @@ export class CreateProgramWork extends Work { programName: CompletedProgramName; // amount of effective work completed on the program (time boosted by skills). unitCompleted: number; - + unitRate: number; constructor(params?: CreateProgramWorkParams) { super(WorkType.CREATE_PROGRAM, params?.singularity ?? true); this.unitCompleted = 0; + this.unitRate = 0; this.programName = params?.programName ?? CompletedProgramName.bruteSsh; if (params) { @@ -63,7 +64,8 @@ export class CreateProgramWork extends Work { skillMult *= focusBonus; //Skill multiplier directly applied to "time worked" this.cyclesWorked += cycles; - this.unitCompleted += CONSTANTS.MilliPerCycle * cycles * skillMult; + this.unitRate = CONSTANTS.MilliPerCycle * cycles * skillMult; + this.unitCompleted += this.unitRate; if (this.unitCompleted >= this.unitNeeded()) { return true; diff --git a/src/Work/GraftingWork.tsx b/src/Work/GraftingWork.tsx index cd2f8eea9..3ee202015 100644 --- a/src/Work/GraftingWork.tsx +++ b/src/Work/GraftingWork.tsx @@ -21,10 +21,12 @@ interface GraftingWorkParams { export class GraftingWork extends Work { augmentation: AugmentationName; unitCompleted: number; + unitRate: number; constructor(params?: GraftingWorkParams) { super(WorkType.GRAFTING, params?.singularity ?? true); this.unitCompleted = 0; + this.unitRate = 0; this.augmentation = params?.augmentation ?? AugmentationName.Targeting1; const gAugs = GraftableAugmentations(); if (params) Player.loseMoney(gAugs[this.augmentation].cost, "augmentations"); @@ -37,8 +39,8 @@ export class GraftingWork extends Work { process(cycles: number): boolean { const focusBonus = Player.focusPenalty(); this.cyclesWorked += cycles; - this.unitCompleted += CONSTANTS.MilliPerCycle * cycles * graftingIntBonus() * focusBonus; - + this.unitRate = CONSTANTS.MilliPerCycle * cycles * graftingIntBonus() * focusBonus; + this.unitCompleted += this.unitRate; return this.unitCompleted >= this.unitNeeded(); } diff --git a/src/ui/WorkInProgressRoot.tsx b/src/ui/WorkInProgressRoot.tsx index 25b7fb222..586d1acc6 100644 --- a/src/ui/WorkInProgressRoot.tsx +++ b/src/ui/WorkInProgressRoot.tsx @@ -286,7 +286,7 @@ export function WorkInProgressRoot(): React.ReactElement { if (isCreateProgramWork(Player.currentWork)) { const create = Player.currentWork; const completion = (create.unitCompleted / create.unitNeeded()) * 100; - + const remainingTime = ((create.unitNeeded() - create.unitCompleted) / create.unitRate) * CONSTANTS.MilliPerCycle; workInfo = { buttons: { cancel: () => { @@ -305,7 +305,7 @@ export function WorkInProgressRoot(): React.ReactElement { ), progress: { - elapsed: create.cyclesWorked * CONSTANTS.MilliPerCycle, + remaining: remainingTime, percentage: completion, }, @@ -316,7 +316,8 @@ export function WorkInProgressRoot(): React.ReactElement { if (isGraftingWork(Player.currentWork)) { const graftWork = Player.currentWork; - + const remainingTime = + ((graftWork.unitNeeded() - graftWork.unitCompleted) / graftWork.unitRate) * CONSTANTS.MilliPerCycle; workInfo = { buttons: { cancel: () => { @@ -335,7 +336,7 @@ export function WorkInProgressRoot(): React.ReactElement { ), progress: { - elapsed: graftWork.cyclesWorked * CONSTANTS.MilliPerCycle, + remaining: remainingTime, percentage: (graftWork.unitCompleted / graftWork.unitNeeded()) * 100, }, From cb92643c7eb3cddc2c129195c6b54467a707cd14 Mon Sep 17 00:00:00 2001 From: Caldwell <115591472+Caldwell-74@users.noreply.github.com> Date: Mon, 3 Jun 2024 18:27:13 +0200 Subject: [PATCH 07/43] IMPROVEMENT: partial migration @mui/styles to tss-react (#1338) --- package-lock.json | 27 +++++- package.json | 9 +- src/Achievements/AchievementsRoot.tsx | 22 ++--- src/BitNode/ui/BitverseRoot.tsx | 55 +++++------ src/Bladeburner/ui/Console.tsx | 47 +++++---- src/Casino/CardDeck/ReactCard.tsx | 53 +++++----- src/Corporation/ui/DivisionWarehouse.tsx | 16 ++- src/Corporation/ui/MoneyCost.tsx | 23 ++--- src/CotMG/ui/Cell.tsx | 6 +- src/DevMenu/ui/SourceFilesDev.tsx | 6 +- src/Faction/ui/Info.tsx | 19 ++-- src/Gang/ui/GangMemberStats.tsx | 2 +- src/Locations/ui/City.tsx | 25 +++-- src/PersonObjects/Sleeve/ui/StatsElement.tsx | 4 +- src/Sidebar/ui/SidebarRoot.tsx | 19 ++-- src/Terminal/commands/ls.tsx | 23 ++--- src/Terminal/ui/TerminalInput.tsx | 48 +++++---- src/Terminal/ui/TerminalRoot.tsx | 45 ++++----- .../ActiveScripts/RecentScriptAccordion.tsx | 7 +- src/ui/ActiveScripts/ScriptProduction.tsx | 29 +++--- .../ActiveScripts/WorkerScriptAccordion.tsx | 6 +- src/ui/GameRoot.tsx | 40 ++++---- .../InteractiveTutorialRoot.tsx | 25 +++-- src/ui/MD/code.tsx | 37 ++++--- src/ui/MD/components.tsx | 34 +++---- src/ui/React/ANSIITypography.tsx | 81 ++++++++-------- src/ui/React/Augmentation.tsx | 17 ++-- src/ui/React/CharacterOverview.tsx | 97 +++++++++---------- src/ui/React/Constants.ts | 1 + src/ui/React/Favor.tsx | 17 ++-- src/ui/React/Hashes.tsx | 17 ++-- src/ui/React/ImportSave/ImportSave.tsx | 67 ++++++------- src/ui/React/LogBoxManager.tsx | 49 +++++----- src/ui/React/Modal.tsx | 63 ++++++------ src/ui/React/Money.tsx | 23 ++--- src/ui/React/Overview.tsx | 6 +- src/ui/React/Progress.tsx | 6 +- src/ui/React/Reputation.tsx | 17 ++-- src/ui/React/Snackbar.tsx | 11 +-- src/ui/React/StatsProgressBar.tsx | 2 +- src/ui/React/StatsRow.tsx | 2 +- src/ui/React/StatsTable.tsx | 6 +- src/ui/React/Table.tsx | 8 +- src/ui/React/WorldMap.tsx | 32 +++--- 44 files changed, 545 insertions(+), 604 deletions(-) create mode 100644 src/ui/React/Constants.ts diff --git a/package-lock.json b/package-lock.json index f8ac88559..b1e4997f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,7 +43,8 @@ "react-resizable": "^3.0.5", "react-syntax-highlighter": "^15.5.0", "remark-gfm": "^3.0.1", - "sprintf-js": "^1.1.3" + "sprintf-js": "^1.1.3", + "tss-react": "^4.9.10" }, "devDependencies": { "@babel/core": "^7.23.0", @@ -16896,6 +16897,30 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, + "node_modules/tss-react": { + "version": "4.9.10", + "resolved": "https://registry.npmjs.org/tss-react/-/tss-react-4.9.10.tgz", + "integrity": "sha512-uQj+r8mOKy0tv+/GAIzViVG81w/WeTCOF7tjsDyNjlicnWbxtssYwTvVjWT4lhWh5FSznDRy6RFp0BDdoLbxyg==", + "dependencies": { + "@emotion/cache": "*", + "@emotion/serialize": "*", + "@emotion/utils": "*" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/server": "^11.4.0", + "@mui/material": "^5.0.0", + "react": "^16.8.0 || ^17.0.2 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/server": { + "optional": true + }, + "@mui/material": { + "optional": true + } + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index a7c4792c1..83b5d786e 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,8 @@ "react-resizable": "^3.0.5", "react-syntax-highlighter": "^15.5.0", "remark-gfm": "^3.0.1", - "sprintf-js": "^1.1.3" + "sprintf-js": "^1.1.3", + "tss-react": "^4.9.10" }, "description": "A cyberpunk-themed incremental game", "devDependencies": { @@ -86,13 +87,13 @@ "prettier": "^2.8.8", "raw-loader": "^4.0.2", "react-refresh": "^0.14.0", + "rehype-mathjax": "^4.0.3", + "remark-math": "^5.1.1", "style-loader": "^3.3.3", "typescript": "^5.2.2", "webpack": "^5.88.2", "webpack-cli": "^5.1.4", - "webpack-dev-server": "^4.15.2", - "remark-math": "^5.1.1", - "rehype-mathjax": "^4.0.3" + "webpack-dev-server": "^4.15.2" }, "engines": { "node": ">=14" diff --git a/src/Achievements/AchievementsRoot.tsx b/src/Achievements/AchievementsRoot.tsx index 5318b5cbb..0e7eb3b11 100644 --- a/src/Achievements/AchievementsRoot.tsx +++ b/src/Achievements/AchievementsRoot.tsx @@ -1,26 +1,22 @@ import React from "react"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; import { Theme } from "@mui/material/styles"; - import { AchievementList } from "./AchievementList"; import { achievements } from "./Achievements"; import { Typography } from "@mui/material"; import { Player } from "@player"; +import { makeStyles } from "tss-react/mui"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - root: { - width: 50, - padding: theme.spacing(2), - userSelect: "none", - }, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + root: { + width: 50, + padding: theme.spacing(2), + userSelect: "none", + }, +})); export function AchievementsRoot(): JSX.Element { - const classes = useStyles(); + const { classes } = useStyles(); return (
Achievements diff --git a/src/BitNode/ui/BitverseRoot.tsx b/src/BitNode/ui/BitverseRoot.tsx index 798d50ae2..92d2eae11 100644 --- a/src/BitNode/ui/BitverseRoot.tsx +++ b/src/BitNode/ui/BitverseRoot.tsx @@ -3,8 +3,7 @@ import { BitNodes } from "../BitNode"; import { PortalModal } from "./PortalModal"; import { CinematicText } from "../../ui/React/CinematicText"; import { Player } from "@player"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; import IconButton from "@mui/material/IconButton"; import Typography from "@mui/material/Typography"; import Tooltip from "@mui/material/Tooltip"; @@ -12,33 +11,31 @@ import { Settings } from "../../Settings/Settings"; import Button from "@mui/material/Button"; import { CompletedProgramName } from "@enums"; -const useStyles = makeStyles(() => - createStyles({ - portal: { - cursor: "pointer", - fontFamily: "inherit", - fontSize: "1rem", - fontWeight: "bold", - lineHeight: 1, - padding: 0, - "&:hover": { - color: "#fff", - }, +const useStyles = makeStyles()(() => ({ + portal: { + cursor: "pointer", + fontFamily: "inherit", + fontSize: "1rem", + fontWeight: "bold", + lineHeight: 1, + padding: 0, + "&:hover": { + color: "#fff", }, - level0: { - color: Settings.theme.bnlvl0, - }, - level1: { - color: Settings.theme.bnlvl1, - }, - level2: { - color: Settings.theme.bnlvl2, - }, - level3: { - color: Settings.theme.bnlvl3, - }, - }), -); + }, + level0: { + color: Settings.theme.bnlvl0, + }, + level1: { + color: Settings.theme.bnlvl1, + }, + level2: { + color: Settings.theme.bnlvl2, + }, + level3: { + color: Settings.theme.bnlvl3, + }, +})); interface IPortalProps { n: number; @@ -48,7 +45,7 @@ interface IPortalProps { } function BitNodePortal(props: IPortalProps): React.ReactElement { const [portalOpen, setPortalOpen] = useState(false); - const classes = useStyles(); + const { classes } = useStyles(); const bitNode = BitNodes[`BitNode${props.n}`]; if (bitNode == null) { return <>O; diff --git a/src/Bladeburner/ui/Console.tsx b/src/Bladeburner/ui/Console.tsx index 995c51813..dd7d8fd30 100644 --- a/src/Bladeburner/ui/Console.tsx +++ b/src/Bladeburner/ui/Console.tsx @@ -5,36 +5,33 @@ import { KEY } from "../../utils/helpers/keyCodes"; import { Box, List, ListItem, Paper, TextField, Typography } from "@mui/material"; import { Theme } from "@mui/material/styles"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; import { useRerender } from "../../ui/React/hooks"; interface ILineProps { content: React.ReactNode; } -const useStyles = makeStyles((theme: Theme) => - createStyles({ - textfield: { - margin: theme.spacing(0), - width: "100%", - }, - input: { - backgroundColor: theme.colors.backgroundsecondary, - }, - nopadding: { - padding: theme.spacing(0), - }, - preformatted: { - whiteSpace: "pre-wrap", - margin: theme.spacing(0), - }, - list: { - padding: theme.spacing(0), - height: "100%", - }, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + textfield: { + margin: theme.spacing(0), + width: "100%", + }, + input: { + backgroundColor: theme.colors.backgroundsecondary, + }, + nopadding: { + padding: theme.spacing(0), + }, + preformatted: { + whiteSpace: "pre-wrap", + margin: theme.spacing(0), + }, + list: { + padding: theme.spacing(0), + height: "100%", + }, +})); function Line(props: ILineProps): React.ReactElement { return ( @@ -49,7 +46,7 @@ interface IProps { } export function Console(props: IProps): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); const [command, setCommand] = useState(""); const consoleInput = useRef(null); useRerender(1000); diff --git a/src/Casino/CardDeck/ReactCard.tsx b/src/Casino/CardDeck/ReactCard.tsx index b308a4a64..73345afba 100644 --- a/src/Casino/CardDeck/ReactCard.tsx +++ b/src/Casino/CardDeck/ReactCard.tsx @@ -1,8 +1,7 @@ import React, { FC } from "react"; import { Card, Suit } from "./Card"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; import Paper from "@mui/material/Paper"; interface Props { @@ -10,35 +9,33 @@ interface Props { hidden?: boolean; } -const useStyles = makeStyles(() => - createStyles({ - card: { - padding: "10px", - border: "solid 1px #808080", - backgroundColor: "white", - display: "inline-block", - borderRadius: "10px", - fontSize: "18.5px", - textAlign: "center", - margin: "3px", - fontWeight: "bold", - }, - red: { - color: "red", - }, +const useStyles = makeStyles()(() => ({ + card: { + padding: "10px", + border: "solid 1px #808080", + backgroundColor: "white", + display: "inline-block", + borderRadius: "10px", + fontSize: "18.5px", + textAlign: "center", + margin: "3px", + fontWeight: "bold", + }, + red: { + color: "red", + }, - black: { - color: "black", - }, - value: { - fontSize: "20px", - fontFamily: "sans-serif", - }, - }), -); + black: { + color: "black", + }, + value: { + fontSize: "20px", + fontFamily: "sans-serif", + }, +})); export const ReactCard: FC = ({ card, hidden }) => { - const classes = useStyles(); + const { classes } = useStyles(); let suit: React.ReactNode; switch (card.suit) { case Suit.Clubs: diff --git a/src/Corporation/ui/DivisionWarehouse.tsx b/src/Corporation/ui/DivisionWarehouse.tsx index 98aabc276..5d08d6e5c 100644 --- a/src/Corporation/ui/DivisionWarehouse.tsx +++ b/src/Corporation/ui/DivisionWarehouse.tsx @@ -1,7 +1,7 @@ // React Component for displaying an Industry's warehouse information // (right-side panel in the Industry UI) import React, { useState } from "react"; -import { createStyles, makeStyles } from "@mui/styles"; +import { makeStyles } from "tss-react/mui"; import { Box, Button, Paper, Tooltip, Typography } from "@mui/material"; import * as corpConstants from "../data/Constants"; import { CityName, CorpUnlockName } from "@enums"; @@ -32,16 +32,14 @@ interface WarehouseProps { rerender: () => void; } -const useStyles = makeStyles(() => - createStyles({ - retainHeight: { - minHeight: "3em", - }, - }), -); +const useStyles = makeStyles()(() => ({ + retainHeight: { + minHeight: "3em", + }, +})); function WarehouseRoot(props: WarehouseProps): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); const corp = useCorporation(); const division = useDivision(); const [smartSupplyOpen, setSmartSupplyOpen] = useState(false); diff --git a/src/Corporation/ui/MoneyCost.tsx b/src/Corporation/ui/MoneyCost.tsx index 585e49dfc..c27d48f8b 100644 --- a/src/Corporation/ui/MoneyCost.tsx +++ b/src/Corporation/ui/MoneyCost.tsx @@ -2,19 +2,16 @@ import * as React from "react"; import { formatMoney } from "../../ui/formatNumber"; import { Corporation } from "../Corporation"; import { Theme } from "@mui/material/styles"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - unbuyable: { - color: theme.palette.action.disabled, - }, - money: { - color: theme.colors.money, - }, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + unbuyable: { + color: theme.palette.action.disabled, + }, + money: { + color: theme.colors.money, + }, +})); interface IProps { money: number; @@ -22,7 +19,7 @@ interface IProps { } export function MoneyCost(props: IProps): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); if (!(props.corp.funds > props.money)) return {formatMoney(props.money)}; return {formatMoney(props.money)}; diff --git a/src/CotMG/ui/Cell.tsx b/src/CotMG/ui/Cell.tsx index cad801140..14642519c 100644 --- a/src/CotMG/ui/Cell.tsx +++ b/src/CotMG/ui/Cell.tsx @@ -1,9 +1,9 @@ import * as React from "react"; -import makeStyles from "@mui/styles/makeStyles"; +import { makeStyles } from "tss-react/mui"; import { TableCell as MuiTableCell, TableCellProps } from "@mui/material"; -const useStyles = makeStyles({ +const useStyles = makeStyles()({ root: { border: "1px solid white", width: "5px", @@ -16,7 +16,7 @@ export const TableCell: React.FC = (props: TableCellProps) => { diff --git a/src/DevMenu/ui/SourceFilesDev.tsx b/src/DevMenu/ui/SourceFilesDev.tsx index 0adb16357..63bd7e16d 100644 --- a/src/DevMenu/ui/SourceFilesDev.tsx +++ b/src/DevMenu/ui/SourceFilesDev.tsx @@ -2,7 +2,7 @@ import React, { useCallback } from "react"; import { Accordion, AccordionSummary, AccordionDetails, Button, ButtonGroup, Typography } from "@mui/material"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; -import { makeStyles } from "@mui/styles"; +import { makeStyles } from "tss-react/mui"; import { Player } from "@player"; import { Sleeve } from "../../PersonObjects/Sleeve/Sleeve"; @@ -11,7 +11,7 @@ import { MaxSleevesFromCovenant } from "../../PersonObjects/Sleeve/SleeveCovenan // Update as additional BitNodes get implemented const validSFN = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]; -const useStyles = makeStyles({ +const useStyles = makeStyles()({ group: { display: "inline-flex", placeItems: "center", @@ -23,7 +23,7 @@ const useStyles = makeStyles({ }); export function SourceFilesDev({ parentRerender }: { parentRerender: () => void }): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); const setSF = useCallback( (sfN: number, sfLvl: number) => () => { diff --git a/src/Faction/ui/Info.tsx b/src/Faction/ui/Info.tsx index e8028faf4..df54f4cc7 100644 --- a/src/Faction/ui/Info.tsx +++ b/src/Faction/ui/Info.tsx @@ -11,8 +11,7 @@ import { Reputation } from "../../ui/React/Reputation"; import { Favor } from "../../ui/React/Favor"; import { MathJax } from "better-react-mathjax"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; import Typography from "@mui/material/Typography"; import Tooltip from "@mui/material/Tooltip"; import Box from "@mui/material/Box"; @@ -24,14 +23,12 @@ interface IProps { factionInfo: FactionInfo; } -const useStyles = makeStyles(() => - createStyles({ - noformat: { - whiteSpace: "pre-wrap", - lineHeight: "1em", - }, - }), -); +const useStyles = makeStyles()({ + noformat: { + whiteSpace: "pre-wrap", + lineHeight: "1em", + }, +}); function DefaultAssignment(): React.ReactElement { return ( @@ -46,7 +43,7 @@ function DefaultAssignment(): React.ReactElement { export function Info(props: IProps): React.ReactElement { useRerender(200); - const classes = useStyles(); + const { classes } = useStyles(); const Assignment = props.factionInfo.assignment ?? DefaultAssignment; diff --git a/src/Gang/ui/GangMemberStats.tsx b/src/Gang/ui/GangMemberStats.tsx index 58ce26b5e..c3b2b73d4 100644 --- a/src/Gang/ui/GangMemberStats.tsx +++ b/src/Gang/ui/GangMemberStats.tsx @@ -21,7 +21,7 @@ interface IProps { } export function GangMemberStats(props: IProps): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); const asc = { hack: props.member.calculateAscensionMult(props.member.hack_asc_points), diff --git a/src/Locations/ui/City.tsx b/src/Locations/ui/City.tsx index 98ce524df..cae2fa456 100644 --- a/src/Locations/ui/City.tsx +++ b/src/Locations/ui/City.tsx @@ -18,24 +18,21 @@ import { Page } from "../../ui/Router"; import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import { Theme } from "@mui/material/styles"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; interface IProps { city: City; } -const useStyles = makeStyles((theme: Theme) => - createStyles({ - location: { - color: theme.colors.maplocation, - whiteSpace: "nowrap", - margin: "0px", - padding: "0px", - cursor: "pointer", - }, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + location: { + color: theme.colors.maplocation, + whiteSpace: "nowrap", + margin: "0px", + padding: "0px", + cursor: "pointer", + }, +})); function toLocation(location: Location): void { if (location.name === LocationName.TravelAgency) { @@ -97,7 +94,7 @@ function ASCIICity(props: IProps): React.ReactElement { Y: 24, Z: 25, }; - const classes = useStyles(); + const { classes } = useStyles(); const lineElems = (s: string): (string | React.ReactElement)[] => { const elems: (string | React.ReactElement)[] = []; diff --git a/src/PersonObjects/Sleeve/ui/StatsElement.tsx b/src/PersonObjects/Sleeve/ui/StatsElement.tsx index 9beb9f61e..a88c03776 100644 --- a/src/PersonObjects/Sleeve/ui/StatsElement.tsx +++ b/src/PersonObjects/Sleeve/ui/StatsElement.tsx @@ -33,7 +33,7 @@ interface IProps { } export function StatsElement(props: IProps): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); return ( @@ -109,7 +109,7 @@ export function StatsElement(props: IProps): React.ReactElement { } export function EarningsElement(props: IProps): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); let data: (string | JSX.Element)[][] = []; if (isSleeveCrimeWork(props.sleeve.currentWork)) { diff --git a/src/Sidebar/ui/SidebarRoot.tsx b/src/Sidebar/ui/SidebarRoot.tsx index 2e31d25b3..01c864e4c 100644 --- a/src/Sidebar/ui/SidebarRoot.tsx +++ b/src/Sidebar/ui/SidebarRoot.tsx @@ -1,8 +1,7 @@ import React, { useMemo, useCallback, useState, useEffect } from "react"; import { KEYCODE } from "../../utils/helpers/keyCodes"; import { styled, Theme, CSSObject } from "@mui/material/styles"; -import createStyles from "@mui/styles/createStyles"; -import makeStyles from "@mui/styles/makeStyles"; +import { makeStyles } from "tss-react/mui"; import MuiDrawer from "@mui/material/Drawer"; import List from "@mui/material/List"; import Divider from "@mui/material/Divider"; @@ -100,14 +99,12 @@ const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== "open" }), })); -const useStyles = makeStyles((theme: Theme) => - createStyles({ - active: { - borderLeft: "3px solid " + theme.palette.primary.main, - }, - listitem: {}, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + active: { + borderLeft: "3px solid " + theme.palette.primary.main, + }, + listitem: {}, +})); export function SidebarRoot(props: { page: Page }): React.ReactElement { useRerender(200); @@ -256,7 +253,7 @@ export function SidebarRoot(props: { page: Page }): React.ReactElement { return () => document.removeEventListener("keydown", handleShortcuts); }, [canJob, clickPage, props.page]); - const classes = useStyles(); + const { classes } = useStyles(); const [open, setOpen] = useState(Settings.IsSidebarOpened); const toggleDrawer = (): void => setOpen((old) => { diff --git a/src/Terminal/commands/ls.tsx b/src/Terminal/commands/ls.tsx index 9581a83f4..ef1858642 100644 --- a/src/Terminal/commands/ls.tsx +++ b/src/Terminal/commands/ls.tsx @@ -7,8 +7,7 @@ import type { ProgramFilePath } from "../../Paths/ProgramFilePath"; import type { ContentFilePath } from "../../Paths/ContentFile"; import type { ScriptFilePath } from "../../Paths/ScriptFilePath"; -import createStyles from "@mui/styles/createStyles"; -import makeStyles from "@mui/styles/makeStyles"; +import { makeStyles } from "tss-react/mui"; import { BaseServer } from "../../Server/BaseServer"; import { Router } from "../../ui/GameRoot"; import { Page } from "../../ui/Router"; @@ -109,7 +108,7 @@ export function ls(args: (string | number | boolean)[], server: BaseServer): voi folders.sort(); function SegmentGrid(props: { colSize: string; children: React.ReactChild[] }): React.ReactElement { - const classes = makeStyles({ + const { classes } = makeStyles()({ segmentGrid: { display: "grid", gridTemplateColumns: "repeat(auto-fill, var(--colSize))", @@ -123,15 +122,13 @@ export function ls(args: (string | number | boolean)[], server: BaseServer): voi ); } function ClickableContentFileLink(props: { path: ScriptFilePath | TextFilePath }): React.ReactElement { - const classes = makeStyles((theme: Theme) => - createStyles({ - link: { - cursor: "pointer", - textDecorationLine: "underline", - color: theme.palette.warning.main, - }, - }), - )(); + const { classes } = makeStyles()((theme: Theme) => ({ + link: { + cursor: "pointer", + textDecorationLine: "underline", + color: theme.palette.warning.main, + }, + }))(); const fullPath = combinePath(baseDirectory, props.path); function onClick() { let content; @@ -155,7 +152,7 @@ export function ls(args: (string | number | boolean)[], server: BaseServer): voi } function ClickableMessageLink(props: { path: FilePath }): React.ReactElement { - const classes = makeStyles({ + const { classes } = makeStyles()({ link: { cursor: "pointer", textDecorationLine: "underline", diff --git a/src/Terminal/ui/TerminalInput.tsx b/src/Terminal/ui/TerminalInput.tsx index 8d567a4c5..2a276c789 100644 --- a/src/Terminal/ui/TerminalInput.tsx +++ b/src/Terminal/ui/TerminalInput.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect, useRef } from "react"; import { Theme } from "@mui/material/styles"; -import { createStyles, makeStyles } from "@mui/styles"; +import { makeStyles } from "tss-react/mui"; import { Paper, Popper, TextField, Typography } from "@mui/material"; import { KEY, KEYCODE } from "../../utils/helpers/keyCodes"; @@ -10,29 +10,27 @@ import { getTabCompletionPossibilities } from "../getTabCompletionPossibilities" import { Settings } from "../../Settings/Settings"; import { longestCommonStart } from "../../utils/StringHelperFunctions"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - input: { - backgroundColor: theme.colors.backgroundprimary, - }, - nopadding: { - padding: theme.spacing(0), - }, - preformatted: { - margin: theme.spacing(0), - }, - absolute: { - margin: theme.spacing(0), - position: "absolute", - bottom: "12px", - opacity: "0.75", - maxWidth: "100%", - whiteSpace: "pre", - overflow: "hidden", - pointerEvents: "none", - }, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + input: { + backgroundColor: theme.colors.backgroundprimary, + }, + nopadding: { + padding: theme.spacing(0), + }, + preformatted: { + margin: theme.spacing(0), + }, + absolute: { + margin: theme.spacing(0), + position: "absolute", + bottom: "12px", + opacity: "0.75", + maxWidth: "100%", + whiteSpace: "pre", + overflow: "hidden", + pointerEvents: "none", + }, +})); // Save command in case we de-load this screen. let command = ""; @@ -46,7 +44,7 @@ export function TerminalInput(): React.ReactElement { const [searchResults, setSearchResults] = useState([]); const [searchResultsIndex, setSearchResultsIndex] = useState(0); const [autofilledValue, setAutofilledValue] = useState(false); - const classes = useStyles(); + const { classes } = useStyles(); // If we have no data in the current terminal history, let's initialize it from the player save if (Terminal.commandHistory.length === 0 && Player.terminalCommandHistory.length > 0) { diff --git a/src/Terminal/ui/TerminalRoot.tsx b/src/Terminal/ui/TerminalRoot.tsx index bfd9e6eef..404247a51 100644 --- a/src/Terminal/ui/TerminalRoot.tsx +++ b/src/Terminal/ui/TerminalRoot.tsx @@ -1,8 +1,7 @@ import React, { useState, useEffect, useRef } from "react"; import { Link as MuiLink, Typography } from "@mui/material"; import { Theme } from "@mui/material/styles"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; import _ from "lodash"; import { Output, Link, RawOutput } from "../OutputTypes"; @@ -16,27 +15,25 @@ import { ANSIITypography } from "../../ui/React/ANSIITypography"; import { useRerender } from "../../ui/React/hooks"; import { TerminalActionTimer } from "./TerminalActionTimer"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - container: { - display: "flex", - flexDirection: "column", - height: "calc(100vh - 16px)", - }, - entries: { - padding: 0, - overflow: "scroll", - flex: "0 1 auto", - margin: "auto 0 0", - }, - preformatted: { - whiteSpace: "pre-wrap", - overflowWrap: "anywhere", - margin: theme.spacing(0), - width: "100%", - }, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + container: { + display: "flex", + flexDirection: "column", + height: "calc(100vh - 16px)", + }, + entries: { + padding: 0, + overflow: "scroll", + flex: "0 1 auto", + margin: "auto 0 0", + }, + preformatted: { + whiteSpace: "pre-wrap", + overflowWrap: "anywhere", + margin: theme.spacing(0), + width: "100%", + }, +})); export function TerminalRoot(): React.ReactElement { const scrollHook = useRef(null); @@ -82,7 +79,7 @@ export function TerminalRoot(): React.ReactElement { }; }, []); - const classes = useStyles(); + const { classes } = useStyles(); return (
    diff --git a/src/ui/ActiveScripts/RecentScriptAccordion.tsx b/src/ui/ActiveScripts/RecentScriptAccordion.tsx index 53e460495..0af412d5f 100644 --- a/src/ui/ActiveScripts/RecentScriptAccordion.tsx +++ b/src/ui/ActiveScripts/RecentScriptAccordion.tsx @@ -16,8 +16,7 @@ import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import ListItemButton from "@mui/material/ListItemButton"; import ListItemText from "@mui/material/ListItemText"; -import makeStyles from "@mui/styles/makeStyles"; - +import { makeStyles } from "tss-react/mui"; import Collapse from "@mui/material/Collapse"; import ExpandLess from "@mui/icons-material/ExpandLess"; import ExpandMore from "@mui/icons-material/ExpandMore"; @@ -29,7 +28,7 @@ import { MoneyRate } from "../React/MoneyRate"; import { RecentScript } from "../../Netscript/RecentScripts"; import { LogBoxEvents } from "../React/LogBoxManager"; -const useStyles = makeStyles({ +const useStyles = makeStyles()({ noborder: { borderBottom: "none", }, @@ -40,7 +39,7 @@ interface IProps { } export function RecentScriptAccordion(props: IProps): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); const [open, setOpen] = React.useState(false); const recentScript = props.recentScript; diff --git a/src/ui/ActiveScripts/ScriptProduction.tsx b/src/ui/ActiveScripts/ScriptProduction.tsx index 02a8b0b2b..12d57fcbd 100644 --- a/src/ui/ActiveScripts/ScriptProduction.tsx +++ b/src/ui/ActiveScripts/ScriptProduction.tsx @@ -11,28 +11,25 @@ import { Player } from "@player"; import Typography from "@mui/material/Typography"; import { Theme } from "@mui/material/styles"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; import Table from "@mui/material/Table"; import TableBody from "@mui/material/TableBody"; import TableCell from "@mui/material/TableCell"; import TableRow from "@mui/material/TableRow"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - cell: { - borderBottom: "none", - padding: theme.spacing(1), - margin: theme.spacing(1), - whiteSpace: "nowrap", - }, - size: { - width: "1px", - }, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + cell: { + borderBottom: "none", + padding: theme.spacing(1), + margin: theme.spacing(1), + whiteSpace: "nowrap", + }, + size: { + width: "1px", + }, +})); export function ScriptProduction(): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); const prodRateSinceLastAug = Player.scriptProdSinceLastAug / (Player.playtimeSinceLastAug / 1000); return ( diff --git a/src/ui/ActiveScripts/WorkerScriptAccordion.tsx b/src/ui/ActiveScripts/WorkerScriptAccordion.tsx index f210b38cd..bf9311d79 100644 --- a/src/ui/ActiveScripts/WorkerScriptAccordion.tsx +++ b/src/ui/ActiveScripts/WorkerScriptAccordion.tsx @@ -18,7 +18,7 @@ import IconButton from "@mui/material/IconButton"; import DeleteIcon from "@mui/icons-material/Delete"; import ListItemButton from "@mui/material/ListItemButton"; import ListItemText from "@mui/material/ListItemText"; -import makeStyles from "@mui/styles/makeStyles"; +import { makeStyles } from "tss-react/mui"; import Collapse from "@mui/material/Collapse"; import ExpandLess from "@mui/icons-material/ExpandLess"; @@ -34,7 +34,7 @@ import { arrayToString } from "../../utils/helpers/ArrayHelpers"; import { Money } from "../React/Money"; import { MoneyRate } from "../React/MoneyRate"; -const useStyles = makeStyles({ +const useStyles = makeStyles()({ noborder: { borderBottom: "none", }, @@ -45,7 +45,7 @@ interface IProps { } export function WorkerScriptAccordion(props: IProps): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); const [open, setOpen] = React.useState(false); const workerScript = props.workerScript; const scriptRef = workerScript.scriptRef; diff --git a/src/ui/GameRoot.tsx b/src/ui/GameRoot.tsx index 8b7ddfc13..0ecb80787 100644 --- a/src/ui/GameRoot.tsx +++ b/src/ui/GameRoot.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from "react"; -import { createStyles, makeStyles } from "@mui/styles"; import { Box, Typography } from "@mui/material"; import { Theme } from "@mui/material/styles"; +import { makeStyles } from "tss-react/mui"; import { Player } from "@player"; import { installAugmentations } from "../Augmentation/AugmentationHelpers"; @@ -75,25 +75,21 @@ import { GoRoot } from "../Go/ui/GoRoot"; const htmlLocation = location; -const useStyles = makeStyles( - (theme: Theme) => - createStyles({ - root: { - "-ms-overflow-style": "none" /* for Internet Explorer, Edge */, - "scrollbar-width": "none" /* for Firefox */, - margin: theme.spacing(0), - flexGrow: 1, - padding: "8px", - minHeight: "100vh", - boxSizing: "border-box", - width: "1px", - }, - }), - { name: "GameRoot" }, -); +const useStyles = makeStyles()((theme: Theme) => ({ + root: { + "-ms-overflow-style": "none" /* for Internet Explorer, Edge */, + "scrollbar-width": "none" /* for Firefox */, + margin: theme.spacing(0), + flexGrow: 1, + padding: "8px", + minHeight: "100vh", + boxSizing: "border-box", + width: "1px", + }, +})); const uninitialized = (): void => { - throw new Error("Router called before initialization"); + throw new Error("Router called before initialization - uninitialized"); }; const MAX_PAGES_IN_HISTORY = 10; @@ -101,14 +97,14 @@ const MAX_PAGES_IN_HISTORY = 10; export let Router: IRouter = { isInitialized: false, page: () => { - throw new Error("Router called before initialization"); + throw new Error("Router called before initialization - page"); }, allowRouting: uninitialized, toPage: () => { - throw new Error("Router called before initialization"); + throw new Error("Router called before initialization - toPage"); }, back: () => { - throw new Error("Router called before initialization"); + throw new Error("Router called before initialization - back"); }, }; @@ -119,7 +115,7 @@ function determineStartPage() { } export function GameRoot(): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); const [pages, setPages] = useState(() => [{ page: determineStartPage() }]); const pageWithContext = pages[0]; diff --git a/src/ui/InteractiveTutorial/InteractiveTutorialRoot.tsx b/src/ui/InteractiveTutorial/InteractiveTutorialRoot.tsx index 86966943e..350b51759 100644 --- a/src/ui/InteractiveTutorial/InteractiveTutorialRoot.tsx +++ b/src/ui/InteractiveTutorial/InteractiveTutorialRoot.tsx @@ -14,8 +14,7 @@ import AccountTreeIcon from "@mui/icons-material/AccountTree"; import StorageIcon from "@mui/icons-material/Storage"; import LocationCityIcon from "@mui/icons-material/LocationCity"; import { Theme } from "@mui/material/styles"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; import { iTutorialPrevStep, @@ -31,20 +30,18 @@ interface IContent { canNext: boolean; } -const useStyles = makeStyles((theme: Theme) => - createStyles({ - textfield: { - borderBottom: "1px solid " + theme.palette.primary.main, - }, - code: { - whiteSpace: "pre", - backgroundColor: theme.palette.background.paper, - }, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + textfield: { + borderBottom: "1px solid " + theme.palette.primary.main, + }, + code: { + whiteSpace: "pre", + backgroundColor: theme.palette.background.paper, + }, +})); export function InteractiveTutorialRoot(): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); const rerender = useRerender(); const tutorialScriptName = `n00dles.js`; diff --git a/src/ui/MD/code.tsx b/src/ui/MD/code.tsx index fd2334c75..93aa640c0 100644 --- a/src/ui/MD/code.tsx +++ b/src/ui/MD/code.tsx @@ -2,30 +2,27 @@ import React from "react"; import SyntaxHighlighter from "react-syntax-highlighter"; import { monokaiSublime as theme } from "react-syntax-highlighter/dist/esm/styles/hljs"; import { Theme } from "@mui/material/styles"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; import { CodeProps } from "react-markdown/lib/ast-to-react"; import { Typography } from "@mui/material"; +import { makeStyles } from "tss-react/mui"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - pre: { - borderRadius: "6px", - }, - code: { - paddingBottom: "2.72px", - paddingLeft: "5.44px", - paddingRight: "5.44px", - paddingTop: "2.72px", - borderRadius: "6px", - display: "inline", - backgroundColor: theme.palette.background.paper, - }, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + pre: { + borderRadius: "6px", + }, + code: { + paddingBottom: "2.72px", + paddingLeft: "5.44px", + paddingRight: "5.44px", + paddingTop: "2.72px", + borderRadius: "6px", + display: "inline", + backgroundColor: theme.palette.background.paper, + }, +})); export const Pre = (props: React.PropsWithChildren): React.ReactElement => { - const classes = useStyles(); + const { classes } = useStyles(); return ( {props.children} @@ -34,7 +31,7 @@ export const Pre = (props: React.PropsWithChildren): React.ReactElement }; const InlineCode = (props: React.PropsWithChildren): React.ReactElement => ( - + {props.children} ); diff --git a/src/ui/MD/components.tsx b/src/ui/MD/components.tsx index 63e8411ad..91d3dfc5e 100644 --- a/src/ui/MD/components.tsx +++ b/src/ui/MD/components.tsx @@ -1,23 +1,19 @@ import React from "react"; import { Theme } from "@mui/material/styles"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; import { ListItemText, Table, TableCell, TableCellProps, TableRow, Typography } from "@mui/material"; import { LiProps, TableDataCellProps, TableHeaderCellProps } from "react-markdown/lib/ast-to-react"; - -const useStyles = makeStyles((theme: Theme) => - createStyles({ - th: { whiteSpace: "pre", fontWeight: "bold" }, - td: { whiteSpace: "pre" }, - blockquote: { - borderLeftColor: theme.palette.background.paper, - borderLeftStyle: "solid", - borderLeftWidth: "4px", - paddingLeft: "16px", - paddingRight: "16px", - }, - }), -); +import { makeStyles } from "tss-react/mui"; +const useStyles = makeStyles()((theme: Theme) => ({ + th: { whiteSpace: "pre", fontWeight: "bold" }, + td: { whiteSpace: "pre" }, + blockquote: { + borderLeftColor: theme.palette.background.paper, + borderLeftStyle: "solid", + borderLeftWidth: "4px", + paddingLeft: "16px", + paddingRight: "16px", + }, +})); export const h1 = (props: React.PropsWithChildren): React.ReactElement => ( // We are just going to cheat and lower every h# by 1. @@ -78,7 +74,7 @@ const fixAlign = (align: React.CSSProperties["textAlign"]): TableCellProps["alig }; export const Td = (props: React.PropsWithChildren): React.ReactElement => { - const classes = useStyles(); + const { classes } = useStyles(); const align = fixAlign(props.style?.textAlign); const content = props.children?.map((child, i) => { if (child === "
    ") return
    ; @@ -94,7 +90,7 @@ export const Td = (props: React.PropsWithChildren): React.Re }; export const Th = (props: React.PropsWithChildren): React.ReactElement => { - const classes = useStyles(); + const { classes } = useStyles(); const align = fixAlign(props.style?.textAlign); return ( @@ -115,6 +111,6 @@ export const tr = (props: React.PropsWithChildren): React.ReactElement = }; export const Blockquote = (props: React.PropsWithChildren): React.ReactElement => { - const classes = useStyles(); + const { classes } = useStyles(); return
    {props.children}
    ; }; diff --git a/src/ui/React/ANSIITypography.tsx b/src/ui/React/ANSIITypography.tsx index fab65fca1..1bc05aba8 100644 --- a/src/ui/React/ANSIITypography.tsx +++ b/src/ui/React/ANSIITypography.tsx @@ -1,7 +1,6 @@ import { Typography } from "@mui/material"; import React from "react"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; import { Theme } from "@mui/material/styles"; import { Settings } from "../../Settings/Settings"; @@ -10,45 +9,43 @@ import { Settings } from "../../Settings/Settings"; // eslint-disable-next-line no-control-regex const ANSI_ESCAPE = new RegExp("\u{001b}\\[(?.*?)m", "ug"); -const useStyles = makeStyles((theme: Theme) => - createStyles({ - success: { - whiteSpace: "pre-wrap", - overflowWrap: "anywhere", - margin: theme.spacing(0), - color: theme.colors.success, - "--padForFlushBg": (Settings.styles.lineHeight - 1) / 2 + "em", - }, - error: { - whiteSpace: "pre-wrap", - overflowWrap: "anywhere", - margin: theme.spacing(0), - color: theme.palette.error.main, - "--padForFlushBg": (Settings.styles.lineHeight - 1) / 2 + "em", - }, - primary: { - whiteSpace: "pre-wrap", - overflowWrap: "anywhere", - margin: theme.spacing(0), - color: theme.palette.primary.main, - "--padForFlushBg": (Settings.styles.lineHeight - 1) / 2 + "em", - }, - info: { - whiteSpace: "pre-wrap", - overflowWrap: "anywhere", - margin: theme.spacing(0), - color: theme.palette.info.main, - "--padForFlushBg": (Settings.styles.lineHeight - 1) / 2 + "em", - }, - warning: { - whiteSpace: "pre-wrap", - overflowWrap: "anywhere", - margin: theme.spacing(0), - color: theme.palette.warning.main, - "--padForFlushBg": (Settings.styles.lineHeight - 1) / 2 + "em", - }, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + success: { + whiteSpace: "pre-wrap", + overflowWrap: "anywhere", + margin: theme.spacing(0), + color: theme.colors.success, + "--padForFlushBg": (Settings.styles.lineHeight - 1) / 2 + "em", + }, + error: { + whiteSpace: "pre-wrap", + overflowWrap: "anywhere", + margin: theme.spacing(0), + color: theme.palette.error.main, + "--padForFlushBg": (Settings.styles.lineHeight - 1) / 2 + "em", + }, + primary: { + whiteSpace: "pre-wrap", + overflowWrap: "anywhere", + margin: theme.spacing(0), + color: theme.palette.primary.main, + "--padForFlushBg": (Settings.styles.lineHeight - 1) / 2 + "em", + }, + info: { + whiteSpace: "pre-wrap", + overflowWrap: "anywhere", + margin: theme.spacing(0), + color: theme.palette.info.main, + "--padForFlushBg": (Settings.styles.lineHeight - 1) / 2 + "em", + }, + warning: { + whiteSpace: "pre-wrap", + overflowWrap: "anywhere", + margin: theme.spacing(0), + color: theme.palette.warning.main, + "--padForFlushBg": (Settings.styles.lineHeight - 1) / 2 + "em", + }, +})); const lineClass = (classes: Record, s: string): string => { const lineClassMap: Record = { @@ -67,7 +64,7 @@ type ANSIITypographyProps = { export const ANSIITypography = React.memo(function ANSIITypography(props: ANSIITypographyProps): React.ReactElement { const text = String(props.text); - const classes = useStyles(); + const { classes } = useStyles(); const parts = []; // Build a look-alike regex match to place at the front of the matches list diff --git a/src/ui/React/Augmentation.tsx b/src/ui/React/Augmentation.tsx index e92707ddf..81573156c 100644 --- a/src/ui/React/Augmentation.tsx +++ b/src/ui/React/Augmentation.tsx @@ -1,17 +1,14 @@ import * as React from "react"; import { Theme } from "@mui/material/styles"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - aug: { - color: theme.colors.combat, - }, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + aug: { + color: theme.colors.combat, + }, +})); export function Augmentation({ name }: { name: string }): JSX.Element { - const classes = useStyles(); + const { classes } = useStyles(); return {name}; } diff --git a/src/ui/React/CharacterOverview.tsx b/src/ui/React/CharacterOverview.tsx index 6b8de5da2..859e1dca3 100644 --- a/src/ui/React/CharacterOverview.tsx +++ b/src/ui/React/CharacterOverview.tsx @@ -6,8 +6,7 @@ import { Box, Button, IconButton, Table, TableBody, TableCell, TableRow, Tooltip import SaveIcon from "@mui/icons-material/Save"; import ClearAllIcon from "@mui/icons-material/ClearAll"; import { Theme, useTheme } from "@mui/material/styles"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; import { Player } from "@player"; import { formatHp, formatMoney, formatSkill } from "../formatNumber"; @@ -129,7 +128,7 @@ interface DataRowProps { cellType: "cellNone" | "cell"; } export function DataRow({ name, showBar, color, cellType }: DataRowProps): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); const isSkill = name in skillNameMap; const skillBar = showBar && isSkill ? : <>; return ( @@ -171,7 +170,7 @@ export function CharacterOverview({ parentOpen, save, killScripts }: OverviewPro }, 600); return () => clearInterval(interval); }, [parentOpen]); - const classes = useStyles(); + const { classes } = useStyles(); const theme = useTheme(); return ( <> @@ -243,7 +242,7 @@ function ActionText({ action }: { action: ActionIdentifier }): React.ReactElemen } function BladeburnerText(): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); const rerender = useRerender(); useEffect(() => { const clearSubscription = OverviewEventEmitter.subscribe(rerender); @@ -284,7 +283,7 @@ const onClickFocusWork = (): void => { Router.toPage(Page.Work); }; function WorkInProgressOverview({ tooltip, children, header }: WorkInProgressOverviewProps): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); return ( <> @@ -409,52 +408,50 @@ function Work(): React.ReactElement { ); } -const useStyles = makeStyles((theme: Theme) => - createStyles({ - workCell: { - textAlign: "center", - maxWidth: "200px", - borderBottom: "none", - padding: 0, - margin: 0, - }, +const useStyles = makeStyles()((theme: Theme) => ({ + workCell: { + textAlign: "center", + maxWidth: "200px", + borderBottom: "none", + padding: 0, + margin: 0, + }, - workHeader: { - fontSize: "0.9rem", - }, + workHeader: { + fontSize: "0.9rem", + }, - workSubtitles: { - fontSize: "0.8rem", - }, + workSubtitles: { + fontSize: "0.8rem", + }, - cellNone: { - borderBottom: "none", - padding: 0, - margin: 0, - }, - cell: { - padding: 0, - margin: 0, - }, - hp: { - color: theme.colors.hp, - }, - money: { - color: theme.colors.money, - }, - hack: { - color: theme.colors.hack, - }, - combat: { - color: theme.colors.combat, - }, - cha: { - color: theme.colors.cha, - }, - int: { - color: theme.colors.int, - }, - }), -); + cellNone: { + borderBottom: "none", + padding: 0, + margin: 0, + }, + cell: { + padding: 0, + margin: 0, + }, + hp: { + color: theme.colors.hp, + }, + money: { + color: theme.colors.money, + }, + hack: { + color: theme.colors.hack, + }, + combat: { + color: theme.colors.combat, + }, + cha: { + color: theme.colors.cha, + }, + int: { + color: theme.colors.int, + }, +})); export { useStyles }; diff --git a/src/ui/React/Constants.ts b/src/ui/React/Constants.ts new file mode 100644 index 000000000..61e6979c3 --- /dev/null +++ b/src/ui/React/Constants.ts @@ -0,0 +1 @@ +export const logBoxBaseZIndex = 1500; diff --git a/src/ui/React/Favor.tsx b/src/ui/React/Favor.tsx index 35c5912b5..6e8f7b9ca 100644 --- a/src/ui/React/Favor.tsx +++ b/src/ui/React/Favor.tsx @@ -1,18 +1,15 @@ import * as React from "react"; import { formatFavor } from "../formatNumber"; import { Theme } from "@mui/material/styles"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - favor: { - color: theme.colors.rep, - }, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + favor: { + color: theme.colors.rep, + }, +})); export function Favor({ favor }: { favor: number | string }): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); return {typeof favor === "number" ? formatFavor(favor) : favor}; } diff --git a/src/ui/React/Hashes.tsx b/src/ui/React/Hashes.tsx index 04a403d0b..99b4ca660 100644 --- a/src/ui/React/Hashes.tsx +++ b/src/ui/React/Hashes.tsx @@ -1,18 +1,15 @@ import * as React from "react"; import { formatHashes } from "../formatNumber"; import { Theme } from "@mui/material/styles"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - money: { - color: theme.colors.money, - }, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + money: { + color: theme.colors.money, + }, +})); export function Hashes({ hashes }: { hashes: number | string }): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); return {typeof hashes === "number" ? formatHashes(hashes) : hashes}; } diff --git a/src/ui/React/ImportSave/ImportSave.tsx b/src/ui/React/ImportSave/ImportSave.tsx index 640fb13e8..c87a3b11a 100644 --- a/src/ui/React/ImportSave/ImportSave.tsx +++ b/src/ui/React/ImportSave/ImportSave.tsx @@ -15,8 +15,7 @@ import TableCell from "@mui/material/TableCell"; import Tooltip from "@mui/material/Tooltip"; import Typography from "@mui/material/Typography"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; import { Theme } from "@mui/material/styles"; import WarningIcon from "@mui/icons-material/Warning"; @@ -41,50 +40,48 @@ import { ComparisonIcon } from "./ComparisonIcon"; import { SaveData } from "../../../types"; import { handleGetSaveDataError } from "../../../Netscript/ErrorMessages"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - root: { - padding: theme.spacing(2), - maxWidth: "1000px", +const useStyles = makeStyles()((theme: Theme) => ({ + root: { + padding: theme.spacing(2), + maxWidth: "1000px", + + "& .MuiTable-root": { + "& .MuiTableCell-root": { + borderBottom: `1px solid ${Settings.theme.welllight}`, + }, + + "& .MuiTableHead-root .MuiTableRow-root": { + backgroundColor: Settings.theme.backgroundsecondary, - "& .MuiTable-root": { "& .MuiTableCell-root": { - borderBottom: `1px solid ${Settings.theme.welllight}`, + color: Settings.theme.primary, + fontWeight: "bold", }, + }, - "& .MuiTableHead-root .MuiTableRow-root": { + "& .MuiTableBody-root": { + "& .MuiTableRow-root:nth-of-type(odd)": { + backgroundColor: Settings.theme.well, + + "& .MuiTableCell-root": { + color: Settings.theme.primarylight, + }, + }, + "& .MuiTableRow-root:nth-of-type(even)": { backgroundColor: Settings.theme.backgroundsecondary, "& .MuiTableCell-root": { - color: Settings.theme.primary, - fontWeight: "bold", - }, - }, - - "& .MuiTableBody-root": { - "& .MuiTableRow-root:nth-of-type(odd)": { - backgroundColor: Settings.theme.well, - - "& .MuiTableCell-root": { - color: Settings.theme.primarylight, - }, - }, - "& .MuiTableRow-root:nth-of-type(even)": { - backgroundColor: Settings.theme.backgroundsecondary, - - "& .MuiTableCell-root": { - color: Settings.theme.primarylight, - }, + color: Settings.theme.primarylight, }, }, }, }, + }, - skillTitle: { - textTransform: "capitalize", - }, - }), -); + skillTitle: { + textTransform: "capitalize", + }, +})); // TODO: move to game constants and/or extract as an enum const playerSkills: (keyof Skills)[] = ["hacking", "strength", "defense", "dexterity", "agility", "charisma"]; @@ -92,7 +89,7 @@ const playerSkills: (keyof Skills)[] = ["hacking", "strength", "defense", "dexte let initialAutosave = 0; export const ImportSave = (props: { saveData: SaveData; automatic: boolean }): JSX.Element => { - const classes = useStyles(); + const { classes } = useStyles(); const [importData, setImportData] = useState(); const [currentData, setCurrentData] = useState(); const [isImportModalOpen, { on: openImportModal, off: closeImportModal }] = useBoolean(false); diff --git a/src/ui/React/LogBoxManager.tsx b/src/ui/React/LogBoxManager.tsx index 5c5d0e648..9bf2301fe 100644 --- a/src/ui/React/LogBoxManager.tsx +++ b/src/ui/React/LogBoxManager.tsx @@ -2,14 +2,14 @@ import React, { useState, useEffect, useRef, useCallback, useMemo } from "react" import { EventEmitter } from "../../utils/EventEmitter"; import { RunningScript } from "../../Script/RunningScript"; import { killWorkerScriptByPid } from "../../Netscript/killWorkerScript"; + import Typography from "@mui/material/Typography"; import Box from "@mui/material/Box"; import Paper from "@mui/material/Paper"; + import Draggable, { DraggableEvent } from "react-draggable"; import { ResizableBox, ResizeCallbackData } from "react-resizable"; import IconButton from "@mui/material/IconButton"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; import ArrowForwardIosIcon from "@mui/icons-material/ArrowForwardIos"; import CloseIcon from "@mui/icons-material/Close"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; @@ -25,7 +25,8 @@ import { Settings } from "../../Settings/Settings"; import { ANSIITypography } from "./ANSIITypography"; import { useRerender } from "./hooks"; import { dialogBoxCreate } from "./DialogBox"; - +import { makeStyles } from "tss-react/mui"; +import { logBoxBaseZIndex } from "./Constants"; let layerCounter = 0; export const LogBoxEvents = new EventEmitter<[RunningScript]>(); @@ -143,33 +144,29 @@ interface LogWindowProps { hidden: boolean; } -const useStyles = makeStyles(() => - createStyles({ - logs: { - overflowY: "scroll", - overflowX: "hidden", - scrollbarWidth: "auto", - flexDirection: "column-reverse", - whiteSpace: "pre-wrap", - wordWrap: "break-word", - }, - titleButton: { - borderWidth: "0 0 0 1px", - borderColor: Settings.theme.welllight, - borderStyle: "solid", - borderRadius: "0", - padding: "0", - height: "100%", - }, - }), -); - -export const logBoxBaseZIndex = 1500; +const useStyles = makeStyles()({ + logs: { + overflowY: "scroll", + overflowX: "hidden", + scrollbarWidth: "auto", + flexDirection: "column-reverse", + whiteSpace: "pre-wrap", + wordWrap: "break-word", + }, + titleButton: { + borderWidth: "0 0 0 1px", + borderColor: Settings.theme.welllight, + borderStyle: "solid", + borderRadius: "0", + padding: "0", + height: "100%", + }, +}); function LogWindow({ hidden, script, onClose }: LogWindowProps): React.ReactElement { const draggableRef = useRef(null); const rootRef = useRef(null); - const classes = useStyles(); + const { classes } = useStyles(); const container = useRef(null); const textArea = useRef(null); const rerender = useRerender(Settings.TailRenderInterval); diff --git a/src/ui/React/Modal.tsx b/src/ui/React/Modal.tsx index 1263eef68..bb1c065e0 100644 --- a/src/ui/React/Modal.tsx +++ b/src/ui/React/Modal.tsx @@ -4,42 +4,39 @@ import Box from "@mui/material/Box"; import IconButton from "@mui/material/IconButton"; import Fade from "@mui/material/Fade"; import M from "@mui/material/Modal"; -import createStyles from "@mui/styles/createStyles"; -import makeStyles from "@mui/styles/makeStyles"; +import { makeStyles } from "tss-react/mui"; import { SxProps } from "@mui/system"; import CloseIcon from "@mui/icons-material/Close"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - modal: { - display: "flex", - alignItems: "center", - justifyContent: "center", +const useStyles = makeStyles()((theme: Theme) => ({ + modal: { + display: "flex", + alignItems: "center", + justifyContent: "center", + }, + paper: { + position: "relative", + backgroundColor: theme.palette.background.default, + border: "2px solid " + theme.palette.primary.main, + boxShadow: `0px 3px 5px -1px ${theme.palette.primary.dark},0px 5px 8px 0px ${theme.palette.primary.dark},0px 1px 14px 0px ${theme.palette.primary.dark}`, + padding: 2, + maxWidth: "80%", + maxHeight: "80%", + overflow: "auto", + "&::-webkit-scrollbar": { + // webkit + display: "none", }, - paper: { - position: "relative", - backgroundColor: theme.palette.background.default, - border: "2px solid " + theme.palette.primary.main, - boxShadow: `0px 3px 5px -1px ${theme.palette.primary.dark},0px 5px 8px 0px ${theme.palette.primary.dark},0px 1px 14px 0px ${theme.palette.primary.dark}`, - padding: 2, - maxWidth: "80%", - maxHeight: "80%", - overflow: "auto", - "&::-webkit-scrollbar": { - // webkit - display: "none", - }, - scrollbarWidth: "none", // firefox - }, - closeButton: { - position: "absolute", - right: 3, - top: 3, - width: 20, - height: 20, - }, - }), -); + scrollbarWidth: "none", // firefox + }, + closeButton: { + position: "absolute", + right: 3, + top: 3, + width: 20, + height: 20, + }, +})); interface ModalProps { open: boolean; @@ -49,7 +46,7 @@ interface ModalProps { } export const Modal = ({ open, onClose, children, sx }: ModalProps): React.ReactElement => { - const classes = useStyles(); + const { classes } = useStyles(); const [content, setContent] = useState(children); useEffect(() => { if (!open) return; diff --git a/src/ui/React/Money.tsx b/src/ui/React/Money.tsx index 0f1667871..b25d85933 100644 --- a/src/ui/React/Money.tsx +++ b/src/ui/React/Money.tsx @@ -2,26 +2,23 @@ import * as React from "react"; import { formatMoney } from "../formatNumber"; import { Player } from "@player"; import { Theme } from "@mui/material/styles"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - unbuyable: { - color: theme.palette.action.disabled, - }, - money: { - color: theme.colors.money, - }, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + unbuyable: { + color: theme.palette.action.disabled, + }, + money: { + color: theme.colors.money, + }, +})); interface IProps { money: number | string; forPurchase?: boolean; } export function Money(props: IProps): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); if (props.forPurchase) { if (typeof props.money !== "number") throw new Error("if value is for a purchase, money should be number, contact dev"); diff --git a/src/ui/React/Overview.tsx b/src/ui/React/Overview.tsx index c04d8f6d4..073500917 100644 --- a/src/ui/React/Overview.tsx +++ b/src/ui/React/Overview.tsx @@ -1,6 +1,6 @@ import React, { useState, useEffect, useRef, useMemo } from "react"; import Draggable, { DraggableEventHandler } from "react-draggable"; -import makeStyles from "@mui/styles/makeStyles"; +import { makeStyles } from "tss-react/mui"; import Collapse from "@mui/material/Collapse"; import Paper from "@mui/material/Paper"; import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; @@ -13,7 +13,7 @@ import { Settings } from "../../Settings/Settings"; import { Box, Button, Typography } from "@mui/material"; import { debounce } from "lodash"; -const useStyles = makeStyles({ +const useStyles = makeStyles()({ overviewContainer: { position: "fixed", top: 0, @@ -68,7 +68,7 @@ export function Overview({ children, mode }: IProps): React.ReactElement { const [open, setOpen] = useState(Settings.overview.opened); const [x, setX] = useState(Settings.overview.x); const [y, setY] = useState(Settings.overview.y); - const classes = useStyles(); + const { classes } = useStyles(); const CurrentIcon = open ? KeyboardArrowUpIcon : KeyboardArrowDownIcon; const LeftIcon = mode === "tutorial" ? SchoolIcon : EqualizerIcon; diff --git a/src/ui/React/Progress.tsx b/src/ui/React/Progress.tsx index 0a29ae311..6c17c6aab 100644 --- a/src/ui/React/Progress.tsx +++ b/src/ui/React/Progress.tsx @@ -1,8 +1,8 @@ import LinearProgress from "@mui/material/LinearProgress"; import { Theme } from "@mui/material/styles"; -import withStyles from "@mui/styles/withStyles"; +import { withStyles } from "tss-react/mui"; -export const ProgressBar = withStyles((theme: Theme) => ({ +export const ProgressBar = withStyles(LinearProgress, (theme: Theme) => ({ root: { backgroundColor: theme.palette.background.paper, }, @@ -10,4 +10,4 @@ export const ProgressBar = withStyles((theme: Theme) => ({ transition: "none", backgroundColor: theme.palette.primary.main, }, -}))(LinearProgress); +})); diff --git a/src/ui/React/Reputation.tsx b/src/ui/React/Reputation.tsx index 18ad9415f..b66282b00 100644 --- a/src/ui/React/Reputation.tsx +++ b/src/ui/React/Reputation.tsx @@ -1,19 +1,16 @@ import * as React from "react"; import { formatReputation } from "../formatNumber"; import { Theme } from "@mui/material/styles"; -import makeStyles from "@mui/styles/makeStyles"; -import createStyles from "@mui/styles/createStyles"; +import { makeStyles } from "tss-react/mui"; -const useStyles = makeStyles((theme: Theme) => - createStyles({ - reputation: { - color: theme.colors.rep, - }, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + reputation: { + color: theme.colors.rep, + }, +})); export function Reputation({ reputation }: { reputation: number | string }): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); return ( {typeof reputation === "number" ? formatReputation(reputation) : reputation} diff --git a/src/ui/React/Snackbar.tsx b/src/ui/React/Snackbar.tsx index 20d470860..e7bb63a04 100644 --- a/src/ui/React/Snackbar.tsx +++ b/src/ui/React/Snackbar.tsx @@ -2,17 +2,16 @@ import type { ToastVariant } from "@enums"; import React, { useEffect } from "react"; import { useSnackbar, SnackbarProvider as SB } from "notistack"; -import makeStyles from "@mui/styles/makeStyles"; +import { makeStyles } from "tss-react/mui"; import { EventEmitter } from "../../utils/EventEmitter"; import Alert from "@mui/material/Alert"; import Paper from "@mui/material/Paper"; -import { logBoxBaseZIndex } from "./LogBoxManager"; +import { logBoxBaseZIndex } from "./Constants"; interface IProps { children: React.ReactNode | React.ReactNode[]; } - -const useStyles = makeStyles(() => ({ +const useStyles = makeStyles()({ snackbar: { // Log popup z-index increments, so let's add a padding to be well above them. zIndex: `${logBoxBaseZIndex + 1000} !important` as any, @@ -21,10 +20,10 @@ const useStyles = makeStyles(() => ({ alignSelf: "center", }, }, -})); +}); export function SnackbarProvider(props: IProps): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); return ( { - const classes = useStyles(); + const { classes } = useStyles(); let content = ""; if (data) { diff --git a/src/ui/React/StatsTable.tsx b/src/ui/React/StatsTable.tsx index fce945d84..4c1c781ca 100644 --- a/src/ui/React/StatsTable.tsx +++ b/src/ui/React/StatsTable.tsx @@ -2,7 +2,7 @@ import React, { ReactNode, ReactElement } from "react"; import { Table, TableCell } from "./Table"; import { TableBody, TableRow, Table as MuiTable, Typography } from "@mui/material"; -import { makeStyles } from "@mui/styles"; +import { makeStyles } from "tss-react/mui"; interface StatsTableProps { rows: ReactNode[][]; @@ -12,14 +12,14 @@ interface StatsTableProps { } const useStyles = (paddingLeft: string) => - makeStyles({ + makeStyles()({ firstCell: { textAlign: "left" }, nonFirstCell: { textAlign: "right", paddingLeft: paddingLeft }, })(); export function StatsTable({ rows, title, wide, paddingLeft }: StatsTableProps): ReactElement { const T = wide ? MuiTable : Table; - const classes = useStyles(paddingLeft ?? "0.5em"); + const { classes } = useStyles(paddingLeft ?? "0.5em"); return ( <> {title && {title}} diff --git a/src/ui/React/Table.tsx b/src/ui/React/Table.tsx index 0b742840c..008a076e7 100644 --- a/src/ui/React/Table.tsx +++ b/src/ui/React/Table.tsx @@ -1,9 +1,9 @@ import React from "react"; import { TableCell as MuiTableCell, TableCellProps, Table as MuiTable, TableProps } from "@mui/material"; -import makeStyles from "@mui/styles/makeStyles"; +import { makeStyles } from "tss-react/mui"; -const useStyles = makeStyles({ +const useStyles = makeStyles()({ root: { borderBottom: "none", }, @@ -17,7 +17,7 @@ export const TableCell: React.FC = (props: TableCellProps) => { @@ -29,7 +29,7 @@ export const Table: React.FC = (props: TableProps) => { diff --git a/src/ui/React/WorldMap.tsx b/src/ui/React/WorldMap.tsx index ec028c0c0..ae949f2e4 100644 --- a/src/ui/React/WorldMap.tsx +++ b/src/ui/React/WorldMap.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { createStyles, makeStyles } from "@mui/styles"; +import { makeStyles } from "tss-react/mui"; import { Tooltip, Typography } from "@mui/material"; import { Theme } from "@mui/material/styles"; @@ -11,24 +11,22 @@ interface ICityProps { onTravel: (city: CityName) => void; } -const useStyles = makeStyles((theme: Theme) => - createStyles({ - travel: { - color: theme.colors.maplocation, - lineHeight: "1em", - whiteSpace: "pre", - cursor: "pointer", - }, - currentCity: { - color: theme.colors.disabled, - lineHeight: "1em", - whiteSpace: "pre", - }, - }), -); +const useStyles = makeStyles()((theme: Theme) => ({ + travel: { + color: theme.colors.maplocation, + lineHeight: "1em", + whiteSpace: "pre", + cursor: "pointer", + }, + currentCity: { + color: theme.colors.disabled, + lineHeight: "1em", + whiteSpace: "pre", + }, +})); function City(props: ICityProps): React.ReactElement { - const classes = useStyles(); + const { classes } = useStyles(); if (props.city !== props.currentCity) { return ( {props.city}}> From 3afafe4454f2dea00d59133f5576fc51ced83ef8 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Tue, 4 Jun 2024 09:49:23 -0400 Subject: [PATCH 08/43] SLEEVE: Editorial followup on #1314 (#1347) --- src/NetscriptFunctions/Sleeve.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/NetscriptFunctions/Sleeve.ts b/src/NetscriptFunctions/Sleeve.ts index 144cb3938..253a09d3b 100644 --- a/src/NetscriptFunctions/Sleeve.ts +++ b/src/NetscriptFunctions/Sleeve.ts @@ -3,7 +3,7 @@ import type { Sleeve as NetscriptSleeve } from "@nsdefs"; import type { ActionIdentifier } from "../Bladeburner/Types"; import { Player } from "@player"; -import { BladeActionType } from "@enums"; +import { BladeActionType, type BladeContractName } from "@enums"; import { Augmentations } from "../Augmentation/Augmentations"; import { findCrime } from "../Crime/CrimeHelpers"; import { getEnumHelper } from "../utils/EnumHelper"; @@ -238,24 +238,23 @@ export function NetscriptSleeve(): InternalAPI { const action = helpers.string(ctx, "action", _action); checkSleeveAPIAccess(ctx); checkSleeveNumber(ctx, sleeveNumber); - let contractName = undefined; + let contract: BladeContractName | undefined = undefined; if (action === "Take on contracts") { - const contractEnum = getEnumHelper("BladeContractName").nsGetMember(ctx, _contract); - contractName = helpers.string(ctx, "contract", _contract); + contract = getEnumHelper("BladeContractName").nsGetMember(ctx, _contract); for (let i = 0; i < Player.sleeves.length; ++i) { if (i === sleeveNumber) continue; const otherWork = Player.sleeves[i].currentWork; - if (otherWork?.type === SleeveWorkType.BLADEBURNER && otherWork.actionId.name === contractEnum) { + if (otherWork?.type === SleeveWorkType.BLADEBURNER && otherWork.actionId.name === contract) { throw helpers.errorMessage( ctx, `Sleeve ${sleeveNumber} cannot take on contracts because Sleeve ${i} is already performing that action.`, ); } } - const actionId: ActionIdentifier = { type: BladeActionType.contract, name: contractEnum }; + const actionId: ActionIdentifier = { type: BladeActionType.contract, name: contract }; Player.sleeves[sleeveNumber].startWork(new SleeveBladeburnerWork({ actionId })); } - return Player.sleeves[sleeveNumber].bladeburner(action, contractName); + return Player.sleeves[sleeveNumber].bladeburner(action, contract); }, }; From 101914b660862a05b3a77f698ddce28e5e6f35f9 Mon Sep 17 00:00:00 2001 From: TheAimMan <147098375+TheAimMan@users.noreply.github.com> Date: Tue, 4 Jun 2024 09:50:28 -0400 Subject: [PATCH 09/43] MISC: Add a potential of more than 1 core for initial servers (#963) --- src/Server/AllServers.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Server/AllServers.ts b/src/Server/AllServers.ts index 5aa915a35..ec956ec27 100644 --- a/src/Server/AllServers.ts +++ b/src/Server/AllServers.ts @@ -154,6 +154,12 @@ export function initForeignServers(homeComputer: Server): void { if (metadata.serverGrowth) serverParams.serverGrowth = toNumber(metadata.serverGrowth); const server = new Server(serverParams); + + if (metadata.networkLayer) { + const layer = toNumber(metadata.networkLayer); + server.cpuCores = getRandomIntInclusive(Math.ceil(layer / 2), layer); + } + for (const filename of metadata.literature || []) { server.messages.push(filename); } From 18ae6ce215786d2bf7e0c33838092bd5e0986237 Mon Sep 17 00:00:00 2001 From: Snarling <84951833+Snarling@users.noreply.github.com> Date: Tue, 4 Jun 2024 10:21:44 -0400 Subject: [PATCH 10/43] Changelog update --- src/Constants.ts | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/src/Constants.ts b/src/Constants.ts index c19f82bd2..c9feb193f 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -158,12 +158,48 @@ export const CONSTANTS: { // Also update doc/source/changelog.rst LatestUpdate: ` -## v2.6.2 dev - Last update 2 June 2024 +## v2.6.2 dev - Last update 4 June 2024 See 2.6.1 changelog at https://github.com/bitburner-official/bitburner-src/blob/v2.6.1/src/Documentation/doc/changelog.md -### HOTFIX (changes also added to 2.6.1 post release) +### CHANGES -- Fixed an issue with invalid format on steam cloud save (@catloversg) +- Hotfix (also backported to 2.6.1): Fixed an issue with invalid format on steam cloud save (@catloversg) +- Augmentations: Adjusted handling of augmentations that affect starting money or programs (@jjclark1982) +- Coding Contracts: Improved the performance of the All Valid Math Expressions contract checker (@yichizhng) +- Coding Contracts: Simplified the Shortest Path contract checker (@gmcew) +- Coding Contracts: Clarification on HammingCodes: Encoded Binary to Integer description (@gmcew) +- Faction: Fixed some edge cases around Favor overflow (@catloversg) +- Faction Invites: Code refactoring, all available invites are sent at once (@catloversg) +- Faction UI: show which skills are relevant for each type of Faction work (@gmcew) +- Font: Embedded the JetBrains Mono font as "JetBrainsMono" (@catloversg) +- Go: Support playing manually as white against your own scripts (@ficocelliguy) +- Go: Save a full game history to prevent repeat moves (@ficocelliguy) +- Infiltration: Updated Slash game text to be less confusing (@catloversg) +- Netscript API docs: Fixed some invalid usage issues + general type improvements (@catloversg, @ficocelliguy) +- Programs UI: Changed time elapsed display to time left (@TheAimMan) +- Servers: Game servers can now start with more than 1 core (@TheAimMan) +- Scripts: Relative imports should now work correctly (@Caldwell-74) +- Script Editor: Improved detection of possible infinite loops (@G4mingJon4s) +- Script Editor: should now remember cursor location when switching tabs or game pages (@catloversg) +- Skill XP: Fix an issue where in some cases, too much experience was needed to raise a skill from 1 to 2 (@catloversg) +- Terminal: Improved autocompletion code for mixed case strings (@yichizhng) +- Codebase: Partial migration away from outdated mui/styles (@Caldwell-74) + +### SPOILER CHANGES + +- Bladeburner: Added a button to stop the current action (@Kelenius) +- Bladeburner UI: Display Black Operations in the expected order (@catloversg) +- Corporation: Allow mass discarding products by selling for 0 (@gmcew) +- Grafting: Fixed a spacing issue (@Sphyxis) +- Grafting/Hacknet: Fixed an issue that could cause hacknet node production to be inaccurrate when combined with Grafting (@catloversg) +- Grafting: Fixed an issue that could cause inaccurate HP after Grafting (@catloversg) +- Hashnet: Clarified effect of hacknet multipliers in in documentation (@catloversg) +- Sleeve: Sleeve travel can no longer be performed if the player has insufficient funds (@gmcew) +- Sleeve: Added a missing availability check when installing augmentations on Sleeves (@yichizhng) +- Sleeve API: Fix an issue in ns.sleeve.setToBladeburnerAction that prevented setting sleeves to contract work (@Sphyxis) + +### OTHER +- Nerf noodle bar `, }; From c42d4143c911d8667c57f11beb4c96b3ec87c04f Mon Sep 17 00:00:00 2001 From: Caldwell <115591472+Caldwell-74@users.noreply.github.com> Date: Wed, 5 Jun 2024 03:19:41 +0200 Subject: [PATCH 11/43] BUGFIX: clamp Hackchance to prevent infinity / infinity (#1349) --- src/Hacking.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Hacking.ts b/src/Hacking.ts index 54cdca136..2d6c7d25c 100644 --- a/src/Hacking.ts +++ b/src/Hacking.ts @@ -2,6 +2,7 @@ import { currentNodeMults } from "./BitNode/BitNodeMultipliers"; import { Person as IPerson } from "@nsdefs"; import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence"; import { Server as IServer } from "@nsdefs"; +import { clampNumber } from "./utils/helpers/clampNumber"; /** Returns the chance the person has to successfully hack a server */ export function calculateHackingChance(server: IServer, person: IPerson): number { @@ -11,14 +12,14 @@ export function calculateHackingChance(server: IServer, person: IPerson): number if (!server.hasAdminRights || hackDifficulty >= 100) return 0; const hackFactor = 1.75; const difficultyMult = (100 - hackDifficulty) / 100; - const skillMult = hackFactor * person.skills.hacking; + const skillMult = clampNumber(hackFactor * person.skills.hacking, 1); const skillChance = (skillMult - requiredHackingSkill) / skillMult; const chance = skillChance * difficultyMult * person.mults.hacking_chance * calculateIntelligenceBonus(person.skills.intelligence, 1); - return Math.min(1, Math.max(chance, 0)); + return clampNumber(chance, 0, 1); } /** From 2316bf5b69bbe6bd96b51eebd0dc336c6c5d2a8f Mon Sep 17 00:00:00 2001 From: Caldwell <115591472+Caldwell-74@users.noreply.github.com> Date: Wed, 5 Jun 2024 03:20:43 +0200 Subject: [PATCH 12/43] BUGFIX: clamp bitnode mults (#1350) --- src/BitNode/BitNodeMultipliers.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/BitNode/BitNodeMultipliers.ts b/src/BitNode/BitNodeMultipliers.ts index eb2a98219..277b8dbe6 100644 --- a/src/BitNode/BitNodeMultipliers.ts +++ b/src/BitNode/BitNodeMultipliers.ts @@ -1,5 +1,5 @@ import { PartialRecord, getRecordEntries } from "../Types/Record"; - +import { clampNumber } from "../utils/helpers/clampNumber"; /** * Bitnode multipliers influence the difficulty of different aspects of the game. * Each Bitnode has a different theme/strategy to achieving the end goal, so these multipliers will can help drive the @@ -173,7 +173,7 @@ export class BitNodeMultipliers { CorporationDivisions = 1; constructor(a: PartialRecord = {}) { - for (const [key, value] of getRecordEntries(a)) this[key] = value; + for (const [key, value] of getRecordEntries(a)) this[key] = clampNumber(value); } } From 7321d6438344d15ed4536426ebab219bb3eeb94d Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Wed, 5 Jun 2024 08:32:24 +0700 Subject: [PATCH 13/43] BUGFIX: Fix manual hack exploit (#1324) Formula is updated to be still relevant, but not crushing --- src/Constants.ts | 2 -- src/Terminal/Terminal.ts | 6 ++++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Constants.ts b/src/Constants.ts index c9feb193f..15337bfde 100644 --- a/src/Constants.ts +++ b/src/Constants.ts @@ -24,7 +24,6 @@ export const CONSTANTS: { IntelligenceCrimeBaseExpGain: number; IntelligenceProgramBaseExpGain: number; IntelligenceGraftBaseExpGain: number; - IntelligenceTerminalHackBaseExpGain: number; IntelligenceSingFnBaseExpGain: number; MillisecondsPer20Hours: number; GameCyclesPer20Hours: number; @@ -101,7 +100,6 @@ export const CONSTANTS: { IntelligenceCrimeBaseExpGain: 0.05, IntelligenceProgramBaseExpGain: 0.1, // Program required hack level divided by this to determine int exp gain IntelligenceGraftBaseExpGain: 0.05, - IntelligenceTerminalHackBaseExpGain: 200, // Hacking exp divided by this to determine int exp gain IntelligenceSingFnBaseExpGain: 1.5, // Time-related constants diff --git a/src/Terminal/Terminal.ts b/src/Terminal/Terminal.ts index d37411fb0..bf6716a6f 100644 --- a/src/Terminal/Terminal.ts +++ b/src/Terminal/Terminal.ts @@ -211,7 +211,7 @@ export class Terminal { Router.toPage(Page.BitVerse, { flume: false, quick: false }); return; } - // Manunally check for faction invites + // Manually check for faction invitations Engine.Counters.checkFactionInvitations = 0; Engine.checkCounters(); @@ -225,7 +225,9 @@ export class Terminal { server.moneyAvailable -= moneyGained; Player.gainMoney(moneyGained, "hacking"); Player.gainHackingExp(expGainedOnSuccess); - Player.gainIntelligenceExp(expGainedOnSuccess / CONSTANTS.IntelligenceTerminalHackBaseExpGain); + if (expGainedOnSuccess > 1) { + Player.gainIntelligenceExp(4 * Math.log10(expGainedOnSuccess)); + } const oldSec = server.hackDifficulty; server.fortify(ServerConstants.ServerFortifyAmount); From 5f6a5c8785253cda1226b5e4b81b9a8c52eb0aaf Mon Sep 17 00:00:00 2001 From: Michael Ficocelli Date: Tue, 4 Jun 2024 21:37:00 -0400 Subject: [PATCH 14/43] IPVGO: Fix non-async promise-returning methods to be more consistent (#1327) --- src/Go/effects/netscriptGoImplementation.ts | 27 +++++++++------------ src/NetscriptFunctions/Go.ts | 4 +-- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/Go/effects/netscriptGoImplementation.ts b/src/Go/effects/netscriptGoImplementation.ts index f11953824..f4bf6503d 100644 --- a/src/Go/effects/netscriptGoImplementation.ts +++ b/src/Go/effects/netscriptGoImplementation.ts @@ -11,7 +11,7 @@ import { getPreviousMove, simpleBoardFromBoard, } from "../boardAnalysis/boardAnalysis"; -import { getOpponentStats, getScore, resetWinstreak } from "../boardAnalysis/scoring"; +import { endGoGame, getOpponentStats, getScore, resetWinstreak } from "../boardAnalysis/scoring"; import { WHRNG } from "../../Casino/RNG"; import { getRecordKeys } from "../../Types/Record"; import { CalculateEffect, getEffectTypeForFaction } from "./effect"; @@ -337,30 +337,27 @@ export async function determineCheatSuccess( ): Promise { const state = Go.currentGame; const rng = new WHRNG(Player.totalPlaytime); + state.passCount = 0; + // If cheat is successful, run callback if ((successRngOverride ?? rng.random()) <= cheatSuccessChance(state.cheatCount)) { callback(); - state.cheatCount++; GoEvents.emit(); - return makeAIMove(state); } // If there have been prior cheat attempts, and the cheat fails, there is a 10% chance of instantly losing else if (state.cheatCount && (ejectRngOverride ?? rng.random()) < 0.1) { logger(`Cheat failed! You have been ejected from the subnet.`); - resetBoardState(logger, logger, state.ai, state.board[0].length); - return { - type: GoPlayType.gameOver, - x: null, - y: null, - }; + endGoGame(state); + return Go.nextTurn; } // If the cheat fails, your turn is skipped else { logger(`Cheat failed. Your turn has been skipped.`); passTurn(state, GoColor.black, false); - state.cheatCount++; - return makeAIMove(state); } + + state.cheatCount++; + return makeAIMove(state); } /** @@ -395,7 +392,7 @@ export function cheatRemoveRouter( y: number, successRngOverride?: number, ejectRngOverride?: number, -) { +): Promise { const point = Go.currentGame.board[x][y]!; return determineCheatSuccess( logger, @@ -421,7 +418,7 @@ export function cheatPlayTwoMoves( y2: number, successRngOverride?: number, ejectRngOverride?: number, -) { +): Promise { const point1 = Go.currentGame.board[x1][y1]!; const point2 = Go.currentGame.board[x2][y2]!; @@ -446,7 +443,7 @@ export function cheatRepairOfflineNode( y: number, successRngOverride?: number, ejectRngOverride?: number, -) { +): Promise { return determineCheatSuccess( logger, () => { @@ -472,7 +469,7 @@ export function cheatDestroyNode( y: number, successRngOverride?: number, ejectRngOverride?: number, -) { +): Promise { return determineCheatSuccess( logger, () => { diff --git a/src/NetscriptFunctions/Go.ts b/src/NetscriptFunctions/Go.ts index 9a76c7e17..91f379c5f 100644 --- a/src/NetscriptFunctions/Go.ts +++ b/src/NetscriptFunctions/Go.ts @@ -47,11 +47,11 @@ export function NetscriptGo(): InternalAPI { validateMove(error(ctx), x, y, "makeMove"); return makePlayerMove(logger(ctx), error(ctx), x, y); }, - passTurn: (ctx: NetscriptContext) => (): Promise => { + passTurn: (ctx: NetscriptContext) => async (): Promise => { validateTurn(error(ctx), "passTurn()"); return handlePassTurn(logger(ctx)); }, - opponentNextTurn: (ctx: NetscriptContext) => (_logOpponentMove) => { + opponentNextTurn: (ctx: NetscriptContext) => async (_logOpponentMove) => { const logOpponentMove = typeof _logOpponentMove === "boolean" ? _logOpponentMove : true; return getOpponentNextMove(logOpponentMove, logger(ctx)); }, From bd5c502f530c764a89610403452cc70e13089e99 Mon Sep 17 00:00:00 2001 From: Michael Ficocelli Date: Tue, 4 Jun 2024 21:43:29 -0400 Subject: [PATCH 15/43] IPVGO: Support bonus cycles from offline time (#1345) --- src/Go/Go.ts | 11 ++++++++++ src/Go/SaveLoad.ts | 11 ++++++++++ src/Go/boardAnalysis/goAI.ts | 20 +++++++++++++++---- src/engine.tsx | 3 +++ test/jest/__snapshots__/FullSave.test.ts.snap | 1 + 5 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/Go/Go.ts b/src/Go/Go.ts index a8ba1c012..ad91cf3d5 100644 --- a/src/Go/Go.ts +++ b/src/Go/Go.ts @@ -11,6 +11,7 @@ export class GoObject { currentGame: BoardState = getNewBoardState(7); stats: PartialRecord = {}; nextTurn: Promise = Promise.resolve({ type: GoPlayType.gameOver, x: null, y: null }); + storedCycles: number = 0; prestigeAugmentation() { for (const stats of getRecordValues(this.stats)) { @@ -24,6 +25,16 @@ export class GoObject { this.currentGame = getNewBoardState(7); this.stats = {}; } + + /** + * Stores offline time that is consumed to speed up the AI. + * Only stores offline time if the player has actually been using the mechanic. + */ + storeCycles(offlineCycles: number) { + if (this.previousGame) { + this.storedCycles += offlineCycles ?? 0; + } + } } export const Go = new GoObject(); diff --git a/src/Go/SaveLoad.ts b/src/Go/SaveLoad.ts index b9d70d0ae..48f908124 100644 --- a/src/Go/SaveLoad.ts +++ b/src/Go/SaveLoad.ts @@ -21,6 +21,7 @@ type SaveFormat = { previousGame: PreviousGameSaveData; currentGame: CurrentGameSaveData; stats: PartialRecord; + storedCycles: number; }; export function getGoSave(): SaveFormat { @@ -40,6 +41,7 @@ export function getGoSave(): SaveFormat { passCount: Go.currentGame.passCount, }, stats: Go.stats, + storedCycles: Go.storedCycles, }; } @@ -78,6 +80,7 @@ export function loadGo(data: unknown): boolean { Go.currentGame = currentGame; Go.previousGame = previousGame; Go.stats = stats; + Go.storeCycles(loadStoredCycles(parsedData.storedCycles)); // If it's the AI's turn, initiate their turn, which will populate nextTurn if (currentGame.previousPlayer === GoColor.black && currentGame.ai !== GoOpponent.none) makeAIMove(currentGame); @@ -178,3 +181,11 @@ function loadSimpleBoard(simpleBoard: unknown, requiredSize?: number): SimpleBoa } return simpleBoard; } + +function loadStoredCycles(storedCycles: unknown): number { + if (!storedCycles || isNaN(+storedCycles)) { + return 0; + } + + return +storedCycles; +} diff --git a/src/Go/boardAnalysis/goAI.ts b/src/Go/boardAnalysis/goAI.ts index e4d0198fb..232153516 100644 --- a/src/Go/boardAnalysis/goAI.ts +++ b/src/Go/boardAnalysis/goAI.ts @@ -57,7 +57,7 @@ export function makeAIMove(boardState: BoardState): Promise { } // Handle AI making a move - await sleep(500); + await waitCycle(); const aiUpdatedBoard = makeMove(boardState, play.x, play.y, GoColor.white); // Handle the AI breaking. This shouldn't ever happen. @@ -114,7 +114,7 @@ export async function getMove( opponent: GoOpponent, rngOverride?: number, ): Promise { - await sleep(300); + await waitCycle(); const rng = new WHRNG(rngOverride || Player.totalPlaytime); const smart = isSmart(opponent, rng.random()); const moves = getMoveOptions(boardState, player, rng.random(), smart); @@ -142,9 +142,9 @@ export async function getMove( .filter((point) => evaluateIfMoveIsValid(boardState, point.x, point.y, player, false)); const chosenMove = moveOptions[Math.floor(rng.random() * moveOptions.length)]; + await waitCycle(); if (chosenMove) { - await sleep(200); //console.debug(`Non-priority move chosen: ${chosenMove.x} ${chosenMove.y}`); return { type: GoPlayType.move, x: chosenMove.x, y: chosenMove.y }; } @@ -786,7 +786,7 @@ function getMoveOptions( }; async function retrieveMoveOption(id: keyof typeof moveOptions): Promise { - await sleep(100); + await waitCycle(); if (moveOptions[id] !== undefined) { return moveOptions[id] ?? null; } @@ -813,6 +813,18 @@ export function sleep(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); } +/** + * Spend some time waiting to allow the UI & CSS to render smoothly + * If bonus time is available, significantly decrease the length of the wait + */ +function waitCycle(): Promise { + if (Go.storedCycles > 0) { + Go.storedCycles -= 1; + return sleep(40); + } + return sleep(200); +} + export function showWorldDemon() { return Player.hasAugmentation(AugmentationName.TheRedPill, true) && Player.sourceFileLvl(1); } diff --git a/src/engine.tsx b/src/engine.tsx index 554cf3c43..a68e6dc3b 100644 --- a/src/engine.tsx +++ b/src/engine.tsx @@ -44,6 +44,7 @@ import { setupUncaughtPromiseHandler } from "./UncaughtPromiseHandler"; import { Button, Typography } from "@mui/material"; import { SnackbarEvents } from "./ui/React/Snackbar"; import { SaveData } from "./types"; +import { Go } from "./Go/Go"; /** Game engine. Handles the main game loop. */ const Engine: { @@ -330,6 +331,8 @@ const Engine: { // Bladeburner offline progress if (Player.bladeburner) Player.bladeburner.storeCycles(numCyclesOffline); + Go.storeCycles(numCyclesOffline); + staneksGift.process(numCyclesOffline); // Sleeves offline progress diff --git a/test/jest/__snapshots__/FullSave.test.ts.snap b/test/jest/__snapshots__/FullSave.test.ts.snap index b6bb4ed06..5d8c7330e 100644 --- a/test/jest/__snapshots__/FullSave.test.ts.snap +++ b/test/jest/__snapshots__/FullSave.test.ts.snap @@ -45,6 +45,7 @@ exports[`Check Save File Continuity GoSave continuity 1`] = ` }, "previousGame": null, "stats": {}, + "storedCycles": 0, } `; From 653d531d0aaeac00c8d785a601d5c524a0940ade Mon Sep 17 00:00:00 2001 From: Kelenius Date: Thu, 6 Jun 2024 01:25:54 +0300 Subject: [PATCH 16/43] Remove sleeve message when quitting job from a script (#1357) --- src/NetscriptFunctions/Singularity.ts | 2 +- src/PersonObjects/Player/PlayerObjectGeneralMethods.ts | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/NetscriptFunctions/Singularity.ts b/src/NetscriptFunctions/Singularity.ts index 15935d562..e0628ceae 100644 --- a/src/NetscriptFunctions/Singularity.ts +++ b/src/NetscriptFunctions/Singularity.ts @@ -747,7 +747,7 @@ export function NetscriptSingularity(): InternalAPI { quitJob: (ctx) => (_companyName) => { helpers.checkSingularityAccess(ctx); const companyName = getEnumHelper("CompanyName").nsGetMember(ctx, _companyName); - Player.quitJob(companyName); + Player.quitJob(companyName, true); }, getCompanyRep: (ctx) => (_companyName) => { helpers.checkSingularityAccess(ctx); diff --git a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts index 91e41177b..62e45e4f9 100644 --- a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts @@ -361,14 +361,16 @@ export function getNextCompanyPosition( return pos; } -export function quitJob(this: PlayerObject, company: CompanyName): void { +export function quitJob(this: PlayerObject, company: CompanyName, suppressDialog?: boolean): void { if (isCompanyWork(this.currentWork) && this.currentWork.companyName === company) { this.finishWork(true); } for (const sleeve of this.sleeves) { if (sleeve.currentWork?.type === SleeveWorkType.COMPANY && sleeve.currentWork.companyName === company) { sleeve.stopWork(); - dialogBoxCreate(`You quit ${company} while one of your sleeves was working there. The sleeve is now idle.`); + if (!suppressDialog) { + dialogBoxCreate(`You quit ${company} while one of your sleeves was working there. The sleeve is now idle.`); + } } } delete this.jobs[company]; From d9e8161a64e8249230ab149dc15ca34df4836a1f Mon Sep 17 00:00:00 2001 From: Michael Ficocelli Date: Wed, 5 Jun 2024 18:27:27 -0400 Subject: [PATCH 17/43] IPVGO: Fix mismatch in board size options on save loader [save corruption bugfix] (#1355) --- src/Go/Constants.ts | 2 +- src/Go/ui/GoSubnetSearch.tsx | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Go/Constants.ts b/src/Go/Constants.ts index ff6a4e0a7..d0f6fb3de 100644 --- a/src/Go/Constants.ts +++ b/src/Go/Constants.ts @@ -68,7 +68,7 @@ export const opponentDetails = { }, }; -export const boardSizes = [5, 7, 9, 13]; +export const boardSizes = [5, 7, 9, 13, 19]; export const columnIndexes = "ABCDEFGHJKLMNOPQRSTUVWXYZ"; diff --git a/src/Go/ui/GoSubnetSearch.tsx b/src/Go/ui/GoSubnetSearch.tsx index 8853c09d6..40ad0be59 100644 --- a/src/Go/ui/GoSubnetSearch.tsx +++ b/src/Go/ui/GoSubnetSearch.tsx @@ -18,6 +18,7 @@ interface IProps { cancel: () => void; showInstructions: () => void; } +const boardSizeOptions = boardSizes.filter((size) => size !== 19); export const GoSubnetSearch = ({ open, search, cancel, showInstructions }: IProps): React.ReactElement => { const classes = boardStyles(); @@ -88,7 +89,7 @@ export const GoSubnetSearch = ({ open, search, cancel, showInstructions }: IProp ???? ) : ( + )} + {!this.showInput &&
    } + + {this.buffer} + + ); + } +} diff --git a/src/ScriptEditor/ui/useVimEditor.tsx b/src/ScriptEditor/ui/useVimEditor.tsx index 3157457b3..4ad98b809 100644 --- a/src/ScriptEditor/ui/useVimEditor.tsx +++ b/src/ScriptEditor/ui/useVimEditor.tsx @@ -4,10 +4,10 @@ import * as MonacoVim from "monaco-vim"; import type { editor } from "monaco-editor"; type IStandaloneCodeEditor = editor.IStandaloneCodeEditor; -import Box from "@mui/material/Box"; - import { Router } from "../../ui/GameRoot"; import { Page } from "../../ui/Router"; +import { StatusBar } from "./StatusBar"; +import { useRerender } from "../../ui/React/hooks"; interface IProps { vim: boolean; @@ -21,7 +21,8 @@ export function useVimEditor({ editor, vim, onOpenNextTab, onOpenPreviousTab, on // monaco-vim does not have types, so this is an any const [vimEditor, setVimEditor] = useState(null); - const vimStatusRef = useRef(null); + const statusBarRef = useRef(null); + const rerender = useRerender(); const actionsRef = useRef({ save: onSave, openNextTab: onOpenNextTab, openPreviousTab: onOpenPreviousTab }); actionsRef.current = { save: onSave, openNextTab: onOpenNextTab, openPreviousTab: onOpenPreviousTab }; @@ -31,7 +32,7 @@ export function useVimEditor({ editor, vim, onOpenNextTab, onOpenPreviousTab, on if (vim && editor && !vimEditor) { // Using try/catch because MonacoVim does not have types. try { - setVimEditor(MonacoVim.initVimMode(editor, vimStatusRef.current)); + setVimEditor(MonacoVim.initVimMode(editor, statusBarRef, StatusBar, rerender)); MonacoVim.VimMode.Vim.defineEx("write", "w", function () { // your own implementation on what you want to do when :w is pressed actionsRef.current.save(); @@ -40,6 +41,10 @@ export function useVimEditor({ editor, vim, onOpenNextTab, onOpenPreviousTab, on Router.toPage(Page.Terminal); }); + // Remove any macro recording, since it isn't supported. + MonacoVim.VimMode.Vim.mapCommand("q", "", "", null, { context: "normal" }); + MonacoVim.VimMode.Vim.mapCommand("@", "", "", null, { context: "normal" }); + const saveNQuit = (): void => { actionsRef.current.save(); Router.toPage(Page.Terminal); @@ -72,19 +77,7 @@ export function useVimEditor({ editor, vim, onOpenNextTab, onOpenPreviousTab, on return () => { vimEditor?.dispose(); }; - }, [vim, editor, vimEditor]); + }, [vim, editor, vimEditor, rerender]); - const VimStatus = ( - - ); - - return { VimStatus }; + return { statusBarRef }; } From 481938a2fbc9cdbb2aebc77edec4febfac4417c7 Mon Sep 17 00:00:00 2001 From: Michael Ficocelli Date: Wed, 5 Jun 2024 22:39:22 -0400 Subject: [PATCH 24/43] IPVGO: Balance and improvements for offline bonus time cycles (#1356) --- src/Go/boardAnalysis/goAI.ts | 59 +++++++++++++++++--------------- src/Go/ui/GoGameboardWrapper.tsx | 2 +- test/jest/Go/goAI.test.ts | 2 +- 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/src/Go/boardAnalysis/goAI.ts b/src/Go/boardAnalysis/goAI.ts index 232153516..ca929e6d5 100644 --- a/src/Go/boardAnalysis/goAI.ts +++ b/src/Go/boardAnalysis/goAI.ts @@ -28,7 +28,7 @@ let currentTurnResolver: (() => void) | null = null; /** * Retrieves a move from the current faction in response to the player's move */ -export function makeAIMove(boardState: BoardState): Promise { +export function makeAIMove(boardState: BoardState, useOfflineCycles = true): Promise { // If AI is already taking their turn, return the existing turn. if (isAiThinking) { return Go.nextTurn; @@ -43,31 +43,33 @@ export function makeAIMove(boardState: BoardState): Promise { } // If an AI is in use, find the faction's move in response, and resolve the Go.nextTurn promise once it is found and played. else { - Go.nextTurn = getMove(boardState, GoColor.white, Go.currentGame.ai).then(async (play): Promise => { - if (boardState !== Go.currentGame) return play; //Stale game + Go.nextTurn = getMove(boardState, GoColor.white, Go.currentGame.ai, useOfflineCycles).then( + async (play): Promise => { + if (boardState !== Go.currentGame) return play; //Stale game - // Handle AI passing - if (play.type === GoPlayType.pass) { - passTurn(boardState, GoColor.white); - // if passTurn called endGoGame, or the player has no valid moves left, the move should be shown as a game over - if (boardState.previousPlayer === null || !getAllValidMoves(boardState, GoColor.black).length) { - return { type: GoPlayType.gameOver, x: null, y: null }; + // Handle AI passing + if (play.type === GoPlayType.pass) { + passTurn(boardState, GoColor.white); + // if passTurn called endGoGame, or the player has no valid moves left, the move should be shown as a game over + if (boardState.previousPlayer === null || !getAllValidMoves(boardState, GoColor.black).length) { + return { type: GoPlayType.gameOver, x: null, y: null }; + } + return play; } + + // Handle AI making a move + await waitCycle(useOfflineCycles); + const aiUpdatedBoard = makeMove(boardState, play.x, play.y, GoColor.white); + + // Handle the AI breaking. This shouldn't ever happen. + if (!aiUpdatedBoard) { + boardState.previousPlayer = GoColor.white; + console.error(`Invalid AI move attempted: ${play.x}, ${play.y}. This should not happen.`); + } + return play; - } - - // Handle AI making a move - await waitCycle(); - const aiUpdatedBoard = makeMove(boardState, play.x, play.y, GoColor.white); - - // Handle the AI breaking. This shouldn't ever happen. - if (!aiUpdatedBoard) { - boardState.previousPlayer = GoColor.white; - console.error(`Invalid AI move attempted: ${play.x}, ${play.y}. This should not happen.`); - } - - return play; - }); + }, + ); } // Once the AI moves (or the player playing as white with No AI moves), @@ -112,9 +114,10 @@ export async function getMove( boardState: BoardState, player: GoColor, opponent: GoOpponent, + useOfflineCycles = true, rngOverride?: number, ): Promise { - await waitCycle(); + await waitCycle(useOfflineCycles); const rng = new WHRNG(rngOverride || Player.totalPlaytime); const smart = isSmart(opponent, rng.random()); const moves = getMoveOptions(boardState, player, rng.random(), smart); @@ -142,7 +145,7 @@ export async function getMove( .filter((point) => evaluateIfMoveIsValid(boardState, point.x, point.y, player, false)); const chosenMove = moveOptions[Math.floor(rng.random() * moveOptions.length)]; - await waitCycle(); + await waitCycle(useOfflineCycles); if (chosenMove) { //console.debug(`Non-priority move chosen: ${chosenMove.x} ${chosenMove.y}`); @@ -817,9 +820,9 @@ export function sleep(ms: number): Promise { * Spend some time waiting to allow the UI & CSS to render smoothly * If bonus time is available, significantly decrease the length of the wait */ -function waitCycle(): Promise { - if (Go.storedCycles > 0) { - Go.storedCycles -= 1; +function waitCycle(useOfflineCycles = true): Promise { + if (useOfflineCycles && Go.storedCycles > 0) { + Go.storedCycles -= 2; return sleep(40); } return sleep(200); diff --git a/src/Go/ui/GoGameboardWrapper.tsx b/src/Go/ui/GoGameboardWrapper.tsx index a89f6a6d1..92c7edc1a 100644 --- a/src/Go/ui/GoGameboardWrapper.tsx +++ b/src/Go/ui/GoGameboardWrapper.tsx @@ -115,7 +115,7 @@ export function GoGameboardWrapper({ showInstructions }: GoGameboardWrapperProps return; } - const move = await makeAIMove(boardState); + const move = await makeAIMove(boardState, false); if (move.type === GoPlayType.pass) { SnackbarEvents.emit(`The opponent passes their turn; It is now your turn to move.`, ToastVariant.WARNING, 4000); diff --git a/test/jest/Go/goAI.test.ts b/test/jest/Go/goAI.test.ts index 575d9bcda..0b4b9892e 100644 --- a/test/jest/Go/goAI.test.ts +++ b/test/jest/Go/goAI.test.ts @@ -31,7 +31,7 @@ describe("Go AI tests", () => { it("prioritizes eye creation moves for Illuminati", async () => { const board = ["...O...", "OOOO...", ".......", ".......", ".......", ".......", "......."]; const boardState = boardStateFromSimpleBoard(board, GoOpponent.Daedalus); - const move = await getMove(boardState, GoColor.white, GoOpponent.Daedalus, 0); + const move = await getMove(boardState, GoColor.white, GoOpponent.Daedalus, false, 0); expect([move.x, move.y]).toEqual([0, 1]); }); From 7b3cf4845344492756a7822b402de63dc5c07e02 Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Fri, 7 Jun 2024 13:10:16 +0700 Subject: [PATCH 25/43] CORPORATION: Refactor markup multiplier (#1362) --- src/Corporation/Division.ts | 32 ++++--------------- src/Corporation/helpers.ts | 23 +++++++++++++ .../optimal-selling-price-market-ta2.md | 11 ++++--- 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/Corporation/Division.ts b/src/Corporation/Division.ts index ebf00a409..124c58e79 100644 --- a/src/Corporation/Division.ts +++ b/src/Corporation/Division.ts @@ -15,6 +15,7 @@ import { JSONMap, JSONSet } from "../Types/Jsonable"; import { PartialRecord, getRecordEntries, getRecordKeys, getRecordValues } from "../Types/Record"; import { Material } from "./Material"; import { getKeyList } from "../utils/helpers/getKeyList"; +import { calculateMarkupMultiplier } from "./helpers"; interface DivisionParams { name: string; @@ -582,26 +583,13 @@ export class Division { } mat.uiMarketPrice = sCost; - // Calculate how much of the material sells (per second) - let markup = 1; - if (sCost > mat.marketPrice) { - //Penalty if difference between sCost and bCost is greater than markup limit - if (sCost - mat.marketPrice > markupLimit) { - markup = Math.pow(markupLimit / (sCost - mat.marketPrice), 2); - } - } else if (sCost < mat.marketPrice) { - if (sCost <= 0) { - markup = 1e12; //Sell everything, essentially discard - } else { - //Lower prices than market increases sales - markup = mat.marketPrice / sCost; - } - } + const markupMultiplier = calculateMarkupMultiplier(sCost, mat.marketPrice, markupLimit); + // Calculate how much of the material sells (per second) mat.maxSellPerCycle = (mat.quality + 0.001) * marketFactor * - markup * + markupMultiplier * businessFactor * corporation.getSalesMult() * advertisingFactor * @@ -920,21 +908,15 @@ export class Division { sCost = sellPrice; } product.uiMarketPrice[city] = sCost; - let markup = 1; - if (sCost > product.cityData[city].productionCost) { - if (sCost - product.cityData[city].productionCost > markupLimit) { - markup = markupLimit / (sCost - product.cityData[city].productionCost); - } - } else if (sCost <= 0) { - markup = 1e12; //Sell everything, essentially discard - as materials - } + + const markupMultiplier = calculateMarkupMultiplier(sCost, product.cityData[city].productionCost, markupLimit); product.maxSellAmount = 0.5 * Math.pow(product.cityData[city].effectiveRating, 0.65) * marketFactor * corporation.getSalesMult() * - Math.pow(markup, 2) * + markupMultiplier * businessFactor * advertisingFactor * this.getSalesMultiplier(); diff --git a/src/Corporation/helpers.ts b/src/Corporation/helpers.ts index b515cd67f..c9a431e11 100644 --- a/src/Corporation/helpers.ts +++ b/src/Corporation/helpers.ts @@ -88,3 +88,26 @@ export function issueNewSharesFailureReason(corp: Corporation, numShares: number return ""; } + +export function calculateMarkupMultiplier(sellingPrice: number, marketPrice: number, markupLimit: number): number { + // Sanitize sellingPrice + if (!Number.isFinite(sellingPrice)) { + return 1; + } + let markupMultiplier = 1; + if (sellingPrice > marketPrice) { + // markupMultiplier is a penalty modifier if sellingPrice is greater than the sum of marketPrice and markupLimit. + if (sellingPrice > marketPrice + markupLimit) { + markupMultiplier = Math.pow(markupLimit / (sellingPrice - marketPrice), 2); + } + } else { + if (sellingPrice <= 0) { + // Discard + markupMultiplier = 1e12; + } else { + // markupMultiplier is a bonus modifier if sellingPrice is less than marketPrice. + markupMultiplier = marketPrice / sellingPrice; + } + } + return markupMultiplier; +} diff --git a/src/Documentation/doc/advanced/corporation/optimal-selling-price-market-ta2.md b/src/Documentation/doc/advanced/corporation/optimal-selling-price-market-ta2.md index 25dde7b01..35a4b1db5 100644 --- a/src/Documentation/doc/advanced/corporation/optimal-selling-price-market-ta2.md +++ b/src/Documentation/doc/advanced/corporation/optimal-selling-price-market-ta2.md @@ -63,12 +63,13 @@ $$MarketFactor = Max\left(0.1,{Demand\ast(100 - Competition)}\ast{0.01}\right)$$ - Division's research bonus: this is always 1. Currently there is not any research that increases the sales bonus. - `MarkupMultiplier`: initialize with 1. - `SellingPrice` is the selling price that you set. - - With materials, if we set `SellingPrice` to 0, `MarkupMultiplier` is $10^{12}$ (check the formula below). Extremely high `MarkupMultiplier` means that we can sell all units, regardless of other factors. This is the fastest way to discard materials. - - If `(SellingPrice > MarketPrice + MarkupLimit)`: - $$MarkupMultiplier = \left(\frac{MarkupLimit}{SellingPrice - MarketPrice}\right)^{2}$$ - - If item is material and `SellingPrice` is less than `MarketPrice`: + - If we set `SellingPrice` to 0 or a negative number, `MarkupMultiplier` is $10^{12}$ (check the formula below). With an extremely high `MarkupMultiplier`, we can sell all units, regardless of other factors. This is the fastest way to discard stored units. + - If `(SellingPrice > MarketPrice)`: + - If `(SellingPrice > MarketPrice + MarkupLimit)`: + $$MarkupMultiplier = \left(\frac{MarkupLimit}{SellingPrice - MarketPrice}\right)^{2}$$ + - If `(SellingPrice <= MarketPrice)`: -$$MarkupMultiplier = \begin{cases}\frac{MarketPrice}{SellingPrice}, & SellingPrice > 0 \land SellingPrice < MarketPrice \newline 10^{12}, & SellingPrice \leq 0 \end{cases}$$ +$$MarkupMultiplier = \begin{cases}\frac{MarketPrice}{SellingPrice}, & SellingPrice > 0 \newline 10^{12}, & SellingPrice \leq 0 \end{cases}$$ ## Optimal selling price From e64247571d14ae733aefc91940a61efb801578fb Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Sat, 8 Jun 2024 03:15:46 +0700 Subject: [PATCH 26/43] IPVGO: Add missing space characters in API documentation (#1373) --- markdown/bitburner.go.getgamestate.md | 4 +++- markdown/bitburner.go.getmovehistory.md | 21 +++++++++++++++++++++ markdown/bitburner.go.md | 1 + src/ScriptEditor/NetscriptDefinitions.d.ts | 14 +++++++------- 4 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 markdown/bitburner.go.getmovehistory.md diff --git a/markdown/bitburner.go.getgamestate.md b/markdown/bitburner.go.getgamestate.md index 56bb4016e..494dd8349 100644 --- a/markdown/bitburner.go.getgamestate.md +++ b/markdown/bitburner.go.getgamestate.md @@ -14,9 +14,11 @@ getGameState(): { whiteScore: number; blackScore: number; previousMove: [number, number] | null; + komi: number; + bonusCycles: number; }; ``` **Returns:** -{ currentPlayer: "White" \| "Black" \| "None"; whiteScore: number; blackScore: number; previousMove: \[number, number\] \| null; } +{ currentPlayer: "White" \| "Black" \| "None"; whiteScore: number; blackScore: number; previousMove: \[number, number\] \| null; komi: number; bonusCycles: number; } diff --git a/markdown/bitburner.go.getmovehistory.md b/markdown/bitburner.go.getmovehistory.md new file mode 100644 index 000000000..93b4c45cb --- /dev/null +++ b/markdown/bitburner.go.getmovehistory.md @@ -0,0 +1,21 @@ + + +[Home](./index.md) > [bitburner](./bitburner.md) > [Go](./bitburner.go.md) > [getMoveHistory](./bitburner.go.getmovehistory.md) + +## Go.getMoveHistory() method + +Returns all the prior moves in the current game, as an array of simple board states. + +For example, a single 5x5 prior move board might look like this: + +\[
    "XX.O.",
    "X..OO",
    ".XO..",
    "XXO.\#",
    ".XO.\#",
    \] + +**Signature:** + +```typescript +getMoveHistory(): string[][]; +``` +**Returns:** + +string\[\]\[\] + diff --git a/markdown/bitburner.go.md b/markdown/bitburner.go.md index d477706a5..0a4b2c493 100644 --- a/markdown/bitburner.go.md +++ b/markdown/bitburner.go.md @@ -26,6 +26,7 @@ export interface Go | [getBoardState()](./bitburner.go.getboardstate.md) |

    Retrieves a simplified version of the board state. "X" represents black pieces, "O" white, and "." empty points. "\#" are dead nodes that are not part of the subnet. (They are not territory nor open nodes.)

    For example, a 5x5 board might look like this:

    \[
    "XX.O.",
    "X..OO",
    ".XO..",
    "XXO.\#",
    ".XO.\#",
    \]

    Each string represents a vertical column on the board, and each character in the string represents a point.

    Traditional notation for Go is e.g. "B,1" referring to second ("B") column, first rank. This is the equivalent of index \[1\]\[0\].

    Note that the \[0\]\[0\] point is shown on the bottom-left on the visual board (as is traditional), and each string represents a vertical column on the board. In other words, the printed example above can be understood to be rotated 90 degrees clockwise compared to the board UI as shown in the IPvGO subnet tab.

    | | [getCurrentPlayer()](./bitburner.go.getcurrentplayer.md) | Returns the color of the current player, or 'None' if the game is over. | | [getGameState()](./bitburner.go.getgamestate.md) | Gets the status of the current game. Shows the current player, current score, and the previous move coordinates. Previous move coordinates will be \[-1, -1\] for a pass, or if there are no prior moves. | +| [getMoveHistory()](./bitburner.go.getmovehistory.md) |

    Returns all the prior moves in the current game, as an array of simple board states.

    For example, a single 5x5 prior move board might look like this:

    \[
    "XX.O.",
    "X..OO",
    ".XO..",
    "XXO.\#",
    ".XO.\#",
    \]

    | | [getOpponent()](./bitburner.go.getopponent.md) | Returns the name of the opponent faction in the current subnet. | | [makeMove(x, y)](./bitburner.go.makemove.md) | Make a move on the IPvGO subnet gameboard, and await the opponent's response. x:0 y:0 represents the bottom-left corner of the board in the UI. | | [opponentNextTurn(logOpponentMove)](./bitburner.go.opponentnextturn.md) | Returns a promise that resolves with the success or failure state of your last move, and the AI's response, if applicable. x:0 y:0 represents the bottom-left corner of the board in the UI. | diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index 4d15d6695..bcfb207a2 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -4054,13 +4054,13 @@ export interface Go { * * For example, a single 5x5 prior move board might look like this: * - * [
    - * "XX.O.",
    - * "X..OO",
    - * ".XO..",
    - * "XXO.#",
    - * ".XO.#",
    - * ] + [
    + "XX.O.",
    + "X..OO",
    + ".XO..",
    + "XXO.#",
    + ".XO.#",
    + ] */ getMoveHistory(): string[][]; From e782b6fd7c84e324b75dc24a052671aa07dee116 Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Sat, 8 Jun 2024 03:20:18 +0700 Subject: [PATCH 27/43] DOCUMENTATION: Split changelog.md (#1374) --- src/Documentation/doc/changelog-v0.md | 2518 ++++++++++++++++++++ src/Documentation/doc/changelog-v1.md | 659 +++++ src/Documentation/doc/changelog.md | 3175 ------------------------- src/Documentation/doc/index.md | 2 + src/Documentation/pages.ts | 56 +- 5 files changed, 3209 insertions(+), 3201 deletions(-) create mode 100644 src/Documentation/doc/changelog-v0.md create mode 100644 src/Documentation/doc/changelog-v1.md diff --git a/src/Documentation/doc/changelog-v0.md b/src/Documentation/doc/changelog-v0.md new file mode 100644 index 000000000..10986aed3 --- /dev/null +++ b/src/Documentation/doc/changelog-v0.md @@ -0,0 +1,2518 @@ +# Changelog - Legacy v0 + +## v0.58.0 - 2021-10-27 Road to Steam (hydroflame & community) + +** Announcement ** + +- To prepare for Steam we will fix some inconsistencies in the Netscript API. Ideally we can also write a + save file migration that will automatically convert all breaking changes in your scripts without any + player input. + +** BREAKING (kindof) ** + +- All stock market functions are now under the 'stock' namespace, like 'hacknet' + However when you load your game with v0.58.0 for the first time it should automatically convert everything. + +** SF -1 ** + +- new SF -1: Reality Alteration + +** Gang ** + +- Ascension formula now better +- Karma requirement now much lower in most nodes +- Territory heavily penalizes gains +- T.R.P. not available outside BN2. + +** Netscript ** + +- It is no longer possible to send anything but strings or numbers to other scripts. (prevents exploits) +- Improve code for some netscript functions (@omuretsu) + +** Script Editor ** + +- Added Solarized light/dark as theme (@CalvinTrops) +- Fixed sleeve namespace smart autocomplete. + +** Hacknet Servers ** + +- Cores affect grow/weaken like they do on home computer + +** Infiltration ** + +- Slash game modified to be easier. + +** Misc. ** + +- Fix typo in corp (@Saynt_Garmo) +- Fixed a bug where corp wouldn't let you buyback shares. (@Saynt_Garmo) +- Fixed a bug where sleeves couldn't perform some crimes. (@Saynt_Garmo) +- Hospitalization and Eating noodles are now toasts (@Saynt_Garmo) +- Fixed some repeated code (@omuretsu) +- Fixed Character Overview preventing clicks underneath it even when hidden. (@omuretsu) +- Fixed typo in tutorial. (@omuretsu) +- Create Programs and Factions invitation badges now dissapear when you open their respective pages. +- Add killall script in character overview. +- Fixed bug in corp that made last city production be the production for all cities for newly created product. +- Fix bug that allowed reputation to transfer to new jobs. +- Fixed memory leak with ns2. +- nerf noodle bar + +## v0.57.0 - 2021-10-16 It was too cheap! (hydroflame & community) + +** BREAKING (kindof) ** + +- purchased server cost now scales exponentially past 2^10. + I'm going to actually explain this one: Currently the cost of a 2^20GB server is 57b + Most players can get that before their first install. In an effort to nerf good players + a softcap was added. This softcap is different for every BN. + +** Script Editor ** + +- Added a theme that is close to monokai. Unfortunately a full monokai is impossible because + Monaco doesn't have a very good tokenizer. +- Opening a file and connecting to a new server will still save the file on the server that the file + was opened. + +** Netscript ** + +- New function: alert, which creates a textbox. +- New function: toast, creates a notification in the bottom right. +- New function: upgradeHomeCores (@Saynt_Garmo) +- New function: atExit, allows you to set a callback for when the script closes. +- New kindof function: autocomplete, this allows you to tell the game what it should + autocomplete on the terminal. + +** Augmentation ** + +- ENM Core (the Augmentation from The Black Hand with the highest rep cost) rep cost + reduced from 250 to 175. This will help new players transition from TBH to BitRunners more easily. + +** Bladeburner ** + +- New general action: Incite Violence. This action adds other action counts but increases chaos. + +** Misc. ** + +- Current bladeburner action is shown on the character overview. +- Fix blackop being #000 on #000. +- The last clicked Tail Box goes in front of the others. +- Fixed an issue where some values were loaded as 0 when they should be null. +- Implemented toasts. +- .msg are no longer saved in the text file. +- Tail boxes no longer display all the args, they use "..." after 30 characters. +- Fixed cancelation penalty bonus not being properly applied after the IP <-> hostname switch. +- Fixed an exploit where you could send non-strings or numbers to other scripts. +- Fixed issue when trying to work for a faction with a work type that doesn't exist while + already working for that faction. +- Fixed not being able to work for the CIA. (Don't ask) +- nerf noodle bar + +## v0.56.0 - 2021-10-11 Trimming the backlog (hydroflame & community) + +** BREAKING ** + +- The 'write' function is now async. This helps when making scripts that write scripts. + +** Terminal ** + +- 'grow' and 'weaken' have been added as terminal command. This should help player transition + from commands to scripts. The tutorial also talks about it. +- 'cp' command added +- Improved performance by rate limiting refresh. + +** IP vs Hostname ** + +- The game now uses hostname as primary key for it's servers (yeah believe it or not IPs were + used until then). This has caused some issues with purchased servers (they couldn't be sold). + You might need to soft reset for the game to fully convert itself. + +** Sleeve ** + +- Fixed bug where they couldn't train at Volhaven. +- No longer consume all bonus time at once, making it look buggy. + +** SF9 ** + +- Now boosts hacknet production by 8/12/14% + +** Hacknet Servers ** + +- production nerfed by 10% +- Max money increase gets weaker above 10t max money + +** Corporation ** + +- Warehouse tooltip now also displays the amount of space taken by products. +- Changed research box completely to avoid dependency on Treant (Treant is a pita) +- All textbox should accept MAX/MP case insensitive. +- Fixed export popup not refreshing dropdowns correctly. +- Fixed product mku becoming zero +- Increased scaling of Wilson to avoid feedback loop. +- Can no longer get in debt by buying real estate +- Bonus time is consumed faster. + +** Netscript ** + +- isBusy takes bitverse and infiltration into account +- hospitalize can't be called when in infiltration. +- setToCommitCrime now accepts crime rough name instead of perfect name. +- disableLog All now works for bladeburner functions. +- Fixed netscript port for ns1. + +** Augmentation ** + +- Added augmentation to Ti Di Hui that removes penalty for being unfocused. +- Neuroflux no longer appears in special factions. + +** Script Editor ** + +- Ram check is debounced instead of refreshed every second. +- Added the vscode extension documentation to the game (it doesn't work well, thought) +- Fixed issue where autocomplete list would grow forever +- Added semi-monokai as theme. +- Fixed issue where modifying filename would mess it up. +- Font size can be changed now. + +** Infiltration ** + +- Fixed issue where game controls would become unfocused. + +** Misc. ** + +- Fixed loader incorrectly assuming some null values are incorrect. +- installBackdoor trigger Bitverse sequence +- Some improvements to the theme editor +- Improved documentation about where to learn javascript. +- Added some instructions for contributors. +- Fixed typo in corporation sell shares modal (@Saynt_Garmo) +- Fixed pagination being black on black in Active Scripts +- Create Script tab renamed to Script Editor +- Fixed an issue where corp some textbox wouldn't update when changing city. +- Fixed an issue where hacknet online time was always 0. +- Netscript function prompt fixed. +- Fixed miscalculation in growth. +- Script with syntax errors will try to be a tad more helpful. +- Corporations can no longer bribe bladeburners. +- Augmentation Graphene Branchiblade renamed to Brachi, like the rest of them. +- All ram is displayed in GB/TB/PB now. +- Game now saves when saving a file, this can be turned off. +- Several improvement to log window. +- Bladeburner current action returns General type instead of the name of the action. +- Bladeburner travel and Sleeve travel respect disable ASCII. +- Tutorial fits on small screens. +- Import is much slower but more consistent now. +- Fix intelligence not updating properly. +- Added SF -1: Time Compression +- ReadTheDoc theme now matches the game. +- Logbox should wrap text better +- Logbox behavior should feel better. +- Fix font for AutoLink.exe +- nerf noodle bar + +## v0.55.0 - 2021-09-20 Material UI (hydroflame & community) + +** Global ** + +- The game is now 100% in typescript, react, and Material-UI + +** Misc. ** + +- Corporations can no longer bribe special factions +- Infiltration can no longer lose focus of the keyboard. +- Fix terminal line limit +- Added theme editor +- Theme applies on game load (@Nolshine) +- Sleeves no longer consume all bonus time for some actions +- Fix a bug where the autocomlete list would get duplicates +- Fix tutorial not scaling properly on small screens +- Import should be more consistent +- Typo with 'help' command +- Fix infinite loop in casino +- nerf noodle bar + +## v0.54.0 - 2021-09-20 One big react node (hydroflame & community) + +** UI ** + +- The UI is now completely(ish) in react and I'm starting to implement + Material-UI everywhere. This will help make the game feel more consistent. +- Major help from (@threehams) +- New Terminal +- New Active Scripts page +- New sidebar. +- New Character overview +- New tutorial +- New options page +- New create program page (@Nolshine) + +** Netscript ** + +- Add companyName to getPlayer + +** Factions ** + +- Megacorp factions are no longer removed when installing. + +** Corporation ** + +- All research tooltips are always visible. +- Smart supply is enabled by default if purchased (@Nolshine) + +** Misc. ** + +- Fix "Game saved" animation. (@Nolshine) +- Update commitCrime documentation (@Tryneus) +- Fix logbox scrolling weird (@Nolshine) +- Fix weird scrolling in corporations (@BartKoppelmans) +- Fix typo (@BartKoppelmans & @Nolshine) +- Delete game now has a confirmation modal (@Nolshine) +- Fix issue where skills would not get properly updated when entering new + BN. (@Nolshine) +- Convert create gang to popup (@vmesecher) +- Fixed a bug that prevented travel to Sector-12 and New Tokyo when not using + ASCII art. +- nerf noodle bar + +## v0.53.0 - 2021-09-09 Way too many things. (hydroflame & community) + +** Dev? ** + +- The entire codebase has been run through a code prettifier, hurray for consistency. (@threehams) +- Lots of test. (@threehams) +- Massive improvements to build speed. (@threehams) +- Dev notes: This won't affect any players but is immensely useful for me. + +** Hacknet ** + +- Converted to ts/react + +** Resleeving ** + +- Converted to ts/react + +** Sleeves ** + +- Converted to ts/react. The ui should also have a better feel. +- Fixed a bug that allowed players to recover shock much faster than intended. + +** BN10 ** + +- You have access to Sleeves right away +- In BN10 Sleeves start with 75 shock and 25 sync. + +** MathJax ** + +- Several tooltips have been updated to display the relevant formula in Mathjax, e.g. Favor and reputation + +** Corporation ** + +- Completely rewritten in React. Paving the way for bigger change. +- Smart Supply is now smarter and won't deadlock the warehouse. It is also more configurable. +- Several UI fixes. + +** Bladeburner ** + +- Action count is no longer decided when joining the Bladeburners. Experiences for all players should be more similar. + +** Factions ** + +- No factions have home computer ram requirement. This caused some confusion for new players. + +** Gang ** + +- Made it clear when there's a new equipment coming up. + +** Netscript ** + +- getActionCountRemaining now returns Infinity for bladeburner general actions. (@brubsy) +- getActionEstimatedSuccessChance now returns 100% for Diplomacy and Hyperbolic Regeneration Chamber. (@brubsy) +- disableLog('ALL') now disables all logs individually, meaning you can re-enable the ones you want after. (@Cass) +- getPlayer returns numPeopleKilled. +- Dynamic RAM calculation errors have a better error message. +- Hide some functions from autocomplete. +- Added getAugmentationPrice, getAugmentationRepReq, deprecated getAugmentationCost. (@TempFound) +- Fixed bug where some crime API would return "assassinate" when that's not accepted in other functions. + +** Coding Contract ** + +- Spiralize Matrix is easier to read. + +** Misc. ** + +- The world map is now used in sleeve travel and bladeburner travel. +- noselect a bunch of stuff. +- Ascii maps letters are more contrasting +- Updated documentation for infiltration. +- Most money costs in the game will turn grey/cyan when you don't have enough money. +- Donation textbox has better look & feel. +- Tech vendors ram & cores buttons have better look and feels. +- cores cost modified to be a formula instead of a semi-random array of numbers. +- Tech vendors now give a hint about where to get bigger servers. +- logboxes now displays whitespaces exactly. (@Cass) +- nerf noodle bar + +## v0.52.9 - 2021-08-27 Less lag! (hydroflame & community) + +** Active Scripts page ** + +- Now less laggy, has pagination. + +** File diagnostic ** + +- Added a popup found under options that shows the files you own and how + large they are. This help find bugs and leftover massive logs files. + +** Corporation ** + +- Added safeguard against a very specific bug that causes NaN money. I'm + still not sure what the root cause is but it should prevent corp from + breaking. + +** Netscript ** + +- tprintf is a new function that doesn't print the filename. + +** Misc. ** + +- Infiltration kills you if you try to automate it. (@threehams) +- Fix beautify button not working +- Added bladeburner_analysis_mult to getPlayer() (@brubsby) +- Fixed joining bladeburner via netscript functions. (@omuretsu) +- All bladeburner actions are click-to-copy +- nerf noodle bar + +## v0.52.8 - 2021-08-23 Fixing the previous patch tbh ROUND 2 (hydroflame) + +** Script editor ** + +- Correctly reloads old script when clicking "Script Editor" +- No longer jumps to the end of the text for no reason. + +** Hash upgrades ** + +- Fixed an issue where the default option would say ecorp but was really + foodnstuff + +** Misc. ** + +- The "Delete all active script" button under the options has a clearer + description. +- Removed some debug console.log +- nerf noodle bar + +## v0.52.7 - 2021-08-21 Fixing the previous patch tbh (hydroflame) + +** Netscript ** + +- API BREAKING CHANGE: getActionEstimatedSuccessChance now returns a pair of + value to reflect the UI changes. I'm very sorry. + +** Bladeburner ** + +- General actions now display time required. +- Recruitment now displays success chance. +- All other success chance now display a range instead of a single value + The real value is guaranteed to be within that range. + +** Misc. ** + +- Fix tutorial not working after Monaco upate +- Fix logbox logs not taking up the whole logbox +- Fix script editor shortcut (ctrl+b) +- Fix Corporation popup appearing in the wrong order, hiding one of them +- Fix error when loading Corp +- Fix logbox dragging (smoother now) +- Fix logbox name collision +- Fix logbox allowing to open the same box multiple times +- Fix netscript write. +- nerf noodle bar + +## v0.52.6 - 2021-08-21 Logboxes and VS-code (hydroflame) + +** Text Editor ** + +- Ace and Codemirror have been removed in favor of monaco (web version of + vs-code). The options are a bit lackluster but more will be added as + feedback comes. + +** Log boxes ** + +- Multiple log boxes can be opened at once. They can be moved around the + screen. (but the movement behavior is a bit weird.) + +** Misc. ** + +- Job promotion now correctly updates the UI. +- Milestones now call the faction CyberSec instead of CSEC +- Can no longer create file that break the filesystem. +- Remove dollar sign in blade contract UI element +- nerf noodle bar + +## v0.52.5 - 2021-08-19 CPU cores are useful!? (hydroflame) + +** Terminal ** + +- When executing 'run SCRIPT' any script can now add '--tail' to + automatically bring up the logs. + +** Netscript ** + +- The 'flags' function now works with single letter flags but they only take + one dash. +- Fix several broken bladeburner netscript functions. +- Fix gang.getMemberInformation returning inconsistent data after the gang + rework. + +** CPU Cores ** + +- CPU Cores on the home computer now provide a bonus to grow() money gain + and makes weaken lower more security. Only for scripts running on 'home' + +** Misc. ** + +- Fix weird scrolling in the new Bladeburner React console. +- nerf noodle bar + +## v0.52.4 - 2021-08-19 Bladeburner in React (hydroflame) + +** Bladeburner ** + +- The entire UI was rebuild in React. It should be more responsive + +** Hacknet ** + +- Displays how many time each hash upgrade was bought. +- Displays cummulative effect of the upgrade. +- Removed "Close" button from hash upgrade menu. + +** Misc. ** + +- More popup/modals have dark background, can be dismissed by clicking + outside, or by pressing escape. +- Small reword in the guide. +- Fix several typos in the bladeburner documentation. +- Linting (no one cares except the dev) +- nerf noodle bar + +## v0.52.3 - 2021-08-15 Gangs were OP (hydroflame) + +** Gang ** + +- Significant rework. Ascension is now based on exp gained. +- All upgrades give exp bonuses. +- Maximum gang members reduced to 12. +- Respect required to recruit sharply increased. +- Rewritten in React, the UI should be smoother and less laggy now. + +** Infiltration ** + +- Now isTrusted protected. + +** Misc. ** + +- Many UI element are now "noselect" protected. +- Fixed an issue where you could join the same faction twice via script and + UI simultaneously. +- Factions list screen converted to React. +- nerf noodle bar + +## v0.52.2 - 2021-08-15 Oh yeah, BN11 is a thing (drunk hydroflame tbh) + +** Source-Files ** + +- Source-File 11 now also provides a small reduction to the price increase + multiplier. + +** Augmentations ** + +- New Augmentation offered by Aevum, themed around 777 and offers some basic + programs. +- Augmentation descriptions are now more concise and consistent. + +** Misc. ** + +- nerf noodle bar + +## v0.52.1 - 2021-08-10 bugfixing (hydroflame & community) + +** Misc. ** + +- Fix game crash/corruption when quitting a job while working for it unfocused. +- Fix typo in corporation Market Data. +- Fix typo in docs for hackPercent. +- The tutorial encourages the players to connect to home before creating `n00dles.script` +- The dark web `buy` command now accepts `-1` (one) and `--list` instead of just `-l`. Helps some confused players. +- Character overview screen no longer hidden on the corporation screen. +- Infiltration difficulty display is now more explicit (It's a big arrow instead of just one word.) +- Fix wrong ram value in tutorial. (@MageKing17) +- Plenty of augmentation description cleanup (@Kwazygloo) +- Plenty of typo/description fixed (@MageKing17) +- Cleanup description of singularity function on readthedocs (@PurePandemonium) +- Fix bug when autolinking a server while backdooring (@schroederIT) +- nerf noodle bar + +## v0.52.0 - 2021-06-13 Infiltration 2.0 (hydroflame & community) + +**Infiltration** + +- Completely reworked. Not the same mechanic at all. + +**Terminal** + +- tail is smarter. It automatically assume the only possible options in some + cases. + +**Intelligence** + +- Now available when starting BN5 instead of after beating it for the first + time. +- Nerf the effect of intelligence on reputation gain. + +**Augmentation** + +- Added a new augmentation, the 'Unstable Circadian Modulator', whose + gimmick is that its stats are randomized every hour. + +**Netscript** + +- 'getPlayer' is not a singularity function anymore. +- 'hacknetNodes.constants' returns the correct values. +- 'createGang' has been added. +- 'inGang' has been added. + +**Tutorial** + +- Updated the tutorial. Made it look cleaner, fixed typos, etc. + +**Misc.** + +- Fix many typos in literature (@kwazygloo) +- Fix being able to unfocus from gym and university. +- Fix being able to do hacking missions while unfocused. +- Fix many typos in Augmentation descriptions (@kwazygloo) +- More numbers handle absurdly large values. (@Tesseract1234567890) +- Fix many typos (@Tesseract1234567890) +- Fixed an issue that caused a UI desync when sleeves were set to workout + stats other than strength at the gym. +- Fix weird alignment of donation text box and button. (@Tesseract1234567890) +- Fixed an issue where reputation could be transfered to new jobs when unfocused. +- Empty stack traces should no longer appear. +- Purchasing anything with Infinity money doesn't result in NaN. +- nerf noodle bar + +## v0.51.10 - 2021-05-31 Focus Mark, Focus! (hydroflame) + +**Focus** + +- You can now use the terminal and write scripts while working for factions + but you will gain reputation at a slower rate. + +**SF -1** + +- Added a new SF -1: Bypass + +**Gang** + +- "Vigilante justice"/"Ethical hacking" now reduces wanted level by a very + small percentage as well an absolute value. + +**Netscript** + +- 'tFormat' now has a second argument to display with millisecond precision. +- 'purchaseSleeveAug' can no longer purchase the same aug over and over for + the same sleeve. +- fix typo in logging for 'getServerSecurityLevel' +- Fixed some weird issue where very rarely you would get 0 exp from 'grow' +- 'getActionTime' now returns correct values for Diplomacy and Regeneration. + +**Corporations** + +- Fixed an exploit where you could get nearly infinite corporation funds by + entering negative numbers in textboxes. +- Fixed an exploit where shares could be sold again by clicking the + "sell share" button via scripts. + +**Documentation** + +- typo fix in purchaseTor +- typo fix in basicgameplay/stats + +**Misc.** + +- Very large number will no longer appear as "\$NaNt" +- Hash capacity now displays in the "big number" format. +- nerf noodle bar + +## v0.51.9 - 2021-05-17 offline progress and exports! (hydroflame & community) + +**Alias** + +- several commands can be included in 1 alias. Recursive alias now work to + a depth of 10. (@Dawe) + +**Offline** + +- Offline money gain has been reworked (it is more generous) +- If you're not working anywhere and go offline the game will work for you + at all your factions evenly. + +**Export** + +- Exporting now gives +1 favor to all joined factions every 24h. + +**Corp** + +- Self-fund with an invalid name no longer takes away 150b anyway. +- Can no longer export negative amount + +**Bladeburner** + +- No longer waste overflowing time. + +**Text Editors** + +- All settings will now be saved and loaded correctly. + +**Terminal** + +- 'scan' now works for servers that are more than 21 character long. + +**Misc.** + +- ls now correctly lists all files. +- importing auto save+reloads (@Dawe) +- Fix a bug where .fconf could not be created +- Fix formatting inconsistencies for some logs of netscript functions. +- Fix a bug where Cashroot starter kit would appear as [object Object] in + confirmation dialog. +- Fix some ram not displayed as 0.00GB +- Fix error message throw undefined variable error +- City hall now has some generic text if you can't create a corp yet. +- Deleting a file without extension now returns an appropriate error message. +- Fixed an issue where bladeburner would miscalculate the cost of hospitalization. +- It is now possible to suppress bladeburner "action stopped" popup. +- Updated several dependencies (big who cares, I know) +- ls no longer prints lingering newline. +- Money earned/spent by sleeves is now tracked under Character>Money +- nerf noodle bar + +## v0.51.8 - 2021-05-07 It was there all along (hydroflame & community) + +**Servers** + +- Update n00dles metadata + +**Netscript** + +- 'hashGainRate' use the correct 'usedRam' and 'maxRam' +- Fix 'setActionAutolevel' logging. +- Fix 'setActionLevel' not working at all. +- Add 'installBackdoor' singularity function. + +**Hacknet** + +- Fix Hacknet Servers total production always displaying 0 + +**Documentation** + +- Updated guide to no longer recommend BN12. +- Fix documentation for maxNumNodes (@ModdedGamers) +- Fix typo in 'sourcefiles.rst' +- Fix typo in 'recommendedbitnodeorder.rst' +- Fix 'getServer' documentation missing 'server' argument. +- Fix missing ram cost in 'getData.rst' +- Fix basic formulas examples. +- Fix typo in BN11 description. +- Fix formatting issue in Bladeburner (@Pimgd) + +**Misc.** + +- Fix negative money being displayed in full. +- Fix Hacking Missions not working. +- Fix Corporation tree not rendering. +- Fix script being needlessly recompiled. This should save real ram (not game ram) +- w0r1d_d43m0n can be backdoored +- Coding Contracts title is click-to-copy (@Rodeth) +- Covenant memory upgrade works better. +- Fix Neuroflux not being correctly calculated when entering BN with SF12. +- Delete Active Script now delete all active scripts, not just home. +- Now you can 'cd' in directories that only contain '.txt' files. +- Fix 'analyze' always saying players had root access +- Passive faction rep no longer builds for special factions. +- Donation option no longer appears for special factions. +- Rephrased some milestones. +- donation textbox now accepts money in the format '1b' and the like (@Dawe) +- Fix being able to join hated factions simultaneously. (@Dawe) +- 'ls' now displays files in multiple column. (Helps players with many files) +- Bladeburner multiplers now appear under Character>Stats and + Character>Augmentation when they are relevant. +- Fix missing functions syntax highlight in codemirror. +- Fix infiltration number formatting. +- script income transfers to parent on death. This helps keep track of + income for scripts that spawn short lived scripts. +- nerf noodle bar + +## v0.51.7 - 2021-04-28 n00dles (hydroflame & community) + +**Tutorial servers** + +- All the tutorial servers have been reverted to their original value +- The new server n00dles has been added as tutorial server. + +**Terminal** + +- 'tail' now accepts Pid. +- 'analyze' now handles Hacknet Servers correctly. +- 'ServerProfiler.exe' now handles Hacknet Servers correctly. + +**SF12** + +- Now makes you start with Neuroflux Governor equal to the level of the SF. + +**Netscript** + +- Deprecated 'getServerRam'. +- 'getServerMaxRam' added to replace 'getServerRam' +- 'getServerUsedRam' added to replace 'getServerRam' +- 'getBitnodeMultipliers' is available inside BN5 +- Time logged by hack/grow/weaken now displays in human time. +- thread count logged by hack/grow/weaken now displays with commas every + thousands place. + +**Donation** + +- Always visible but locked until favor requirements are reached. + +**Augmentations** + +- City factions has been rebalanced to give a reason to visit them all. + +**Sleeves** + +- Fix sleeves not being able to work at Volhavens gym. + +**Lint** + +- This shouldn't change anything but was like 10h of work. So I'm logging it. + +**Misc.** + +- Plethora of typo fixed (@Pimgd) +- ps documentation fix (@Dawe) +- The dev menu now has a quick bitflume option. +- Fix SF -1 not being as powerful as intended. +- Fix cashroot starter kit not displaying correctly. +- Fix DOM element 'character-overview-text' being nested twice. +- Hacknet documentation example fix. +- Money amount under 1000 dont display 3 decimal anymore. +- Fix nextSourceFile flag miscalculation on the bitverse (for Bn12) +- Faction invite text says "Decide later"/"Join!" instead of "No"/"Yes" +- nerf noodle bar + +## v0.51.6 - 2021-04-28 Backdoor! (hydroflame & community) + +**Backdoor** + +- a new terminal command, backdoor, has been added to help differentiate + between the terminal hack command and the netscript hack function. (@dewint) + +**Servers** + +- foodnstuff, sigma-cosmetics, and joesguns have been rebalanced to help new players. + +**Milestones** + +- A new tab under the Help menu has been added to guide players through the + game. + +**Casino** + +- Blackjack has been added (@BigD) + +**Netscript** + +- 'prompt' now converts input to JSON. +- 'getRunningScript' is a new netscript function that returns a bunch of + data related to a running script. + +**Coding contracts** + +- trivial puzzles should no longer appear. + +**Infiltration** + +- All numbers are formatted like the rest of the game. + +**Misc.** + +- Server security is capped at 100. +- Added option to quit a job. +- 'cd' no longer works on unexistent folders. +- cd with no arguments brings you back to top level folder (@Andreas) +- 'softReset' documentation udpated. +- Money tracker now accounts for going to the hospital manually. +- codemirror is now the default editor (for new save files) +- fix typo in dark web help text (@Rodeth) +- so many documentation and typos fixes (@Pimgd) +- A corruption visual effect has been added to location with servers that + have backdoor installed. (@dewint) +- nerf noodle bar + +## v0.51.5 - 2021-04-20 Flags! (hydroflame) + +**Netscript** + +- 'flags' is a new function that helps script handle flags. + This is subject to change if it doesn't meet the need of the players. +- 'ps' now returns the pid. +- 'tail' now works with pid as first argument. +- 'tail' hostname defaults to current server. (like the documentation says) +- 'isRunning' hostname defaults to current server. +- 'isRunning' now works with pid as first argument. + +**Gang** + +- Nerfed ascension mechanic once again :( + +**Misc.** + +- Souce-File typo fix +- Fix 'while you were away' screen. +- Bladeburner team size can no longer be set to negative amounts. +- nerf noodle bar + +## v0.51.4 - 2021-04-19 Manual hacking is fun (hydroflame) + +**Manual hacking** + +- These bonus require an install or a soft reset to take effect. +- Manual hacking gyms and university gives you a 10% discount. +- Manual hacking a corporation server decreases the penalty for leaving work + early. + +**BladeBurner** + +- nerfed int exp gained. + +**Documentation** + +- purchaseServer specifies what happens on failure. +- Fixed typo in recommended bitnode page. +- Removed misleading ram requirements for hacking factions. + +**Netscript** + +- growthAnalyze handles Infinity correctly. + +**Misc.** + +- Faction Augmentation will list how much reputation is required even after + that goal has been reached. +- Removed dollar sign in travel agency confirmation dialog box. +- Fixed typo in alpha-omega.lit +- the 'Game saved!' text no longer blocks the save game/options button. +- The text editor now remembers the location of your cursor and restores it. +- skills are recalculated instantly. +- Fix typo in Operation Zero description. +- nerf noodle bar + +## v0.51.3 - 2021-04-16 Y'all broke it on the first day (hydroflame) + +**Passive faction reputation** + +- Reworked, from 1 rep / 2 minute. Now is a complicated percentage of the + reputation you'd gain working for them. It's not op but it feels a bit + more useful. + +**Netscript** + +- print/tprint now take any number of arguments. +- print/tprint will now print object as json. +- print/tprint now handle passing in an undefined argument properly. + +**Casino** + +- Cannot bet negative money anymore. +- Roulette max bet is a bit higher. +- Coin Flip has a small cooldown. +- All buttons reject unstrusted mouse events. + +**Documentation** + +- Changed a message that said nsjs only works on Chrome. + +**Bugfix** + +- hacknet.maxNumNodes now works for both nodes and servers. +- Fixed a bug where the popup boxes would contain data from previous popup boxes. +- .js files will also have the 'export async function' boilerplate. + +**Misc.** + +- turned off web form autocomplete for the terminal text input. +- Fixed an issue on Windows+Firefox where pressing up on the terminal would + bring the cursor to the begining of the line. (Issue #836) +- Hacknet node names is easier to handle for screen readers. +- Money spent on classes is now tracked independently of work money. +- running coding contract from the terminal will display its name. +- nerf noodle bar + +## v0.51.2 - 2021-04-09 Vegas, Baby! (hydroflame) + +**New location: The Iker Molina Casino** + +- A casino opened in Aevum. However the house is rumored to cheat. If only + we could give them a taste of their own medicine. + +**Misc.** + +- Link to discord added under options +- 'getMemberInformation' doc updated, oops +- tech vendor now handle max ram and cores. +- nerf noodle bar + +## v0.51.1 - 2021-04-06 Bugfixes because the author of the last patch sucks (it's hydroflame) + +**Netscript** + +- 'getPlayer' returns players faction and tor +- 'hospitalization' is a new singularity function. +- 'gang.getMemberInformation' now returns more information. +- 'hacknet.hashCapacity' is a new hacknet function that returns the maximum hash capacity. + +**Hospitalization** + +- Now only cost at most 10% of your money. + +**Bugfix** + +- confirmation dialog box no longer use previous text + +**Accessibility** + +- The game is a little easier to handle for screen readers (yes, there's an + absolute legend playing this game with a screen reader) +- Infiltration use buttons instead of a-links +- New option to disable ASCII art. This will make the metro map and world + map display as a list of buttons. + +**Misc.** + +- 'fl1ght.exe' will no longer suggest the combat path. Related faction + requirements unchanged. +- nerf noodle bar + +## v0.51.0 - 2021-03-31 Formulas (hydroflame) + +**Formulas API** + +- A new API is introduced, this gives players access to various formulas used in the game. + It'll help you make more informed decisions. + +**Netscript** + +- 'getServer' is a new function meant to be used with the formulas API. +- 'getPlayer' is a new function meant to be used with the formulas API. +- 'getStats' and 'getCharacterInformation' are deprecated in favor of 'getPlayer' +- 'getCurrentServer' is a new function that returns the server the player is currently connected. + +**Display** + +- All money should now consistently be orange. +- All rep should now consistently be light-yellow. +- Most numbers should display consistently now (aka all money is formatted the same). + +**Click to copy** + +- Certain UI elements are now 'click-to-copy' + +** Misc. ** + +- nerf noodle bar + +## v0.50.2 - 2021-03-25 Everyone asked for this one. (hydroflame) + +**BitNodeMultipliers** + +- 'GangKarmaRequirements': a new multipler that influences how much karma is required to make a gang different bitnodes. + +**Netscript** + +- 'connect': a new singularity function that connects you to a server. (like the terminal command) +- 'manualHack': a new singularity function that performs a manual hack on the players current server. +- ns2 stack trace works on Firefox now. + +**Misc.** + +- New shortcut, Alt + b, brings you to bladeburner +- New shortcut, Alt + g, brings you to gang +- nerf noodle bar + +## v0.50.1 - 2021-03-22 (hydroflame) + +**Netscript** + +- getTaskStats works + +**Source-File -1** + +- Added a new Exploit + +**Factions** + +- Augmentations offered by a Faction but already bought are in a separate list at the bottom of the page. + +**Bug fixed** + +- Fixed a bug where completing a maxed non-repeatable BitNode would make its color on the BitVerse like level 1. + +**Misc.** + +- Minor spacing in stats tables. +- nerf noodle bar + +## v0.50.0 - 2021-03-20 Intelligence (hydroflame) + +**Intelligence** + +- int exp gain and effect has been reworked. It is now much more easy to + acquire and far more powerful. The goal here is to feel like players have + another tool in their arsenal. + +**Factions** + +- Hacking factions no longer have hacking level requirements since their associated servers do. + +**Misc.** + +- Sleeve styling. +- number formatting +- remove wiki button in Hacking Missions. +- Fix NaN displayed when very very large numbers are reached. +- nerf noodle bar + +## v0.49.2 - 2021-03-13 (hydroflame) + +**BN8** + +- A new bitnode multipler has been added, it lets you reduce money from a + server without gaining actually any money. This is important for BN8 where + hack/grow can influence the stock market. No money can be gained from + hacking but server money can still be reduced. + +**Documentation** + +- readthedocs should now be more consistent and many examples were added. + +**Netscript** + +- Ace editor will now correctly highlight all functions. +- 'tFormat' is a new netscript function that returns a human readable + representation of milliseconds. eg. "2 hours 15 minute 43 seconds" + +**Gang** + +- style improvements + +**Bladeburner** + +- style improvements +- fix bug where 'skill list SKILL' would crash if skill is level 0. + +**Sleeve** + +- karma gain now scales with sync. + +**Misc.** + +- Fix issue where the effective stats under Character>Stats were being calculated. +- nerf noodle bar + +## v0.49.0 - 2021-03-11 Source-File -1 (hydroflame) + +**Source-File -1** + +- For advanced players: The game now embraces exploits and will reward + players for doing so. + +**Gang** + +- ascension is less effective as the ascension multiplier goes up. +- territory gain scales with power difference. + +**Netscript** + +- 'gang.getEquipmentStats' returns the stats of the equipment. +- 'gang.getTaskStats' returns the stats of a task. +- 'getCrimeStats' returns the stats of a crime. +- Crashes should now print the ns stack trace. +- Log messages are now more consistent. +- 'softReset' now accepts a callback script like 'installAugmentations' + +**Misc.** + +- Minor formatting under Hacking>Active Scripts +- option menu colors now match the rest of the game, kinda. +- nerf noodle bar + +## v0.48.0 - ASCII - 2021-03-07 (hydroflame) + +**ASCII** + +- Travel Agency now displays a world map +- Cities are now top view of metro station maps + +**Netscript** + +- 'softReset' is a new netscript function that performs a soft reset + regardless of if the player has bought augmentations or not. +- 'getAugmentationStats' is a new netscript function that returns the stats of + an augmentation. +- getCharacterInformation now additionally returns exp +- pid resets back to 1 when installing or destroying a BitNode. +- New '.ns' scripts start with a main function. +- 'hacknet.maxNumNodes' returns the maximum number of hacknet nodes. + +**Bladeburner** + +- Current stamina will scale as max stamina increases, this prevents players + from having very high penalty when they gain huge amount of exp at the + start of a reset. + +**Misc.** + +- Fixed an issue where SF3 was listed as infinitly repeatable and SF12 as + having a limit of 3. +- Fixed an issue where the gang equipment screen would freeze the game if a + script installed augmentations while it is open. +- All BonusTime now displays in the 'H M S' format. +- Donation textbox style updated to match the rest of the game. +- Corporation name style updated to match the rest of the game. +- minor formatting under Hacking>Active Scripts +- typo in BN12 description +- BN12 now reduces contract money +- Character>Stats percentages are aligned, server and hacknet limit are + displayed, if the player has SF5 the reduces stats are shown. +- Character>Augmentations now displays by how much the player stats will + increase. +- Character>Augmentations has a badge indicating how many augs the player + has bought but not installed +- Character>Factions has a badge indicating how many factions have pending + invites. +- nerf noodle bar + +## v0.47.2 - 7/15/2019 + +**Netscript Changes** + +- Added tail() Netscript function +- hacknet.getNodeStats() function now returns an additional property for Hacknet Servers: hashCapacity +- When writing to a file, the write() function now casts the data being written to a string (using String()) +- BitNode-selection page now shows what Source-File level you have for each BitNode +- Overloaded kill() function so that you can kill a script by its PID +- spawn() now only takes 10 seconds to run (decreased from 20 seconds) +- run() and exec() now return the PID of the newly-executed scripts, rather than a boolean + - (A PID is just a positive integer) +- run(), exec(), and spawn() no longer need to be await-ed in NetscriptJS +- Script parsing and RAM calculations now support ES9 +- installAugmentations() no longer has a return value since it causes all scripts to die +- isBusy() now returns true if you are in a Hacking Mission +- Bug fix: workForFaction() function now properly accounts for disabled logs +- Bug fix: RAM should now be properly calculated when running a callback script with installAugmentations() +- Bug fix: Fixed bug that caused scripts killed by exit()/spawn() to "clean up" twice + +**Misc Changes** + +- The 'kill' Terminal command can now kill a script by its PID +- Added 'Solarized Dark' theme to CodeMirror editor +- After Infiltration, you will now return to the company page rather than the city page +- Bug fix: Stock Market UI should no longer crash for certain locale settings +- Bug fix: You can now properly remove unfinished programs (the `*.exe-N%-INC` files) +- Bug fix: Fixed an issue that allowed you to increase money on servers with a 'maxMoney' of 0 (like CSEC) +- Bug fix: Scripts no longer persist if they were started with syntax/import errors +- Bug fix: 'hack' and 'analyze' Terminal commands are now blocking +- Bug fix: Exp earned by duplicate sleeves at universities/gyms now takes hash upgrades into account + +## v0.47.1 - 6/27/2019 + +- Stock Market changes: + + - Transactions no longer influence stock prices (but they still influence forecast) + - Changed the way stocks behave, particularly with regard to how the stock forecast occasionally "flips" + - Hacking & growing a server can potentially affect the way the corresponding stock's forecast changes + - Working for a company positively affects the way the corresponding stock's forecast changes + +- Scripts now start/stop instantly +- Improved performance when starting up many copies of a new NetscriptJS script (by Ornedan) +- Improved performance when killing scripts +- Dialog boxes can now be closed with the ESC key (by jaguilar) +- NetscriptJS scripts should now be "re-compiled" if their dependencies change (by jaguilar) +- write() function should now properly cause NetscriptJS scripts to "re-compile" (by jaguilar) + +## v0.47.0 - 5/17/2019 + +- Stock Market changes: + + - Implemented spread. Stock's now have bid and ask prices at which transactions occur + - Large transactions will now influence a stock's price and forecast + - This "influencing" can take effect in the middle of a transaction + - See documentation for more details on these changes + - Added getStockAskPrice(), getStockBidPrice() Netscript functions to the TIX API + - Added getStockPurchaseCost(), getStockSaleGain() Netscript functions to the TIX API + +- Re-sleeves can no longer have the NeuroFlux Governor augmentation + + - This is just a temporary patch until the mechanic gets re-worked + +- hack(), grow(), and weaken() functions now take optional arguments for number of threads to use (by MasonD) +- codingcontract.attempt() now takes an optional argument that allows you to configure the function to return a contract's reward +- Adjusted RAM costs of Netscript Singularity functions (mostly increased) +- Adjusted RAM cost of codingcontract.getNumTriesRemaining() Netscript function +- Netscript Singularity functions no longer cost extra RAM outside of BitNode-4 +- Corporation employees no longer have an "age" stat +- Gang Wanted level gain rate capped at 100 (per employee) +- Script startup/kill is now processed every 3 seconds, instead of 6 seconds +- getHackTime(), getGrowTime(), and getWeakenTime() now return Infinity if called on a Hacknet Server +- Money/Income tracker now displays money lost from hospitalizations +- Exported saves now have a unique filename based on current BitNode and timestamp +- Maximum number of Hacknet Servers decreased from 25 to 20 +- Bug Fix: Corporation employees stats should no longer become negative +- Bug Fix: Fixed sleeve.getInformation() throwing error in certain scenarios +- Bug Fix: Coding contracts should no longer generate on the w0r1d_d43m0n server +- Bug Fix: Duplicate Sleeves now properly have access to all Augmentations if you have a gang +- Bug Fix: getAugmentationsFromFaction() & purchaseAugmentation() functions should now work properly if you have a gang +- Bug Fix: Fixed issue that caused messages (.msg) to be sent when refreshing/reloading the game +- Bug Fix: Purchasing hash upgrades for Bladeburner/Corporation when you don't actually have access to those mechanics no longer gives hashes +- Bug Fix: run(), exec(), and spawn() Netscript functions now throw if called with 0 threads +- Bug Fix: Faction UI should now automatically update reputation +- Bug Fix: Fixed purchase4SMarketData() +- Bug Fix: Netscript1.0 now works properly for multiple 'namespace' imports (import \* as namespace from "script") +- Bug Fix: Terminal 'wget' command now correctly evaluates directory paths +- Bug Fix: wget(), write(), and scp() Netscript functions now fail if an invalid filepath is passed in +- Bug Fix: Having Corporation warehouses at full capacity should no longer freeze game in certain conditions +- Bug Fix: Prevented an exploit that allows you to buy multiple copies of an Augmentation by holding the 'Enter' button +- Bug Fix: gang.getOtherGangInformation() now properly returns a deep copy +- Bug Fix: Fixed getScriptIncome() returning an undefined value +- Bug Fix: Fixed an issue with Hacknet Server hash rate not always updating + +## v0.46.3 - 4/20/2019 + +- Added a new Augmentation: The Shadow's Simulacrum +- Improved tab autocompletion feature in Terminal so that it works better with directories +- Bug Fix: Tech vendor location UI now properly refreshed when purchasing a TOR router +- Bug Fix: Fixed UI issue with faction donations +- Bug Fix: The money statistics & breakdown should now properly track money earned from Hacknet Server (hashes -> money) +- Bug Fix: Fixed issue with changing input in 'Minimum Path Sum in a Triangle' coding contract problem +- Fixed several typos in various places + +## v0.46.2 - 4/14/2019 + +- Source-File 2 now allows you to form gangs in other BitNodes when your karma reaches a very large negative value + + - (Karma is a hidden stat and is lowered by committing crimes) + +- Gang changes: + + - Bug Fix: Gangs can no longer clash with themselve + - Bug Fix: Winning against another gang should properly reduce their power + +- Bug Fix: Terminal 'wget' command now works properly +- Bug Fix: Hacknet Server Hash upgrades now properly reset upon installing Augs/switching BitNodes +- Bug Fix: Fixed button for creating Corporations + +## v0.46.1 - 4/12/2019 + +- Added a very rudimentary directory system to the Terminal + +- Added numHashes(), hashCost(), and spendHashes() functions to the Netscript Hacknet Node API +- 'Generate Coding Contract' hash upgrade is now more expensive +- 'Generate Coding Contract' hash upgrade now generates the contract randomly on the server, rather than on home computer +- The cost of selling hashes for money no longer increases each time +- Selling hashes for money now costs 4 hashes (in exchange for \$1m) +- Bug Fix: Hacknet Node earnings should work properly when game is inactive/offline +- Bug Fix: Duplicate Sleeve augmentations are now properly reset when switching to a new BitNode + +## v0.46.0 - 4/3/2019 + +- Added BitNode-9: Hacktocracy +- Changed BitNode-11's multipliers to make it slightly harder overall +- Source-File 11 is now slightly stronger +- Added several functions to Netscript Sleeve API for buying Sleeve augmentations (by hydroflame) +- Added a new stat for Duplicate Sleeves: Memory +- Increase baseline experience earned from Infiltration, but it now gives diminishing returns (on exp) as you get to higher difficulties/levels +- In Bladeburner, stamina gained from Hyperbolic Regeneration Chamber is now a percentage of your max stamina + +- Corporation Changes: + + - 'Demand' value of products decreases more slowly + - Bug Fix: Fixed a Corporation issue that broke the Market-TA2 Research + - Bug Fix: Issuing New Shares now works properly + +- Bug Fix: Money Statistics tracker was incorrectly recording profits when selling stocks manually +- Bug Fix: Fixed an issue with the job requirement tooltip for security jobs + +## v0.45.1 - 3/23/2019 + +- Added two new Corporation Researches +- General UI improvements (by hydroflame and koriar) +- Bug Fix: Sleeve Netscript API should no longer cause Dynamic RAM errors +- Bug Fix: sleeve.getSleeveStats() should now work properly + +## v0.45.0 - 3/22/2019 + +- Corporation changes: + + - Decreased the time of a full market cycle from 15 seconds to 10 seconds. + - This means that each Corporation 'state' will now only take 2 seconds, rather than 3 + - Increased initial salaries for newly-hired employees + - Increased the cost multiplier for upgrading office size (the cost will increase faster) + - The stats of your employees now has a slightly larger effect on production & sales + - Added several new Research upgrades + - Market-TA research now allows you to automatically set sale price at optimal values + - Market-TA research now works for Products (not just Materials) + - Reduced the amount of Scientific Research needed to unlock the Hi-Tech R&D Laboratory from 10k to 5k + - Energy Material requirement of the Software industry reduced from 1 to 0.5 + - It is now slightly easier to increase the Software industry's production multiplier + - Industries now have a maximum number of allowed products, starting at 3. This can be increased through research. + - You can now see an approximation of how each material affects an industry's production multiplier by clicking the "?" help tip next to it + - Significantly changed the effects of the different employee positions. See updated descriptions + - Reduced the amount of money you gain from private investors + - Training employees is now 3x more effective + - Bug Fix: An industry's products are now properly separated between different cities + +- The QLink Augemntation is now significantly stronger, but also significantly more expensive (by hydroflame) +- Added a Netscript API for Duplicate Sleeves (by hydroflame) +- Modified the multipliers of BitNode-3 and BitNode-8 to make them slightly harder +- After installing Augmentations, Duplicate Sleeves will now default to Synchronize if their Shock is 0 +- Bug Fix: Bladeburner's Hyperbolic Regeneration Chamber should no longer instantly refill all stamina +- Bug Fix: growthAnalyze() function now properly accounts for BitNode multipliers +- Bug Fix: The cost of purchasing Augmentations for Duplicate Sleeves no longer scales with how many Augs you've purchased for yourself + +## v0.44.1 - 3/4/2019 + +- Duplicate Sleeve changes: + + - You can now purchase Augmentations for your Duplicate Sleeves + - Sleeves are now assigned to Shock Recovery task by default + - Shock Recovery and Synchronize tasks are now twice as effective + +- Changed documentation so that Netscript functions are own their own pages. Sorry if this is annoying, it was necessary for properly cross-referencing +- Officially deprecated the Wiki (the fandom site). Use the 'readthedocs' Documentation instead +- Bug Fix: 'rm' Terminal and Netscript commands now work on non-program files that have '.exe' in the name (by Github user MasonD) +- Bug Fix: The 'Find All Valid Math Expressions' Coding Contract should now properly ignore whitespace in answers +- Bug Fix: The 'Merge Overlapping Intervals' Coding Contract should now properly accept 2D arrays when being attempted through Netscript + +## v0.44.0 - 2/26/2019 + +- Bladeburner Changes: + - Reduced the amount of rank needed to earn a skill point + - Reduced the effects of the "Reaper" and "Evasive System" skills + - Increased the effect of the "Hyperdrive" and "Hands of Midas" skills + - Slightly increased the rate which the skill point cost rises for almost all skills + - The "Overlock" Skill now has a maximum level of 90 instead of 95 + - Money earned from Contracts increased by 400% + - Changed the way population affects success rate. Extreme populations now have less dramatic effects + - Added two new General Actions: Diplomacy and Hyperbolic Regeneration Chamber + - Lowered the rep and money cost of the "Blade's Simulacrum" augmentation + - Significantly decreased the initial amount of Contracts/Operations (the "Contracts/Operations remaining" value) + - Decreased the rate at which the amount of Contracts/Operations increases over time + - Decreased the number of successes you need to increase the max level of a Contract/Operation + - Increased the average number of Synthoid communities each city has + - Reduced the amount by which a successful raid will decrease the population of a city + - The "riots" event will now increase the chaos of a city by a greater amount + - Significantly increased the effect that Agility and Dexterity have on action time +- Added new BitNode multipliers: + - HomeComputerRamCost - Affects how much it costs to upgrade home computer's RAM + - DaedalusAugsRequirement - Affects how many Augmentations you need in order to get invited to Daedalus + - FourSigmaMarketDataCost - Affects how much it costs to unlock the stock market's 4S Market Data + - FourSigmaMarketDataApiCost - Affects how much it costs to unlock the stock market's 4S Market Data API +- A few minor changes to BitNode multipliers across the board (mostly for the new multipliers) +- 'The Covenant' now requires 20 total Augmentations to get invited, rather than 30 +- You can now purchase permanent Duplicate Sleeves from 'The Covenant'. This requires Source-File 10, and you must be in BN-10 or after +- You can now track where all of your money comes from in the 'Stats' page +- Increased the money gained from Coding Contracts by 50% +- getCharacterInformation() function now returns the player's HP and max HP +- Bug Fix: You can no longer disconnect the enemy's connections in Hacking Missions +- Bug Fix: Duplicate Sleeve faction reputation gain is now properly affected by faction favor +- Bug Fix: After installing Augmentations, the Terminal display will now correctly show the current server as "home" +- Bug Fix: Fixed an exploit where you could change the duration of timed functions (e.g. hack, weaken) in NetscriptJS +- Bug Fix: You should now properly be able to use the ServerProfile.exe program +- Bug Fix: Prevented exploit that allowed you to accept faction invites programmatically through NetscriptJS +- Bug Fix: Faction invitations for megacorporations should now work properly + +## v0.43.1 - 2/11/2019 + +- Terminal changes: + + - Quoted arguments are now properly parsed. (e.g. 'run f.script "this is one argument"' will be correctly parsed) + - Errors are now shown in red text + - 'unalias' command now has a different format and no longer needs the quotations + - Bug Fix: Fixed several edge cases where autocomplete wasn't working properly + +- Added two new Bladeburner skills for increasing money and experience gain +- Made some minor adjustments to Bladeburner UI +- Corporation "Smart Factories" and "Smart Storage" upgrades have slightly lower price multipliers +- Added nFormat Netscript function +- Added 6 new Coding Contract problems +- Updated documentation with list of all Coding Contract problems +- Minor improvements for 'Active Scripts' UI +- Implemented several optimizations for active scripts. The game should now use less memory and the savefile should be slightly smaller when there are many scripts running +- Bug Fix: A Stock Forecast should no longer go above 1 (i.e. 100%) +- Bug Fix: The cost of Resleeves should no longer be affected by buying Augs +- Bug Fix: Duplicate Sleeves now use their own stats to determine crime success rate, instead of the host consciousness' stats +- Bug Fix: You can now call the prompt() Netscript function from multiple scripts simultaneously + +## v0.43.0 - 2/4/2019 + +- Added BitNode-10: Digital Carbon + +- Stock Market Changes: + + - Each stock now has a maximum number of shares you can purchase (both Long and Short positions combined) + - Added getStockMaxShares() Netscript function to the TIX API + - The cost of 4S Market Data TIX API Access increased from \$20b to \$25b + +- Job Changes: + + - You can now hold multiple jobs at once. This means you no longer lose reputation when leaving a company + - Because of this change, the getCharacterInformation() Netscript function returns a slightly different value + +- Script Editor Changes: + + - Added new script editor: CodeMirror. You can choose between the old editor (Ace) or CodeMirror + - Navigation keyboard shortcuts no longer work if the script editor is focused + +- Trying to programmatically run a script (run(), exec()) with a 'threads' argument of 0 will now cause the function to return false without running the script +- Home Computer RAM is now capped at 2 ^ 30 GB (1073741824 GB) +- The maximum amount, maximum RAM, and cost of purchasing servers can now vary between different BitNodes (new BitNode multipliers) +- Pop-up dialog boxes are a little bit bigger +- Bug Fix: When importing scripts, "./" will now be properly ignored (e.g. import { foo } from "./lib.script" ) + +## v0.42.0 - 1/8/2019 + +- Corporation Changes: + + - Corporation can now be self-funded with \$150b or using seed money in exchange for 500m newly-issued shares + - In BitNode-3, you no longer start with \$150b + - Changed initial market prices for many materials + - Changed the way a material's demand, competition, and market price change over time + - The sale price of materials can no longer be marked-up as high + - Added a Research Tree mechanic. Spend Scientific Research on permanent upgrades for each industry + - You can now redistribute earnings to shareholders (including yourself) as dividends + - Cost of "Smart Supply" upgraded reduced from \$50b to \$25b + - Now has offline progress, which works similarly to the Gang/Bladeburner mechanics + - Slightly reduced the amount of money offered to you by investment firms + - Employee salaries now slowly increase over time + - Slightly reduced the effect "Real Estate" has on the Production Multiplier for the Agriculture industry + - Changed the way your Corporation's value is calculated (this is what determines stock price) + - After taking your corporation public, it is now possible to issue new shares to raise capital + - Issuing new shares can only be done once every 12 hours + - Buying back shares must now be done at a premium + - Selling shares can now only be done once per hour + - Selling large amounts of shares now immediately impacts stock price (during the transaction) + - Reduced the initial cost of the DreamSense upgrade from \$8b to \$4b, but increased its price multiplier + - Reduced the price multiplier for ABC SalesBots upgrade + +- Added getOrders() Netscript function to the TIX API +- Added getAugmentationPrereq() Singularity function (by havocmayhem) +- Added hackAnalyzePercent() and hackAnalyzeThreads() Netscript functions +- Stock Market, Travel, and Corporation main menu links are now properly styled +- Many pop-up/dialog boxes now support the 'Enter' and 'Esc' hotkeys. If you find a pop-up/dialog box that doesnt support this, let me know specifically which one ('Enter' for the default option, 'Esc' for cancelling and closing the pop-up box) +- Added "brace_style = preserve_inline" configuration to Script Editor Beautifier +- ServerProfiler.exe can now be purchased from the Dark Web +- Added an option to copy save data to clipboard +- Added total multiplier information on the "Augmentations" page +- Bug Fix: gymWorkout() Singularity function should now work properly with Millenium Fitness Gym +- Began migrating gameplay information to the ReadTheDocs documentation + +## v0.41.2 - 11/23/2018 + +- IMPORTANT - Netscript Changes: + + - rm() now takes an optional parameter that lets you specify on which server to delete the file + - Added growthAnalyze() Netscript function + +- Gang Changes: + + - UI now displays your chance to win a clash with other gangs + - Added getChanceToWinClash() function to the Gang API + - Added getEquipmentType() function to the Gang API + - Added several new hacking-based equipment and Augmentations + - Rebalanced several equipment/upgrades to give less defense + - Wanted level gain rate is now be slightly higher for all tasks + - Rebalanced parameters for "hacking" tasks + +- Added new Main Menu configuration in .fconf: "compact" +- Added the terminal command 'expr', which can be used to evaluate simple mathematical expressions +- Bug Fix: Can no longer purchase duplicate equipment/Augmentations through gang.purchaseEquipment() +- Bug Fix: scp() should no longer throw errors when used with 2-arguments and an array of files +- Bug Fix: Coding Contracts no longer give money in BitNode-8 +- Bug Fix: In Bladeburner, you can no longer start a BlackOp through the Netscript API if it has already been completed +- Bug Fix: In Bladeburner, fixed a bug which caused the configured 'automate' actions to occasionally be switched to other actions +- Bug Fix: 'Return to World' button at locations no longer accumulates event listeners +- Bug Fix: Working & taking classes now continuously add/subtract money during the action, instead of doing it at completion +- Bug Fix: Top-right overview panel now displays negative money using '-' instead of '()' +- Bug Fix: Stock Market UI should no longer show 'NaN' profit immediately after buying a stock + +## v0.41.1 - 11/5/2018 + +- IMPORTANT - Netscript Changes: + + - purchaseTor() now returns true if you already have a TOR router (it used to return false) + - getPurchasedServerCost() now returns Infinity if the specified RAM is an invalid amount or is greater than the max amount of RAM (2 ^ 20 GB) + - Added purchase4SMarketData() and purchase4SMarketDataTixApi() functions + - getScriptLogs() now takes in optional arguments that let you get the logs of another script + +- Stock Market changes: + + - Stocks now have "maximum prices". These are hidden from the player + - If a stock reaches its "maximum price", it will most likely drop in value (although it might still rise) + - Each stock has its own, unique maximum price + - Maximum price for each stock are randomly generated and change during each 'reset' + - Stock Market cycles are now accumulated/stored, much like it is for Gangs and Bladeburners + - Accumulated/stored cycles cause stock prices to update up to 50% faster (from every 6 seconds to 4 seconds) + - This means that after coming back from being offline, stock prices will update faster to make up for offline time + +- Decreased the Hacking Level multiplier for BitNodes 6 and 7 to 0.4 (from 0.5) +- Bladeburner console history is now saved and persists when switching screens or closing/reopening the game +- In Bladeburner, if your stamina reaches 0 your current action will be cancelled +- b1t_flum3.exe is no longer removed from your home computer upon reset +- Added main menu link for the Stock Market (once you've purchased an account) +- Job main menu link only appears if you actually have a job +- Bug Fix: Netscript Gang API functions purchaseEquipment() and ascendMember() should now work properly +- Bug Fix: After installing Augs, the "Portfolio Mode" button on the Stock Market page should be properly reset +- Bug Fix: bladeburner.getActionCountRemaining()'s return value is now rounded down (by Kline-) + +## v0.41.0 - 10/29/2018 + +- WARNING: In NetscriptJS, defining a function called print() is no longer possible +- Gang Mechanic Changes (BitNode-2): + - Added a Gang Netscript API + - Added new 'ascension' mechanic for Gang Members + - The first three gang members are now 'free' (can be recruited instantly) + - Maximum number of increased Gang Members increased from 20 to 30 + - Changed the formula for calculating respect needed to recruit the next gang member + - Added a new category of upgrades for Gang Members: Augmentations + - Non-Augmentation Gang member upgrades are now significantly weaker + - Reputation for your Gang faction can no longer be gained through Infiltration + - Re-worked the territory 'warfare' mechanic so that player can choose when to engage in it + - Gang Members can now be killed during territory 'warfare' + - Changed BitNode-2 Multipliers to make hacking slightly less profitable + - Gang Member Equipment + Upgrades now get cheaper as your gang grows in power and respect + - The effects of Source-File 2 are now slightly more powerful +- RAM Cost of accessing the global document object lowered from 100 GB to 25 GB +- RAM Cost to use Singularity Functions outside of BitNode-4 lowered by 75%. They now only cost twice as much as they do in BitNode-4 +- b1t_flum3.exe now takes significantly less time to create +- Crimes commited through Singularity function no longer give half money/exp (there is now no penalty) +- Improved number formatting for Player 'work' actions (including crimes, etc.). These numbers should also adhere to locale settings now (by Kline-) +- The order that Augmentations are listed in (when purchasing from Faction and viewing your Augmentations) is now saved and persists when choosing different orders +- getCharacterInformation() Singularity function now returns multiplier information (from Augmentations/Source Files) +- Bug Fix: Calling print() in NetscriptJS no longer brings up the print dialog +- Bug Fix: Fixed a bug that sometimes caused a blank black screen when destroying/resetting/switching BitNodes +- Bug Fix: Netscript calls that throw errors will now no longer cause the 'concurrent calls' error if they are caught in the script. i.e. try/catch should now work properly in scripts +- Bug Fix: Fixed a bug where sometimes the NeuroFlux Governor Augmentation level would be incorrectly calculated when the game was loaded +- Bug Fix: Fixed a bug where calling the scp() Netscript function with invalid hostname/ips would throw an unclear error message +- Bug Fix: Bladeburner API function getActionCountRemaining() should now work properly for BlackOps +- Bug Fix: Black Ops can no longer be attempted out-of-order or without the required rank via Bladeburner API +- Bug Fix: Dynamic RAM Calculation now properly accounts for number of threads +- RAM cost for basic Netscript functions added to documentation (by CBJamo) + +## v0.40.5 - 10/09/2018 + +- Added codingcontract.getContractType() Netscript function +- Bug Fix: codingcontract.getData() Netscript function now returns arrays by value rather than reference +- Bug Fix: Decreased highest possible data value for 'Find Largest Prime Factor' Coding Contract (to avoid hangs when solving it) +- Bug Fix: Fixed a bug that caused game to freeze during Coding Contract generation + +## v0.40.4 - 9/29/2018 + +- Added new Coding Contracts mechanic. Solve programming problems to earn rewards +- The write() and read() Netscript functions now work on scripts +- Added getStockSymbols() Netscript function to the TIX API (by InfraK) +- Added wget() Netscript function +- Added bladeburner.getActionRepGain() function to the Netscript Bladeburner API +- The getLevelUpgradeCost(), getRamUpgradeCost(), and getCoreUpgradeCost() functions in the Hacknet API now return Infinity if the node is at max level. See documentation +- It is now possible to use freely use angled bracket (<, >) and create DOM elements using tprint() +- The game's theme colors can now be set through the Terminal configuration (.fconf). +- You can now switch to the old left-hand main menu bar through the Terminal configuration (.fconf) +- Bug Fix: grow() percentage is no longer reported as Infinity when a server's money is grown from 0 to X +- Bug Fix: Infiltration popup now displays the correct amount of exp gained + +## v0.40.3 - 9/15/2018 + +- Bladeburner Changes: + - Increased the effect that agi and dexterity have on action time + - Starting number of contracts/operations available will be slightly lower + - Random events will now happen slightly more often + - Slightly increased the rate at which the Overclock skill point cost increases +- The maximum volatility of stocks is now randomized (randomly generated within a certain range every time the game resets) +- Increased the range of possible values for initial stock prices +- b1t_flum3.exe program can now be created immediately at Hacking level 1 (rather than hacking level 5) +- UI improvements for the character overview panel and the left-hand menu (by mat-jaworski) +- General UI improvements for displays and Terminal (by mat-jaworski) +- Added optional parameters to the getHackTime(), getGrowTime(), and getWeakenTime() Netscript functions +- Added isLogEnabled() and getScriptLogs() Netscript functions +- Added donateToFaction() Singularity function +- Updated documentation to reflect the fact that Netscript port handles (getPortHandle()) only works in NetscriptJS (2.0), NOT Netscript 1.0 +- Added tryWrite() Netscript function +- When working (for a company/faction), experience is gained immediately/continuously rather than all at once when the work is finished +- Added a setting in .fconf for enabling line-wrap in the Terminal input +- Adding a game option for changing the locale that most numbers are displayed in (this mostly applies for whenever money is displayed) +- The randomized parameters of many high-level servers can now take on a higher range of values +- Many 'foreign' servers (hackable servers that you don't own) now have a randomized amount of RAM +- Added 'wget' Terminal command +- Improved the introductory tutorial + +## v0.40.2 - 8/27/2018 + +- Bladeburner Changes: + - Added getBonusTime(), getSkillUpgradeCost(), and getCity() Netscript functions to the API + - Buffed the effects of many Bladeburner Augmentations + - The Blade's Simulacrum Augmentation requires significantly less reputation but slightly more money + - Slightly increased the amount of successes needed for a Contract/Operation in order to increase its max level + - Increased the amount of money gained from Contracts by ~25% + - Increased the base amount of rank gained from Operations by 10% + - Significantly increased the 'randomness' in determining a Contract/Operation's initial count and rate of count increase + - The number (count) of Operations should now increase significantly faster + - There are now, on average, more Synthoid communities in a city + - If automation is enabled (the feature in Bladeburner console), then switching to another action such as working for a company will now disable the automation +- Stock Market Changes: + - Added a watchlist filter feature to the UI that allows you to specify which stocks to show + - Added the Four Sigma (4S) Market Data feed, which provides volatility and price forecast information about stocks + - Added the 4S Market Data TIX API, which lets you access the aforementioned data through Netscript +- There is now a setting for enabling/disabling the popup that appears when you are hospitalized +- Bug Fix: Stock market should now be correctly initialized in BitNode-8 (by Kline-) +- Bug Fix: bladeburner.getCurrentAction() should now properly an 'Idle' object rather than null (by Kline-) +- Bug Fix: Bladeburner skill cost multiplier should now properly increase in BitNode-12 (by hydroflame) +- Bug Fix: 'document', 'hacknet', and 'window' keywords should no longer be counted multiple times in RAM calculations +- Bug Fix: Joining factions through Singularity functions should now prevent you from joining opposing factions +- Bug Fix: Four Sigma should no longer have two 'Speech Enhancement' Augmentations (by Kline-) + +## v0.40.1 - 8/5/2018 - Community Update + +- Added getPurchasedServerCost() Netscript function (by kopelli) +- Added getFavorToDonate() Netscript function (by hydroflame) +- Added getFactionFavorGain() and getCompanyFavorGain() Singularity functions (by hydroflame) +- Accumulated 'bonus' time in Bladeburner is now displayed in the UI (by hydroflame) +- The Red Pill can now be purchased with negative money (since its supposed to be free) (by hydroflame) +- Cranial Signal Processor Augmentations now have the previous generation as a prerequisite. i.e. Cranial Signal Processor - Gen II requires Gen I (by Kline-) +- Terminal now supports semicolon usage (end of command). This allows chaining multiple Terminal commands (by hydroflame) +- Bladeburner Raid operations can no longer be performed if your estimate of Synthoid communities is zero (by hydroflame) +- The difficulty of BN-12 now scales faster (by hydroflame) +- Active Scripts UI now shows a RAM Usage bar for each server (by kopelli) +- Bug Fix: Corrected terminal timestamp format (by kopelli) +- Bug Fix: NetscriptJS scripts should now die properly if they don't have a 'main' function (by hydroflame) +- Bug Fix: write(), read(), and tryWrite() Netscript functions should now work properly for writing Arrays/objects to Netscript Ports +- Various minor UI/QOL fixes by hydroflame, kopelli, and Kline- + +## v0.40.0 - 7/28/2018 + +- **WARNING: This update makes some significant changes to Netscript and therefore you may need to make some changes to your scripts. See** `this post `\_ **this post for details** +- Netscript 1.0 (NS1) now uses a fully-fledged ES5 JavaScript Interpreter. This means many new features are now available in NS1, and this also fixes several bugs. + However this also means any ES6+ features are no longer supported in NS1 +- When a server is hacked with a very large number of threads and left with no money, the server's security level + now only increases by however many threads were needed to drain the server. For example, if you hack a server with + 5000 threads but it only needed 2000 threads to deplete the server's money, then the server's security will only increase + as if you had hacked it with 2000 threads (change by hydroflame) +- Added getCurrentAction() to Bladeburner API +- Added a variety of functions to Bladeburner API that deal with action levels (change by hydroflame) +- Added getPurchasedServerLimit() and getPurchasedServerMaxRam() functions to Netscript (change by hydroflame & kopelli) +- Added getOwnedSourceFiles() Singularity function (by hydroflame) +- Completely re-designed the Hacknet Node API +- getSkillLevel() in Bladeburner API now returns an error if no argument is passed in (as opposed to an object with all skill levels). This may break scripts +- Minimum Netscript execution time reduced from 15ms to 10ms (configurable in Options) +- Company reputation needed to get invited to Megacorporation factions decreased from 250k to 200k +- HP is now reset (restored) when Augmenting +- Source-File 6 now increases both the level and experience gain of all combat stats (it was only experience gain previously) +- Reverted a previous change for Source-File 12. It's benefits are now multiplicative rather than additive +- Starting Infiltration security level for almost every location decreased by ~10% +- Changed 'fl1ght.exe' message when its listed conditions are fulfilled (by hydroflame) +- The 'Save Game' button in the top-right overview panel now flashes red if autosave is disabled +- Bug Fix: Infiltration buttons can no longer be clicked through NetscriptJS +- Bug Fix: Bladeburner 'Overclock' skill can no longer be leveled above max level through the API (by hydroflame) +- Bug Fix: Healthcare division in Bladeburner should no longer cause game to crash + +## v0.39.1 - 7/4/2018 + +- Bladeburner Rank gain in BN-7 is now reduced by 40% instead of 50% +- Quadrupled the amount of money gained from Bladeburner contracts +- Added joinBladeburnerDivision() Netscript function to Bladeburner API +- Doubled the effects of Source-File 5. Now gives 8%, 12%, and 14% increase to all hacking multipliers at levels 1, 2, and 3, respectively (increased from 4%/6%, 7%) +- Increased the effect of Source-File 8. It now gives a 12%, 18% and 21% to your hacking growth multiplier at levels 1, 2, and 3, respectively (increased from 8%, 12%, 14%) +- The effect of Source-File 12 is now additive with itself, rather than multiplicative. This means that level N of Source-File 12 now increases all multipliers by N% +- The setting to suppress the confirmation box when purchasing Augmentations was moved into the main Options menu (by Github user hydroflame) +- Bug Fix: Crime Success rates were being calculated incorrectly (by Github user hydroflame) +- When an Infiltration is finished, you will now return back to the company's page, rather than the city +- Infiltration faction reputation selector now remembers your last choice +- Significantly increased the amount of money gained from Infiltration +- Bug Fix: Copying a NetscriptJS script to another server using scp now properly takes into account the script's changes. +- Bug Fix: Fixed an issue where game would not load in Edge due to incompatible features +- travelToCity() Singularity function no longer grants Intelligence exp" + +## v0.39.0 - 6/25/2018 + +- Added BitNode-7: Bladeburner 2079 +- Infiltration base difficulty decreased by 10% for most locations +- Experience gains from Infiltration slightly increased +- Money gained from Infiltration increased by 20% +- Added 'var' declarations in Netscript 1.0 (only works with 'var', not 'let' or 'const') +- Script base RAM cost is now 1.6 GB (increased from 1.4 GB) +- While/for loops and if statements no longer cost RAM in scripts +- Made short-circuit evaluation logic more consistent in Netscript 1.0 +- Changelog button in the Options menu now links to the new Changelog URL (by Github user thePalindrome) +- Skill level calculation is now 'smoother' (by Github user hydroflame) +- Added a button to 'beautify' scripts in the text editor (by Github user hydroflame) +- Added favicon (by Github user kopelli) + +## v0.38.1 - 6/15/2018 + +- Bug Fix: Using 'Object.prototype' functions like toLocaleString() or toString() should no longer cause errors in NetscriptJS +- Implemented by Github user hydroflame: + - Accessing the 'window' and 'document' objects in Netscript JS now requires a large amount of RAM (100 GB) + - Added game option to suppress travel confirmation + - Text on buttons can no longer be highlighted + - Bug Fix: Fixed an issue that caused NaN values when exporting Real Estate in Corporations + - Bug Fix: Competition and Demand displays in Corporation are now correct (were reversed before) + - Added ps() Netscript function + - Bug Fix: grow() should no longer return/log a negative value when it runs on a server that's already at max money + - Bug Fix: serverExists() Netscript function should now properly return false for non-existent hostname/ips + - Bug Fix: Sever's security level should now properly increase when its money is grown to max value + +## v0.38.0 - 6/12/2018 + +- New BitNode: BN-12 The Recursion - Implemented by Github user hydroflame +- Bladeburner Changes: + - Bladeburner progress is no longer reset when installing Augmentations + - The number of successess needed to increase a Contract/Operation's max level now scales with the current max level (gradually gets harder) + - All Bladeburner Augmentations are now slightly more expensive and require more reputation + - Black Operations now give higher rank rewards + - Doubled the base amount of money gained from Contracts + - Increased the amount of experience gained from Contracts/Actions + - Added a new Augmentation: The Blade's Simulacrum + - Bladeburner faction reputation gain is now properly affected by favor +- Hacking is now slightly less profitable in BitNode-3 +- Updated Hacknet Nodes UI - Implemented by Github user kopelli +- Bug Fix: Fixed an exploit that allowed calling any Netscript function without incurring any RAM Cost in NetscriptJS + +## v0.37.2 - 6/2/2018 + +- After joining the Bladeburners division, there is now a button to go to the Bladeburner content + in the 'City' page +- You now start with \$250m in BitNode-8 (increased from \$100m) +- Bug Fix: You can now no longer directly edit Hacknet Node values through NetscriptJS (hopefully) +- Bug Fix: Bladeburners is no longer accessible in BN-8 +- Bug Fix: getBitNodeMultipliers() Netscript function now returns a copy rather than the original object + +## v0.37.1 - 5/22/2018 + +- You now earn money from successfully completing Bladeburner contracts. The amount you earn is based + on the difficulty of the contract. +- Completing Field Analysis in Bladeburner now grants 0.1 rank +- The maximum RAM you can get on a purchased server is now 1,048,576 GB (2^20) +- Bug Fix: Fixed Netscript syntax highlighting issues with the new NetscriptJS +- Bug Fix: Netscript Functions now properly incur RAM costs in NetscriptJS +- Bug Fix: deleteServer() now fails if its called on the server you are currently connected to +- Removed in-game Netscript documentation, since it was outdated and difficult to maintain. +- Bug Fix: Updated the gymWorkout() Singularity function with the new exp/cost values for gyms + +## v0.37.0 - 5/20/2018 + +- NetscriptJS (Netscript 2.0) released +- Running the game with the '?noScripts' query will start the game without loading any of your scripts. This should be used if you accidentally write a script that crashes your game + +## v0.36.1 - 5/11/2018 + +- Bladeburner Changes: + - Bug Fix: You can no longer get Bladeburner faction reputation through Infiltration + - Initial difficulty of Tracking contracts reduced + - Datamancer skill effect increased from 4% per level to 5% + - Slightly decreased the base stamina cost of contracts/operations + - Slightly increased the effects of the Tracer, Digital Observer, Short Circuit, Cloak, and Blade's Intuition skills + - Overclock skill capped at level 95, rather than 99 + - Training gives significantly more exp/s +- Crime, Infiltration, and Hacking are now slightly more profitable in BN-6 +- Gyms are now more expensive, but give slightly more exp +- Added getScriptName() and getHacknetMultipliers() Netscript functions (added by Github user hydroflame) +- getScriptRam() Netscript function now has default value for the second argument, which is hostname/ip (implemented by Github user hydroflame) +- There is now a soft-cap on stock price, which means it's no longer possible for the price of a stock to reach insanely-high values +- The ctrl+b hotkey in the text editor should now also be triggered by command+b on OSX (I don't have OSX so I can't confirm if this works) +- Many servers now have additional RAM +- Added an option to disable hotkeys/keyboard shortcuts +- Refactored 'Active Scripts' UI page to optimize its performance +- Added a new .fconf Terminal setting: ENABLE_TIMESTAMP +- 'Netscript Execution Time', which can be found in the Options, now has a minimum value of 15ms rather than 25ms +- Bug Fix: Fixed a typo in the Fulcrum Technologies company name (Technolgies -> Technologies) +- Bug Fix: hacknetnodes keyword should no longer incur RAM cost if its in a comment +- Bug Fix: disableLog() now works for the commitCrime() Netscript function (fixed by Github user hydroflame) + +## v0.36.0 - 5/2/2018 + +- Added BN-6: Bladeburners +- Rebalanced many combat Augmentations so that they are slightly less powerful +- Bug Fix: When faction invites are suppressed, an invitation will no longer load the Faction page + +## v0.35.2 - 3/26/2018 + +- Corporation Changes: + - Fixed an issue with Warehouse upgrade cost. Should now be significantly cheaper than before. + - Scientific Research now has a slightly more significant effect on Product quality + - The Energy and Water Utilities industries are now slightly more profitable + - The Robotics and Computer Hardware industries are now less profitable + - The Software industry is slightly less profitable + - When selling Materials and Products, the 'PROD' qualifier can now be used to set dynamic sell amounts based on your production + - Exporting MAX should now work properly + - You can no longer export past storage limits + - Scientific Research production reduced + - Effects of AdVert. Inc upgrade were reduced, but the effect that popularity and awareness have on sales was increased to compensate (popularity/awareness numbers were getting too big with Advert. Inc) + - Bug Fix: Products from Computer Hardware division should now properly have ratings +- Improved Augmentation UI/UX. Now contains collapsible headers and sort buttons +- Improved Faction Augmentations display UI/UX. Now contains sort buttons. There is also an option to disable confirmation when purchasing Augmentations + +## v0.35.1 - 3/12/2018 + +- You can now easily download all of your scripts/text files as zip folders. Use the 'help download' Terminal command for details +- Scripts are now downloaded with the .script.js extension at the end of their filename +- Corporation Management Changes: + - Implemented Smart Supply unlock + - Changed the way a division's Production Multiplier is calculated. It is now the sum of the individual Production Multiplier for every city. Therefore, it is now beneficial to open offices in different cities + - Several small UI/UX improvements + - Numerous balance changes. The significant ones are listed below. + - Product descriptions will now display their estimated market price + - The sale price of Products can no longer be marked up as high as before + - Scientific Research now affects the rating of Products + - In general, the maximum amount of product you are able to sell is reduced + - Sale bonus from advertising (popularity/awareness) now has diminishing returns rather than scaling linearly +- Experience gained during Infiltration now scales linearly based on the clearance level you reach. Compared to before, the experience gained will be much less at lower clearance levels, but much more at higher clearance levels +- The editor can now be used to edit both scripts and text files +- New Terminal config file that can be edited using the command 'nano .fconf'. Right now there is only one option, but there will be more in the future. +- You can now enable Bash-style Terminal hotkeys using the .fconf file referenced above +- Bug Fix: Fixed an issue with the UI elements of Gang Management persisting across different instances of BitNode-2 + +## v0.35.0 - 3/3/2018 + +- Minor rebalancing of BitNodes due to the fact that Corporations provide a (relatively) new method of progressing +- Corporation Management Changes: + - Once your Corporation gets big/powerful enough, you can now bribe Factions for reputation using company funds an/or stock shares + - You can now only create one Division for every Industry type + - Added several new UI/UX elements + - Wilson Analytics multiplier was significantly reduced to 1% per level (additive). + - Reduced the effect of Advert Inc upgrade. Advert Inc. upgrade price increases faster + - Materials can now be marked up at higher prices +- Added Javascript's built-in Number object to Netscript +- Added getCharacterInformation(), getCompanyFavor(), and getFactionFavor() Netscript Singularity functions +- Rebalanced Singularity Function RAM Costs. They now cost x8 as much when outside of BN-4 (rather than x10). Also, many of the functions now use significantly less RAM +- Refactored Netscript Ports. You can now get a handle for a Netscript port using the getPortHandle() Netscript function. This allows you to access a port's underlying queue (which is just an array) and also makes several new functions available such as tryWrite(), full(), and empty(). +- Number of Netscript Ports increased from 10 to 20 +- Netscript assignments should now return proper values. i.e. i = 5 should return 5. +- Added throw statements to Netscript. It's not super useful since 'catch' isn't implemented, but it can be used to generate custom runtime error messages. +- Added import declaration to Netscript. With this, you are able to import functions (and only functions) from other files. Using export declarations is not necessary +- Most Netscript Runtime errors (the ones that cause your script to crash) should now include the line number where the error occured +- When working for a company, your current company reputation is now displayed +- Whenever you get a Faction Invite it will be immediately appended to your 'invited factions' list. Therefore the checkFactionInvitations() Singularity Function should now be properly useable since you no longer need to decline a Faction Invitation before it shows up in the result. +- Bug Fix: When purchasing servers, whitespace should now automatically be removed from the hostname +- Bug Fix: Can no longer have whitespace in the filename of text files created using write() +- Bug Fix: In Netscript, you can no longer assign a Hacknet Node handle (hacknetnodes[i]) to another value +- Bug Fix: If you are in the Factions tab when you accept an invitation from a Faction, the page will now properly 'refresh' +- Bug Fix: Scripts that run recursive functions should now be killed properly + +## v0.34.5 - 2/24/2018 + +- Corporation Management Changes: + - Market Research unlocks are now cheaper + - New 'VeChain' upgrade: displays useful statistics about Corporation + - Corporation cycles are processed 25% faster + - Corporation valuation was lowered by ~10% (this affects stock price and investments) + - Rebalanced the effects of advertising. Should now be more effective for every Industry + - Fixed several bugs/exploits involving selling and buying back stock shares + - You will now receive a Corporation Handbook (.lit file) when starting out BitNode-3. It contains a brief guide to help you get started. This same handbook can be viewed from the Corporation management screen + - Slightly decreased the amount by which a Product's sell price can be marked up + - Employees can now be assigned to a 'Training' task, during which they will slowly increase several of their stats +- Hopefully fixed an exploit with Array.forEach(). If there are any issues with using forEach, let me know +- Arguments passed into a script are now passed by value. This means modifying the 'args' array in a script should no longer cause issues +- Scripts executed programatically (via run(), exec(), etc.) will now fail if null/undefined is passed in as an argument +- Added peek() Netscript function +- killall() Netscript function now returns true if any scripts were killed, and false otherwise. +- hack() Netscript function now returns the amount of money gained for successful hacks, and 0 for failed hacks +- scp Terminal command and Netscript function now work for txt files +- Changes courtesy of Wraithan: + - Text files are now displayed using 'pre' rather than 'p' elements when using the 'cat' Terminal command. This means tabs are retained and lines don't automatically wrap + - ls() Netscript function now returns text files as well +- Removed round() Netscript function, since you can just use Math.round() instead +- Added disableLog() and enableLog() Netscript functions +- Removed the 'log' argument from sleep(), since you can now use the new disableLog function +- 'Netscript Documentation' button on script editor now points to new readthedocs documentation rather than wiki +- When working for a faction, your current faction reputation is now displayed +- Bug Fix: Hacking Missions should no longer break when dragging an existing connection to another Node +- Bug Fix: Fixed RAM usage of getNextHacknetNodeCost() (is not 1.5GB instead of 4GB) + +## v0.34.4 - 2/14/2018 + +- Added several new features to Gang UI to make it easier to manage your Gang. +- Changed the Gang Member upgrade mechanic. Now, rather than only being able to have one weapon/armor/vehicle/etc., you can purchase all the upgrades for each Gang member and their multipliers will stack. To balance this out, the effects (AKA multipliers) of each Gang member upgrade were reduced. +- Added a new script editor option: Max Error Count. This affects how many approximate lines the script editor will process (JSHint) for common errors. Increasing this option can affect negatively affect performance +- Game theme colors (set using 'theme' Terminal command) are now saved when re-opening the game +- 'download' Terminal command now works on scripts +- Added stopAction() Singularity function and the spawn() Netscript function +- The 'Purchase Augmentations' UI screen will now tell you if you need a certain prerequisite for Augmentations. +- Augmentations with prerequisites can now be purchased as long as their prerequisites are puchased (before, you had to actually install the prerequisites before being able to purchase) + +## v0.34.3 - 1/31/2018 + +- Minor balance changes to Corporations: + - Upgrades are generally cheaper and/or have more powerful effects. + - You will receive more funding while your are a private company. + - Product demand decreases at a slower rate. + - Production multiplier for Industries (receives for owning real estate/hardware/robots/etc.) is slightly higher +- Accessing the hacknetnodes array in Netscript now costs 4.0GB of RAM (only counts against RAM usage once) +- Bug Fix: Corporation oustanding shares should now be numeric rather than a string +- Bug Fix: Corporation production now properly calculated for industries that dont produce materials. +- Bug Fix: Gangs should now properly reset when switching BitNodes +- Bug Fix: Corporation UI should now properly reset when you go public + +## v0.34.2 - 1/27/2018 + +- Corporation Management Changes: + - Added advertising mechanics + - Added Industry-specific purchases + - Re-designed employee management UI + - Rebalancing: Made many upgrades/purchases cheaper. Receive more money from investors in early stage. Company valuation is higher after going public + - Multiple bug fixes +- Added rm() Netscript function +- Updated the way script RAM usage is calculated. Now, a function only increases RAM usage the first time it is called. i.e. even if you call hack() multiple times in a script, it only counts against RAM usage once. The same change applies for while/for loops and if conditionals. +- The RAM cost of the following were increased: + - If statements: increased by 0.05GB + - run() and exec(): increased by 0.2GB + - scp(): increased by 0.1GB + - purchaseServer(): increased by 0.25GB +- Note: You may need to re-save all of your scripts in order to re-calculate their RAM usages. Otherwise, it should automatically be re-calculated when you reset/prestige +- The cost to upgrade your home computer's RAM has been increased (both the base cost and the exponential upgrade multiplier) +- The cost of purchasing a server was increased by 10% (it is now \$55k per RAM) +- Bug fix: (Hopefully) removed an exploit where you could avoid RAM usage for Netscript function calls by assigning functions to a variable (foo = hack(); foo('helios');) +- Bug fix: (Hopefully) removed an exploit where you could run arbitrary Javascript code using the constructor() method +- Thanks to Github user mateon1 and Reddit users havoc_mayhem and spaceglace for notifying me of the above exploits +- The fileExists() Netscript function now works on text files (.txt). Thanks to Github user devoidfury for this + +## v0.34.1 - 1/19/2018 + +- Updates to Corporation Management: + - Added a number of upgrades to various aspects of your Corporation + - Rebalanced the properties of Materials and the formula for determining the valuation of the Corporation + - Fixed a number of bugs +- 'Stats' page now shows information about current BitNode +- You should now be able to create Corporations in other BitNodes if you have Source-File 3 +- Added a new create-able program called b1t_flum3.exe. This program can be used to reset and switch BitNodes +- Added an option to adjust autosave interval +- Line feeds, newlines, and tabs will now work with the tprint() Netscript function +- Bug fix: 'check' Terminal command was broken +- Bug fix: 'theme' Terminal command was broken when manually specifying hex codes +- Bug fix: Incorrect promotion requirement for 'Business'-type jobs +- Bug fix: Settings input bars were incorrectly formatted when loading game + +## v0.34.0 - 12/6/2017 + +- Added clear() and exit() Netscript functions +- When starting out or prestiging, you will now receive a 'Hacking Starter Guide'. It provides tips/pointers for new players +- Doubled the amount of RAM on low-level servers (up to required hacking level 150) +- Slightly increased experience gain from Infiltration +- buyStock(), sellStock(), shortStock(), and sellShort() Netscript function now return the stock price at which the transaction occurred, rather than a boolean. If the function fails for some reason, 0 will be returned. +- Hacking Mission Changes: + - You can now select multiple Nodes of the same type by double clicking. This allows you to set the action of all of selected nodes at once (e.g. set all Transfer Nodes to Fortify). Creating connections does not work with this multi-select functionality yet + - Shield and Firewall Nodes can now fortify + - The effects of Fortifying are now ~5% lower + - Conquering a Spam Node now increases your time limit by 25 seconds instead of 15 + - Damage dealt by Attacking was slightly reduced + - The effect of Scanning was slightly reduced + - Enemy CPU Core Nodes start with slightly more attack. Misc Nodes start with slightly less defense +- Corporation Management changes: + - Added several upgrades that unlock new features + - Implemented Exporting mechanic + - Fixed many bugs + +## v0.33.0 - 12/1/2017 + +- Added BitNode-3: Corporatocracy. In this BitNode you can start and manage your own corporation. This feature is incomplete. Much more will be added to it in the near future +- Minor bug fixes + +## v0.32.1 - 11/2/2017 + +- Updated Netscript's 'interpreter/engine' to use the Bluebird promise library instead of native promises. It should now be faster and more memory-efficient. If this has broken any Netscript features please report it through Github or the subreddit (reddit.com/r/bitburner) +- Rebalanced stock market (adjusted parameters such as the volatility/trends/starting price of certain stocks) +- Added prompt() Netscript function +- Added 'Buy Max' and 'Sell All' functions to Stock Market UI +- Added 'Portfolio' Mode to Stock Market UI so you can only view stocks you have a position/order in +- Added a button to kill a script from its log display box + +## v0.32.0 - 10/25/2017 + +- Added BitNode-8: Ghost of Wall Street +- Re-designed Stock Market UI +- Minor bug fixes + +## v0.31.0 - 10/15/2017 + +- Game now saves to IndexedDb (if your browser supports it). This means you should no longer have trouble saving the game when your save file gets too big (from running too many scripts). The game will still be saved to localStorage as well +- New file type: text files (.txt). You can read or write to text files using the read()/write() Netscript commands. You can view text files in Terminal using 'cat'. Eventually I will make it so you can edit them in the editor but that's not available yet. You can also download files to your real computer using the 'download' Terminal command +- Added a new Crime: Bond Forgery. This crime takes 5 minutes to attempt and gives \$4,500,000 if successful. It is meant for mid game. +- Added commitCrime(), getCrimeChance(), isBusy(), and getStats() Singularity Functions. +- Removed getIntelligence() Netscript function +- Added sprintf and vsprintf to Netscript. See [https://github.com/alexei/sprintf.js this Github page for details] +- Increased the amount of money gained from Infiltration by 20%, and the amount of faction reputation by 12% +- Rebalanced BitNode-2 so that Crime and Infiltration are more profitable but hacking is less profitable. Infiltration also gives more faction rep +- Rebalanced BitNode-4 so that hacking is slightly less profitable +- Rebalanced BitNode-5 so that Infiltration is more profitable and gives more faction rep +- Rebalanced BitNode-11 so that Crime and Infiltration are more profitable. Infiltration also gives more faction rep. +- Fixed an annoying issue in Hacking Missions where sometimes you would click a Node but it wouldnt actually get selected +- Made the Hacking Mission gameplay a bit slower by lowering the effect of Scan and reducing Attack damage +- Slightly increased the base reputation gain rate for factions when doing Field Work and Security Work + +## v0.30.0 - 10/9/2017 + +- Added getAugmentations() and getAugmentationsFromFaction() Netscript Singularity Functions +- Increased the rate of Intelligence exp gain +- Added a new upgrade for home computers: CPU Cores. Each CPU core on the home computer grants an additional starting Core Node in Hacking Missions. I may add in other benefits later. Like RAM upgrades, upgrading the CPU Core on your home computer persists until you enter a new BitNode. +- Added lscpu Terminal command to check number of CPU Cores +- Changed the effect of Source-File 11 and made BitNode-11 a little bit harder +- Fixed a bug with Netscript functions (the ones you create yourself) +- Hacking Missions officially released (they give reputation now). Notable changes in the last few updates: + - Misc Nodes slowly gain hp/defense over time + - Conquering a Misc Node will increase the defense of all remaining Misc Nodes that are not being targeted by a certain percentage + - Reputation reward for winning a Mission is now affected by faction favor and Player's faction rep multiplier + - Whenever a Node is conquered, its stats are reduced + +## v0.29.3 - 10/3/2017 + +- Fixed bug for killing scripts and showing error messages when there are errors in a player-defined function +- Added function name autocompletion in Script Editor. Press Ctrl+space on a prefix to show autocompletion options. +- Minor rebalancing and bug fixes for Infiltration and Hacking Missions + +## v0.29.2 - 10/1/2017 + +- installAugmentations() Singularity Function now takes a callback script as an argument. This is a script that gets ran automatically after Augmentations are installed. The script is run with no arguments and only a single thread, and must be found on your home computer. +- Added the ability to create your own functions in Netscript. See [[Netscript Functions|this link]] for details +- Added :q, :x, and :wq Vim Ex Commands when using the Vim script editor keybindings. :w, :x, and :wq will all save the script and return to Terminal. :q will quit (return to Terminal) WITHOUT saving. If anyone thinks theres an issue with this please let me know, I don't use Vim +- Added a new Augmentation: ADR-V2 Pheromone Gene +- In Hacking Missions, enemy nodes will now automatically target Nodes and perform actions. +- Re-balanced Hacking Missions through minor tweaking of many numbers +- The faction reputation reward for Hacking Missions was slightly increased + +## v0.29.1 - 9/27/2017 + +- New gameplay feature that is currently in BETA: Hacking Missions. Hacking Missions is an active gameplay mechanic (its a minigame) that is meant to be used to earn faction reputation. However, since this is currently in beta, hacking missions will NOT grant reputation for the time being, since the feature likely has many bugs, balance problems, and other issues. If you have any feedback regarding the new feature, feel free to let me know +- CHANGED THE RETURN VALUE OF getScriptIncome() WHEN RAN WITH NO ARGUMENTS. It will now return an array of two values rather than a single value. This may break your scripts, so make sure to update them! +- Added continue statement for for/while loops +- Added getServerMinSecurityLevel(), getPurchasedServers(), and getTimeSinceLastAug() Netscript functions +- Netscript scp() function can now take an array as the first argument, and will try to copy every file specified in the array (it will just call scp() normally for every element in the array). If an array is passed in, then the scp() function returns true if at least one element from the array is successfully copied +- Added Javascript's Date module to Netscript. Since 'new' is not supported in Netscript yet, only the Date module's static methods will work (now(), UTC(), parse(), etc.). +- Failing a crime now gives half the experience it did before +- The forced repeated 'Find The-Cave' message after installing The Red Pill Augmentation now only happens if you've never destroyed a BitNode before, and will only popup every 15 minutes. If you have already destroyed a BitNode, the message will not pop up if you have messages suppressed (if you don't have messages suppressed it WILL still repeatedly popup) +- fileExists() function now works on literature files + +## v0.29.0 - 9/19/2017 + +- Added BitNode-5: Artificial Intelligence +- Added getIp(), getIntelligence(), getHackingMultipliers(), and getBitNodeMultipliers() Netscript functions (requires Source-File 5) +- Updated scan() Netscript function so that you can choose to have it print IPs rather than hostnames +- Refactored scp() Netscript function so that it takes an optional 'source server' argument +- For Infiltration, decreased the percentage by which the security level increases by about 10% for every location +- Using :w in the script editor's Vim keybinding mode should now save and quit to Terminal +- Some minor optimizations that should reduce the size of the save file +- scan-analyze Terminal command will no longer show your purchased servers, unless you pass a '-a' flag into the command +- After installing the Red Pill augmentation from Daedalus, the message telling you to find 'The-Cave' will now repeatedly pop up regardless of whether or not you have messages suppressed +- Various bugfixes + +## v0.28.6 - 9/15/2017 + +- Time required to create programs now scales better with hacking level, and should generally be much faster +- Added serverExists(hostname/ip) and getScriptExpGain(scriptname, ip, args...) Netscript functions +- Short circuiting && and || logical operators should now work +- Assigning to multidimensional arrays should now work +- Scripts will no longer wait for hack/grow/weaken functions to finish if they are killed. They will die immediately +- The script loop that checks whether any scripts need to be started/stopped now runs every 6 seconds rather than 10 (resulting in less delays when stopping/starting scripts) +- Fixed several bugs/exploits +- Added some description for BitNode-5 (not implemented yet, should be soon though) + +## v0.28.5 - 9/13/2017 + +- The fl1ght.exe program that is received from jump3r is now sent very early on in the game, rather than at hacking level 1000 +- Hostname is now displayed in Terminal +- Syntax highlighting now works for all Netscript functions +- Export should now work on Edge/IE + +## v0.28.4 - 9/11/2017 + +- Added getScriptIncome() Netscript function +- Added Javascript's math module to Netscript. See [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math this link for details] +- Added several member variables for the Hacknet Node API that allow you to access info about their income +- All valid Netscript functions are now syntax highlighted as keywords in the editor. This means they will a different color than invalid netscript functions. The color will depend on your theme. Note that right now, this only applies for normal Netscript functions, not functions in the TIX API, Hacknet Node API, or Singularity Functions. +- Comments and operators no longer count towards RAM usage in scripts. +- Variety of bug fixes and updates to informational text in the game + +## v0.28.3 - 9/7/2017 + +- Added ls() Netscript function +- Increased company wages by about ~10% across the board +- The scp() Netsction function and Terminal command now works for .lit files +- Increased the amount of RAM on many lower level servers (up to level 200 hacking level required). + +## v0.28.2 - 9/4/2017 + +- Added several configuration options for script editor (key bindings, themes, etc.) +- Certain menu options will now be hidden until their relevant gameplay is unlocked. This includes the Factions, Augmentations, Create Program, Travel, and Job tabs. This will only affect newer players. +- Most unrecognize or un-implemented syntax errors in Netscript will now include the line number in the error message + +## v0.28.1 - 9/1/2017 + +- The script editor now uses the open-source Ace editor, which provides a much better experience when coding! +- Added tprint() Netscript function + +## v0.28.0 - 8/30/2017 + +- Added BitNode-4: The Singularity +- Added BitNode-11: The Big Crash +- Migrated the codebase to use webpack (doesn't affect any in game content, except maybe some slight performance improvements and there may be bugs that result from dependency errors + +## v0.27.3 - 8/19/2017 + +- You can now purchase upgrades for Gang Members (BitNode 2 only) +- Decreased Gang respect gains and slightly increased wanted gains (BitNode 2 only) +- Other gangs will increase in power faster (BitNode 2 only) +- Added getHackTime(), getGrowTime(), and getWeakenTime() Netscript functions + +## v0.27.2 - 8/18/2017 + +- Added getServerGrowth() Netscript function +- Added getNextHacknetNodeCost() Netscript function +- Added new 'literature' files (.lit extension) that are used to build lore for the game. These .lit files can be found in certain servers throughout the game. They can be viewed with the 'cat' Terminal command and copied over to other servers using the 'scp' command. These .lit files won't be found until you reset by installing Augmentations +- Fixed some bugs with Gang Territory(BitNode 2 only) + +## v0.27.1 - 8/15/2017 + +- Changed the way Gang power was calculated to make it scale better late game (BitNode 2 only) +- Lowered the respect gain rate in Gangs (Bitnode 2 only) +- Added '| grep pattern' option for ls Terminal command. This allows you to only list files that contain a certain pattern +- Added break statement in Netscript +- Display for some numerical values is now done in shorthand (e.g 1.000m instead of 1,000,000) + +## v0.27.0 - 8/13/2017 + +- Added secondary 'prestige' system - featuring Source Files and BitNodes +- MILD SPOILERS HERE: Installing 'The Red Pill' Augmentation from Daedalus will unlock a special server called w0r1d_d43m0n. Finding and manually hacking this server through Terminal will destroy the Player's current BitNode, and allow the player to enter a new one. When destroying a BitNode, the player loses everything except the scripts on his/her home computer. The player will then gain a powerful second-tier persistent upgrade called a Source File. The player can then enter a new BitNode to start the game over. Each BitNode has different characteristics, and many will have new content/mechanics as well. Right now there are only 2 BitNodes. Each BitNode grants its own unique Source File. Restarting and destroying a BitNode you already have a Source File for will upgrade your Source File up to a maximum level of 3. + +- Reputation gain with factions and companies is no longer a linear conversion, but an exponential one. It will be much easier to gain faction favor at first, but much harder later on. +- Significantly increased Infiltration exp gains +- Fixed a bug with company job requirement tooltips +- Added scriptRunning(), scriptKill(), and getScriptRam() Netscript functions. See documentation for details +- Fixed a bug with deleteServer() Netscript function + +## v0.26.4 - 8/1/2017 + +- All of the 'low-level servers' in early game that have a required hacking level now have 8GB of RAM instead of 4GB +- Increased the amount of experience given at university +- Slightly increased the production of Hacknet Nodes and made them cheaper to upgrade +- Infiltration now gives slightly more EXP and faction reputation +- Added two new crimes. These crimes are viable to attempt early on in the game and are relatively passive (each take 60+ seconds to complete) +- Crimes give more exp and more money +- Max money available on a server decreased from 50x the server's starting money to 25x +- Significantly increased wages for all jobs + +## v0.26.3 + +- Added support for large numbers using Decimal.js. Right now it only applies for the player's money +- Purchasing servers with the Netscript function purchaseServer() is no longer 2x as expensive as doing manually it now costs the same +- Early game servers have more starting money + +## v0.26.2 + +- Major rebalancing and randomization of the amount of money that servers start with +- Significantly lowered hacking exp gain from hacking servers. The exp gain for higher-level servers was lowered more than that of low level servers. (~16% for lower level servers, up to ~25% for higher-level servers) +- Added deleteServer() Netscript function +- You can now purchase a maximum of 25 servers each run (Deleting a server will allow you to purchase a new one) +- Added autocompletion for './' Terminal command +- Darkweb prices now displayed properly using toLocaleString() +- Added NOT operator (!) and negation operator(-) in Netscript, so negative numbers should be functional now +- Rejected faction invitations will now show up as 'Outstanding Faction Invites' in the Factions page. These can be accepted at any point in the future +- Added a few more configurable game settings for suppressing messages and faction invitations +- Added tooltips for company job requirements + +## v0.26.1 + +- Added autocompletion for aliases +- Added getServerRam() Netscript function() +- Added getLevelUpgradeCost(n), getRamUpgradeCost(), getCoreUpgradeCost() functions for Netscript Hacknet Node API +- Added some configurable settings (See Game Options menu) + +## v0.26.0 + +- Game now has a real ending, although it's not very interesting/satisfying right now. It sets up the framework for the secondary prestige system in the future +- Forgot to mention that since last update, comments now work in Netscript. Use // for single line comments or /\* and \*/ for multiline comments just like in Javascript +- Added ports to Netscript. These ports are essentially serialized queues. You can use the write() Netscript function to write a value to a queue, and then you can use the read() Netscript function to read the value from the queue. Once you read a value from the queue it will be removed. There are only 10 queues (1-10), and each has a maximum capacity of 50 entries. If you try to write to a queue that is full, the the first value is removed. See wiki/Netscript documentation for more details +- You can now use the 'help' Terminal command for specific commands +- You can now use './' to run a script/program (./NUKE.exe). However, tab completion currently doesn't work for it (I'm working on it) +- Decreased the base growth rate of servers by ~25% +- Both the effect of weaken() and its time to execute were halved. In other words, calling weaken() on a server only lowers its security by 0.05 (was 0.1 before) but the time to execute the function is half of what it was before. Therefore, the effective rate of weaken() should be about the same +- Increased all Infiltration rewards by ~10%, and increased infiltration rep gains by an additional 20% (~32% total for rep gains) +- The rate at which the security level of a facility increases during Infiltration was decreased significantly (~33%) +- Getting treated at the Hospital is now 33% more expensive +- Slightly increased the amount of time it takes to hack a server +- Slightly decreased the amount of money gained when hacking a server (~6%) +- Slightly decreased the base cost for RAM on home computer, but increased the cost multiplier. This means that upgrading RAM on the home computer should be slightly cheaper at the start, but slightly more expensive later on +- Increased the required hacking level for many late game servers +- The sleep() Netscript function now takes an optional 'log' argument that specifies whether or not the 'Sleeping for N milliseconds' will be logged for the script +- Added clearLog() Netscript function +- Deleted a few stocks. Didn't see a reason for having so many, and it just affects performance. Won't take effect until you reset by installing Augmentations +- There was a typo with Zeus Medical's server hostname. It is now 'zeus-med' rather than 'zeud-med' +- Added keyboard shortcuts to quickly navigate between different menus. See wiki link (http://bitburner.wikia.com/wiki/Shortcuts) +- Changed the Navigation Menu UI + +## v0.25.0 + +- Refactored Netscript to use the open-source Acorns Parser. This re-implementation was done by [https://github.com/MrNuggelz Github user MrNuggelz]. This has resulted in several changes in the Netscript language. Some scripts might break because of these changes. Changes listed below: +- Arrays are now fully functional Javascript arrays. You no longer need to use the 'Array' keyword to declare them. +- The length(), clear/clear(), insert(), and remove() functions no longer work for arrays. +- All Javascript array methods are available (splice(), push(), pop(), join(), shift(), indexOf(), etc. See documentation) +- Variables assigned to arrays are now passed by value rather than reference + +- Incrementing/Decrementing are now available (i++, ++i) + +- You no longer need semicolons at the end of block statements + +- Elif is no longer valid. Use 'else if' instead + +- Netscript's Hacknet Node API functions no longer log anything +- Stock prices now update every ~6 seconds when the game is active (was 10 seconds before) +- Added a new mechanic that affects how stock prices change +- Script editor now has dynamic indicators for RAM Usage and Line number +- Augmentation Rebalancing - Many late game augmentations are now slightly more expensive. Several early game augmentations had their effects slightly decreased +- Increased the amount of rewards (both money and rep) you get from infiltration +- Purchasing servers is now slightly more expensive +- Calling the Netscript function getServerMoneyAvailable('home') now return's the player's money +- Added round(n) Netscript function - Rounds a number +- Added purchaseServer(hostname, ram) Netscript function +- Added the TIX API. This must be purchased in the WSE. It persists through resets. Access to the TIX API allows you to write scripts that perform automated algorithmic trading. See Netscript documentation +- Minor rebalancing in a lot of different areas +- Changed the format of IP Addresses so that they are smaller (will consist mostly of single digit numbers now). This will reduce the size of the game's save file. + +## v0.24.1 + +- Adjusted cost of upgrading home computer RAM. Should be a little cheaper for the first few upgrades (up to ~64GB), and then will start being more expensive than before. High RAM upgrades should now be significantly more expensive than before. +- Slightly lowered the starting money available on most mid-game and end-game servers (servers with required hacking level greater than 200) by about 10-15% +- Rebalanced company/company position reputation gains and requirements +- Studying at a university now gives slightly more EXP and early jobs give slightly less EXP +- Studying at a university is now considerably more expensive +- Rebalanced stock market +- Significantly increased cost multiplier for purchasing additional Hacknet Nodes +- The rate at which facility security level increases during infiltration for each clearance level was lowered slightly for all companies +- Updated Faction descriptions +- Changed the way alias works. Normal aliases now only work at the start of a Terminal command (they will only replace the first word in the Terminal command). You can also create global aliases that work on any part of the command, like before. Declare global aliases by entering the optional -g flag: alias -g name="value" - [https://github.com/MrNuggelz Courtesy of Github user MrNuggelz] +- 'top' Terminal command implemented courtesy of [https://github.com/LTCNugget Github user LTCNugget]. Currently, the formatting gets screwed up if your script names are really long. + +## v0.24.0 + +- Players now have HP, which is displayed in the top right. To regain HP, visit the hospital. Currently the only way to lose HP is through infiltration +- Infiltration - Attempt to infiltrate a company and steal their classified secrets. See 'Companies' documentation for more details +- Stock Market - Added the World Stock Exchange (WSE), a brokerage that lets you buy/sell stocks. To begin trading you must first purchase an account. A WSE account will persist even after resetting by installing Augmentations. How the stock market works should hopefully be self explanatory. There is no documentation about it currently, I will add some later. NOTE: Stock prices only change when the game is open. The Stock Market is reset when installing Augmentations, which means you will lose all your stocks +- Decreased money gained from hacking by ~12% +- Increased reputation required for all Augmentations by ~40% +- Cost increase when purchasing multiple augmentations increased from 75% to 90% +- Added basic variable runtime to Netscript operations. Basic commands run in 100ms. Any function incurs another 100ms in runtime (200ms total). Any function that starts with getServer incurs another 100ms runtime (300ms total). exec() and scp() require 400ms total. +- Slightly reduced the amount of experience gained from hacking + +## v0.23.1 + +- scan() Netscript function now takes a single argument representing the server from which to scan. + +## v0.23.0 + +- You can now purchase multiple Augmentations in a run. When you purchase an Augmentation you will lose money equal to the price and then the cost of purchasing another Augmentation during this run will be increased by 75%. You do not gain the benefits of your purchased Augmentations until you install them. This installation can be done through the 'Augmentation' tab. When you install your Augmentations, your game will reset like before. +- Reputation needed to gain a favor from faction decreased from 7500 to 6500 +- Reputation needed to gain a favor from company increased from 5000 to 6000 +- Reputation cost of all Augmentations increased by 16% +- Higher positions at companies now grant slightly more reputation for working +- Added getServerMaxMoney() Netscript function +- Added scan() Netscript function +- Added getServerNumPortsRequired() Netscript function +- There is now no additional RAM cost incurred when multithreading a script + +## v0.22.1 + +- You no longer lose progress on creating programs when cancelling your work. Your progress will be saved and you will pick up where you left off when you start working on it again +- Added two new programs: AutoLink.exe and ServerProfiler.exe +- Fixed bug with Faction Field work reputation gain + +## v0.22.0 - Major rebalancing, optimization, and favor system + +- Significantly nerfed most augmentations +- Almost every server with a required hacking level of 200 or more now has slightly randomized server parameters. This means that after every Augmentation purchase, the required hacking level, base security level, and growth factor of these servers will all be slightly different +- The hacking speed multiplier now increases rather than decreases. The hacking time is now divided by your hacking speed multiplier rather than multiplied. In other words, a higher hacking speed multiplier is better +- Servers now have a minimum server security, which is approximately one third of their starting ('base') server security +- If you do not steal any money from a server, then you gain hacking experience equal to the amount you would have gained had you failed the hack +- The effects of grow() were increased by 50% +- grow() and weaken() now give hacking experience based on the server's base security level, rather than a flat exp amount +- Slightly reduced amount of exp gained from hack(), weaken(), and grow() +- Rebalanced formulas that determine crime success +- Reduced RAM cost for multithreading a script. The RAM multiplier for each thread was reduced from 1.02 to 1.005 +- Optimized Script objects so they take less space in the save file +- Added getServerBaseSecurityLevel() Netscript function +- New favor system for companies and factions. Earning reputation at a company/faction will give you favor for that entity when you reset after installing an Augmentation. This favor persists through the rest of the game. The more favor you have, the faster you will earn reputation with that faction/company +- You can no longer donate to a faction for reputation until you have 150 favor with that faction +- Added unalias Terminal command +- Changed requirements for endgame Factions + +## v0.21.1 + +- IF YOUR GAME BREAKS, DO THE FOLLOWING: Options -> Soft Reset -> Save Game -> Reload Page. Sorry about that! +- Autocompletion for aliases - courtesy of [https://github.com/LTCNugget Github user LTCNugget] + +## v0.21.0 + +- Added dynamic arrays. See Netscript documentation +- Added ability to pass arguments into scripts. See documentation +- The implementation/function signature of functions that deal with scripts have changed. Therefore, some old scripts might not work anymore. Some of these functions include run(), exec(), isRunning(), kill(), and some others I may have forgot about. Please check the updated Netscript documentation if you run into issues.-Note that scripts are now uniquely identified by the script name and their arguments. For example, you can run a script using:: + + run foodnstuff.script 1 + +and you can also run the same script with a different argument:: + + run foodnstuff.script 2 + +These will be considered two different scripts. To kill the first script you must run:: + + kill foodnstuff.script 1 + +and to kill the second you must run:: + + kill foodnstuff.script 2 + +Similar concepts apply for Terminal Commands such as tail, and Netscript commands such as run(), exec(), kill(), isRunning(), etc. + +- Added basic theme functionality using the 'theme' Terminal command - All credit goes to /u/0x726564646974 who implemented the awesome feature +- Optimized Script objects, which were causing save errors when the player had too many scripts +- Formula for determining exp gained from hacking was changed +- Fixed bug where you could purchase Darkweb items without TOR router +- Slightly increased cost multiplier for Home Computer RAM +- Fixed bug where you could hack too much money from a server (and bring its money available below zero) +- Changed tail command so that it brings up a display box with dynamic log contents. To get old functionality where the logs are printed to the Terminal, use the new 'check' command +- As a result of the change above, you can no longer call tail/check on scripts that are not running +- Added autocompletion for buying Programs in Darkweb + +## v0.20.2 + +- Fixed several small bugs +- Added basic array functionality to Netscript +- Added ability to run scripts with multiple threads. Running a script with n threads will multiply the effects of all hack(), grow(), and weaken() commands by n. However, running a script with multiple threads has drawbacks in terms of RAM usage. A script's ram usage when it is 'multithreaded' is calculated as: base cost _ numThreads _ (1.02 ^ numThreads). A script can be run multithreaded using the 'run [script] -t n' Terminal command or by passing in an argument to the run() and exec() Netscript commands. See documentation. +- RAM is slightly (~10%) more expensive (affects purchasing server and upgrading RAM on home computer) +- NeuroFlux Governor augmentation cost multiplier decreased +- Netscript default operation runtime lowered to 200ms (was 500ms previously) + +## v0.20.1 + +- Fixed bug where sometimes scripts would crash without showing the error +- Added Deepscan programs to Dark Web +- Declining a faction invite will stop you from receiving invitations from that faction for the rest of the run +- (BETA) Added functionality to export/import saves. WARNING This is only lightly tested. You cannot choose where to save your file it just goes to the default save location. Also I have no idea what will happen if you try to import a file that is not a valid save. I will address these in later updates + +## v0.20.0 + +- Refactored Netscript Interpreter code. Operations in Netscript should now run significantly faster (Every operation such as a variable assignment, a function call, a binary operator, getting a variable's value, etc. used to take up to several seconds, now each one should only take ~500 milliseconds). +- Percentage money stolen when hacking lowered to compensate for faster script speeds +- Hacking experience granted by grow() halved +- Weaken() is now ~11% faster, but only grants 3 base hacking exp upon completion instead of 5 +- Rebalancing of script RAM costs. Base RAM Cost for a script increased from 1GB to 1.5GB. Loops, hack(), grow() and weaken() all cost slightly less RAM than before +- Added getServerRequiredHackingLevel(server) Netscript command. +- Added fileExists(file, [server]) Netscript command, which is used to check if a script/program exists on a specified server +- Added isRunning(script, [server]) Netscript command, which is used to check if a script is running on the specified server +- Added killall Terminal command. Kills all running scripts on the current machine +- Added kill() and killall() Netscript commands. Used to kill scripts on specified machines. See Netscript documentation +- Re-designed 'Active Scripts' tab +- Hacknet Node base production rate lowered from 1.6 to 1.55 (\$/second) +- Increased monetary cost of RAM (Upgrading home computer and purchasing servers will now be more expensive) +- NEW GROWTH MECHANICS - The rate of growth on a server now depends on a server's security level. A higher security level will result in lower growth on a server when using the grow() command. Furthermore, calling grow() on a server raises that server's security level by 0.004. For reference, if a server has a security level of 10 it will have approximately the same growth rate as before. +- Server growth no longer happens naturally +- Servers now have a maximum limit to their money. This limit is 50 times it's starting money +- Hacking now grants 10% less hacking experience +- You can now edit scripts that are running +- Augmentations cost ~11% more money and 25% more faction reputation + +## v0.19.7 + +- Added changelog to Options menu +- Bug fix with autocompletion (wasn't working properly for capitalized filenames/programs + +## v0.19.6 + +- Script editor now saves its state even when you change tabs +- scp() command in Terminal/script will now overwrite files at the destination +- Terminal commands are no longer case-sensitive (only the commands themselves such as 'run' or 'nano'. Filenames are still case sensitive +- Tab automcompletion will now work on commands + +## v0.19.0 + +- Hacknet Nodes have slightly higher base production, and slightly increased RAM multiplier. But they are also a bit more expensive at higher levels +- Calling grow() and weaken() in a script will now work offline, at slower rates than while online (The script now keeps track of the rate at which grow() and weaken() are called when the game is open. These calculated rates are used to determine how many times the calls would be made while the game is offline) +- Augmentations now cost 20% more reputation and 50% more money +- Changed the mechanic for getting invited to the hacking factions (CyberSec, NiteSec, The Black Hand, BitRunners) Now when you get to the required level to join these factions you will get a message giving you instructions on what to do in order to get invited. +- Added a bit of backstory/plot into the game. It's not fully fleshed out yet but it will be used in the future +- Made the effects of many Augmentations slightly more powerful +- Slightly increased company job wages across the board (~5-10% for each position) +- Gyms and classes are now significantly more expensive +- Doubled the amount by which a server's security increases when it is hacked. Now, it will increase by 0.002. Calling weaken() on a server will lower the security by 0.1. + +## v0.18.0 + +- Major rebalancing (sorry didn't record specifics. But in general hacking gives more money and hacknet nodes give less) +- Server growth rate (both natural and manual using grow()) doubled +- Added option to Soft Reset +- Cancelling a full time job early now only results in halved gains for reputation. Exp and money earnings are gained in full +- Added exec() Netscript command, used to run scripts on other servers. +- NEW HACKING MECHANICS: Whenever a server is hacked, its 'security level' is increased by a very small amount. The security level is denoted by a number between 1-100. A higher security level makes it harder to hack a server and also decreases the amount of money you steal from it. Two Netscript functions, weaken() and getServerSecurityLevel() level, were added. The weaken(server) function lowers a server's security level. See the Netscript documentation for more details +- When donating to factions, the base rate is now \$1,000,000 for 1 reputation point. Before, it was \$1,000 for 1 reputation point. +- Monetary costs for all Augmentations increased. They are now about ~3.3 - 3.75 times more expensive than before + +## v0.17.1 + +- Fixed issue with purchasing Augmentations that are 'upgrades' and require previous Augmentations to be installed +- Increased the percentage of money stolen from servers when hacking + +## v0.17.0 + +- Greatly increased amount of money gained for crimes (by about 400% for most crimes) +- Criminal factions require slightly less negative karma to get invited to +- Increased the percentage of money stolen from servers when hacking +- Increased the starting amount of money available on beginning servers (servers with <50 required hacking)) +- Increased the growth rate of servers (both naturally and manually when using the grow() command in a script) +- Added getHostname() command in Netscript that returns the hostname of the server a script is running on +- jQuery preventDefault() called when pressing ctrl+b in script editor +- The Neuroflux Governor augmentation (the one that can be repeatedly leveled up) now increases ALL multipliers by 1%. To balance it out, it's price multiplier when it levels up was increased +- Hacknet Node base production decreased from \$1.75/s to \$1.65/s +- Fixed issue with nested for loops in Netscript (stupid Javascript references) +- Added 'scp' command to Terminal and Netscript +- Slightly nerfed Hacknet Node Kernel DNI and Hacknet Node Core DNI Augmentations +- Increased TOR Router cost to \$200k + +## v0.16.0 + +- New Script Editor interface +- Rebalanced hacknet node - Increased base production but halved the multiplier from additional cores. This should boost its early-game production but nerf its late-game production +- Player now starts with 8GB of RAM on home computer +- 'scan-analyze' terminal command displays RAM on servers +- Slightly buffed the amount of money the player steals when hacking servers (by about ~8%) +- Time to execute grow() now depends on hacking skill and server security, rather than taking a flat 2 minutes. +- Clicking outside of a pop-up dialog box will now close it +- BruteSSH.exe takes 33% less time to create +- 'iron-gym' and 'max-hardware' servers now have 2GB of RAM +- Buffed job salaries across the board +- Updated Tutorial +- Created a Hacknet Node API for Netscript that allows you to access and upgrade your Hacknet Nodes. See the Netscript documentation for more details. WARNING The old upgradeHacknetNode() and getNumHacknetNodes() functions waere removed so any script that has these will no longer work + +## v0.15.0 + +- Slightly reduced production multiplier for Hacknet Node RAM +- Faction pages now scroll +- Slightly increased amount of money gained from hacking +- Added 'alias' command +- Added 'scan-analyze' terminal command - used to get basic hacking info about all immediate network connections +- Fixed bugs with upgradeHacknetNode() and purchaseHacknetNode() commands +- Added getNumHacknetNodes() and hasRootAccess(hostname/ip) commands to Netscript +- Increased Cost of university classes/gym +- You can now see what an Augmentation does and its price even while its locked diff --git a/src/Documentation/doc/changelog-v1.md b/src/Documentation/doc/changelog-v1.md new file mode 100644 index 000000000..2f37938ae --- /dev/null +++ b/src/Documentation/doc/changelog-v1.md @@ -0,0 +1,659 @@ +# Changelog - Legacy v1 + +## v1.6.3 - 2022-04-01 Few stanek fixes + +Stanek Gift + +- Has a minimum size of 2x3 +- Active Fragment property 'avgCharge' renamed to 'highestCharge' +- Formula for fragment effect updated to make 561% more sense. + Now you can charge to your heart content. +- Logs for the 'chargeFragment' function updated. + + Misc. + +- Nerf noodle bar. + +## v1.6.0 - 2022-03-29 Grafting + +** Vitalife secret lab ** + +- A new mechanic called Augmentation Grafting has been added. Resleeving has been removed. +- Credit to @violet for her incredible work. + +** Stanek ** + +- BREAKING: Many functions in the stanek API were renamed in order to avoid name collision with things like Map.prototype.get + +** UI ** + +- Major update to Sleeve, Gang UI, and Create Program (@violet) +- re-add pre tags to support slash n in prompt (@jacktose) +- Tabelize linked output of 'ls' (@Master-Guy) +- Add the ability to filter open scripts (@phyzical) +- Add minHeight to editor tabs (@violet) +- Properly expand gang equipment cards to fill entire screen (@violet) +- Add shortcut to Faction augmentations page from FactionsRoot (@violet) +- Fix extra space on editor tabs (@violet) +- Present offline message as list (@DSteve595) +- add box showing remaining augments per faction (@jjayeon) +- Add tab switching support to vim mode (@JParisFerrer) +- Show current task on gang management screen (@zeddrak) +- Fix for ui of gang members current task when set via api (@phyzical) +- Don't hide irrelevant materials if their stock is not empty and hide irrelevant divisions from Export (@SagePtr) +- Fix regex to enable alpha transparency hex codes (8 digits) (@surdaft) + +** API ** + +- Added dark web functions to ns api +- BREAKING: purchaseTor() should returns true if player already has Tor. (@DavidGrinberg, @waffleattack) +- Implement getBonusTime in Corporation API (@t-wolfeadam) +- Added functions to purchase TIX and WSI (@incubusnb) +- purchaseSleeveAug checks shock value (@incubusnb) +- Fix bug with hacknet api +- Fix spendHashes bug +- Added 0 cost of asleep() (@Master-Guy) +- Fix some misleading corporation errors (@TheRealMaxion) +- expose the inBladeburner on the player object (@phyzical) +- added ram charge for stanek width and height (@phyzical) +- Fix sufficient player money check to buy back shares. (@ChrissiQ) +- Fix Static Ram Circumventing for some NS functions (@CrafterKolyan) +- added CorporationSoftCap to NetscriptDefinitions (@phyzical) +- Added definition of autocomplete() 'data' argument. (@tigercat2000) +- Adding support for text/select options in Prompt command (@PhilipArmstead) +- Added the ability to exportGame via api (@phyzical) + +** Arcade ** + +- Added an arcade to New Tokyo where you can play a 4 year old version of bitburner. + +** Misc. ** + +- Add a warning triggered while auto-saves are off. (@MartinFournier) +- Log info for field analysis now displays actual rank gained. (@ApamNapat) +- Removed BladeburnerSkillCost from skill point cost description. (@ApamNapat) +- Fix handling for UpArrow in bladeburner console. (@dowinter) +- Add GitHub action to check PRs for generated files. (@MartinFournier) +- Cap Staneks gift at 25x25 to prevent crashes. (@waffleattack) +- Remove old & unused files from repository. (@MartinFournier) +- Factions on the factions screens are sorted by story progress / type. (@phyzical) +- Fix log manager not picking up new runs of scripts. (@phyzical) +- Added prettier to cicd. +- UI improvements (@phyzical) +- Documentation / Typos (@nanogyth, @Master-Guy, @incubusnb, @ApamNapat, @phyzical, @SagePtr) +- Give player code a copy of Division.upgrades instead of the live object (@Ornedan) +- Fix bug with small town achievement. +- Fix bug with purchaseSleeveAug (@phyzical) +- Check before unlocking corp upgrade (@gianfun) +- General codebase improvements. (@phyzical, @Master-Guy, @ApamNapat) +- Waiting on promises in NS1 no longer freezes the script. (@Master-Guy) +- Fix bug with missing ramcost for tFormat (@TheMas3212) +- Fix crash with new prompt +- Quick fix to prevent division by 0 in terminal (@Master-Guy) +- removed ip references (@phyzical, @Master-Guy) +- Terminal now supports 'ls -l' +- Fix negative number formatting (@Master-Guy) +- Fix unique ip generation (@InDieTasten) +- remove terminal command theme from docs (@phyzical) +- Fix 'Augmentations Left' with gang factions (@violet) +- Attempt to fix 'bladeburner.process()' early routing issue (@MartinFournier) +- work in progress augment fix (@phyzical) +- Fixes missing space in Smart Supply (@TheRealMaxion) +- Change license to Apache 2 with Commons Clause +- updated regex sanitization (@mbrannen) +- Sleeve fix for when faction isnt found (@phyzical) +- Fix editor "close" naming (@phyzical) +- Fix bug with sleeves where some factions would be listed as workable. (@phyzical) +- Fix research tree of product industries post-prestige (@pd) +- Added a check for exisiting industry type before expanding (@phyzical) +- fix hackAnalyzeThreads returning infinity (@chrisrabe) +- Make growthAnalyze more accurate (@dwRchyngqxs) +- Add 'Zoom -> Reset Zoom' command to Steam (@smolgumball) +- Add hasOwnProperty check to GetServer (@SagePtr) +- Speed up employee productivity calculation (@pd) +- Field Work and Security Work benefit from 'share' (@SagePtr) +- Nerf noodle bar. + +## v1.5.0 - Steam Cloud integration + +** Steam Cloud Saving ** + +- Added support for steam cloud saving (@MartinFournier) + +** UI ** + +- background now matches game primary color (@violet) +- page title contains version (@MartinFourier) +- Major text editor improvements (@violet) +- Display bonus time on sleeve page (@MartinFourier) +- Several UI improvements (@violet, @smolgumball, @DrCuriosity, @phyzical) +- Fix aug display in alpha (@Dominik Winter) +- Fix display of corporation product equation (@SagePtr) +- Make Bitverse more accessible (@ChrissiQ) +- Make corporation warehouse more accessible (@ChrissiQ) +- Make tab style more consistent (@violet) + +** Netscript ** + +- Fix bug with async. +- Add 'printf' ns function (@Ninetailed) +- Remove blob caching. +- Fix formulas access check (@Ornedan) +- Fix bug in exp calculation (@qcorradi) +- Fix NaN comparison (@qcorradi) +- Fix travelToCity with bad argument (@SlyCedix) +- Fix bug where augs could not be purchased via sing (@reacocard) +- Fix rounding error in donateToFaction (@Risenafis) +- Fix bug with weakenAnalyze (@rhobes) +- Prevent exploit with atExit (@Ornedan) +- Double 'share' power + +** Corporations ** + +- Fix bugs with corp API (@pigalot) +- Add smart supply func to corp API (@pd) + +** Misc. ** + +- The file API now allows GET and DELETE (@lordducky) +- Force achievement calculation on BN completion (@SagePtr) +- Cleanup in repository (@MartinFourier) +- Several improvements to the electron version (@MartinFourier) +- Fix bug with casino roulette (@jamie-mac) +- Terminal history persists in savefile (@MartinFourier) +- Fix tests (@jamie-mac) +- Fix crash with electron windows tracker (@smolgumball) +- Fix BN6/7 passive reputation gain (@BrianLDev) +- Fix Sleeve not resetting on install (@waffleattack) +- Sort joined factions (@jjayeon) +- Update documentation / typo (@lethern, @Meowdoleon, @JohnnyUrosevic, @JosephDavidTalbot, + @pd, @lethern, @lordducky, @zeddrak, @fearnlj01, @reasonablytall, @MatthewTh0, + @SagePtr, @manniL, @Jedimaster4559, @loganville, @Arrow2thekn33, @wdpk, @fwolfst, + @fschoenfeldt, @Waladil, @AdamTReineke, @citrusmunch, @factubsio, @ashtongreen, + @ChrissiQ, @DJ-Laser, @waffleattack, @ApamNapat, @CrafterKolyan, @DSteve595) +- Nerf noodle bar. + +## v1.4.0 - 2022-01-18 Sharing is caring + +** Computer sharing ** + +- A new mechanic has been added, it's is invoked by calling the new function 'share'. + This mechanic helps you farm reputation faster. + +** gang ** + +- Installing augs means losing a little bit of ascension multipliers. + +** Misc. ** + +- Prevent gang API from performing actions for the type of gang they are not. (@TheMas3212) +- Fix donation to gang faction. (@TheMas3212) +- Fix gang check crashing the game. (@TheMas3212) +- Make time compression more robust. +- Fix bug with scp. +- Add zoom to steam version. (@MartinFourier) +- Fix donateToFaction accepts donation of NaN. (@woody-lam-cwl) +- Show correct hash capacity gain on cache level upgrade tooltip. (@woody-lam-cwl) +- Fix tests (@woody-lam-cwl) +- Fix cache tooltip (@woody-lam-cwl) +- Added script to prettify save file for debugging (@MartinFourier) +- Update documentation / typos (@theit8514, @thadguidry, @tigercat2000, @SlyCedix, @Spacejoker, @KenJohansson, + @Ornedan, @JustAnOkapi, @violet, @philarmstead, @TheMas3212, @dcragusa, @XxKingsxX-Pinu, + @paiv, @smolgumball, @zeddrak, @stinky-lizard, @violet, @Feodoric, @daanflore, + @markusariliu, @mstruebing, @erplsf, @waffleattack, @Dexalt142, @AIT-OLPE, @deathly809, @BuckAMayzing, + @MartinFourier, @pigalot, @lethern) +- Fix BN3+ achievement (@SagePtr) +- Fix reputation carry over bug (@TheMas3212) +- Add button to exit infiltrations (@TheMas3212) +- Add dev menu achievement check (@TheMas3212) +- Add 'host' config for electron server (@MartinFourier) +- Suppress save toast only works for autosave (@MartinFourier) +- Fix some achievements not triggering with 'backdoor' (@SagePtr) +- Update Neuroflux Governor description. +- Fix bug with electron server. +- Fix bug with corporation employee assignment function (@Ornedan) +- Add detailed information to terminal 'mem' command (@MartinFourier) +- Add savestamp to savefile (@MartinFourier) +- Dev menu can apply export bonus (@MartinFourier) +- Icarus message no longer applies on top of itself (@Feodoric) +- purchase augment via API can no longer buy Neuroflux when it shouldn't (@Feodoric) +- Syntax highlighter should be smarter (@neuralsim) +- Fix some miscalculation when calculating money stolen (@zeddrak) +- Fix max cache achievement working with 0 cache (@MartinFourier) +- Add achievements in the game, not just steam (@MartinFourier) +- Overflow hash converts to money automatically (@MartinFourier) +- Make mathjax load locally (@MartinFourier) +- Make favor calculation more efficient (@kittycat2002) +- Fix some scripts crashing the game on startup (@MartinFourier) +- Toasts will appear above tail window (@MartinFourier) +- Fix issue that can cause terminal actions to start on one server and end on another (@MartinFourier) +- Fix 'fileExists' not correctly matching file names (@TheMas3212) +- Refactor some code to be more efficient (@TheMas3212) +- Fix exp gain for terminal grow and weaken (@violet) +- Refactor script death code to reject waiting promises instead of resolving (@Ornedan) +- HP recalculates on defense exp gain (@TheMas3212) +- Fix log for ascendMember (@TheMas3212) +- Netscript ports clear on reset (@TheMas3212) +- Fix bug related to company (@TheMas3212) +- Fix bug where corporation handbook would not be correctly added (@TheMas3212) +- Servers in hash upgrades are sorted alpha (@MartinFourier) +- Fix very old save not properly migrating augmentation renamed in 0.56 (@MartinFourier) +- Add font height and line height in theme settings (@MartinFourier) +- Fix crash when quitting job (@MartinFourier) +- Added save file validation system (@TheMas3212) +- React and ReactDOM are now global objects (@pigalot) +- 'nano' supports globs (@smolgumball) +- Character overview can be dragged (@MartinFourier) +- Job page updates in real time (@violet) +- Company favor gain uses the same calculation as faction, this is just performance + the value didn't change (@violet) +- ns2 files work with more import options (@theit8514) +- Allow autocomplete for partial executables (@violet) +- Add support for contract completion (@violet) +- 'ls' link are clickable (@smolgumball) +- Prevent steam from opening external LOCAL files (@MartinFourier) +- Fix a bug with autocomplete (@Feodoric) +- Optimise achievement checks (@Feodoric) +- Hacknet server achievements grant associated hacknet node achievement (@Feodoric) +- Fix display bug with hacknet (@Feodoric) +- 'analyze' now says if the server is backdoored (@deathly809) +- Add option to exclude running script from save (@MartinFourier) +- Game now catches more errors and redirects to recovery page (@MartinFourier) +- Fix bug with autocomplete (@violet) +- Add tooltip to unfocus work (@violet) +- Add detailst overview (@MartinFourier) +- Fix focus bug (@deathly809) +- Fix some NaN handling (@deathly809) +- Added 'mv' ns function (@deathly809) +- Add focus argument to some singularity functions (@violet) +- Fix some functions not disabling log correctly (@deathly809) +- General UI improvements (@violet) +- Handle steamworks errors gravefully (@MartinFourier) +- Fix some react component not unmounting correctly (@MartinFourier) +- 'help' autocompletes (@violet) +- No longer push all achievements to steam (@Ornedan) +- Recovery page has more information (@MartinFourier) +- Added 'getGameInfo' ns function (@MartinFourier) +- SF3.3 unlocks all corp API (@pigalot) +- Major improvements to corp API (@pigalot) +- Prevent seed money outside BN3 (@pigalot) +- Fix bug where using keyboard shortcuts would crash if the feature is not available (@MartinFourier)\ +- Sidebar remains opened/closed on save (@MartinFourier) +- Added tooltip to sidebar when closed (@MartinFourier) +- Fix bug where Formulas.exe is not available when starting BN5 (@TheMas3212) +- Fix CI (@tvanderpol) +- Change shortcuts to match sidebar (@MartinFourier) +- Format gang respect (@attrib) +- Add modal to text editor with ram details (@violet) +- Fix several bugs with singularity focus (@violet) +- Nerf noodle bar. + +## v1.3.0 - 2022-01-04 Cleaning up + +** External IDE integration ** + +- The Steam version has a webserver that allows integration with external IDEs. + A VSCode extension is available on the market place. (The documentation for the ext. isn't + written yet) + +** Source-Files ** + +- SF4 has been reworked. +- New SF -1. + +** UI ** + +- Fix some edge case with skill bat tooltips (@MartinFournier) +- Made some background match theme color (@Kejikus) +- Fix problem with script editor height not adjusting correctly (@billyvg) +- Fix some formatting issues with Bladeburner (@MartinFournier, @violet) +- Fix some functions like 'alert' format messages better (@MageKing17) +- Many community themes added. +- New script editor theme (@Hedrauta, @Dexalt142) +- Improvements to tail windows (@theit8514) +- Training is more consise (@mikomyazaki) +- Fix Investopedia not displaying properly (@JotaroS) +- Remove alpha from theme editor (@MartinFournier) +- Fix corporation tooltip not displaying properly (@MartinFournier) +- Add tooltip on backdoored location names (@MartinFournier) +- Allow toasts to be dismissed by clicking them (@violet) +- Darkweb item listing now shows what you own. (@hexnaught) + +** Bug fix ** + +- Fix unit tests (@MartinFournier) +- Fixed issue with 'cat' and 'read' not finding foldered files (@Nick-Colclasure) +- Buying on the dark web will remove incomplete exe (@hexnaught) +- Fix bug that would cause the game to crash trying to go to a job without a job (@hexnaught) +- purchaseServer validation (@violet) +- Script Editor focuses code when changing tab (@MartinFournier) +- Fix script editor for .txt files (@65-7a) +- Fix 'buy' command not displaying correctly. (@hexnaught) +- Fix hackAnalyzeThread returning NaN (@mikomyazaki) +- Electron handles exceptions better (@MageKing17) +- Electron will handle 'unresponsive' event and present the opportunity to reload the game with no scripts (@MartinFournier) +- Fix 'cp' between folders (@theit8514) +- Fix throwing null/undefined errors (@violet) +- Allow shortcuts to work when unfocused (@MageKing17) +- Fix some dependency issue (@locriacyber) +- Fix corporation state returning an object instead of a string (@antonvmironov) +- Fix 'mv' overwriting files (@theit8514) +- Fix joesguns not being influenced by hack/grow (@dou867, @MartinFournier) +- Added warning when opening external links. (@MartinFournier) +- Prevent applying for positions that aren't offered (@TheMas3212) +- Import has validation (@MartinFournier) + +** Misc. ** + +- Added vim mode to script editor (@billyvg) +- Clean up script editor code (@Rez855) +- 'cat' works on scripts (@65-7a) +- Add wordWrap for Monaco (@MartinFournier) +- Include map bundles in electron for easier debugging (@MartinFournier) +- Fix importing very large files (@MartinFournier) +- Cache program blob, reducing ram usage of the game (@theit8514) +- Dev menu can set server to \$0 (@mikomyazaki) +- 'backdoor' allows direct connect (@mikomyazaki) +- Github workflow work (@MartinFournier) +- workForFaction / workForCompany have a new parameter (@theit8514) +- Alias accept single quotes (@sporkwitch, @FaintSpeaker) +- Add grep options to 'ps' (@maxtimum) +- Added buy all option to 'buy' (@anthonydroberts) +- Added more shortcuts to terminal input (@Frank-py) +- Refactor some port code (@ErzengelLichtes) +- Settings to control GiB vs GB (@ErzengelLichtes) +- Add electron option to export save game (@MartinFournier) +- Electron improvements (@MartinFournier) +- Expose some notifications functions to electron (@MartinFournier) +- Documentation (@MartinFournier, @cyn, @millennIumAMbiguity, @2PacIsAlive, + @TheCoderJT, @hexnaught, @sschmidTU, @FOLLGAD, @Hedrauta, @Xynrati, + @mikomyazaki, @Icehawk78, @aaronransley, @TheMas3212, @Hedrauta, @alkemann, + @ReeseJones, @amclark42, @thadguidry, @jasonhaxstuff, @pan-kuleczka, @jhollowe, + @ApatheticsAnonymous, @erplsf, @daanflore, @violet, @Kebap, @smolgumball, + @woody-lam-cwl) + +## v1.1.0 - 2021-12-18 You guys are awesome (community because they're god damn awesome) + +** Script Editor ** + +- The text editor can open several files at once. (@Rez855 / @Shadow72) + It's not perfect so keep the feedback coming. + +** Steam ** + +- Windows has a new launch option that lets player start with killing all their scripts + This is a safety net in case all the other safety nets fail. +- Linux has several launch options that use different flags for different OS. +- Debug and Fullscreen are available in the window utility bar. +- Tried (and maybe failed) to make the game completely kill itself after closing. + This one I still don't know wtf is going. +- No longer has background throttling. +- Default color should be pitch black when loading +- Add BN13: Challenge achievement. + +** Tutorial ** + +- I watched someone play bitburner on youtube and reworked part of + the tutorial to try to make some parts of the game clearer. + https://www.youtube.com/watch?v=-_JETXff4Zo +- Add option to restart tutorial. + +** Netscript ** + +- getGangInformation returns more information. +- getAscensionResult added +- getMemberInformation returns more info +- Formulas API has new functions for gang. +- Added documentation for corp API. +- exec has clearer error message when you send invalid data. +- getServer returns all defined field for hacknet servers. +- Fix a bug with scp multiple files (@theit8514) +- Stack traces should be smarter at replacing blobs with filenames +- Fix a weird error message that would occur when throwing raw strings. +- Fix shortcuts not working. +- Re-added setFocus and isFocused (@theit8514) +- new function getHashUpgrades (@MartinFournier) +- enableLog accepts "ALL" like disableLog (@wynro) +- toast() doesn't crash on invalid data (@ivanjermakov) +- alert() doesn't crash on invalid data (@Siern) +- Fixed an issue where scripts don't run where they should. +- Sleeve getInformation now returns cha +- getServer does work with no argument now +- workForFaction returns false when it mistakenly returned null + +** Character Overview ** + +- The character overview now shows the amount of exp needed to next level (@MartinFournier) + +** Misc. ** + +- Add option to supress Game Saved! toasts (@MartinFournier) +- Fix bug where ctrl+alt+j was eaten by the wrong process. (@billyvg) +- Theme Editor lets you paste colors (@MartinFournier) +- ctrl + u/k/w should work on terminal (@billyvg) +- Game now shows commit number, this is mostly for me. (@MartinFourier) +- running a bad script will give a clearer error message (@TheCoderJT) +- Default terminal capacity is maximum (@SayntGarmo) +- Fix problems with cp and mv (@theit8514) +- Make monaco load fully offline for players behind firewalls. +- change beginer guide to use n00dles instead of foodnstuff +- BN13 is harder +- nerf int gain from manualHack +- Fix UI displaying wrong stats (@DJMatch3000) +- Fix button not disabling as it should. +- New location in Ishima. +- Add setting to suppress stock market popups. +- Typo fixes (@Hedrauta, @cvr-119, @Ationi, @millennIumAMbiguity + @TealKoi, @TheCoderJT, @cblte, @2PacIsAlive, @MageKing17, + @Xynrati, @Adraxas, @pobiega) +- Fix 100% territory achievement. +- Reword message on active scripts page. +- Fix terminal not clearing after BN +- Remove references to .fconf +- Augmentation pages shows BN difficulty with SF5 +- Fix scripts saving on wrong server while 'connect'ing +- Fix gym discount not working. +- Fix scan-analyze not working with timestamps +- Hash upgrades remember last choice. +- Save files now sort by date +- The covenant no longer supports negative memory purchases +- Fix corp shares buyback triggering by pressing enter +- Staneks gift display avg / num charges +- Infiltration rewards no longer decay with better stats +- terminal 'true' is parsed as boolean not string +- tail and kill use autocomplete() +- Fix focus for coding contract +- massive boost to noodle bar. + +** Special Thanks ** + +- Special thank you to everyone on Discord who can answer + new player questions so I can focus on more important things. + +## v1.1.0 - 2021-12-03 BN13: They're Lunatics (hydroflame & community) + +** BN13: They're Lunatics ** + +- BN13 added. + +** Steam ** + +- Tested on all 3 major OS. +- 94 achievements added +- Release is 2021-12-10. + +** Corporation API ** + +- Added corporation API. (Unstable) + +** Netscript ** + +- tprintf crashes when not giving a format as first arg. +- tprintf no longer prints filename (@BartKoppelmans) +- TIX buy/sell/sellShort all return askprice/bidprice (@Insight) +- getRunningScript now works. +- Fix disableLog for gang and TIX API +- getOwnedSourceFiles is not singularity anymore (makes it easier to share scripts.) (@theit8514) +- true/false is a valid value to send to other scripts. +- workForFaction no longer returns null when trying to work for gang. +- Scripts logging no longer generates the string if logging is disabled. + This should give performance boost for some scripts. + +** Gang ** + +- Gang with 0 territory can no longer fight +- Territory now caps at exactly 0 or 1. + +** Misc. ** + +- Clicking "previous" on the browser will not pretend you had unsaved information + allowing you to cancel if needs be. +- Fixed some tail box coloring issue. +- Fixed BladeBurner getCityCommunities ram cost +- The download terminal command no longer duplicate extensions (@Insight) +- Fix #000 on #000 text in blackjack. (@Insight) +- Remove reference to .fconf +- Tail boxes all die on soft reset. +- Fix codign contract focus bug. +- Megacorp factions simply re-invite you instead of auto added on reset. (@theit8514) +- Tail window is bound to html body. +- Infiltration reward is tied to your potential stats, not your actual stats + So you won't lose reward for doing the same thing over and over. +- intelligence lowers program creation requirements. +- Terminal parses true as the boolean, not the string. +- Tail and kill autocomplete using the ns2 autocomplete feature. +- scan-analyze doesn't take up as many terminal entries. +- GangOtherInfo documentation now renders correctly. +- ActiveScripts search box also searches for script names. +- Infinite money no longer allows for infinite hacknet server. +- Blackjack doesn't make you lose money twice. +- Recent Scripts is now from most to least recent. +- Fix mathjax ascii art bug in NiteSec. +- Remove warning that the theme editor is slow, it's only slow in dev mode. +- In BN8 is it possible to reduce the money on a server without gaining any. +- In the options, the timestamp feature has a placeholder explaining the expected format. +- Bunch of doc typo fix. (hydroflame & @BartKoppelmans & @cvr-119) +- nerf noodle bar + +## v1.0.2 - 2021-11-17 It's the little things (hydroflame) + +** Breaking (very small I promise!) ** + +- buy / sell now return getAskPrice / getBidPrice instead of just price. + This should help solve some inconsistencies. + +** Misc. ** + +- scripts logs are colorized. Start your log with SUCCESS, ERROR, FAIL, WARN, INFO. +- documentation for scp not say string | string[] +- Donation link updated. +- nerf noodle bar + +## v1.0.1 - 2021-11-17 New documentation (hydroflame) + +** Documentation ** + +- The new documentation for the netscript API is available at + https://github.com/bitburner-official/bitburner-src/blob/stable/markdown/bitburner.ns.md + This documentation is used in-game to validate the code, in-editor to autocomplete, and + for users to reference. This is a huge quality of life improvements for me. + +** Reputation ** + +- Fixed favor not affecting faction work reputation gain (Yeah, I know right?) + +** Hacknet ** + +- Servers are now considerd "purchasedByPlayers" + +** Script Editor ** + +- solarized themes now work. + +** Corporation ** + +- Dividends are now much more taxed. +- The 2 upgrades that reduced taxes are now much stronger. + +** Misc. ** + +- Starting / Stopping scripts on hashnet servers immediately updates their hash rate (instead of on the next tick) +- Hacknet has tooltip showing what the result of the upgrade would be. +- Augmentations page displayes current price multiplier as well as explains the mechanic. +- Terminal now is 25x stronger. +- Tail boxes use pre-wrap for it's lines. +- Tail boxes allow you to rerun dead scripts. +- Tail boxes can no longer open the same one twice. +- Terminal now autocompletes through aliases. +- Make alter reality harder. +- Fix bladeburner cancelling actions when manually starting anything with Simulacrum. +- Buying hash upgrade to increase uni class or gym training will apply to current class. +- Internally the game no longer uses the decimal library. +- Fix an issue where 'download \*' would generate weird windows files. +- Timestamps can be set to any format in the options. +- Fix typo in documentation share popup. +- Remove bunch of debug log. +- Fix typo in corporation handbook literature. +- Fix typo in documentation +- Fix duplicate SF -1 exploit. (Yeah, an exploit of exploits, now were meta) +- Fix offline hacking earning being attributed to hacknet. +- nerf noodle bar + +## v1.0.0 - 2021-11-10 Breaking the API :( (blame hydroflame) + +** Announcement ** + +- Several API breaks have been implemented. +- See the v1.0.0 migration guide under Documentation +- Everyone gets 10 free neuroflux level. + +** Netscript ** + +- Fix a bug that would cause RAM to not get recalculated. +- New function: hackAnalyzeSecurity +- New function: growthAnalyzeSecurity +- New function: weakenAnalyze + +** Script Editor ** + +- Sometimes warn you about unawaited infinite loops. +- ns1 functions are now correctly colors in Monokai. + +** Programs ** + +- Formulas.exe is a new program that lets you use the formulas API. + +** Corporations ** + +- Real Estate takes up a tiny bit of room. +- Dividends are now taxes exponentially in certain bitnodes. +- UI displays how many level of each corporation upgrade. +- Fix exploit with going public. +- Employee salary no longer increase. + +** Documentation ** + +- The documentation is now autogenerated into .md files. + It is usable but not yet linked to readthedocs. It's on github. + +** Misc. ** + +- Favor is not internall floating point. Meaning I don't have to save an extra variable. +- Manually starting a Bladeburner action cancels unfocused action. +- Updated description of gang territory to be clearer. +- Hacknet expenses and profit are in different categories. +- Fixed favor equation. +- Toast messages aren't hidden behind work in progress screen. +- Fix bug that made infiltration checkmark look off by one. +- Fix some inconsistency with running files that start or don't start with / +- Can't tail the same window twice. +- Added recovery mode. Hopefully no one will ever have to use it. +- Fix readthedocs +- Programs now give int exp based on time not program. +- Many sing. functions now give int exp. +- Active Scripts page now displays some arguments next to script name. +- Fixed some invisible black text. +- Button colors can be edited. +- Added 2 new colors in the theme editor: background primary and background secondary. +- infiltration uses key instead of keycode so it should work better on non-american keyboards. +- buff noodle bar. diff --git a/src/Documentation/doc/changelog.md b/src/Documentation/doc/changelog.md index ff26035ac..6a3207bde 100644 --- a/src/Documentation/doc/changelog.md +++ b/src/Documentation/doc/changelog.md @@ -1081,3178 +1081,3 @@ API breaks - Fix #3803 Servers can no longer have duplicate IPs (@crimsonhawk47) - Fix #3854 ctrl+c does not clear terminal input (@evil-tim) - Nerf noodle bar, obviously. - -## v1.6.3 - 2022-04-01 Few stanek fixes - -Stanek Gift - -- Has a minimum size of 2x3 -- Active Fragment property 'avgCharge' renamed to 'highestCharge' -- Formula for fragment effect updated to make 561% more sense. - Now you can charge to your heart content. -- Logs for the 'chargeFragment' function updated. - - Misc. - -- Nerf noodle bar. - -## v1.6.0 - 2022-03-29 Grafting - -** Vitalife secret lab ** - -- A new mechanic called Augmentation Grafting has been added. Resleeving has been removed. -- Credit to @violet for her incredible work. - -** Stanek ** - -- BREAKING: Many functions in the stanek API were renamed in order to avoid name collision with things like Map.prototype.get - -** UI ** - -- Major update to Sleeve, Gang UI, and Create Program (@violet) -- re-add pre tags to support slash n in prompt (@jacktose) -- Tabelize linked output of 'ls' (@Master-Guy) -- Add the ability to filter open scripts (@phyzical) -- Add minHeight to editor tabs (@violet) -- Properly expand gang equipment cards to fill entire screen (@violet) -- Add shortcut to Faction augmentations page from FactionsRoot (@violet) -- Fix extra space on editor tabs (@violet) -- Present offline message as list (@DSteve595) -- add box showing remaining augments per faction (@jjayeon) -- Add tab switching support to vim mode (@JParisFerrer) -- Show current task on gang management screen (@zeddrak) -- Fix for ui of gang members current task when set via api (@phyzical) -- Don't hide irrelevant materials if their stock is not empty and hide irrelevant divisions from Export (@SagePtr) -- Fix regex to enable alpha transparency hex codes (8 digits) (@surdaft) - -** API ** - -- Added dark web functions to ns api -- BREAKING: purchaseTor() should returns true if player already has Tor. (@DavidGrinberg, @waffleattack) -- Implement getBonusTime in Corporation API (@t-wolfeadam) -- Added functions to purchase TIX and WSI (@incubusnb) -- purchaseSleeveAug checks shock value (@incubusnb) -- Fix bug with hacknet api -- Fix spendHashes bug -- Added 0 cost of asleep() (@Master-Guy) -- Fix some misleading corporation errors (@TheRealMaxion) -- expose the inBladeburner on the player object (@phyzical) -- added ram charge for stanek width and height (@phyzical) -- Fix sufficient player money check to buy back shares. (@ChrissiQ) -- Fix Static Ram Circumventing for some NS functions (@CrafterKolyan) -- added CorporationSoftCap to NetscriptDefinitions (@phyzical) -- Added definition of autocomplete() 'data' argument. (@tigercat2000) -- Adding support for text/select options in Prompt command (@PhilipArmstead) -- Added the ability to exportGame via api (@phyzical) - -** Arcade ** - -- Added an arcade to New Tokyo where you can play a 4 year old version of bitburner. - -** Misc. ** - -- Add a warning triggered while auto-saves are off. (@MartinFournier) -- Log info for field analysis now displays actual rank gained. (@ApamNapat) -- Removed BladeburnerSkillCost from skill point cost description. (@ApamNapat) -- Fix handling for UpArrow in bladeburner console. (@dowinter) -- Add GitHub action to check PRs for generated files. (@MartinFournier) -- Cap Staneks gift at 25x25 to prevent crashes. (@waffleattack) -- Remove old & unused files from repository. (@MartinFournier) -- Factions on the factions screens are sorted by story progress / type. (@phyzical) -- Fix log manager not picking up new runs of scripts. (@phyzical) -- Added prettier to cicd. -- UI improvements (@phyzical) -- Documentation / Typos (@nanogyth, @Master-Guy, @incubusnb, @ApamNapat, @phyzical, @SagePtr) -- Give player code a copy of Division.upgrades instead of the live object (@Ornedan) -- Fix bug with small town achievement. -- Fix bug with purchaseSleeveAug (@phyzical) -- Check before unlocking corp upgrade (@gianfun) -- General codebase improvements. (@phyzical, @Master-Guy, @ApamNapat) -- Waiting on promises in NS1 no longer freezes the script. (@Master-Guy) -- Fix bug with missing ramcost for tFormat (@TheMas3212) -- Fix crash with new prompt -- Quick fix to prevent division by 0 in terminal (@Master-Guy) -- removed ip references (@phyzical, @Master-Guy) -- Terminal now supports 'ls -l' -- Fix negative number formatting (@Master-Guy) -- Fix unique ip generation (@InDieTasten) -- remove terminal command theme from docs (@phyzical) -- Fix 'Augmentations Left' with gang factions (@violet) -- Attempt to fix 'bladeburner.process()' early routing issue (@MartinFournier) -- work in progress augment fix (@phyzical) -- Fixes missing space in Smart Supply (@TheRealMaxion) -- Change license to Apache 2 with Commons Clause -- updated regex sanitization (@mbrannen) -- Sleeve fix for when faction isnt found (@phyzical) -- Fix editor "close" naming (@phyzical) -- Fix bug with sleeves where some factions would be listed as workable. (@phyzical) -- Fix research tree of product industries post-prestige (@pd) -- Added a check for exisiting industry type before expanding (@phyzical) -- fix hackAnalyzeThreads returning infinity (@chrisrabe) -- Make growthAnalyze more accurate (@dwRchyngqxs) -- Add 'Zoom -> Reset Zoom' command to Steam (@smolgumball) -- Add hasOwnProperty check to GetServer (@SagePtr) -- Speed up employee productivity calculation (@pd) -- Field Work and Security Work benefit from 'share' (@SagePtr) -- Nerf noodle bar. - -## v1.5.0 - Steam Cloud integration - -** Steam Cloud Saving ** - -- Added support for steam cloud saving (@MartinFournier) - -** UI ** - -- background now matches game primary color (@violet) -- page title contains version (@MartinFourier) -- Major text editor improvements (@violet) -- Display bonus time on sleeve page (@MartinFourier) -- Several UI improvements (@violet, @smolgumball, @DrCuriosity, @phyzical) -- Fix aug display in alpha (@Dominik Winter) -- Fix display of corporation product equation (@SagePtr) -- Make Bitverse more accessible (@ChrissiQ) -- Make corporation warehouse more accessible (@ChrissiQ) -- Make tab style more consistent (@violet) - -** Netscript ** - -- Fix bug with async. -- Add 'printf' ns function (@Ninetailed) -- Remove blob caching. -- Fix formulas access check (@Ornedan) -- Fix bug in exp calculation (@qcorradi) -- Fix NaN comparison (@qcorradi) -- Fix travelToCity with bad argument (@SlyCedix) -- Fix bug where augs could not be purchased via sing (@reacocard) -- Fix rounding error in donateToFaction (@Risenafis) -- Fix bug with weakenAnalyze (@rhobes) -- Prevent exploit with atExit (@Ornedan) -- Double 'share' power - -** Corporations ** - -- Fix bugs with corp API (@pigalot) -- Add smart supply func to corp API (@pd) - -** Misc. ** - -- The file API now allows GET and DELETE (@lordducky) -- Force achievement calculation on BN completion (@SagePtr) -- Cleanup in repository (@MartinFourier) -- Several improvements to the electron version (@MartinFourier) -- Fix bug with casino roulette (@jamie-mac) -- Terminal history persists in savefile (@MartinFourier) -- Fix tests (@jamie-mac) -- Fix crash with electron windows tracker (@smolgumball) -- Fix BN6/7 passive reputation gain (@BrianLDev) -- Fix Sleeve not resetting on install (@waffleattack) -- Sort joined factions (@jjayeon) -- Update documentation / typo (@lethern, @Meowdoleon, @JohnnyUrosevic, @JosephDavidTalbot, - @pd, @lethern, @lordducky, @zeddrak, @fearnlj01, @reasonablytall, @MatthewTh0, - @SagePtr, @manniL, @Jedimaster4559, @loganville, @Arrow2thekn33, @wdpk, @fwolfst, - @fschoenfeldt, @Waladil, @AdamTReineke, @citrusmunch, @factubsio, @ashtongreen, - @ChrissiQ, @DJ-Laser, @waffleattack, @ApamNapat, @CrafterKolyan, @DSteve595) -- Nerf noodle bar. - -## v1.4.0 - 2022-01-18 Sharing is caring - -** Computer sharing ** - -- A new mechanic has been added, it's is invoked by calling the new function 'share'. - This mechanic helps you farm reputation faster. - -** gang ** - -- Installing augs means losing a little bit of ascension multipliers. - -** Misc. ** - -- Prevent gang API from performing actions for the type of gang they are not. (@TheMas3212) -- Fix donation to gang faction. (@TheMas3212) -- Fix gang check crashing the game. (@TheMas3212) -- Make time compression more robust. -- Fix bug with scp. -- Add zoom to steam version. (@MartinFourier) -- Fix donateToFaction accepts donation of NaN. (@woody-lam-cwl) -- Show correct hash capacity gain on cache level upgrade tooltip. (@woody-lam-cwl) -- Fix tests (@woody-lam-cwl) -- Fix cache tooltip (@woody-lam-cwl) -- Added script to prettify save file for debugging (@MartinFourier) -- Update documentation / typos (@theit8514, @thadguidry, @tigercat2000, @SlyCedix, @Spacejoker, @KenJohansson, - @Ornedan, @JustAnOkapi, @violet, @philarmstead, @TheMas3212, @dcragusa, @XxKingsxX-Pinu, - @paiv, @smolgumball, @zeddrak, @stinky-lizard, @violet, @Feodoric, @daanflore, - @markusariliu, @mstruebing, @erplsf, @waffleattack, @Dexalt142, @AIT-OLPE, @deathly809, @BuckAMayzing, - @MartinFourier, @pigalot, @lethern) -- Fix BN3+ achievement (@SagePtr) -- Fix reputation carry over bug (@TheMas3212) -- Add button to exit infiltrations (@TheMas3212) -- Add dev menu achievement check (@TheMas3212) -- Add 'host' config for electron server (@MartinFourier) -- Suppress save toast only works for autosave (@MartinFourier) -- Fix some achievements not triggering with 'backdoor' (@SagePtr) -- Update Neuroflux Governor description. -- Fix bug with electron server. -- Fix bug with corporation employee assignment function (@Ornedan) -- Add detailed information to terminal 'mem' command (@MartinFourier) -- Add savestamp to savefile (@MartinFourier) -- Dev menu can apply export bonus (@MartinFourier) -- Icarus message no longer applies on top of itself (@Feodoric) -- purchase augment via API can no longer buy Neuroflux when it shouldn't (@Feodoric) -- Syntax highlighter should be smarter (@neuralsim) -- Fix some miscalculation when calculating money stolen (@zeddrak) -- Fix max cache achievement working with 0 cache (@MartinFourier) -- Add achievements in the game, not just steam (@MartinFourier) -- Overflow hash converts to money automatically (@MartinFourier) -- Make mathjax load locally (@MartinFourier) -- Make favor calculation more efficient (@kittycat2002) -- Fix some scripts crashing the game on startup (@MartinFourier) -- Toasts will appear above tail window (@MartinFourier) -- Fix issue that can cause terminal actions to start on one server and end on another (@MartinFourier) -- Fix 'fileExists' not correctly matching file names (@TheMas3212) -- Refactor some code to be more efficient (@TheMas3212) -- Fix exp gain for terminal grow and weaken (@violet) -- Refactor script death code to reject waiting promises instead of resolving (@Ornedan) -- HP recalculates on defense exp gain (@TheMas3212) -- Fix log for ascendMember (@TheMas3212) -- Netscript ports clear on reset (@TheMas3212) -- Fix bug related to company (@TheMas3212) -- Fix bug where corporation handbook would not be correctly added (@TheMas3212) -- Servers in hash upgrades are sorted alpha (@MartinFourier) -- Fix very old save not properly migrating augmentation renamed in 0.56 (@MartinFourier) -- Add font height and line height in theme settings (@MartinFourier) -- Fix crash when quitting job (@MartinFourier) -- Added save file validation system (@TheMas3212) -- React and ReactDOM are now global objects (@pigalot) -- 'nano' supports globs (@smolgumball) -- Character overview can be dragged (@MartinFourier) -- Job page updates in real time (@violet) -- Company favor gain uses the same calculation as faction, this is just performance - the value didn't change (@violet) -- ns2 files work with more import options (@theit8514) -- Allow autocomplete for partial executables (@violet) -- Add support for contract completion (@violet) -- 'ls' link are clickable (@smolgumball) -- Prevent steam from opening external LOCAL files (@MartinFourier) -- Fix a bug with autocomplete (@Feodoric) -- Optimise achievement checks (@Feodoric) -- Hacknet server achievements grant associated hacknet node achievement (@Feodoric) -- Fix display bug with hacknet (@Feodoric) -- 'analyze' now says if the server is backdoored (@deathly809) -- Add option to exclude running script from save (@MartinFourier) -- Game now catches more errors and redirects to recovery page (@MartinFourier) -- Fix bug with autocomplete (@violet) -- Add tooltip to unfocus work (@violet) -- Add detailst overview (@MartinFourier) -- Fix focus bug (@deathly809) -- Fix some NaN handling (@deathly809) -- Added 'mv' ns function (@deathly809) -- Add focus argument to some singularity functions (@violet) -- Fix some functions not disabling log correctly (@deathly809) -- General UI improvements (@violet) -- Handle steamworks errors gravefully (@MartinFourier) -- Fix some react component not unmounting correctly (@MartinFourier) -- 'help' autocompletes (@violet) -- No longer push all achievements to steam (@Ornedan) -- Recovery page has more information (@MartinFourier) -- Added 'getGameInfo' ns function (@MartinFourier) -- SF3.3 unlocks all corp API (@pigalot) -- Major improvements to corp API (@pigalot) -- Prevent seed money outside BN3 (@pigalot) -- Fix bug where using keyboard shortcuts would crash if the feature is not available (@MartinFourier)\ -- Sidebar remains opened/closed on save (@MartinFourier) -- Added tooltip to sidebar when closed (@MartinFourier) -- Fix bug where Formulas.exe is not available when starting BN5 (@TheMas3212) -- Fix CI (@tvanderpol) -- Change shortcuts to match sidebar (@MartinFourier) -- Format gang respect (@attrib) -- Add modal to text editor with ram details (@violet) -- Fix several bugs with singularity focus (@violet) -- Nerf noodle bar. - -## v1.3.0 - 2022-01-04 Cleaning up - -** External IDE integration ** - -- The Steam version has a webserver that allows integration with external IDEs. - A VSCode extension is available on the market place. (The documentation for the ext. isn't - written yet) - -** Source-Files ** - -- SF4 has been reworked. -- New SF -1. - -** UI ** - -- Fix some edge case with skill bat tooltips (@MartinFournier) -- Made some background match theme color (@Kejikus) -- Fix problem with script editor height not adjusting correctly (@billyvg) -- Fix some formatting issues with Bladeburner (@MartinFournier, @violet) -- Fix some functions like 'alert' format messages better (@MageKing17) -- Many community themes added. -- New script editor theme (@Hedrauta, @Dexalt142) -- Improvements to tail windows (@theit8514) -- Training is more consise (@mikomyazaki) -- Fix Investopedia not displaying properly (@JotaroS) -- Remove alpha from theme editor (@MartinFournier) -- Fix corporation tooltip not displaying properly (@MartinFournier) -- Add tooltip on backdoored location names (@MartinFournier) -- Allow toasts to be dismissed by clicking them (@violet) -- Darkweb item listing now shows what you own. (@hexnaught) - -** Bug fix ** - -- Fix unit tests (@MartinFournier) -- Fixed issue with 'cat' and 'read' not finding foldered files (@Nick-Colclasure) -- Buying on the dark web will remove incomplete exe (@hexnaught) -- Fix bug that would cause the game to crash trying to go to a job without a job (@hexnaught) -- purchaseServer validation (@violet) -- Script Editor focuses code when changing tab (@MartinFournier) -- Fix script editor for .txt files (@65-7a) -- Fix 'buy' command not displaying correctly. (@hexnaught) -- Fix hackAnalyzeThread returning NaN (@mikomyazaki) -- Electron handles exceptions better (@MageKing17) -- Electron will handle 'unresponsive' event and present the opportunity to reload the game with no scripts (@MartinFournier) -- Fix 'cp' between folders (@theit8514) -- Fix throwing null/undefined errors (@violet) -- Allow shortcuts to work when unfocused (@MageKing17) -- Fix some dependency issue (@locriacyber) -- Fix corporation state returning an object instead of a string (@antonvmironov) -- Fix 'mv' overwriting files (@theit8514) -- Fix joesguns not being influenced by hack/grow (@dou867, @MartinFournier) -- Added warning when opening external links. (@MartinFournier) -- Prevent applying for positions that aren't offered (@TheMas3212) -- Import has validation (@MartinFournier) - -** Misc. ** - -- Added vim mode to script editor (@billyvg) -- Clean up script editor code (@Rez855) -- 'cat' works on scripts (@65-7a) -- Add wordWrap for Monaco (@MartinFournier) -- Include map bundles in electron for easier debugging (@MartinFournier) -- Fix importing very large files (@MartinFournier) -- Cache program blob, reducing ram usage of the game (@theit8514) -- Dev menu can set server to \$0 (@mikomyazaki) -- 'backdoor' allows direct connect (@mikomyazaki) -- Github workflow work (@MartinFournier) -- workForFaction / workForCompany have a new parameter (@theit8514) -- Alias accept single quotes (@sporkwitch, @FaintSpeaker) -- Add grep options to 'ps' (@maxtimum) -- Added buy all option to 'buy' (@anthonydroberts) -- Added more shortcuts to terminal input (@Frank-py) -- Refactor some port code (@ErzengelLichtes) -- Settings to control GiB vs GB (@ErzengelLichtes) -- Add electron option to export save game (@MartinFournier) -- Electron improvements (@MartinFournier) -- Expose some notifications functions to electron (@MartinFournier) -- Documentation (@MartinFournier, @cyn, @millennIumAMbiguity, @2PacIsAlive, - @TheCoderJT, @hexnaught, @sschmidTU, @FOLLGAD, @Hedrauta, @Xynrati, - @mikomyazaki, @Icehawk78, @aaronransley, @TheMas3212, @Hedrauta, @alkemann, - @ReeseJones, @amclark42, @thadguidry, @jasonhaxstuff, @pan-kuleczka, @jhollowe, - @ApatheticsAnonymous, @erplsf, @daanflore, @violet, @Kebap, @smolgumball, - @woody-lam-cwl) - -## v1.1.0 - 2021-12-18 You guys are awesome (community because they're god damn awesome) - -** Script Editor ** - -- The text editor can open several files at once. (@Rez855 / @Shadow72) - It's not perfect so keep the feedback coming. - -** Steam ** - -- Windows has a new launch option that lets player start with killing all their scripts - This is a safety net in case all the other safety nets fail. -- Linux has several launch options that use different flags for different OS. -- Debug and Fullscreen are available in the window utility bar. -- Tried (and maybe failed) to make the game completely kill itself after closing. - This one I still don't know wtf is going. -- No longer has background throttling. -- Default color should be pitch black when loading -- Add BN13: Challenge achievement. - -** Tutorial ** - -- I watched someone play bitburner on youtube and reworked part of - the tutorial to try to make some parts of the game clearer. - https://www.youtube.com/watch?v=-_JETXff4Zo -- Add option to restart tutorial. - -** Netscript ** - -- getGangInformation returns more information. -- getAscensionResult added -- getMemberInformation returns more info -- Formulas API has new functions for gang. -- Added documentation for corp API. -- exec has clearer error message when you send invalid data. -- getServer returns all defined field for hacknet servers. -- Fix a bug with scp multiple files (@theit8514) -- Stack traces should be smarter at replacing blobs with filenames -- Fix a weird error message that would occur when throwing raw strings. -- Fix shortcuts not working. -- Re-added setFocus and isFocused (@theit8514) -- new function getHashUpgrades (@MartinFournier) -- enableLog accepts "ALL" like disableLog (@wynro) -- toast() doesn't crash on invalid data (@ivanjermakov) -- alert() doesn't crash on invalid data (@Siern) -- Fixed an issue where scripts don't run where they should. -- Sleeve getInformation now returns cha -- getServer does work with no argument now -- workForFaction returns false when it mistakenly returned null - -** Character Overview ** - -- The character overview now shows the amount of exp needed to next level (@MartinFournier) - -** Misc. ** - -- Add option to supress Game Saved! toasts (@MartinFournier) -- Fix bug where ctrl+alt+j was eaten by the wrong process. (@billyvg) -- Theme Editor lets you paste colors (@MartinFournier) -- ctrl + u/k/w should work on terminal (@billyvg) -- Game now shows commit number, this is mostly for me. (@MartinFourier) -- running a bad script will give a clearer error message (@TheCoderJT) -- Default terminal capacity is maximum (@SayntGarmo) -- Fix problems with cp and mv (@theit8514) -- Make monaco load fully offline for players behind firewalls. -- change beginer guide to use n00dles instead of foodnstuff -- BN13 is harder -- nerf int gain from manualHack -- Fix UI displaying wrong stats (@DJMatch3000) -- Fix button not disabling as it should. -- New location in Ishima. -- Add setting to suppress stock market popups. -- Typo fixes (@Hedrauta, @cvr-119, @Ationi, @millennIumAMbiguity - @TealKoi, @TheCoderJT, @cblte, @2PacIsAlive, @MageKing17, - @Xynrati, @Adraxas, @pobiega) -- Fix 100% territory achievement. -- Reword message on active scripts page. -- Fix terminal not clearing after BN -- Remove references to .fconf -- Augmentation pages shows BN difficulty with SF5 -- Fix scripts saving on wrong server while 'connect'ing -- Fix gym discount not working. -- Fix scan-analyze not working with timestamps -- Hash upgrades remember last choice. -- Save files now sort by date -- The covenant no longer supports negative memory purchases -- Fix corp shares buyback triggering by pressing enter -- Staneks gift display avg / num charges -- Infiltration rewards no longer decay with better stats -- terminal 'true' is parsed as boolean not string -- tail and kill use autocomplete() -- Fix focus for coding contract -- massive boost to noodle bar. - -** Special Thanks ** - -- Special thank you to everyone on Discord who can answer - new player questions so I can focus on more important things. - -## v1.1.0 - 2021-12-03 BN13: They're Lunatics (hydroflame & community) - -** BN13: They're Lunatics ** - -- BN13 added. - -** Steam ** - -- Tested on all 3 major OS. -- 94 achievements added -- Release is 2021-12-10. - -** Corporation API ** - -- Added corporation API. (Unstable) - -** Netscript ** - -- tprintf crashes when not giving a format as first arg. -- tprintf no longer prints filename (@BartKoppelmans) -- TIX buy/sell/sellShort all return askprice/bidprice (@Insight) -- getRunningScript now works. -- Fix disableLog for gang and TIX API -- getOwnedSourceFiles is not singularity anymore (makes it easier to share scripts.) (@theit8514) -- true/false is a valid value to send to other scripts. -- workForFaction no longer returns null when trying to work for gang. -- Scripts logging no longer generates the string if logging is disabled. - This should give performance boost for some scripts. - -** Gang ** - -- Gang with 0 territory can no longer fight -- Territory now caps at exactly 0 or 1. - -** Misc. ** - -- Clicking "previous" on the browser will not pretend you had unsaved information - allowing you to cancel if needs be. -- Fixed some tail box coloring issue. -- Fixed BladeBurner getCityCommunities ram cost -- The download terminal command no longer duplicate extensions (@Insight) -- Fix #000 on #000 text in blackjack. (@Insight) -- Remove reference to .fconf -- Tail boxes all die on soft reset. -- Fix codign contract focus bug. -- Megacorp factions simply re-invite you instead of auto added on reset. (@theit8514) -- Tail window is bound to html body. -- Infiltration reward is tied to your potential stats, not your actual stats - So you won't lose reward for doing the same thing over and over. -- intelligence lowers program creation requirements. -- Terminal parses true as the boolean, not the string. -- Tail and kill autocomplete using the ns2 autocomplete feature. -- scan-analyze doesn't take up as many terminal entries. -- GangOtherInfo documentation now renders correctly. -- ActiveScripts search box also searches for script names. -- Infinite money no longer allows for infinite hacknet server. -- Blackjack doesn't make you lose money twice. -- Recent Scripts is now from most to least recent. -- Fix mathjax ascii art bug in NiteSec. -- Remove warning that the theme editor is slow, it's only slow in dev mode. -- In BN8 is it possible to reduce the money on a server without gaining any. -- In the options, the timestamp feature has a placeholder explaining the expected format. -- Bunch of doc typo fix. (hydroflame & @BartKoppelmans & @cvr-119) -- nerf noodle bar - -## v1.0.2 - 2021-11-17 It's the little things (hydroflame) - -** Breaking (very small I promise!) ** - -- buy / sell now return getAskPrice / getBidPrice instead of just price. - This should help solve some inconsistencies. - -** Misc. ** - -- scripts logs are colorized. Start your log with SUCCESS, ERROR, FAIL, WARN, INFO. -- documentation for scp not say string | string[] -- Donation link updated. -- nerf noodle bar - -## v1.0.1 - 2021-11-17 New documentation (hydroflame) - -** Documentation ** - -- The new documentation for the netscript API is available at - https://github.com/bitburner-official/bitburner-src/blob/stable/markdown/bitburner.ns.md - This documentation is used in-game to validate the code, in-editor to autocomplete, and - for users to reference. This is a huge quality of life improvements for me. - -** Reputation ** - -- Fixed favor not affecting faction work reputation gain (Yeah, I know right?) - -** Hacknet ** - -- Servers are now considerd "purchasedByPlayers" - -** Script Editor ** - -- solarized themes now work. - -** Corporation ** - -- Dividends are now much more taxed. -- The 2 upgrades that reduced taxes are now much stronger. - -** Misc. ** - -- Starting / Stopping scripts on hashnet servers immediately updates their hash rate (instead of on the next tick) -- Hacknet has tooltip showing what the result of the upgrade would be. -- Augmentations page displayes current price multiplier as well as explains the mechanic. -- Terminal now is 25x stronger. -- Tail boxes use pre-wrap for it's lines. -- Tail boxes allow you to rerun dead scripts. -- Tail boxes can no longer open the same one twice. -- Terminal now autocompletes through aliases. -- Make alter reality harder. -- Fix bladeburner cancelling actions when manually starting anything with Simulacrum. -- Buying hash upgrade to increase uni class or gym training will apply to current class. -- Internally the game no longer uses the decimal library. -- Fix an issue where 'download \*' would generate weird windows files. -- Timestamps can be set to any format in the options. -- Fix typo in documentation share popup. -- Remove bunch of debug log. -- Fix typo in corporation handbook literature. -- Fix typo in documentation -- Fix duplicate SF -1 exploit. (Yeah, an exploit of exploits, now were meta) -- Fix offline hacking earning being attributed to hacknet. -- nerf noodle bar - -## v1.0.0 - 2021-11-10 Breaking the API :( (blame hydroflame) - -** Announcement ** - -- Several API breaks have been implemented. -- See the v1.0.0 migration guide under Documentation -- Everyone gets 10 free neuroflux level. - -** Netscript ** - -- Fix a bug that would cause RAM to not get recalculated. -- New function: hackAnalyzeSecurity -- New function: growthAnalyzeSecurity -- New function: weakenAnalyze - -** Script Editor ** - -- Sometimes warn you about unawaited infinite loops. -- ns1 functions are now correctly colors in Monokai. - -** Programs ** - -- Formulas.exe is a new program that lets you use the formulas API. - -** Corporations ** - -- Real Estate takes up a tiny bit of room. -- Dividends are now taxes exponentially in certain bitnodes. -- UI displays how many level of each corporation upgrade. -- Fix exploit with going public. -- Employee salary no longer increase. - -** Documentation ** - -- The documentation is now autogenerated into .md files. - It is usable but not yet linked to readthedocs. It's on github. - -** Misc. ** - -- Favor is not internall floating point. Meaning I don't have to save an extra variable. -- Manually starting a Bladeburner action cancels unfocused action. -- Updated description of gang territory to be clearer. -- Hacknet expenses and profit are in different categories. -- Fixed favor equation. -- Toast messages aren't hidden behind work in progress screen. -- Fix bug that made infiltration checkmark look off by one. -- Fix some inconsistency with running files that start or don't start with / -- Can't tail the same window twice. -- Added recovery mode. Hopefully no one will ever have to use it. -- Fix readthedocs -- Programs now give int exp based on time not program. -- Many sing. functions now give int exp. -- Active Scripts page now displays some arguments next to script name. -- Fixed some invisible black text. -- Button colors can be edited. -- Added 2 new colors in the theme editor: background primary and background secondary. -- infiltration uses key instead of keycode so it should work better on non-american keyboards. -- buff noodle bar. - -## v0.58.0 - 2021-10-27 Road to Steam (hydroflame & community) - -** Announcement ** - -- To prepare for Steam we will fix some inconsistencies in the Netscript API. Ideally we can also write a - save file migration that will automatically convert all breaking changes in your scripts without any - player input. - -** BREAKING (kindof) ** - -- All stock market functions are now under the 'stock' namespace, like 'hacknet' - However when you load your game with v0.58.0 for the first time it should automatically convert everything. - -** SF -1 ** - -- new SF -1: Reality Alteration - -** Gang ** - -- Ascension formula now better -- Karma requirement now much lower in most nodes -- Territory heavily penalizes gains -- T.R.P. not available outside BN2. - -** Netscript ** - -- It is no longer possible to send anything but strings or numbers to other scripts. (prevents exploits) -- Improve code for some netscript functions (@omuretsu) - -** Script Editor ** - -- Added Solarized light/dark as theme (@CalvinTrops) -- Fixed sleeve namespace smart autocomplete. - -** Hacknet Servers ** - -- Cores affect grow/weaken like they do on home computer - -** Infiltration ** - -- Slash game modified to be easier. - -** Misc. ** - -- Fix typo in corp (@Saynt_Garmo) -- Fixed a bug where corp wouldn't let you buyback shares. (@Saynt_Garmo) -- Fixed a bug where sleeves couldn't perform some crimes. (@Saynt_Garmo) -- Hospitalization and Eating noodles are now toasts (@Saynt_Garmo) -- Fixed some repeated code (@omuretsu) -- Fixed Character Overview preventing clicks underneath it even when hidden. (@omuretsu) -- Fixed typo in tutorial. (@omuretsu) -- Create Programs and Factions invitation badges now dissapear when you open their respective pages. -- Add killall script in character overview. -- Fixed bug in corp that made last city production be the production for all cities for newly created product. -- Fix bug that allowed reputation to transfer to new jobs. -- Fixed memory leak with ns2. -- nerf noodle bar - -## v0.57.0 - 2021-10-16 It was too cheap! (hydroflame & community) - -** BREAKING (kindof) ** - -- purchased server cost now scales exponentially past 2^10. - I'm going to actually explain this one: Currently the cost of a 2^20GB server is 57b - Most players can get that before their first install. In an effort to nerf good players - a softcap was added. This softcap is different for every BN. - -** Script Editor ** - -- Added a theme that is close to monokai. Unfortunately a full monokai is impossible because - Monaco doesn't have a very good tokenizer. -- Opening a file and connecting to a new server will still save the file on the server that the file - was opened. - -** Netscript ** - -- New function: alert, which creates a textbox. -- New function: toast, creates a notification in the bottom right. -- New function: upgradeHomeCores (@Saynt_Garmo) -- New function: atExit, allows you to set a callback for when the script closes. -- New kindof function: autocomplete, this allows you to tell the game what it should - autocomplete on the terminal. - -** Augmentation ** - -- ENM Core (the Augmentation from The Black Hand with the highest rep cost) rep cost - reduced from 250 to 175. This will help new players transition from TBH to BitRunners more easily. - -** Bladeburner ** - -- New general action: Incite Violence. This action adds other action counts but increases chaos. - -** Misc. ** - -- Current bladeburner action is shown on the character overview. -- Fix blackop being #000 on #000. -- The last clicked Tail Box goes in front of the others. -- Fixed an issue where some values were loaded as 0 when they should be null. -- Implemented toasts. -- .msg are no longer saved in the text file. -- Tail boxes no longer display all the args, they use "..." after 30 characters. -- Fixed cancelation penalty bonus not being properly applied after the IP <-> hostname switch. -- Fixed an exploit where you could send non-strings or numbers to other scripts. -- Fixed issue when trying to work for a faction with a work type that doesn't exist while - already working for that faction. -- Fixed not being able to work for the CIA. (Don't ask) -- nerf noodle bar - -## v0.56.0 - 2021-10-11 Trimming the backlog (hydroflame & community) - -** BREAKING ** - -- The 'write' function is now async. This helps when making scripts that write scripts. - -** Terminal ** - -- 'grow' and 'weaken' have been added as terminal command. This should help player transition - from commands to scripts. The tutorial also talks about it. -- 'cp' command added -- Improved performance by rate limiting refresh. - -** IP vs Hostname ** - -- The game now uses hostname as primary key for it's servers (yeah believe it or not IPs were - used until then). This has caused some issues with purchased servers (they couldn't be sold). - You might need to soft reset for the game to fully convert itself. - -** Sleeve ** - -- Fixed bug where they couldn't train at Volhaven. -- No longer consume all bonus time at once, making it look buggy. - -** SF9 ** - -- Now boosts hacknet production by 8/12/14% - -** Hacknet Servers ** - -- production nerfed by 10% -- Max money increase gets weaker above 10t max money - -** Corporation ** - -- Warehouse tooltip now also displays the amount of space taken by products. -- Changed research box completely to avoid dependency on Treant (Treant is a pita) -- All textbox should accept MAX/MP case insensitive. -- Fixed export popup not refreshing dropdowns correctly. -- Fixed product mku becoming zero -- Increased scaling of Wilson to avoid feedback loop. -- Can no longer get in debt by buying real estate -- Bonus time is consumed faster. - -** Netscript ** - -- isBusy takes bitverse and infiltration into account -- hospitalize can't be called when in infiltration. -- setToCommitCrime now accepts crime rough name instead of perfect name. -- disableLog All now works for bladeburner functions. -- Fixed netscript port for ns1. - -** Augmentation ** - -- Added augmentation to Ti Di Hui that removes penalty for being unfocused. -- Neuroflux no longer appears in special factions. - -** Script Editor ** - -- Ram check is debounced instead of refreshed every second. -- Added the vscode extension documentation to the game (it doesn't work well, thought) -- Fixed issue where autocomplete list would grow forever -- Added semi-monokai as theme. -- Fixed issue where modifying filename would mess it up. -- Font size can be changed now. - -** Infiltration ** - -- Fixed issue where game controls would become unfocused. - -** Misc. ** - -- Fixed loader incorrectly assuming some null values are incorrect. -- installBackdoor trigger Bitverse sequence -- Some improvements to the theme editor -- Improved documentation about where to learn javascript. -- Added some instructions for contributors. -- Fixed typo in corporation sell shares modal (@Saynt_Garmo) -- Fixed pagination being black on black in Active Scripts -- Create Script tab renamed to Script Editor -- Fixed an issue where corp some textbox wouldn't update when changing city. -- Fixed an issue where hacknet online time was always 0. -- Netscript function prompt fixed. -- Fixed miscalculation in growth. -- Script with syntax errors will try to be a tad more helpful. -- Corporations can no longer bribe bladeburners. -- Augmentation Graphene Branchiblade renamed to Brachi, like the rest of them. -- All ram is displayed in GB/TB/PB now. -- Game now saves when saving a file, this can be turned off. -- Several improvement to log window. -- Bladeburner current action returns General type instead of the name of the action. -- Bladeburner travel and Sleeve travel respect disable ASCII. -- Tutorial fits on small screens. -- Import is much slower but more consistent now. -- Fix intelligence not updating properly. -- Added SF -1: Time Compression -- ReadTheDoc theme now matches the game. -- Logbox should wrap text better -- Logbox behavior should feel better. -- Fix font for AutoLink.exe -- nerf noodle bar - -## v0.55.0 - 2021-09-20 Material UI (hydroflame & community) - -** Global ** - -- The game is now 100% in typescript, react, and Material-UI - -** Misc. ** - -- Corporations can no longer bribe special factions -- Infiltration can no longer lose focus of the keyboard. -- Fix terminal line limit -- Added theme editor -- Theme applies on game load (@Nolshine) -- Sleeves no longer consume all bonus time for some actions -- Fix a bug where the autocomlete list would get duplicates -- Fix tutorial not scaling properly on small screens -- Import should be more consistent -- Typo with 'help' command -- Fix infinite loop in casino -- nerf noodle bar - -## v0.54.0 - 2021-09-20 One big react node (hydroflame & community) - -** UI ** - -- The UI is now completely(ish) in react and I'm starting to implement - Material-UI everywhere. This will help make the game feel more consistent. -- Major help from (@threehams) -- New Terminal -- New Active Scripts page -- New sidebar. -- New Character overview -- New tutorial -- New options page -- New create program page (@Nolshine) - -** Netscript ** - -- Add companyName to getPlayer - -** Factions ** - -- Megacorp factions are no longer removed when installing. - -** Corporation ** - -- All research tooltips are always visible. -- Smart supply is enabled by default if purchased (@Nolshine) - -** Misc. ** - -- Fix "Game saved" animation. (@Nolshine) -- Update commitCrime documentation (@Tryneus) -- Fix logbox scrolling weird (@Nolshine) -- Fix weird scrolling in corporations (@BartKoppelmans) -- Fix typo (@BartKoppelmans & @Nolshine) -- Delete game now has a confirmation modal (@Nolshine) -- Fix issue where skills would not get properly updated when entering new - BN. (@Nolshine) -- Convert create gang to popup (@vmesecher) -- Fixed a bug that prevented travel to Sector-12 and New Tokyo when not using - ASCII art. -- nerf noodle bar - -## v0.53.0 - 2021-09-09 Way too many things. (hydroflame & community) - -** Dev? ** - -- The entire codebase has been run through a code prettifier, hurray for consistency. (@threehams) -- Lots of test. (@threehams) -- Massive improvements to build speed. (@threehams) -- Dev notes: This won't affect any players but is immensely useful for me. - -** Hacknet ** - -- Converted to ts/react - -** Resleeving ** - -- Converted to ts/react - -** Sleeves ** - -- Converted to ts/react. The ui should also have a better feel. -- Fixed a bug that allowed players to recover shock much faster than intended. - -** BN10 ** - -- You have access to Sleeves right away -- In BN10 Sleeves start with 75 shock and 25 sync. - -** MathJax ** - -- Several tooltips have been updated to display the relevant formula in Mathjax, e.g. Favor and reputation - -** Corporation ** - -- Completely rewritten in React. Paving the way for bigger change. -- Smart Supply is now smarter and won't deadlock the warehouse. It is also more configurable. -- Several UI fixes. - -** Bladeburner ** - -- Action count is no longer decided when joining the Bladeburners. Experiences for all players should be more similar. - -** Factions ** - -- No factions have home computer ram requirement. This caused some confusion for new players. - -** Gang ** - -- Made it clear when there's a new equipment coming up. - -** Netscript ** - -- getActionCountRemaining now returns Infinity for bladeburner general actions. (@brubsy) -- getActionEstimatedSuccessChance now returns 100% for Diplomacy and Hyperbolic Regeneration Chamber. (@brubsy) -- disableLog('ALL') now disables all logs individually, meaning you can re-enable the ones you want after. (@Cass) -- getPlayer returns numPeopleKilled. -- Dynamic RAM calculation errors have a better error message. -- Hide some functions from autocomplete. -- Added getAugmentationPrice, getAugmentationRepReq, deprecated getAugmentationCost. (@TempFound) -- Fixed bug where some crime API would return "assassinate" when that's not accepted in other functions. - -** Coding Contract ** - -- Spiralize Matrix is easier to read. - -** Misc. ** - -- The world map is now used in sleeve travel and bladeburner travel. -- noselect a bunch of stuff. -- Ascii maps letters are more contrasting -- Updated documentation for infiltration. -- Most money costs in the game will turn grey/cyan when you don't have enough money. -- Donation textbox has better look & feel. -- Tech vendors ram & cores buttons have better look and feels. -- cores cost modified to be a formula instead of a semi-random array of numbers. -- Tech vendors now give a hint about where to get bigger servers. -- logboxes now displays whitespaces exactly. (@Cass) -- nerf noodle bar - -## v0.52.9 - 2021-08-27 Less lag! (hydroflame & community) - -** Active Scripts page ** - -- Now less laggy, has pagination. - -** File diagnostic ** - -- Added a popup found under options that shows the files you own and how - large they are. This help find bugs and leftover massive logs files. - -** Corporation ** - -- Added safeguard against a very specific bug that causes NaN money. I'm - still not sure what the root cause is but it should prevent corp from - breaking. - -** Netscript ** - -- tprintf is a new function that doesn't print the filename. - -** Misc. ** - -- Infiltration kills you if you try to automate it. (@threehams) -- Fix beautify button not working -- Added bladeburner_analysis_mult to getPlayer() (@brubsby) -- Fixed joining bladeburner via netscript functions. (@omuretsu) -- All bladeburner actions are click-to-copy -- nerf noodle bar - -## v0.52.8 - 2021-08-23 Fixing the previous patch tbh ROUND 2 (hydroflame) - -** Script editor ** - -- Correctly reloads old script when clicking "Script Editor" -- No longer jumps to the end of the text for no reason. - -** Hash upgrades ** - -- Fixed an issue where the default option would say ecorp but was really - foodnstuff - -** Misc. ** - -- The "Delete all active script" button under the options has a clearer - description. -- Removed some debug console.log -- nerf noodle bar - -## v0.52.7 - 2021-08-21 Fixing the previous patch tbh (hydroflame) - -** Netscript ** - -- API BREAKING CHANGE: getActionEstimatedSuccessChance now returns a pair of - value to reflect the UI changes. I'm very sorry. - -** Bladeburner ** - -- General actions now display time required. -- Recruitment now displays success chance. -- All other success chance now display a range instead of a single value - The real value is guaranteed to be within that range. - -** Misc. ** - -- Fix tutorial not working after Monaco upate -- Fix logbox logs not taking up the whole logbox -- Fix script editor shortcut (ctrl+b) -- Fix Corporation popup appearing in the wrong order, hiding one of them -- Fix error when loading Corp -- Fix logbox dragging (smoother now) -- Fix logbox name collision -- Fix logbox allowing to open the same box multiple times -- Fix netscript write. -- nerf noodle bar - -## v0.52.6 - 2021-08-21 Logboxes and VS-code (hydroflame) - -** Text Editor ** - -- Ace and Codemirror have been removed in favor of monaco (web version of - vs-code). The options are a bit lackluster but more will be added as - feedback comes. - -** Log boxes ** - -- Multiple log boxes can be opened at once. They can be moved around the - screen. (but the movement behavior is a bit weird.) - -** Misc. ** - -- Job promotion now correctly updates the UI. -- Milestones now call the faction CyberSec instead of CSEC -- Can no longer create file that break the filesystem. -- Remove dollar sign in blade contract UI element -- nerf noodle bar - -## v0.52.5 - 2021-08-19 CPU cores are useful!? (hydroflame) - -** Terminal ** - -- When executing 'run SCRIPT' any script can now add '--tail' to - automatically bring up the logs. - -** Netscript ** - -- The 'flags' function now works with single letter flags but they only take - one dash. -- Fix several broken bladeburner netscript functions. -- Fix gang.getMemberInformation returning inconsistent data after the gang - rework. - -** CPU Cores ** - -- CPU Cores on the home computer now provide a bonus to grow() money gain - and makes weaken lower more security. Only for scripts running on 'home' - -** Misc. ** - -- Fix weird scrolling in the new Bladeburner React console. -- nerf noodle bar - -## v0.52.4 - 2021-08-19 Bladeburner in React (hydroflame) - -** Bladeburner ** - -- The entire UI was rebuild in React. It should be more responsive - -** Hacknet ** - -- Displays how many time each hash upgrade was bought. -- Displays cummulative effect of the upgrade. -- Removed "Close" button from hash upgrade menu. - -** Misc. ** - -- More popup/modals have dark background, can be dismissed by clicking - outside, or by pressing escape. -- Small reword in the guide. -- Fix several typos in the bladeburner documentation. -- Linting (no one cares except the dev) -- nerf noodle bar - -## v0.52.3 - 2021-08-15 Gangs were OP (hydroflame) - -** Gang ** - -- Significant rework. Ascension is now based on exp gained. -- All upgrades give exp bonuses. -- Maximum gang members reduced to 12. -- Respect required to recruit sharply increased. -- Rewritten in React, the UI should be smoother and less laggy now. - -** Infiltration ** - -- Now isTrusted protected. - -** Misc. ** - -- Many UI element are now "noselect" protected. -- Fixed an issue where you could join the same faction twice via script and - UI simultaneously. -- Factions list screen converted to React. -- nerf noodle bar - -## v0.52.2 - 2021-08-15 Oh yeah, BN11 is a thing (drunk hydroflame tbh) - -** Source-Files ** - -- Source-File 11 now also provides a small reduction to the price increase - multiplier. - -** Augmentations ** - -- New Augmentation offered by Aevum, themed around 777 and offers some basic - programs. -- Augmentation descriptions are now more concise and consistent. - -** Misc. ** - -- nerf noodle bar - -## v0.52.1 - 2021-08-10 bugfixing (hydroflame & community) - -** Misc. ** - -- Fix game crash/corruption when quitting a job while working for it unfocused. -- Fix typo in corporation Market Data. -- Fix typo in docs for hackPercent. -- The tutorial encourages the players to connect to home before creating `n00dles.script` -- The dark web `buy` command now accepts `-1` (one) and `--list` instead of just `-l`. Helps some confused players. -- Character overview screen no longer hidden on the corporation screen. -- Infiltration difficulty display is now more explicit (It's a big arrow instead of just one word.) -- Fix wrong ram value in tutorial. (@MageKing17) -- Plenty of augmentation description cleanup (@Kwazygloo) -- Plenty of typo/description fixed (@MageKing17) -- Cleanup description of singularity function on readthedocs (@PurePandemonium) -- Fix bug when autolinking a server while backdooring (@schroederIT) -- nerf noodle bar - -## v0.52.0 - 2021-06-13 Infiltration 2.0 (hydroflame & community) - -**Infiltration** - -- Completely reworked. Not the same mechanic at all. - -**Terminal** - -- tail is smarter. It automatically assume the only possible options in some - cases. - -**Intelligence** - -- Now available when starting BN5 instead of after beating it for the first - time. -- Nerf the effect of intelligence on reputation gain. - -**Augmentation** - -- Added a new augmentation, the 'Unstable Circadian Modulator', whose - gimmick is that its stats are randomized every hour. - -**Netscript** - -- 'getPlayer' is not a singularity function anymore. -- 'hacknetNodes.constants' returns the correct values. -- 'createGang' has been added. -- 'inGang' has been added. - -**Tutorial** - -- Updated the tutorial. Made it look cleaner, fixed typos, etc. - -**Misc.** - -- Fix many typos in literature (@kwazygloo) -- Fix being able to unfocus from gym and university. -- Fix being able to do hacking missions while unfocused. -- Fix many typos in Augmentation descriptions (@kwazygloo) -- More numbers handle absurdly large values. (@Tesseract1234567890) -- Fix many typos (@Tesseract1234567890) -- Fixed an issue that caused a UI desync when sleeves were set to workout - stats other than strength at the gym. -- Fix weird alignment of donation text box and button. (@Tesseract1234567890) -- Fixed an issue where reputation could be transfered to new jobs when unfocused. -- Empty stack traces should no longer appear. -- Purchasing anything with Infinity money doesn't result in NaN. -- nerf noodle bar - -## v0.51.10 - 2021-05-31 Focus Mark, Focus! (hydroflame) - -**Focus** - -- You can now use the terminal and write scripts while working for factions - but you will gain reputation at a slower rate. - -**SF -1** - -- Added a new SF -1: Bypass - -**Gang** - -- "Vigilante justice"/"Ethical hacking" now reduces wanted level by a very - small percentage as well an absolute value. - -**Netscript** - -- 'tFormat' now has a second argument to display with millisecond precision. -- 'purchaseSleeveAug' can no longer purchase the same aug over and over for - the same sleeve. -- fix typo in logging for 'getServerSecurityLevel' -- Fixed some weird issue where very rarely you would get 0 exp from 'grow' -- 'getActionTime' now returns correct values for Diplomacy and Regeneration. - -**Corporations** - -- Fixed an exploit where you could get nearly infinite corporation funds by - entering negative numbers in textboxes. -- Fixed an exploit where shares could be sold again by clicking the - "sell share" button via scripts. - -**Documentation** - -- typo fix in purchaseTor -- typo fix in basicgameplay/stats - -**Misc.** - -- Very large number will no longer appear as "\$NaNt" -- Hash capacity now displays in the "big number" format. -- nerf noodle bar - -## v0.51.9 - 2021-05-17 offline progress and exports! (hydroflame & community) - -**Alias** - -- several commands can be included in 1 alias. Recursive alias now work to - a depth of 10. (@Dawe) - -**Offline** - -- Offline money gain has been reworked (it is more generous) -- If you're not working anywhere and go offline the game will work for you - at all your factions evenly. - -**Export** - -- Exporting now gives +1 favor to all joined factions every 24h. - -**Corp** - -- Self-fund with an invalid name no longer takes away 150b anyway. -- Can no longer export negative amount - -**Bladeburner** - -- No longer waste overflowing time. - -**Text Editors** - -- All settings will now be saved and loaded correctly. - -**Terminal** - -- 'scan' now works for servers that are more than 21 character long. - -**Misc.** - -- ls now correctly lists all files. -- importing auto save+reloads (@Dawe) -- Fix a bug where .fconf could not be created -- Fix formatting inconsistencies for some logs of netscript functions. -- Fix a bug where Cashroot starter kit would appear as [object Object] in - confirmation dialog. -- Fix some ram not displayed as 0.00GB -- Fix error message throw undefined variable error -- City hall now has some generic text if you can't create a corp yet. -- Deleting a file without extension now returns an appropriate error message. -- Fixed an issue where bladeburner would miscalculate the cost of hospitalization. -- It is now possible to suppress bladeburner "action stopped" popup. -- Updated several dependencies (big who cares, I know) -- ls no longer prints lingering newline. -- Money earned/spent by sleeves is now tracked under Character>Money -- nerf noodle bar - -## v0.51.8 - 2021-05-07 It was there all along (hydroflame & community) - -**Servers** - -- Update n00dles metadata - -**Netscript** - -- 'hashGainRate' use the correct 'usedRam' and 'maxRam' -- Fix 'setActionAutolevel' logging. -- Fix 'setActionLevel' not working at all. -- Add 'installBackdoor' singularity function. - -**Hacknet** - -- Fix Hacknet Servers total production always displaying 0 - -**Documentation** - -- Updated guide to no longer recommend BN12. -- Fix documentation for maxNumNodes (@ModdedGamers) -- Fix typo in 'sourcefiles.rst' -- Fix typo in 'recommendedbitnodeorder.rst' -- Fix 'getServer' documentation missing 'server' argument. -- Fix missing ram cost in 'getData.rst' -- Fix basic formulas examples. -- Fix typo in BN11 description. -- Fix formatting issue in Bladeburner (@Pimgd) - -**Misc.** - -- Fix negative money being displayed in full. -- Fix Hacking Missions not working. -- Fix Corporation tree not rendering. -- Fix script being needlessly recompiled. This should save real ram (not game ram) -- w0r1d_d43m0n can be backdoored -- Coding Contracts title is click-to-copy (@Rodeth) -- Covenant memory upgrade works better. -- Fix Neuroflux not being correctly calculated when entering BN with SF12. -- Delete Active Script now delete all active scripts, not just home. -- Now you can 'cd' in directories that only contain '.txt' files. -- Fix 'analyze' always saying players had root access -- Passive faction rep no longer builds for special factions. -- Donation option no longer appears for special factions. -- Rephrased some milestones. -- donation textbox now accepts money in the format '1b' and the like (@Dawe) -- Fix being able to join hated factions simultaneously. (@Dawe) -- 'ls' now displays files in multiple column. (Helps players with many files) -- Bladeburner multiplers now appear under Character>Stats and - Character>Augmentation when they are relevant. -- Fix missing functions syntax highlight in codemirror. -- Fix infiltration number formatting. -- script income transfers to parent on death. This helps keep track of - income for scripts that spawn short lived scripts. -- nerf noodle bar - -## v0.51.7 - 2021-04-28 n00dles (hydroflame & community) - -**Tutorial servers** - -- All the tutorial servers have been reverted to their original value -- The new server n00dles has been added as tutorial server. - -**Terminal** - -- 'tail' now accepts Pid. -- 'analyze' now handles Hacknet Servers correctly. -- 'ServerProfiler.exe' now handles Hacknet Servers correctly. - -**SF12** - -- Now makes you start with Neuroflux Governor equal to the level of the SF. - -**Netscript** - -- Deprecated 'getServerRam'. -- 'getServerMaxRam' added to replace 'getServerRam' -- 'getServerUsedRam' added to replace 'getServerRam' -- 'getBitnodeMultipliers' is available inside BN5 -- Time logged by hack/grow/weaken now displays in human time. -- thread count logged by hack/grow/weaken now displays with commas every - thousands place. - -**Donation** - -- Always visible but locked until favor requirements are reached. - -**Augmentations** - -- City factions has been rebalanced to give a reason to visit them all. - -**Sleeves** - -- Fix sleeves not being able to work at Volhavens gym. - -**Lint** - -- This shouldn't change anything but was like 10h of work. So I'm logging it. - -**Misc.** - -- Plethora of typo fixed (@Pimgd) -- ps documentation fix (@Dawe) -- The dev menu now has a quick bitflume option. -- Fix SF -1 not being as powerful as intended. -- Fix cashroot starter kit not displaying correctly. -- Fix DOM element 'character-overview-text' being nested twice. -- Hacknet documentation example fix. -- Money amount under 1000 dont display 3 decimal anymore. -- Fix nextSourceFile flag miscalculation on the bitverse (for Bn12) -- Faction invite text says "Decide later"/"Join!" instead of "No"/"Yes" -- nerf noodle bar - -## v0.51.6 - 2021-04-28 Backdoor! (hydroflame & community) - -**Backdoor** - -- a new terminal command, backdoor, has been added to help differentiate - between the terminal hack command and the netscript hack function. (@dewint) - -**Servers** - -- foodnstuff, sigma-cosmetics, and joesguns have been rebalanced to help new players. - -**Milestones** - -- A new tab under the Help menu has been added to guide players through the - game. - -**Casino** - -- Blackjack has been added (@BigD) - -**Netscript** - -- 'prompt' now converts input to JSON. -- 'getRunningScript' is a new netscript function that returns a bunch of - data related to a running script. - -**Coding contracts** - -- trivial puzzles should no longer appear. - -**Infiltration** - -- All numbers are formatted like the rest of the game. - -**Misc.** - -- Server security is capped at 100. -- Added option to quit a job. -- 'cd' no longer works on unexistent folders. -- cd with no arguments brings you back to top level folder (@Andreas) -- 'softReset' documentation udpated. -- Money tracker now accounts for going to the hospital manually. -- codemirror is now the default editor (for new save files) -- fix typo in dark web help text (@Rodeth) -- so many documentation and typos fixes (@Pimgd) -- A corruption visual effect has been added to location with servers that - have backdoor installed. (@dewint) -- nerf noodle bar - -## v0.51.5 - 2021-04-20 Flags! (hydroflame) - -**Netscript** - -- 'flags' is a new function that helps script handle flags. - This is subject to change if it doesn't meet the need of the players. -- 'ps' now returns the pid. -- 'tail' now works with pid as first argument. -- 'tail' hostname defaults to current server. (like the documentation says) -- 'isRunning' hostname defaults to current server. -- 'isRunning' now works with pid as first argument. - -**Gang** - -- Nerfed ascension mechanic once again :( - -**Misc.** - -- Souce-File typo fix -- Fix 'while you were away' screen. -- Bladeburner team size can no longer be set to negative amounts. -- nerf noodle bar - -## v0.51.4 - 2021-04-19 Manual hacking is fun (hydroflame) - -**Manual hacking** - -- These bonus require an install or a soft reset to take effect. -- Manual hacking gyms and university gives you a 10% discount. -- Manual hacking a corporation server decreases the penalty for leaving work - early. - -**BladeBurner** - -- nerfed int exp gained. - -**Documentation** - -- purchaseServer specifies what happens on failure. -- Fixed typo in recommended bitnode page. -- Removed misleading ram requirements for hacking factions. - -**Netscript** - -- growthAnalyze handles Infinity correctly. - -**Misc.** - -- Faction Augmentation will list how much reputation is required even after - that goal has been reached. -- Removed dollar sign in travel agency confirmation dialog box. -- Fixed typo in alpha-omega.lit -- the 'Game saved!' text no longer blocks the save game/options button. -- The text editor now remembers the location of your cursor and restores it. -- skills are recalculated instantly. -- Fix typo in Operation Zero description. -- nerf noodle bar - -## v0.51.3 - 2021-04-16 Y'all broke it on the first day (hydroflame) - -**Passive faction reputation** - -- Reworked, from 1 rep / 2 minute. Now is a complicated percentage of the - reputation you'd gain working for them. It's not op but it feels a bit - more useful. - -**Netscript** - -- print/tprint now take any number of arguments. -- print/tprint will now print object as json. -- print/tprint now handle passing in an undefined argument properly. - -**Casino** - -- Cannot bet negative money anymore. -- Roulette max bet is a bit higher. -- Coin Flip has a small cooldown. -- All buttons reject unstrusted mouse events. - -**Documentation** - -- Changed a message that said nsjs only works on Chrome. - -**Bugfix** - -- hacknet.maxNumNodes now works for both nodes and servers. -- Fixed a bug where the popup boxes would contain data from previous popup boxes. -- .js files will also have the 'export async function' boilerplate. - -**Misc.** - -- turned off web form autocomplete for the terminal text input. -- Fixed an issue on Windows+Firefox where pressing up on the terminal would - bring the cursor to the begining of the line. (Issue #836) -- Hacknet node names is easier to handle for screen readers. -- Money spent on classes is now tracked independently of work money. -- running coding contract from the terminal will display its name. -- nerf noodle bar - -## v0.51.2 - 2021-04-09 Vegas, Baby! (hydroflame) - -**New location: The Iker Molina Casino** - -- A casino opened in Aevum. However the house is rumored to cheat. If only - we could give them a taste of their own medicine. - -**Misc.** - -- Link to discord added under options -- 'getMemberInformation' doc updated, oops -- tech vendor now handle max ram and cores. -- nerf noodle bar - -## v0.51.1 - 2021-04-06 Bugfixes because the author of the last patch sucks (it's hydroflame) - -**Netscript** - -- 'getPlayer' returns players faction and tor -- 'hospitalization' is a new singularity function. -- 'gang.getMemberInformation' now returns more information. -- 'hacknet.hashCapacity' is a new hacknet function that returns the maximum hash capacity. - -**Hospitalization** - -- Now only cost at most 10% of your money. - -**Bugfix** - -- confirmation dialog box no longer use previous text - -**Accessibility** - -- The game is a little easier to handle for screen readers (yes, there's an - absolute legend playing this game with a screen reader) -- Infiltration use buttons instead of a-links -- New option to disable ASCII art. This will make the metro map and world - map display as a list of buttons. - -**Misc.** - -- 'fl1ght.exe' will no longer suggest the combat path. Related faction - requirements unchanged. -- nerf noodle bar - -## v0.51.0 - 2021-03-31 Formulas (hydroflame) - -**Formulas API** - -- A new API is introduced, this gives players access to various formulas used in the game. - It'll help you make more informed decisions. - -**Netscript** - -- 'getServer' is a new function meant to be used with the formulas API. -- 'getPlayer' is a new function meant to be used with the formulas API. -- 'getStats' and 'getCharacterInformation' are deprecated in favor of 'getPlayer' -- 'getCurrentServer' is a new function that returns the server the player is currently connected. - -**Display** - -- All money should now consistently be orange. -- All rep should now consistently be light-yellow. -- Most numbers should display consistently now (aka all money is formatted the same). - -**Click to copy** - -- Certain UI elements are now 'click-to-copy' - -** Misc. ** - -- nerf noodle bar - -## v0.50.2 - 2021-03-25 Everyone asked for this one. (hydroflame) - -**BitNodeMultipliers** - -- 'GangKarmaRequirements': a new multipler that influences how much karma is required to make a gang different bitnodes. - -**Netscript** - -- 'connect': a new singularity function that connects you to a server. (like the terminal command) -- 'manualHack': a new singularity function that performs a manual hack on the players current server. -- ns2 stack trace works on Firefox now. - -**Misc.** - -- New shortcut, Alt + b, brings you to bladeburner -- New shortcut, Alt + g, brings you to gang -- nerf noodle bar - -## v0.50.1 - 2021-03-22 (hydroflame) - -**Netscript** - -- getTaskStats works - -**Source-File -1** - -- Added a new Exploit - -**Factions** - -- Augmentations offered by a Faction but already bought are in a separate list at the bottom of the page. - -**Bug fixed** - -- Fixed a bug where completing a maxed non-repeatable BitNode would make its color on the BitVerse like level 1. - -**Misc.** - -- Minor spacing in stats tables. -- nerf noodle bar - -## v0.50.0 - 2021-03-20 Intelligence (hydroflame) - -**Intelligence** - -- int exp gain and effect has been reworked. It is now much more easy to - acquire and far more powerful. The goal here is to feel like players have - another tool in their arsenal. - -**Factions** - -- Hacking factions no longer have hacking level requirements since their associated servers do. - -**Misc.** - -- Sleeve styling. -- number formatting -- remove wiki button in Hacking Missions. -- Fix NaN displayed when very very large numbers are reached. -- nerf noodle bar - -## v0.49.2 - 2021-03-13 (hydroflame) - -**BN8** - -- A new bitnode multipler has been added, it lets you reduce money from a - server without gaining actually any money. This is important for BN8 where - hack/grow can influence the stock market. No money can be gained from - hacking but server money can still be reduced. - -**Documentation** - -- readthedocs should now be more consistent and many examples were added. - -**Netscript** - -- Ace editor will now correctly highlight all functions. -- 'tFormat' is a new netscript function that returns a human readable - representation of milliseconds. eg. "2 hours 15 minute 43 seconds" - -**Gang** - -- style improvements - -**Bladeburner** - -- style improvements -- fix bug where 'skill list SKILL' would crash if skill is level 0. - -**Sleeve** - -- karma gain now scales with sync. - -**Misc.** - -- Fix issue where the effective stats under Character>Stats were being calculated. -- nerf noodle bar - -## v0.49.0 - 2021-03-11 Source-File -1 (hydroflame) - -**Source-File -1** - -- For advanced players: The game now embraces exploits and will reward - players for doing so. - -**Gang** - -- ascension is less effective as the ascension multiplier goes up. -- territory gain scales with power difference. - -**Netscript** - -- 'gang.getEquipmentStats' returns the stats of the equipment. -- 'gang.getTaskStats' returns the stats of a task. -- 'getCrimeStats' returns the stats of a crime. -- Crashes should now print the ns stack trace. -- Log messages are now more consistent. -- 'softReset' now accepts a callback script like 'installAugmentations' - -**Misc.** - -- Minor formatting under Hacking>Active Scripts -- option menu colors now match the rest of the game, kinda. -- nerf noodle bar - -## v0.48.0 - ASCII - 2021-03-07 (hydroflame) - -**ASCII** - -- Travel Agency now displays a world map -- Cities are now top view of metro station maps - -**Netscript** - -- 'softReset' is a new netscript function that performs a soft reset - regardless of if the player has bought augmentations or not. -- 'getAugmentationStats' is a new netscript function that returns the stats of - an augmentation. -- getCharacterInformation now additionally returns exp -- pid resets back to 1 when installing or destroying a BitNode. -- New '.ns' scripts start with a main function. -- 'hacknet.maxNumNodes' returns the maximum number of hacknet nodes. - -**Bladeburner** - -- Current stamina will scale as max stamina increases, this prevents players - from having very high penalty when they gain huge amount of exp at the - start of a reset. - -**Misc.** - -- Fixed an issue where SF3 was listed as infinitly repeatable and SF12 as - having a limit of 3. -- Fixed an issue where the gang equipment screen would freeze the game if a - script installed augmentations while it is open. -- All BonusTime now displays in the 'H M S' format. -- Donation textbox style updated to match the rest of the game. -- Corporation name style updated to match the rest of the game. -- minor formatting under Hacking>Active Scripts -- typo in BN12 description -- BN12 now reduces contract money -- Character>Stats percentages are aligned, server and hacknet limit are - displayed, if the player has SF5 the reduces stats are shown. -- Character>Augmentations now displays by how much the player stats will - increase. -- Character>Augmentations has a badge indicating how many augs the player - has bought but not installed -- Character>Factions has a badge indicating how many factions have pending - invites. -- nerf noodle bar - -## v0.47.2 - 7/15/2019 - -**Netscript Changes** - -- Added tail() Netscript function -- hacknet.getNodeStats() function now returns an additional property for Hacknet Servers: hashCapacity -- When writing to a file, the write() function now casts the data being written to a string (using String()) -- BitNode-selection page now shows what Source-File level you have for each BitNode -- Overloaded kill() function so that you can kill a script by its PID -- spawn() now only takes 10 seconds to run (decreased from 20 seconds) -- run() and exec() now return the PID of the newly-executed scripts, rather than a boolean - - (A PID is just a positive integer) -- run(), exec(), and spawn() no longer need to be await-ed in NetscriptJS -- Script parsing and RAM calculations now support ES9 -- installAugmentations() no longer has a return value since it causes all scripts to die -- isBusy() now returns true if you are in a Hacking Mission -- Bug fix: workForFaction() function now properly accounts for disabled logs -- Bug fix: RAM should now be properly calculated when running a callback script with installAugmentations() -- Bug fix: Fixed bug that caused scripts killed by exit()/spawn() to "clean up" twice - -**Misc Changes** - -- The 'kill' Terminal command can now kill a script by its PID -- Added 'Solarized Dark' theme to CodeMirror editor -- After Infiltration, you will now return to the company page rather than the city page -- Bug fix: Stock Market UI should no longer crash for certain locale settings -- Bug fix: You can now properly remove unfinished programs (the `*.exe-N%-INC` files) -- Bug fix: Fixed an issue that allowed you to increase money on servers with a 'maxMoney' of 0 (like CSEC) -- Bug fix: Scripts no longer persist if they were started with syntax/import errors -- Bug fix: 'hack' and 'analyze' Terminal commands are now blocking -- Bug fix: Exp earned by duplicate sleeves at universities/gyms now takes hash upgrades into account - -## v0.47.1 - 6/27/2019 - -- Stock Market changes: - - - Transactions no longer influence stock prices (but they still influence forecast) - - Changed the way stocks behave, particularly with regard to how the stock forecast occasionally "flips" - - Hacking & growing a server can potentially affect the way the corresponding stock's forecast changes - - Working for a company positively affects the way the corresponding stock's forecast changes - -- Scripts now start/stop instantly -- Improved performance when starting up many copies of a new NetscriptJS script (by Ornedan) -- Improved performance when killing scripts -- Dialog boxes can now be closed with the ESC key (by jaguilar) -- NetscriptJS scripts should now be "re-compiled" if their dependencies change (by jaguilar) -- write() function should now properly cause NetscriptJS scripts to "re-compile" (by jaguilar) - -## v0.47.0 - 5/17/2019 - -- Stock Market changes: - - - Implemented spread. Stock's now have bid and ask prices at which transactions occur - - Large transactions will now influence a stock's price and forecast - - This "influencing" can take effect in the middle of a transaction - - See documentation for more details on these changes - - Added getStockAskPrice(), getStockBidPrice() Netscript functions to the TIX API - - Added getStockPurchaseCost(), getStockSaleGain() Netscript functions to the TIX API - -- Re-sleeves can no longer have the NeuroFlux Governor augmentation - - - This is just a temporary patch until the mechanic gets re-worked - -- hack(), grow(), and weaken() functions now take optional arguments for number of threads to use (by MasonD) -- codingcontract.attempt() now takes an optional argument that allows you to configure the function to return a contract's reward -- Adjusted RAM costs of Netscript Singularity functions (mostly increased) -- Adjusted RAM cost of codingcontract.getNumTriesRemaining() Netscript function -- Netscript Singularity functions no longer cost extra RAM outside of BitNode-4 -- Corporation employees no longer have an "age" stat -- Gang Wanted level gain rate capped at 100 (per employee) -- Script startup/kill is now processed every 3 seconds, instead of 6 seconds -- getHackTime(), getGrowTime(), and getWeakenTime() now return Infinity if called on a Hacknet Server -- Money/Income tracker now displays money lost from hospitalizations -- Exported saves now have a unique filename based on current BitNode and timestamp -- Maximum number of Hacknet Servers decreased from 25 to 20 -- Bug Fix: Corporation employees stats should no longer become negative -- Bug Fix: Fixed sleeve.getInformation() throwing error in certain scenarios -- Bug Fix: Coding contracts should no longer generate on the w0r1d_d43m0n server -- Bug Fix: Duplicate Sleeves now properly have access to all Augmentations if you have a gang -- Bug Fix: getAugmentationsFromFaction() & purchaseAugmentation() functions should now work properly if you have a gang -- Bug Fix: Fixed issue that caused messages (.msg) to be sent when refreshing/reloading the game -- Bug Fix: Purchasing hash upgrades for Bladeburner/Corporation when you don't actually have access to those mechanics no longer gives hashes -- Bug Fix: run(), exec(), and spawn() Netscript functions now throw if called with 0 threads -- Bug Fix: Faction UI should now automatically update reputation -- Bug Fix: Fixed purchase4SMarketData() -- Bug Fix: Netscript1.0 now works properly for multiple 'namespace' imports (import \* as namespace from "script") -- Bug Fix: Terminal 'wget' command now correctly evaluates directory paths -- Bug Fix: wget(), write(), and scp() Netscript functions now fail if an invalid filepath is passed in -- Bug Fix: Having Corporation warehouses at full capacity should no longer freeze game in certain conditions -- Bug Fix: Prevented an exploit that allows you to buy multiple copies of an Augmentation by holding the 'Enter' button -- Bug Fix: gang.getOtherGangInformation() now properly returns a deep copy -- Bug Fix: Fixed getScriptIncome() returning an undefined value -- Bug Fix: Fixed an issue with Hacknet Server hash rate not always updating - -## v0.46.3 - 4/20/2019 - -- Added a new Augmentation: The Shadow's Simulacrum -- Improved tab autocompletion feature in Terminal so that it works better with directories -- Bug Fix: Tech vendor location UI now properly refreshed when purchasing a TOR router -- Bug Fix: Fixed UI issue with faction donations -- Bug Fix: The money statistics & breakdown should now properly track money earned from Hacknet Server (hashes -> money) -- Bug Fix: Fixed issue with changing input in 'Minimum Path Sum in a Triangle' coding contract problem -- Fixed several typos in various places - -## v0.46.2 - 4/14/2019 - -- Source-File 2 now allows you to form gangs in other BitNodes when your karma reaches a very large negative value - - - (Karma is a hidden stat and is lowered by committing crimes) - -- Gang changes: - - - Bug Fix: Gangs can no longer clash with themselve - - Bug Fix: Winning against another gang should properly reduce their power - -- Bug Fix: Terminal 'wget' command now works properly -- Bug Fix: Hacknet Server Hash upgrades now properly reset upon installing Augs/switching BitNodes -- Bug Fix: Fixed button for creating Corporations - -## v0.46.1 - 4/12/2019 - -- Added a very rudimentary directory system to the Terminal - -- Added numHashes(), hashCost(), and spendHashes() functions to the Netscript Hacknet Node API -- 'Generate Coding Contract' hash upgrade is now more expensive -- 'Generate Coding Contract' hash upgrade now generates the contract randomly on the server, rather than on home computer -- The cost of selling hashes for money no longer increases each time -- Selling hashes for money now costs 4 hashes (in exchange for \$1m) -- Bug Fix: Hacknet Node earnings should work properly when game is inactive/offline -- Bug Fix: Duplicate Sleeve augmentations are now properly reset when switching to a new BitNode - -## v0.46.0 - 4/3/2019 - -- Added BitNode-9: Hacktocracy -- Changed BitNode-11's multipliers to make it slightly harder overall -- Source-File 11 is now slightly stronger -- Added several functions to Netscript Sleeve API for buying Sleeve augmentations (by hydroflame) -- Added a new stat for Duplicate Sleeves: Memory -- Increase baseline experience earned from Infiltration, but it now gives diminishing returns (on exp) as you get to higher difficulties/levels -- In Bladeburner, stamina gained from Hyperbolic Regeneration Chamber is now a percentage of your max stamina - -- Corporation Changes: - - - 'Demand' value of products decreases more slowly - - Bug Fix: Fixed a Corporation issue that broke the Market-TA2 Research - - Bug Fix: Issuing New Shares now works properly - -- Bug Fix: Money Statistics tracker was incorrectly recording profits when selling stocks manually -- Bug Fix: Fixed an issue with the job requirement tooltip for security jobs - -## v0.45.1 - 3/23/2019 - -- Added two new Corporation Researches -- General UI improvements (by hydroflame and koriar) -- Bug Fix: Sleeve Netscript API should no longer cause Dynamic RAM errors -- Bug Fix: sleeve.getSleeveStats() should now work properly - -## v0.45.0 - 3/22/2019 - -- Corporation changes: - - - Decreased the time of a full market cycle from 15 seconds to 10 seconds. - - This means that each Corporation 'state' will now only take 2 seconds, rather than 3 - - Increased initial salaries for newly-hired employees - - Increased the cost multiplier for upgrading office size (the cost will increase faster) - - The stats of your employees now has a slightly larger effect on production & sales - - Added several new Research upgrades - - Market-TA research now allows you to automatically set sale price at optimal values - - Market-TA research now works for Products (not just Materials) - - Reduced the amount of Scientific Research needed to unlock the Hi-Tech R&D Laboratory from 10k to 5k - - Energy Material requirement of the Software industry reduced from 1 to 0.5 - - It is now slightly easier to increase the Software industry's production multiplier - - Industries now have a maximum number of allowed products, starting at 3. This can be increased through research. - - You can now see an approximation of how each material affects an industry's production multiplier by clicking the "?" help tip next to it - - Significantly changed the effects of the different employee positions. See updated descriptions - - Reduced the amount of money you gain from private investors - - Training employees is now 3x more effective - - Bug Fix: An industry's products are now properly separated between different cities - -- The QLink Augemntation is now significantly stronger, but also significantly more expensive (by hydroflame) -- Added a Netscript API for Duplicate Sleeves (by hydroflame) -- Modified the multipliers of BitNode-3 and BitNode-8 to make them slightly harder -- After installing Augmentations, Duplicate Sleeves will now default to Synchronize if their Shock is 0 -- Bug Fix: Bladeburner's Hyperbolic Regeneration Chamber should no longer instantly refill all stamina -- Bug Fix: growthAnalyze() function now properly accounts for BitNode multipliers -- Bug Fix: The cost of purchasing Augmentations for Duplicate Sleeves no longer scales with how many Augs you've purchased for yourself - -## v0.44.1 - 3/4/2019 - -- Duplicate Sleeve changes: - - - You can now purchase Augmentations for your Duplicate Sleeves - - Sleeves are now assigned to Shock Recovery task by default - - Shock Recovery and Synchronize tasks are now twice as effective - -- Changed documentation so that Netscript functions are own their own pages. Sorry if this is annoying, it was necessary for properly cross-referencing -- Officially deprecated the Wiki (the fandom site). Use the 'readthedocs' Documentation instead -- Bug Fix: 'rm' Terminal and Netscript commands now work on non-program files that have '.exe' in the name (by Github user MasonD) -- Bug Fix: The 'Find All Valid Math Expressions' Coding Contract should now properly ignore whitespace in answers -- Bug Fix: The 'Merge Overlapping Intervals' Coding Contract should now properly accept 2D arrays when being attempted through Netscript - -## v0.44.0 - 2/26/2019 - -- Bladeburner Changes: - - Reduced the amount of rank needed to earn a skill point - - Reduced the effects of the "Reaper" and "Evasive System" skills - - Increased the effect of the "Hyperdrive" and "Hands of Midas" skills - - Slightly increased the rate which the skill point cost rises for almost all skills - - The "Overlock" Skill now has a maximum level of 90 instead of 95 - - Money earned from Contracts increased by 400% - - Changed the way population affects success rate. Extreme populations now have less dramatic effects - - Added two new General Actions: Diplomacy and Hyperbolic Regeneration Chamber - - Lowered the rep and money cost of the "Blade's Simulacrum" augmentation - - Significantly decreased the initial amount of Contracts/Operations (the "Contracts/Operations remaining" value) - - Decreased the rate at which the amount of Contracts/Operations increases over time - - Decreased the number of successes you need to increase the max level of a Contract/Operation - - Increased the average number of Synthoid communities each city has - - Reduced the amount by which a successful raid will decrease the population of a city - - The "riots" event will now increase the chaos of a city by a greater amount - - Significantly increased the effect that Agility and Dexterity have on action time -- Added new BitNode multipliers: - - HomeComputerRamCost - Affects how much it costs to upgrade home computer's RAM - - DaedalusAugsRequirement - Affects how many Augmentations you need in order to get invited to Daedalus - - FourSigmaMarketDataCost - Affects how much it costs to unlock the stock market's 4S Market Data - - FourSigmaMarketDataApiCost - Affects how much it costs to unlock the stock market's 4S Market Data API -- A few minor changes to BitNode multipliers across the board (mostly for the new multipliers) -- 'The Covenant' now requires 20 total Augmentations to get invited, rather than 30 -- You can now purchase permanent Duplicate Sleeves from 'The Covenant'. This requires Source-File 10, and you must be in BN-10 or after -- You can now track where all of your money comes from in the 'Stats' page -- Increased the money gained from Coding Contracts by 50% -- getCharacterInformation() function now returns the player's HP and max HP -- Bug Fix: You can no longer disconnect the enemy's connections in Hacking Missions -- Bug Fix: Duplicate Sleeve faction reputation gain is now properly affected by faction favor -- Bug Fix: After installing Augmentations, the Terminal display will now correctly show the current server as "home" -- Bug Fix: Fixed an exploit where you could change the duration of timed functions (e.g. hack, weaken) in NetscriptJS -- Bug Fix: You should now properly be able to use the ServerProfile.exe program -- Bug Fix: Prevented exploit that allowed you to accept faction invites programmatically through NetscriptJS -- Bug Fix: Faction invitations for megacorporations should now work properly - -## v0.43.1 - 2/11/2019 - -- Terminal changes: - - - Quoted arguments are now properly parsed. (e.g. 'run f.script "this is one argument"' will be correctly parsed) - - Errors are now shown in red text - - 'unalias' command now has a different format and no longer needs the quotations - - Bug Fix: Fixed several edge cases where autocomplete wasn't working properly - -- Added two new Bladeburner skills for increasing money and experience gain -- Made some minor adjustments to Bladeburner UI -- Corporation "Smart Factories" and "Smart Storage" upgrades have slightly lower price multipliers -- Added nFormat Netscript function -- Added 6 new Coding Contract problems -- Updated documentation with list of all Coding Contract problems -- Minor improvements for 'Active Scripts' UI -- Implemented several optimizations for active scripts. The game should now use less memory and the savefile should be slightly smaller when there are many scripts running -- Bug Fix: A Stock Forecast should no longer go above 1 (i.e. 100%) -- Bug Fix: The cost of Resleeves should no longer be affected by buying Augs -- Bug Fix: Duplicate Sleeves now use their own stats to determine crime success rate, instead of the host consciousness' stats -- Bug Fix: You can now call the prompt() Netscript function from multiple scripts simultaneously - -## v0.43.0 - 2/4/2019 - -- Added BitNode-10: Digital Carbon - -- Stock Market Changes: - - - Each stock now has a maximum number of shares you can purchase (both Long and Short positions combined) - - Added getStockMaxShares() Netscript function to the TIX API - - The cost of 4S Market Data TIX API Access increased from \$20b to \$25b - -- Job Changes: - - - You can now hold multiple jobs at once. This means you no longer lose reputation when leaving a company - - Because of this change, the getCharacterInformation() Netscript function returns a slightly different value - -- Script Editor Changes: - - - Added new script editor: CodeMirror. You can choose between the old editor (Ace) or CodeMirror - - Navigation keyboard shortcuts no longer work if the script editor is focused - -- Trying to programmatically run a script (run(), exec()) with a 'threads' argument of 0 will now cause the function to return false without running the script -- Home Computer RAM is now capped at 2 ^ 30 GB (1073741824 GB) -- The maximum amount, maximum RAM, and cost of purchasing servers can now vary between different BitNodes (new BitNode multipliers) -- Pop-up dialog boxes are a little bit bigger -- Bug Fix: When importing scripts, "./" will now be properly ignored (e.g. import { foo } from "./lib.script" ) - -## v0.42.0 - 1/8/2019 - -- Corporation Changes: - - - Corporation can now be self-funded with \$150b or using seed money in exchange for 500m newly-issued shares - - In BitNode-3, you no longer start with \$150b - - Changed initial market prices for many materials - - Changed the way a material's demand, competition, and market price change over time - - The sale price of materials can no longer be marked-up as high - - Added a Research Tree mechanic. Spend Scientific Research on permanent upgrades for each industry - - You can now redistribute earnings to shareholders (including yourself) as dividends - - Cost of "Smart Supply" upgraded reduced from \$50b to \$25b - - Now has offline progress, which works similarly to the Gang/Bladeburner mechanics - - Slightly reduced the amount of money offered to you by investment firms - - Employee salaries now slowly increase over time - - Slightly reduced the effect "Real Estate" has on the Production Multiplier for the Agriculture industry - - Changed the way your Corporation's value is calculated (this is what determines stock price) - - After taking your corporation public, it is now possible to issue new shares to raise capital - - Issuing new shares can only be done once every 12 hours - - Buying back shares must now be done at a premium - - Selling shares can now only be done once per hour - - Selling large amounts of shares now immediately impacts stock price (during the transaction) - - Reduced the initial cost of the DreamSense upgrade from \$8b to \$4b, but increased its price multiplier - - Reduced the price multiplier for ABC SalesBots upgrade - -- Added getOrders() Netscript function to the TIX API -- Added getAugmentationPrereq() Singularity function (by havocmayhem) -- Added hackAnalyzePercent() and hackAnalyzeThreads() Netscript functions -- Stock Market, Travel, and Corporation main menu links are now properly styled -- Many pop-up/dialog boxes now support the 'Enter' and 'Esc' hotkeys. If you find a pop-up/dialog box that doesnt support this, let me know specifically which one ('Enter' for the default option, 'Esc' for cancelling and closing the pop-up box) -- Added "brace_style = preserve_inline" configuration to Script Editor Beautifier -- ServerProfiler.exe can now be purchased from the Dark Web -- Added an option to copy save data to clipboard -- Added total multiplier information on the "Augmentations" page -- Bug Fix: gymWorkout() Singularity function should now work properly with Millenium Fitness Gym -- Began migrating gameplay information to the ReadTheDocs documentation - -## v0.41.2 - 11/23/2018 - -- IMPORTANT - Netscript Changes: - - - rm() now takes an optional parameter that lets you specify on which server to delete the file - - Added growthAnalyze() Netscript function - -- Gang Changes: - - - UI now displays your chance to win a clash with other gangs - - Added getChanceToWinClash() function to the Gang API - - Added getEquipmentType() function to the Gang API - - Added several new hacking-based equipment and Augmentations - - Rebalanced several equipment/upgrades to give less defense - - Wanted level gain rate is now be slightly higher for all tasks - - Rebalanced parameters for "hacking" tasks - -- Added new Main Menu configuration in .fconf: "compact" -- Added the terminal command 'expr', which can be used to evaluate simple mathematical expressions -- Bug Fix: Can no longer purchase duplicate equipment/Augmentations through gang.purchaseEquipment() -- Bug Fix: scp() should no longer throw errors when used with 2-arguments and an array of files -- Bug Fix: Coding Contracts no longer give money in BitNode-8 -- Bug Fix: In Bladeburner, you can no longer start a BlackOp through the Netscript API if it has already been completed -- Bug Fix: In Bladeburner, fixed a bug which caused the configured 'automate' actions to occasionally be switched to other actions -- Bug Fix: 'Return to World' button at locations no longer accumulates event listeners -- Bug Fix: Working & taking classes now continuously add/subtract money during the action, instead of doing it at completion -- Bug Fix: Top-right overview panel now displays negative money using '-' instead of '()' -- Bug Fix: Stock Market UI should no longer show 'NaN' profit immediately after buying a stock - -## v0.41.1 - 11/5/2018 - -- IMPORTANT - Netscript Changes: - - - purchaseTor() now returns true if you already have a TOR router (it used to return false) - - getPurchasedServerCost() now returns Infinity if the specified RAM is an invalid amount or is greater than the max amount of RAM (2 ^ 20 GB) - - Added purchase4SMarketData() and purchase4SMarketDataTixApi() functions - - getScriptLogs() now takes in optional arguments that let you get the logs of another script - -- Stock Market changes: - - - Stocks now have "maximum prices". These are hidden from the player - - If a stock reaches its "maximum price", it will most likely drop in value (although it might still rise) - - Each stock has its own, unique maximum price - - Maximum price for each stock are randomly generated and change during each 'reset' - - Stock Market cycles are now accumulated/stored, much like it is for Gangs and Bladeburners - - Accumulated/stored cycles cause stock prices to update up to 50% faster (from every 6 seconds to 4 seconds) - - This means that after coming back from being offline, stock prices will update faster to make up for offline time - -- Decreased the Hacking Level multiplier for BitNodes 6 and 7 to 0.4 (from 0.5) -- Bladeburner console history is now saved and persists when switching screens or closing/reopening the game -- In Bladeburner, if your stamina reaches 0 your current action will be cancelled -- b1t_flum3.exe is no longer removed from your home computer upon reset -- Added main menu link for the Stock Market (once you've purchased an account) -- Job main menu link only appears if you actually have a job -- Bug Fix: Netscript Gang API functions purchaseEquipment() and ascendMember() should now work properly -- Bug Fix: After installing Augs, the "Portfolio Mode" button on the Stock Market page should be properly reset -- Bug Fix: bladeburner.getActionCountRemaining()'s return value is now rounded down (by Kline-) - -## v0.41.0 - 10/29/2018 - -- WARNING: In NetscriptJS, defining a function called print() is no longer possible -- Gang Mechanic Changes (BitNode-2): - - Added a Gang Netscript API - - Added new 'ascension' mechanic for Gang Members - - The first three gang members are now 'free' (can be recruited instantly) - - Maximum number of increased Gang Members increased from 20 to 30 - - Changed the formula for calculating respect needed to recruit the next gang member - - Added a new category of upgrades for Gang Members: Augmentations - - Non-Augmentation Gang member upgrades are now significantly weaker - - Reputation for your Gang faction can no longer be gained through Infiltration - - Re-worked the territory 'warfare' mechanic so that player can choose when to engage in it - - Gang Members can now be killed during territory 'warfare' - - Changed BitNode-2 Multipliers to make hacking slightly less profitable - - Gang Member Equipment + Upgrades now get cheaper as your gang grows in power and respect - - The effects of Source-File 2 are now slightly more powerful -- RAM Cost of accessing the global document object lowered from 100 GB to 25 GB -- RAM Cost to use Singularity Functions outside of BitNode-4 lowered by 75%. They now only cost twice as much as they do in BitNode-4 -- b1t_flum3.exe now takes significantly less time to create -- Crimes commited through Singularity function no longer give half money/exp (there is now no penalty) -- Improved number formatting for Player 'work' actions (including crimes, etc.). These numbers should also adhere to locale settings now (by Kline-) -- The order that Augmentations are listed in (when purchasing from Faction and viewing your Augmentations) is now saved and persists when choosing different orders -- getCharacterInformation() Singularity function now returns multiplier information (from Augmentations/Source Files) -- Bug Fix: Calling print() in NetscriptJS no longer brings up the print dialog -- Bug Fix: Fixed a bug that sometimes caused a blank black screen when destroying/resetting/switching BitNodes -- Bug Fix: Netscript calls that throw errors will now no longer cause the 'concurrent calls' error if they are caught in the script. i.e. try/catch should now work properly in scripts -- Bug Fix: Fixed a bug where sometimes the NeuroFlux Governor Augmentation level would be incorrectly calculated when the game was loaded -- Bug Fix: Fixed a bug where calling the scp() Netscript function with invalid hostname/ips would throw an unclear error message -- Bug Fix: Bladeburner API function getActionCountRemaining() should now work properly for BlackOps -- Bug Fix: Black Ops can no longer be attempted out-of-order or without the required rank via Bladeburner API -- Bug Fix: Dynamic RAM Calculation now properly accounts for number of threads -- RAM cost for basic Netscript functions added to documentation (by CBJamo) - -## v0.40.5 - 10/09/2018 - -- Added codingcontract.getContractType() Netscript function -- Bug Fix: codingcontract.getData() Netscript function now returns arrays by value rather than reference -- Bug Fix: Decreased highest possible data value for 'Find Largest Prime Factor' Coding Contract (to avoid hangs when solving it) -- Bug Fix: Fixed a bug that caused game to freeze during Coding Contract generation - -## v0.40.4 - 9/29/2018 - -- Added new Coding Contracts mechanic. Solve programming problems to earn rewards -- The write() and read() Netscript functions now work on scripts -- Added getStockSymbols() Netscript function to the TIX API (by InfraK) -- Added wget() Netscript function -- Added bladeburner.getActionRepGain() function to the Netscript Bladeburner API -- The getLevelUpgradeCost(), getRamUpgradeCost(), and getCoreUpgradeCost() functions in the Hacknet API now return Infinity if the node is at max level. See documentation -- It is now possible to use freely use angled bracket (<, >) and create DOM elements using tprint() -- The game's theme colors can now be set through the Terminal configuration (.fconf). -- You can now switch to the old left-hand main menu bar through the Terminal configuration (.fconf) -- Bug Fix: grow() percentage is no longer reported as Infinity when a server's money is grown from 0 to X -- Bug Fix: Infiltration popup now displays the correct amount of exp gained - -## v0.40.3 - 9/15/2018 - -- Bladeburner Changes: - - Increased the effect that agi and dexterity have on action time - - Starting number of contracts/operations available will be slightly lower - - Random events will now happen slightly more often - - Slightly increased the rate at which the Overclock skill point cost increases -- The maximum volatility of stocks is now randomized (randomly generated within a certain range every time the game resets) -- Increased the range of possible values for initial stock prices -- b1t_flum3.exe program can now be created immediately at Hacking level 1 (rather than hacking level 5) -- UI improvements for the character overview panel and the left-hand menu (by mat-jaworski) -- General UI improvements for displays and Terminal (by mat-jaworski) -- Added optional parameters to the getHackTime(), getGrowTime(), and getWeakenTime() Netscript functions -- Added isLogEnabled() and getScriptLogs() Netscript functions -- Added donateToFaction() Singularity function -- Updated documentation to reflect the fact that Netscript port handles (getPortHandle()) only works in NetscriptJS (2.0), NOT Netscript 1.0 -- Added tryWrite() Netscript function -- When working (for a company/faction), experience is gained immediately/continuously rather than all at once when the work is finished -- Added a setting in .fconf for enabling line-wrap in the Terminal input -- Adding a game option for changing the locale that most numbers are displayed in (this mostly applies for whenever money is displayed) -- The randomized parameters of many high-level servers can now take on a higher range of values -- Many 'foreign' servers (hackable servers that you don't own) now have a randomized amount of RAM -- Added 'wget' Terminal command -- Improved the introductory tutorial - -## v0.40.2 - 8/27/2018 - -- Bladeburner Changes: - - Added getBonusTime(), getSkillUpgradeCost(), and getCity() Netscript functions to the API - - Buffed the effects of many Bladeburner Augmentations - - The Blade's Simulacrum Augmentation requires significantly less reputation but slightly more money - - Slightly increased the amount of successes needed for a Contract/Operation in order to increase its max level - - Increased the amount of money gained from Contracts by ~25% - - Increased the base amount of rank gained from Operations by 10% - - Significantly increased the 'randomness' in determining a Contract/Operation's initial count and rate of count increase - - The number (count) of Operations should now increase significantly faster - - There are now, on average, more Synthoid communities in a city - - If automation is enabled (the feature in Bladeburner console), then switching to another action such as working for a company will now disable the automation -- Stock Market Changes: - - Added a watchlist filter feature to the UI that allows you to specify which stocks to show - - Added the Four Sigma (4S) Market Data feed, which provides volatility and price forecast information about stocks - - Added the 4S Market Data TIX API, which lets you access the aforementioned data through Netscript -- There is now a setting for enabling/disabling the popup that appears when you are hospitalized -- Bug Fix: Stock market should now be correctly initialized in BitNode-8 (by Kline-) -- Bug Fix: bladeburner.getCurrentAction() should now properly an 'Idle' object rather than null (by Kline-) -- Bug Fix: Bladeburner skill cost multiplier should now properly increase in BitNode-12 (by hydroflame) -- Bug Fix: 'document', 'hacknet', and 'window' keywords should no longer be counted multiple times in RAM calculations -- Bug Fix: Joining factions through Singularity functions should now prevent you from joining opposing factions -- Bug Fix: Four Sigma should no longer have two 'Speech Enhancement' Augmentations (by Kline-) - -## v0.40.1 - 8/5/2018 - Community Update - -- Added getPurchasedServerCost() Netscript function (by kopelli) -- Added getFavorToDonate() Netscript function (by hydroflame) -- Added getFactionFavorGain() and getCompanyFavorGain() Singularity functions (by hydroflame) -- Accumulated 'bonus' time in Bladeburner is now displayed in the UI (by hydroflame) -- The Red Pill can now be purchased with negative money (since its supposed to be free) (by hydroflame) -- Cranial Signal Processor Augmentations now have the previous generation as a prerequisite. i.e. Cranial Signal Processor - Gen II requires Gen I (by Kline-) -- Terminal now supports semicolon usage (end of command). This allows chaining multiple Terminal commands (by hydroflame) -- Bladeburner Raid operations can no longer be performed if your estimate of Synthoid communities is zero (by hydroflame) -- The difficulty of BN-12 now scales faster (by hydroflame) -- Active Scripts UI now shows a RAM Usage bar for each server (by kopelli) -- Bug Fix: Corrected terminal timestamp format (by kopelli) -- Bug Fix: NetscriptJS scripts should now die properly if they don't have a 'main' function (by hydroflame) -- Bug Fix: write(), read(), and tryWrite() Netscript functions should now work properly for writing Arrays/objects to Netscript Ports -- Various minor UI/QOL fixes by hydroflame, kopelli, and Kline- - -## v0.40.0 - 7/28/2018 - -- **WARNING: This update makes some significant changes to Netscript and therefore you may need to make some changes to your scripts. See** `this post `\_ **this post for details** -- Netscript 1.0 (NS1) now uses a fully-fledged ES5 JavaScript Interpreter. This means many new features are now available in NS1, and this also fixes several bugs. - However this also means any ES6+ features are no longer supported in NS1 -- When a server is hacked with a very large number of threads and left with no money, the server's security level - now only increases by however many threads were needed to drain the server. For example, if you hack a server with - 5000 threads but it only needed 2000 threads to deplete the server's money, then the server's security will only increase - as if you had hacked it with 2000 threads (change by hydroflame) -- Added getCurrentAction() to Bladeburner API -- Added a variety of functions to Bladeburner API that deal with action levels (change by hydroflame) -- Added getPurchasedServerLimit() and getPurchasedServerMaxRam() functions to Netscript (change by hydroflame & kopelli) -- Added getOwnedSourceFiles() Singularity function (by hydroflame) -- Completely re-designed the Hacknet Node API -- getSkillLevel() in Bladeburner API now returns an error if no argument is passed in (as opposed to an object with all skill levels). This may break scripts -- Minimum Netscript execution time reduced from 15ms to 10ms (configurable in Options) -- Company reputation needed to get invited to Megacorporation factions decreased from 250k to 200k -- HP is now reset (restored) when Augmenting -- Source-File 6 now increases both the level and experience gain of all combat stats (it was only experience gain previously) -- Reverted a previous change for Source-File 12. It's benefits are now multiplicative rather than additive -- Starting Infiltration security level for almost every location decreased by ~10% -- Changed 'fl1ght.exe' message when its listed conditions are fulfilled (by hydroflame) -- The 'Save Game' button in the top-right overview panel now flashes red if autosave is disabled -- Bug Fix: Infiltration buttons can no longer be clicked through NetscriptJS -- Bug Fix: Bladeburner 'Overclock' skill can no longer be leveled above max level through the API (by hydroflame) -- Bug Fix: Healthcare division in Bladeburner should no longer cause game to crash - -## v0.39.1 - 7/4/2018 - -- Bladeburner Rank gain in BN-7 is now reduced by 40% instead of 50% -- Quadrupled the amount of money gained from Bladeburner contracts -- Added joinBladeburnerDivision() Netscript function to Bladeburner API -- Doubled the effects of Source-File 5. Now gives 8%, 12%, and 14% increase to all hacking multipliers at levels 1, 2, and 3, respectively (increased from 4%/6%, 7%) -- Increased the effect of Source-File 8. It now gives a 12%, 18% and 21% to your hacking growth multiplier at levels 1, 2, and 3, respectively (increased from 8%, 12%, 14%) -- The effect of Source-File 12 is now additive with itself, rather than multiplicative. This means that level N of Source-File 12 now increases all multipliers by N% -- The setting to suppress the confirmation box when purchasing Augmentations was moved into the main Options menu (by Github user hydroflame) -- Bug Fix: Crime Success rates were being calculated incorrectly (by Github user hydroflame) -- When an Infiltration is finished, you will now return back to the company's page, rather than the city -- Infiltration faction reputation selector now remembers your last choice -- Significantly increased the amount of money gained from Infiltration -- Bug Fix: Copying a NetscriptJS script to another server using scp now properly takes into account the script's changes. -- Bug Fix: Fixed an issue where game would not load in Edge due to incompatible features -- travelToCity() Singularity function no longer grants Intelligence exp" - -## v0.39.0 - 6/25/2018 - -- Added BitNode-7: Bladeburner 2079 -- Infiltration base difficulty decreased by 10% for most locations -- Experience gains from Infiltration slightly increased -- Money gained from Infiltration increased by 20% -- Added 'var' declarations in Netscript 1.0 (only works with 'var', not 'let' or 'const') -- Script base RAM cost is now 1.6 GB (increased from 1.4 GB) -- While/for loops and if statements no longer cost RAM in scripts -- Made short-circuit evaluation logic more consistent in Netscript 1.0 -- Changelog button in the Options menu now links to the new Changelog URL (by Github user thePalindrome) -- Skill level calculation is now 'smoother' (by Github user hydroflame) -- Added a button to 'beautify' scripts in the text editor (by Github user hydroflame) -- Added favicon (by Github user kopelli) - -## v0.38.1 - 6/15/2018 - -- Bug Fix: Using 'Object.prototype' functions like toLocaleString() or toString() should no longer cause errors in NetscriptJS -- Implemented by Github user hydroflame: - - Accessing the 'window' and 'document' objects in Netscript JS now requires a large amount of RAM (100 GB) - - Added game option to suppress travel confirmation - - Text on buttons can no longer be highlighted - - Bug Fix: Fixed an issue that caused NaN values when exporting Real Estate in Corporations - - Bug Fix: Competition and Demand displays in Corporation are now correct (were reversed before) - - Added ps() Netscript function - - Bug Fix: grow() should no longer return/log a negative value when it runs on a server that's already at max money - - Bug Fix: serverExists() Netscript function should now properly return false for non-existent hostname/ips - - Bug Fix: Sever's security level should now properly increase when its money is grown to max value - -## v0.38.0 - 6/12/2018 - -- New BitNode: BN-12 The Recursion - Implemented by Github user hydroflame -- Bladeburner Changes: - - Bladeburner progress is no longer reset when installing Augmentations - - The number of successess needed to increase a Contract/Operation's max level now scales with the current max level (gradually gets harder) - - All Bladeburner Augmentations are now slightly more expensive and require more reputation - - Black Operations now give higher rank rewards - - Doubled the base amount of money gained from Contracts - - Increased the amount of experience gained from Contracts/Actions - - Added a new Augmentation: The Blade's Simulacrum - - Bladeburner faction reputation gain is now properly affected by favor -- Hacking is now slightly less profitable in BitNode-3 -- Updated Hacknet Nodes UI - Implemented by Github user kopelli -- Bug Fix: Fixed an exploit that allowed calling any Netscript function without incurring any RAM Cost in NetscriptJS - -## v0.37.2 - 6/2/2018 - -- After joining the Bladeburners division, there is now a button to go to the Bladeburner content - in the 'City' page -- You now start with \$250m in BitNode-8 (increased from \$100m) -- Bug Fix: You can now no longer directly edit Hacknet Node values through NetscriptJS (hopefully) -- Bug Fix: Bladeburners is no longer accessible in BN-8 -- Bug Fix: getBitNodeMultipliers() Netscript function now returns a copy rather than the original object - -## v0.37.1 - 5/22/2018 - -- You now earn money from successfully completing Bladeburner contracts. The amount you earn is based - on the difficulty of the contract. -- Completing Field Analysis in Bladeburner now grants 0.1 rank -- The maximum RAM you can get on a purchased server is now 1,048,576 GB (2^20) -- Bug Fix: Fixed Netscript syntax highlighting issues with the new NetscriptJS -- Bug Fix: Netscript Functions now properly incur RAM costs in NetscriptJS -- Bug Fix: deleteServer() now fails if its called on the server you are currently connected to -- Removed in-game Netscript documentation, since it was outdated and difficult to maintain. -- Bug Fix: Updated the gymWorkout() Singularity function with the new exp/cost values for gyms - -## v0.37.0 - 5/20/2018 - -- NetscriptJS (Netscript 2.0) released -- Running the game with the '?noScripts' query will start the game without loading any of your scripts. This should be used if you accidentally write a script that crashes your game - -## v0.36.1 - 5/11/2018 - -- Bladeburner Changes: - - Bug Fix: You can no longer get Bladeburner faction reputation through Infiltration - - Initial difficulty of Tracking contracts reduced - - Datamancer skill effect increased from 4% per level to 5% - - Slightly decreased the base stamina cost of contracts/operations - - Slightly increased the effects of the Tracer, Digital Observer, Short Circuit, Cloak, and Blade's Intuition skills - - Overclock skill capped at level 95, rather than 99 - - Training gives significantly more exp/s -- Crime, Infiltration, and Hacking are now slightly more profitable in BN-6 -- Gyms are now more expensive, but give slightly more exp -- Added getScriptName() and getHacknetMultipliers() Netscript functions (added by Github user hydroflame) -- getScriptRam() Netscript function now has default value for the second argument, which is hostname/ip (implemented by Github user hydroflame) -- There is now a soft-cap on stock price, which means it's no longer possible for the price of a stock to reach insanely-high values -- The ctrl+b hotkey in the text editor should now also be triggered by command+b on OSX (I don't have OSX so I can't confirm if this works) -- Many servers now have additional RAM -- Added an option to disable hotkeys/keyboard shortcuts -- Refactored 'Active Scripts' UI page to optimize its performance -- Added a new .fconf Terminal setting: ENABLE_TIMESTAMP -- 'Netscript Execution Time', which can be found in the Options, now has a minimum value of 15ms rather than 25ms -- Bug Fix: Fixed a typo in the Fulcrum Technologies company name (Technolgies -> Technologies) -- Bug Fix: hacknetnodes keyword should no longer incur RAM cost if its in a comment -- Bug Fix: disableLog() now works for the commitCrime() Netscript function (fixed by Github user hydroflame) - -## v0.36.0 - 5/2/2018 - -- Added BN-6: Bladeburners -- Rebalanced many combat Augmentations so that they are slightly less powerful -- Bug Fix: When faction invites are suppressed, an invitation will no longer load the Faction page - -## v0.35.2 - 3/26/2018 - -- Corporation Changes: - - Fixed an issue with Warehouse upgrade cost. Should now be significantly cheaper than before. - - Scientific Research now has a slightly more significant effect on Product quality - - The Energy and Water Utilities industries are now slightly more profitable - - The Robotics and Computer Hardware industries are now less profitable - - The Software industry is slightly less profitable - - When selling Materials and Products, the 'PROD' qualifier can now be used to set dynamic sell amounts based on your production - - Exporting MAX should now work properly - - You can no longer export past storage limits - - Scientific Research production reduced - - Effects of AdVert. Inc upgrade were reduced, but the effect that popularity and awareness have on sales was increased to compensate (popularity/awareness numbers were getting too big with Advert. Inc) - - Bug Fix: Products from Computer Hardware division should now properly have ratings -- Improved Augmentation UI/UX. Now contains collapsible headers and sort buttons -- Improved Faction Augmentations display UI/UX. Now contains sort buttons. There is also an option to disable confirmation when purchasing Augmentations - -## v0.35.1 - 3/12/2018 - -- You can now easily download all of your scripts/text files as zip folders. Use the 'help download' Terminal command for details -- Scripts are now downloaded with the .script.js extension at the end of their filename -- Corporation Management Changes: - - Implemented Smart Supply unlock - - Changed the way a division's Production Multiplier is calculated. It is now the sum of the individual Production Multiplier for every city. Therefore, it is now beneficial to open offices in different cities - - Several small UI/UX improvements - - Numerous balance changes. The significant ones are listed below. - - Product descriptions will now display their estimated market price - - The sale price of Products can no longer be marked up as high as before - - Scientific Research now affects the rating of Products - - In general, the maximum amount of product you are able to sell is reduced - - Sale bonus from advertising (popularity/awareness) now has diminishing returns rather than scaling linearly -- Experience gained during Infiltration now scales linearly based on the clearance level you reach. Compared to before, the experience gained will be much less at lower clearance levels, but much more at higher clearance levels -- The editor can now be used to edit both scripts and text files -- New Terminal config file that can be edited using the command 'nano .fconf'. Right now there is only one option, but there will be more in the future. -- You can now enable Bash-style Terminal hotkeys using the .fconf file referenced above -- Bug Fix: Fixed an issue with the UI elements of Gang Management persisting across different instances of BitNode-2 - -## v0.35.0 - 3/3/2018 - -- Minor rebalancing of BitNodes due to the fact that Corporations provide a (relatively) new method of progressing -- Corporation Management Changes: - - Once your Corporation gets big/powerful enough, you can now bribe Factions for reputation using company funds an/or stock shares - - You can now only create one Division for every Industry type - - Added several new UI/UX elements - - Wilson Analytics multiplier was significantly reduced to 1% per level (additive). - - Reduced the effect of Advert Inc upgrade. Advert Inc. upgrade price increases faster - - Materials can now be marked up at higher prices -- Added Javascript's built-in Number object to Netscript -- Added getCharacterInformation(), getCompanyFavor(), and getFactionFavor() Netscript Singularity functions -- Rebalanced Singularity Function RAM Costs. They now cost x8 as much when outside of BN-4 (rather than x10). Also, many of the functions now use significantly less RAM -- Refactored Netscript Ports. You can now get a handle for a Netscript port using the getPortHandle() Netscript function. This allows you to access a port's underlying queue (which is just an array) and also makes several new functions available such as tryWrite(), full(), and empty(). -- Number of Netscript Ports increased from 10 to 20 -- Netscript assignments should now return proper values. i.e. i = 5 should return 5. -- Added throw statements to Netscript. It's not super useful since 'catch' isn't implemented, but it can be used to generate custom runtime error messages. -- Added import declaration to Netscript. With this, you are able to import functions (and only functions) from other files. Using export declarations is not necessary -- Most Netscript Runtime errors (the ones that cause your script to crash) should now include the line number where the error occured -- When working for a company, your current company reputation is now displayed -- Whenever you get a Faction Invite it will be immediately appended to your 'invited factions' list. Therefore the checkFactionInvitations() Singularity Function should now be properly useable since you no longer need to decline a Faction Invitation before it shows up in the result. -- Bug Fix: When purchasing servers, whitespace should now automatically be removed from the hostname -- Bug Fix: Can no longer have whitespace in the filename of text files created using write() -- Bug Fix: In Netscript, you can no longer assign a Hacknet Node handle (hacknetnodes[i]) to another value -- Bug Fix: If you are in the Factions tab when you accept an invitation from a Faction, the page will now properly 'refresh' -- Bug Fix: Scripts that run recursive functions should now be killed properly - -## v0.34.5 - 2/24/2018 - -- Corporation Management Changes: - - Market Research unlocks are now cheaper - - New 'VeChain' upgrade: displays useful statistics about Corporation - - Corporation cycles are processed 25% faster - - Corporation valuation was lowered by ~10% (this affects stock price and investments) - - Rebalanced the effects of advertising. Should now be more effective for every Industry - - Fixed several bugs/exploits involving selling and buying back stock shares - - You will now receive a Corporation Handbook (.lit file) when starting out BitNode-3. It contains a brief guide to help you get started. This same handbook can be viewed from the Corporation management screen - - Slightly decreased the amount by which a Product's sell price can be marked up - - Employees can now be assigned to a 'Training' task, during which they will slowly increase several of their stats -- Hopefully fixed an exploit with Array.forEach(). If there are any issues with using forEach, let me know -- Arguments passed into a script are now passed by value. This means modifying the 'args' array in a script should no longer cause issues -- Scripts executed programatically (via run(), exec(), etc.) will now fail if null/undefined is passed in as an argument -- Added peek() Netscript function -- killall() Netscript function now returns true if any scripts were killed, and false otherwise. -- hack() Netscript function now returns the amount of money gained for successful hacks, and 0 for failed hacks -- scp Terminal command and Netscript function now work for txt files -- Changes courtesy of Wraithan: - - Text files are now displayed using 'pre' rather than 'p' elements when using the 'cat' Terminal command. This means tabs are retained and lines don't automatically wrap - - ls() Netscript function now returns text files as well -- Removed round() Netscript function, since you can just use Math.round() instead -- Added disableLog() and enableLog() Netscript functions -- Removed the 'log' argument from sleep(), since you can now use the new disableLog function -- 'Netscript Documentation' button on script editor now points to new readthedocs documentation rather than wiki -- When working for a faction, your current faction reputation is now displayed -- Bug Fix: Hacking Missions should no longer break when dragging an existing connection to another Node -- Bug Fix: Fixed RAM usage of getNextHacknetNodeCost() (is not 1.5GB instead of 4GB) - -## v0.34.4 - 2/14/2018 - -- Added several new features to Gang UI to make it easier to manage your Gang. -- Changed the Gang Member upgrade mechanic. Now, rather than only being able to have one weapon/armor/vehicle/etc., you can purchase all the upgrades for each Gang member and their multipliers will stack. To balance this out, the effects (AKA multipliers) of each Gang member upgrade were reduced. -- Added a new script editor option: Max Error Count. This affects how many approximate lines the script editor will process (JSHint) for common errors. Increasing this option can affect negatively affect performance -- Game theme colors (set using 'theme' Terminal command) are now saved when re-opening the game -- 'download' Terminal command now works on scripts -- Added stopAction() Singularity function and the spawn() Netscript function -- The 'Purchase Augmentations' UI screen will now tell you if you need a certain prerequisite for Augmentations. -- Augmentations with prerequisites can now be purchased as long as their prerequisites are puchased (before, you had to actually install the prerequisites before being able to purchase) - -## v0.34.3 - 1/31/2018 - -- Minor balance changes to Corporations: - - Upgrades are generally cheaper and/or have more powerful effects. - - You will receive more funding while your are a private company. - - Product demand decreases at a slower rate. - - Production multiplier for Industries (receives for owning real estate/hardware/robots/etc.) is slightly higher -- Accessing the hacknetnodes array in Netscript now costs 4.0GB of RAM (only counts against RAM usage once) -- Bug Fix: Corporation oustanding shares should now be numeric rather than a string -- Bug Fix: Corporation production now properly calculated for industries that dont produce materials. -- Bug Fix: Gangs should now properly reset when switching BitNodes -- Bug Fix: Corporation UI should now properly reset when you go public - -## v0.34.2 - 1/27/2018 - -- Corporation Management Changes: - - Added advertising mechanics - - Added Industry-specific purchases - - Re-designed employee management UI - - Rebalancing: Made many upgrades/purchases cheaper. Receive more money from investors in early stage. Company valuation is higher after going public - - Multiple bug fixes -- Added rm() Netscript function -- Updated the way script RAM usage is calculated. Now, a function only increases RAM usage the first time it is called. i.e. even if you call hack() multiple times in a script, it only counts against RAM usage once. The same change applies for while/for loops and if conditionals. -- The RAM cost of the following were increased: - - If statements: increased by 0.05GB - - run() and exec(): increased by 0.2GB - - scp(): increased by 0.1GB - - purchaseServer(): increased by 0.25GB -- Note: You may need to re-save all of your scripts in order to re-calculate their RAM usages. Otherwise, it should automatically be re-calculated when you reset/prestige -- The cost to upgrade your home computer's RAM has been increased (both the base cost and the exponential upgrade multiplier) -- The cost of purchasing a server was increased by 10% (it is now \$55k per RAM) -- Bug fix: (Hopefully) removed an exploit where you could avoid RAM usage for Netscript function calls by assigning functions to a variable (foo = hack(); foo('helios');) -- Bug fix: (Hopefully) removed an exploit where you could run arbitrary Javascript code using the constructor() method -- Thanks to Github user mateon1 and Reddit users havoc_mayhem and spaceglace for notifying me of the above exploits -- The fileExists() Netscript function now works on text files (.txt). Thanks to Github user devoidfury for this - -## v0.34.1 - 1/19/2018 - -- Updates to Corporation Management: - - Added a number of upgrades to various aspects of your Corporation - - Rebalanced the properties of Materials and the formula for determining the valuation of the Corporation - - Fixed a number of bugs -- 'Stats' page now shows information about current BitNode -- You should now be able to create Corporations in other BitNodes if you have Source-File 3 -- Added a new create-able program called b1t_flum3.exe. This program can be used to reset and switch BitNodes -- Added an option to adjust autosave interval -- Line feeds, newlines, and tabs will now work with the tprint() Netscript function -- Bug fix: 'check' Terminal command was broken -- Bug fix: 'theme' Terminal command was broken when manually specifying hex codes -- Bug fix: Incorrect promotion requirement for 'Business'-type jobs -- Bug fix: Settings input bars were incorrectly formatted when loading game - -## v0.34.0 - 12/6/2017 - -- Added clear() and exit() Netscript functions -- When starting out or prestiging, you will now receive a 'Hacking Starter Guide'. It provides tips/pointers for new players -- Doubled the amount of RAM on low-level servers (up to required hacking level 150) -- Slightly increased experience gain from Infiltration -- buyStock(), sellStock(), shortStock(), and sellShort() Netscript function now return the stock price at which the transaction occurred, rather than a boolean. If the function fails for some reason, 0 will be returned. -- Hacking Mission Changes: - - You can now select multiple Nodes of the same type by double clicking. This allows you to set the action of all of selected nodes at once (e.g. set all Transfer Nodes to Fortify). Creating connections does not work with this multi-select functionality yet - - Shield and Firewall Nodes can now fortify - - The effects of Fortifying are now ~5% lower - - Conquering a Spam Node now increases your time limit by 25 seconds instead of 15 - - Damage dealt by Attacking was slightly reduced - - The effect of Scanning was slightly reduced - - Enemy CPU Core Nodes start with slightly more attack. Misc Nodes start with slightly less defense -- Corporation Management changes: - - Added several upgrades that unlock new features - - Implemented Exporting mechanic - - Fixed many bugs - -## v0.33.0 - 12/1/2017 - -- Added BitNode-3: Corporatocracy. In this BitNode you can start and manage your own corporation. This feature is incomplete. Much more will be added to it in the near future -- Minor bug fixes - -## v0.32.1 - 11/2/2017 - -- Updated Netscript's 'interpreter/engine' to use the Bluebird promise library instead of native promises. It should now be faster and more memory-efficient. If this has broken any Netscript features please report it through Github or the subreddit (reddit.com/r/bitburner) -- Rebalanced stock market (adjusted parameters such as the volatility/trends/starting price of certain stocks) -- Added prompt() Netscript function -- Added 'Buy Max' and 'Sell All' functions to Stock Market UI -- Added 'Portfolio' Mode to Stock Market UI so you can only view stocks you have a position/order in -- Added a button to kill a script from its log display box - -## v0.32.0 - 10/25/2017 - -- Added BitNode-8: Ghost of Wall Street -- Re-designed Stock Market UI -- Minor bug fixes - -## v0.31.0 - 10/15/2017 - -- Game now saves to IndexedDb (if your browser supports it). This means you should no longer have trouble saving the game when your save file gets too big (from running too many scripts). The game will still be saved to localStorage as well -- New file type: text files (.txt). You can read or write to text files using the read()/write() Netscript commands. You can view text files in Terminal using 'cat'. Eventually I will make it so you can edit them in the editor but that's not available yet. You can also download files to your real computer using the 'download' Terminal command -- Added a new Crime: Bond Forgery. This crime takes 5 minutes to attempt and gives \$4,500,000 if successful. It is meant for mid game. -- Added commitCrime(), getCrimeChance(), isBusy(), and getStats() Singularity Functions. -- Removed getIntelligence() Netscript function -- Added sprintf and vsprintf to Netscript. See [https://github.com/alexei/sprintf.js this Github page for details] -- Increased the amount of money gained from Infiltration by 20%, and the amount of faction reputation by 12% -- Rebalanced BitNode-2 so that Crime and Infiltration are more profitable but hacking is less profitable. Infiltration also gives more faction rep -- Rebalanced BitNode-4 so that hacking is slightly less profitable -- Rebalanced BitNode-5 so that Infiltration is more profitable and gives more faction rep -- Rebalanced BitNode-11 so that Crime and Infiltration are more profitable. Infiltration also gives more faction rep. -- Fixed an annoying issue in Hacking Missions where sometimes you would click a Node but it wouldnt actually get selected -- Made the Hacking Mission gameplay a bit slower by lowering the effect of Scan and reducing Attack damage -- Slightly increased the base reputation gain rate for factions when doing Field Work and Security Work - -## v0.30.0 - 10/9/2017 - -- Added getAugmentations() and getAugmentationsFromFaction() Netscript Singularity Functions -- Increased the rate of Intelligence exp gain -- Added a new upgrade for home computers: CPU Cores. Each CPU core on the home computer grants an additional starting Core Node in Hacking Missions. I may add in other benefits later. Like RAM upgrades, upgrading the CPU Core on your home computer persists until you enter a new BitNode. -- Added lscpu Terminal command to check number of CPU Cores -- Changed the effect of Source-File 11 and made BitNode-11 a little bit harder -- Fixed a bug with Netscript functions (the ones you create yourself) -- Hacking Missions officially released (they give reputation now). Notable changes in the last few updates: - - Misc Nodes slowly gain hp/defense over time - - Conquering a Misc Node will increase the defense of all remaining Misc Nodes that are not being targeted by a certain percentage - - Reputation reward for winning a Mission is now affected by faction favor and Player's faction rep multiplier - - Whenever a Node is conquered, its stats are reduced - -## v0.29.3 - 10/3/2017 - -- Fixed bug for killing scripts and showing error messages when there are errors in a player-defined function -- Added function name autocompletion in Script Editor. Press Ctrl+space on a prefix to show autocompletion options. -- Minor rebalancing and bug fixes for Infiltration and Hacking Missions - -## v0.29.2 - 10/1/2017 - -- installAugmentations() Singularity Function now takes a callback script as an argument. This is a script that gets ran automatically after Augmentations are installed. The script is run with no arguments and only a single thread, and must be found on your home computer. -- Added the ability to create your own functions in Netscript. See [[Netscript Functions|this link]] for details -- Added :q, :x, and :wq Vim Ex Commands when using the Vim script editor keybindings. :w, :x, and :wq will all save the script and return to Terminal. :q will quit (return to Terminal) WITHOUT saving. If anyone thinks theres an issue with this please let me know, I don't use Vim -- Added a new Augmentation: ADR-V2 Pheromone Gene -- In Hacking Missions, enemy nodes will now automatically target Nodes and perform actions. -- Re-balanced Hacking Missions through minor tweaking of many numbers -- The faction reputation reward for Hacking Missions was slightly increased - -## v0.29.1 - 9/27/2017 - -- New gameplay feature that is currently in BETA: Hacking Missions. Hacking Missions is an active gameplay mechanic (its a minigame) that is meant to be used to earn faction reputation. However, since this is currently in beta, hacking missions will NOT grant reputation for the time being, since the feature likely has many bugs, balance problems, and other issues. If you have any feedback regarding the new feature, feel free to let me know -- CHANGED THE RETURN VALUE OF getScriptIncome() WHEN RAN WITH NO ARGUMENTS. It will now return an array of two values rather than a single value. This may break your scripts, so make sure to update them! -- Added continue statement for for/while loops -- Added getServerMinSecurityLevel(), getPurchasedServers(), and getTimeSinceLastAug() Netscript functions -- Netscript scp() function can now take an array as the first argument, and will try to copy every file specified in the array (it will just call scp() normally for every element in the array). If an array is passed in, then the scp() function returns true if at least one element from the array is successfully copied -- Added Javascript's Date module to Netscript. Since 'new' is not supported in Netscript yet, only the Date module's static methods will work (now(), UTC(), parse(), etc.). -- Failing a crime now gives half the experience it did before -- The forced repeated 'Find The-Cave' message after installing The Red Pill Augmentation now only happens if you've never destroyed a BitNode before, and will only popup every 15 minutes. If you have already destroyed a BitNode, the message will not pop up if you have messages suppressed (if you don't have messages suppressed it WILL still repeatedly popup) -- fileExists() function now works on literature files - -## v0.29.0 - 9/19/2017 - -- Added BitNode-5: Artificial Intelligence -- Added getIp(), getIntelligence(), getHackingMultipliers(), and getBitNodeMultipliers() Netscript functions (requires Source-File 5) -- Updated scan() Netscript function so that you can choose to have it print IPs rather than hostnames -- Refactored scp() Netscript function so that it takes an optional 'source server' argument -- For Infiltration, decreased the percentage by which the security level increases by about 10% for every location -- Using :w in the script editor's Vim keybinding mode should now save and quit to Terminal -- Some minor optimizations that should reduce the size of the save file -- scan-analyze Terminal command will no longer show your purchased servers, unless you pass a '-a' flag into the command -- After installing the Red Pill augmentation from Daedalus, the message telling you to find 'The-Cave' will now repeatedly pop up regardless of whether or not you have messages suppressed -- Various bugfixes - -## v0.28.6 - 9/15/2017 - -- Time required to create programs now scales better with hacking level, and should generally be much faster -- Added serverExists(hostname/ip) and getScriptExpGain(scriptname, ip, args...) Netscript functions -- Short circuiting && and || logical operators should now work -- Assigning to multidimensional arrays should now work -- Scripts will no longer wait for hack/grow/weaken functions to finish if they are killed. They will die immediately -- The script loop that checks whether any scripts need to be started/stopped now runs every 6 seconds rather than 10 (resulting in less delays when stopping/starting scripts) -- Fixed several bugs/exploits -- Added some description for BitNode-5 (not implemented yet, should be soon though) - -## v0.28.5 - 9/13/2017 - -- The fl1ght.exe program that is received from jump3r is now sent very early on in the game, rather than at hacking level 1000 -- Hostname is now displayed in Terminal -- Syntax highlighting now works for all Netscript functions -- Export should now work on Edge/IE - -## v0.28.4 - 9/11/2017 - -- Added getScriptIncome() Netscript function -- Added Javascript's math module to Netscript. See [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math this link for details] -- Added several member variables for the Hacknet Node API that allow you to access info about their income -- All valid Netscript functions are now syntax highlighted as keywords in the editor. This means they will a different color than invalid netscript functions. The color will depend on your theme. Note that right now, this only applies for normal Netscript functions, not functions in the TIX API, Hacknet Node API, or Singularity Functions. -- Comments and operators no longer count towards RAM usage in scripts. -- Variety of bug fixes and updates to informational text in the game - -## v0.28.3 - 9/7/2017 - -- Added ls() Netscript function -- Increased company wages by about ~10% across the board -- The scp() Netsction function and Terminal command now works for .lit files -- Increased the amount of RAM on many lower level servers (up to level 200 hacking level required). - -## v0.28.2 - 9/4/2017 - -- Added several configuration options for script editor (key bindings, themes, etc.) -- Certain menu options will now be hidden until their relevant gameplay is unlocked. This includes the Factions, Augmentations, Create Program, Travel, and Job tabs. This will only affect newer players. -- Most unrecognize or un-implemented syntax errors in Netscript will now include the line number in the error message - -## v0.28.1 - 9/1/2017 - -- The script editor now uses the open-source Ace editor, which provides a much better experience when coding! -- Added tprint() Netscript function - -## v0.28.0 - 8/30/2017 - -- Added BitNode-4: The Singularity -- Added BitNode-11: The Big Crash -- Migrated the codebase to use webpack (doesn't affect any in game content, except maybe some slight performance improvements and there may be bugs that result from dependency errors - -## v0.27.3 - 8/19/2017 - -- You can now purchase upgrades for Gang Members (BitNode 2 only) -- Decreased Gang respect gains and slightly increased wanted gains (BitNode 2 only) -- Other gangs will increase in power faster (BitNode 2 only) -- Added getHackTime(), getGrowTime(), and getWeakenTime() Netscript functions - -## v0.27.2 - 8/18/2017 - -- Added getServerGrowth() Netscript function -- Added getNextHacknetNodeCost() Netscript function -- Added new 'literature' files (.lit extension) that are used to build lore for the game. These .lit files can be found in certain servers throughout the game. They can be viewed with the 'cat' Terminal command and copied over to other servers using the 'scp' command. These .lit files won't be found until you reset by installing Augmentations -- Fixed some bugs with Gang Territory(BitNode 2 only) - -## v0.27.1 - 8/15/2017 - -- Changed the way Gang power was calculated to make it scale better late game (BitNode 2 only) -- Lowered the respect gain rate in Gangs (Bitnode 2 only) -- Added '| grep pattern' option for ls Terminal command. This allows you to only list files that contain a certain pattern -- Added break statement in Netscript -- Display for some numerical values is now done in shorthand (e.g 1.000m instead of 1,000,000) - -## v0.27.0 - 8/13/2017 - -- Added secondary 'prestige' system - featuring Source Files and BitNodes -- MILD SPOILERS HERE: Installing 'The Red Pill' Augmentation from Daedalus will unlock a special server called w0r1d_d43m0n. Finding and manually hacking this server through Terminal will destroy the Player's current BitNode, and allow the player to enter a new one. When destroying a BitNode, the player loses everything except the scripts on his/her home computer. The player will then gain a powerful second-tier persistent upgrade called a Source File. The player can then enter a new BitNode to start the game over. Each BitNode has different characteristics, and many will have new content/mechanics as well. Right now there are only 2 BitNodes. Each BitNode grants its own unique Source File. Restarting and destroying a BitNode you already have a Source File for will upgrade your Source File up to a maximum level of 3. - -- Reputation gain with factions and companies is no longer a linear conversion, but an exponential one. It will be much easier to gain faction favor at first, but much harder later on. -- Significantly increased Infiltration exp gains -- Fixed a bug with company job requirement tooltips -- Added scriptRunning(), scriptKill(), and getScriptRam() Netscript functions. See documentation for details -- Fixed a bug with deleteServer() Netscript function - -## v0.26.4 - 8/1/2017 - -- All of the 'low-level servers' in early game that have a required hacking level now have 8GB of RAM instead of 4GB -- Increased the amount of experience given at university -- Slightly increased the production of Hacknet Nodes and made them cheaper to upgrade -- Infiltration now gives slightly more EXP and faction reputation -- Added two new crimes. These crimes are viable to attempt early on in the game and are relatively passive (each take 60+ seconds to complete) -- Crimes give more exp and more money -- Max money available on a server decreased from 50x the server's starting money to 25x -- Significantly increased wages for all jobs - -## v0.26.3 - -- Added support for large numbers using Decimal.js. Right now it only applies for the player's money -- Purchasing servers with the Netscript function purchaseServer() is no longer 2x as expensive as doing manually it now costs the same -- Early game servers have more starting money - -## v0.26.2 - -- Major rebalancing and randomization of the amount of money that servers start with -- Significantly lowered hacking exp gain from hacking servers. The exp gain for higher-level servers was lowered more than that of low level servers. (~16% for lower level servers, up to ~25% for higher-level servers) -- Added deleteServer() Netscript function -- You can now purchase a maximum of 25 servers each run (Deleting a server will allow you to purchase a new one) -- Added autocompletion for './' Terminal command -- Darkweb prices now displayed properly using toLocaleString() -- Added NOT operator (!) and negation operator(-) in Netscript, so negative numbers should be functional now -- Rejected faction invitations will now show up as 'Outstanding Faction Invites' in the Factions page. These can be accepted at any point in the future -- Added a few more configurable game settings for suppressing messages and faction invitations -- Added tooltips for company job requirements - -## v0.26.1 - -- Added autocompletion for aliases -- Added getServerRam() Netscript function() -- Added getLevelUpgradeCost(n), getRamUpgradeCost(), getCoreUpgradeCost() functions for Netscript Hacknet Node API -- Added some configurable settings (See Game Options menu) - -## v0.26.0 - -- Game now has a real ending, although it's not very interesting/satisfying right now. It sets up the framework for the secondary prestige system in the future -- Forgot to mention that since last update, comments now work in Netscript. Use // for single line comments or /\* and \*/ for multiline comments just like in Javascript -- Added ports to Netscript. These ports are essentially serialized queues. You can use the write() Netscript function to write a value to a queue, and then you can use the read() Netscript function to read the value from the queue. Once you read a value from the queue it will be removed. There are only 10 queues (1-10), and each has a maximum capacity of 50 entries. If you try to write to a queue that is full, the the first value is removed. See wiki/Netscript documentation for more details -- You can now use the 'help' Terminal command for specific commands -- You can now use './' to run a script/program (./NUKE.exe). However, tab completion currently doesn't work for it (I'm working on it) -- Decreased the base growth rate of servers by ~25% -- Both the effect of weaken() and its time to execute were halved. In other words, calling weaken() on a server only lowers its security by 0.05 (was 0.1 before) but the time to execute the function is half of what it was before. Therefore, the effective rate of weaken() should be about the same -- Increased all Infiltration rewards by ~10%, and increased infiltration rep gains by an additional 20% (~32% total for rep gains) -- The rate at which the security level of a facility increases during Infiltration was decreased significantly (~33%) -- Getting treated at the Hospital is now 33% more expensive -- Slightly increased the amount of time it takes to hack a server -- Slightly decreased the amount of money gained when hacking a server (~6%) -- Slightly decreased the base cost for RAM on home computer, but increased the cost multiplier. This means that upgrading RAM on the home computer should be slightly cheaper at the start, but slightly more expensive later on -- Increased the required hacking level for many late game servers -- The sleep() Netscript function now takes an optional 'log' argument that specifies whether or not the 'Sleeping for N milliseconds' will be logged for the script -- Added clearLog() Netscript function -- Deleted a few stocks. Didn't see a reason for having so many, and it just affects performance. Won't take effect until you reset by installing Augmentations -- There was a typo with Zeus Medical's server hostname. It is now 'zeus-med' rather than 'zeud-med' -- Added keyboard shortcuts to quickly navigate between different menus. See wiki link (http://bitburner.wikia.com/wiki/Shortcuts) -- Changed the Navigation Menu UI - -## v0.25.0 - -- Refactored Netscript to use the open-source Acorns Parser. This re-implementation was done by [https://github.com/MrNuggelz Github user MrNuggelz]. This has resulted in several changes in the Netscript language. Some scripts might break because of these changes. Changes listed below: -- Arrays are now fully functional Javascript arrays. You no longer need to use the 'Array' keyword to declare them. -- The length(), clear/clear(), insert(), and remove() functions no longer work for arrays. -- All Javascript array methods are available (splice(), push(), pop(), join(), shift(), indexOf(), etc. See documentation) -- Variables assigned to arrays are now passed by value rather than reference - -- Incrementing/Decrementing are now available (i++, ++i) - -- You no longer need semicolons at the end of block statements - -- Elif is no longer valid. Use 'else if' instead - -- Netscript's Hacknet Node API functions no longer log anything -- Stock prices now update every ~6 seconds when the game is active (was 10 seconds before) -- Added a new mechanic that affects how stock prices change -- Script editor now has dynamic indicators for RAM Usage and Line number -- Augmentation Rebalancing - Many late game augmentations are now slightly more expensive. Several early game augmentations had their effects slightly decreased -- Increased the amount of rewards (both money and rep) you get from infiltration -- Purchasing servers is now slightly more expensive -- Calling the Netscript function getServerMoneyAvailable('home') now return's the player's money -- Added round(n) Netscript function - Rounds a number -- Added purchaseServer(hostname, ram) Netscript function -- Added the TIX API. This must be purchased in the WSE. It persists through resets. Access to the TIX API allows you to write scripts that perform automated algorithmic trading. See Netscript documentation -- Minor rebalancing in a lot of different areas -- Changed the format of IP Addresses so that they are smaller (will consist mostly of single digit numbers now). This will reduce the size of the game's save file. - -## v0.24.1 - -- Adjusted cost of upgrading home computer RAM. Should be a little cheaper for the first few upgrades (up to ~64GB), and then will start being more expensive than before. High RAM upgrades should now be significantly more expensive than before. -- Slightly lowered the starting money available on most mid-game and end-game servers (servers with required hacking level greater than 200) by about 10-15% -- Rebalanced company/company position reputation gains and requirements -- Studying at a university now gives slightly more EXP and early jobs give slightly less EXP -- Studying at a university is now considerably more expensive -- Rebalanced stock market -- Significantly increased cost multiplier for purchasing additional Hacknet Nodes -- The rate at which facility security level increases during infiltration for each clearance level was lowered slightly for all companies -- Updated Faction descriptions -- Changed the way alias works. Normal aliases now only work at the start of a Terminal command (they will only replace the first word in the Terminal command). You can also create global aliases that work on any part of the command, like before. Declare global aliases by entering the optional -g flag: alias -g name="value" - [https://github.com/MrNuggelz Courtesy of Github user MrNuggelz] -- 'top' Terminal command implemented courtesy of [https://github.com/LTCNugget Github user LTCNugget]. Currently, the formatting gets screwed up if your script names are really long. - -## v0.24.0 - -- Players now have HP, which is displayed in the top right. To regain HP, visit the hospital. Currently the only way to lose HP is through infiltration -- Infiltration - Attempt to infiltrate a company and steal their classified secrets. See 'Companies' documentation for more details -- Stock Market - Added the World Stock Exchange (WSE), a brokerage that lets you buy/sell stocks. To begin trading you must first purchase an account. A WSE account will persist even after resetting by installing Augmentations. How the stock market works should hopefully be self explanatory. There is no documentation about it currently, I will add some later. NOTE: Stock prices only change when the game is open. The Stock Market is reset when installing Augmentations, which means you will lose all your stocks -- Decreased money gained from hacking by ~12% -- Increased reputation required for all Augmentations by ~40% -- Cost increase when purchasing multiple augmentations increased from 75% to 90% -- Added basic variable runtime to Netscript operations. Basic commands run in 100ms. Any function incurs another 100ms in runtime (200ms total). Any function that starts with getServer incurs another 100ms runtime (300ms total). exec() and scp() require 400ms total. -- Slightly reduced the amount of experience gained from hacking - -## v0.23.1 - -- scan() Netscript function now takes a single argument representing the server from which to scan. - -## v0.23.0 - -- You can now purchase multiple Augmentations in a run. When you purchase an Augmentation you will lose money equal to the price and then the cost of purchasing another Augmentation during this run will be increased by 75%. You do not gain the benefits of your purchased Augmentations until you install them. This installation can be done through the 'Augmentation' tab. When you install your Augmentations, your game will reset like before. -- Reputation needed to gain a favor from faction decreased from 7500 to 6500 -- Reputation needed to gain a favor from company increased from 5000 to 6000 -- Reputation cost of all Augmentations increased by 16% -- Higher positions at companies now grant slightly more reputation for working -- Added getServerMaxMoney() Netscript function -- Added scan() Netscript function -- Added getServerNumPortsRequired() Netscript function -- There is now no additional RAM cost incurred when multithreading a script - -## v0.22.1 - -- You no longer lose progress on creating programs when cancelling your work. Your progress will be saved and you will pick up where you left off when you start working on it again -- Added two new programs: AutoLink.exe and ServerProfiler.exe -- Fixed bug with Faction Field work reputation gain - -## v0.22.0 - Major rebalancing, optimization, and favor system - -- Significantly nerfed most augmentations -- Almost every server with a required hacking level of 200 or more now has slightly randomized server parameters. This means that after every Augmentation purchase, the required hacking level, base security level, and growth factor of these servers will all be slightly different -- The hacking speed multiplier now increases rather than decreases. The hacking time is now divided by your hacking speed multiplier rather than multiplied. In other words, a higher hacking speed multiplier is better -- Servers now have a minimum server security, which is approximately one third of their starting ('base') server security -- If you do not steal any money from a server, then you gain hacking experience equal to the amount you would have gained had you failed the hack -- The effects of grow() were increased by 50% -- grow() and weaken() now give hacking experience based on the server's base security level, rather than a flat exp amount -- Slightly reduced amount of exp gained from hack(), weaken(), and grow() -- Rebalanced formulas that determine crime success -- Reduced RAM cost for multithreading a script. The RAM multiplier for each thread was reduced from 1.02 to 1.005 -- Optimized Script objects so they take less space in the save file -- Added getServerBaseSecurityLevel() Netscript function -- New favor system for companies and factions. Earning reputation at a company/faction will give you favor for that entity when you reset after installing an Augmentation. This favor persists through the rest of the game. The more favor you have, the faster you will earn reputation with that faction/company -- You can no longer donate to a faction for reputation until you have 150 favor with that faction -- Added unalias Terminal command -- Changed requirements for endgame Factions - -## v0.21.1 - -- IF YOUR GAME BREAKS, DO THE FOLLOWING: Options -> Soft Reset -> Save Game -> Reload Page. Sorry about that! -- Autocompletion for aliases - courtesy of [https://github.com/LTCNugget Github user LTCNugget] - -## v0.21.0 - -- Added dynamic arrays. See Netscript documentation -- Added ability to pass arguments into scripts. See documentation -- The implementation/function signature of functions that deal with scripts have changed. Therefore, some old scripts might not work anymore. Some of these functions include run(), exec(), isRunning(), kill(), and some others I may have forgot about. Please check the updated Netscript documentation if you run into issues.-Note that scripts are now uniquely identified by the script name and their arguments. For example, you can run a script using:: - - run foodnstuff.script 1 - -and you can also run the same script with a different argument:: - - run foodnstuff.script 2 - -These will be considered two different scripts. To kill the first script you must run:: - - kill foodnstuff.script 1 - -and to kill the second you must run:: - - kill foodnstuff.script 2 - -Similar concepts apply for Terminal Commands such as tail, and Netscript commands such as run(), exec(), kill(), isRunning(), etc. - -- Added basic theme functionality using the 'theme' Terminal command - All credit goes to /u/0x726564646974 who implemented the awesome feature -- Optimized Script objects, which were causing save errors when the player had too many scripts -- Formula for determining exp gained from hacking was changed -- Fixed bug where you could purchase Darkweb items without TOR router -- Slightly increased cost multiplier for Home Computer RAM -- Fixed bug where you could hack too much money from a server (and bring its money available below zero) -- Changed tail command so that it brings up a display box with dynamic log contents. To get old functionality where the logs are printed to the Terminal, use the new 'check' command -- As a result of the change above, you can no longer call tail/check on scripts that are not running -- Added autocompletion for buying Programs in Darkweb - -## v0.20.2 - -- Fixed several small bugs -- Added basic array functionality to Netscript -- Added ability to run scripts with multiple threads. Running a script with n threads will multiply the effects of all hack(), grow(), and weaken() commands by n. However, running a script with multiple threads has drawbacks in terms of RAM usage. A script's ram usage when it is 'multithreaded' is calculated as: base cost _ numThreads _ (1.02 ^ numThreads). A script can be run multithreaded using the 'run [script] -t n' Terminal command or by passing in an argument to the run() and exec() Netscript commands. See documentation. -- RAM is slightly (~10%) more expensive (affects purchasing server and upgrading RAM on home computer) -- NeuroFlux Governor augmentation cost multiplier decreased -- Netscript default operation runtime lowered to 200ms (was 500ms previously) - -## v0.20.1 - -- Fixed bug where sometimes scripts would crash without showing the error -- Added Deepscan programs to Dark Web -- Declining a faction invite will stop you from receiving invitations from that faction for the rest of the run -- (BETA) Added functionality to export/import saves. WARNING This is only lightly tested. You cannot choose where to save your file it just goes to the default save location. Also I have no idea what will happen if you try to import a file that is not a valid save. I will address these in later updates - -## v0.20.0 - -- Refactored Netscript Interpreter code. Operations in Netscript should now run significantly faster (Every operation such as a variable assignment, a function call, a binary operator, getting a variable's value, etc. used to take up to several seconds, now each one should only take ~500 milliseconds). -- Percentage money stolen when hacking lowered to compensate for faster script speeds -- Hacking experience granted by grow() halved -- Weaken() is now ~11% faster, but only grants 3 base hacking exp upon completion instead of 5 -- Rebalancing of script RAM costs. Base RAM Cost for a script increased from 1GB to 1.5GB. Loops, hack(), grow() and weaken() all cost slightly less RAM than before -- Added getServerRequiredHackingLevel(server) Netscript command. -- Added fileExists(file, [server]) Netscript command, which is used to check if a script/program exists on a specified server -- Added isRunning(script, [server]) Netscript command, which is used to check if a script is running on the specified server -- Added killall Terminal command. Kills all running scripts on the current machine -- Added kill() and killall() Netscript commands. Used to kill scripts on specified machines. See Netscript documentation -- Re-designed 'Active Scripts' tab -- Hacknet Node base production rate lowered from 1.6 to 1.55 (\$/second) -- Increased monetary cost of RAM (Upgrading home computer and purchasing servers will now be more expensive) -- NEW GROWTH MECHANICS - The rate of growth on a server now depends on a server's security level. A higher security level will result in lower growth on a server when using the grow() command. Furthermore, calling grow() on a server raises that server's security level by 0.004. For reference, if a server has a security level of 10 it will have approximately the same growth rate as before. -- Server growth no longer happens naturally -- Servers now have a maximum limit to their money. This limit is 50 times it's starting money -- Hacking now grants 10% less hacking experience -- You can now edit scripts that are running -- Augmentations cost ~11% more money and 25% more faction reputation - -## v0.19.7 - -- Added changelog to Options menu -- Bug fix with autocompletion (wasn't working properly for capitalized filenames/programs - -## v0.19.6 - -- Script editor now saves its state even when you change tabs -- scp() command in Terminal/script will now overwrite files at the destination -- Terminal commands are no longer case-sensitive (only the commands themselves such as 'run' or 'nano'. Filenames are still case sensitive -- Tab automcompletion will now work on commands - -## v0.19.0 - -- Hacknet Nodes have slightly higher base production, and slightly increased RAM multiplier. But they are also a bit more expensive at higher levels -- Calling grow() and weaken() in a script will now work offline, at slower rates than while online (The script now keeps track of the rate at which grow() and weaken() are called when the game is open. These calculated rates are used to determine how many times the calls would be made while the game is offline) -- Augmentations now cost 20% more reputation and 50% more money -- Changed the mechanic for getting invited to the hacking factions (CyberSec, NiteSec, The Black Hand, BitRunners) Now when you get to the required level to join these factions you will get a message giving you instructions on what to do in order to get invited. -- Added a bit of backstory/plot into the game. It's not fully fleshed out yet but it will be used in the future -- Made the effects of many Augmentations slightly more powerful -- Slightly increased company job wages across the board (~5-10% for each position) -- Gyms and classes are now significantly more expensive -- Doubled the amount by which a server's security increases when it is hacked. Now, it will increase by 0.002. Calling weaken() on a server will lower the security by 0.1. - -## v0.18.0 - -- Major rebalancing (sorry didn't record specifics. But in general hacking gives more money and hacknet nodes give less) -- Server growth rate (both natural and manual using grow()) doubled -- Added option to Soft Reset -- Cancelling a full time job early now only results in halved gains for reputation. Exp and money earnings are gained in full -- Added exec() Netscript command, used to run scripts on other servers. -- NEW HACKING MECHANICS: Whenever a server is hacked, its 'security level' is increased by a very small amount. The security level is denoted by a number between 1-100. A higher security level makes it harder to hack a server and also decreases the amount of money you steal from it. Two Netscript functions, weaken() and getServerSecurityLevel() level, were added. The weaken(server) function lowers a server's security level. See the Netscript documentation for more details -- When donating to factions, the base rate is now \$1,000,000 for 1 reputation point. Before, it was \$1,000 for 1 reputation point. -- Monetary costs for all Augmentations increased. They are now about ~3.3 - 3.75 times more expensive than before - -## v0.17.1 - -- Fixed issue with purchasing Augmentations that are 'upgrades' and require previous Augmentations to be installed -- Increased the percentage of money stolen from servers when hacking - -## v0.17.0 - -- Greatly increased amount of money gained for crimes (by about 400% for most crimes) -- Criminal factions require slightly less negative karma to get invited to -- Increased the percentage of money stolen from servers when hacking -- Increased the starting amount of money available on beginning servers (servers with <50 required hacking)) -- Increased the growth rate of servers (both naturally and manually when using the grow() command in a script) -- Added getHostname() command in Netscript that returns the hostname of the server a script is running on -- jQuery preventDefault() called when pressing ctrl+b in script editor -- The Neuroflux Governor augmentation (the one that can be repeatedly leveled up) now increases ALL multipliers by 1%. To balance it out, it's price multiplier when it levels up was increased -- Hacknet Node base production decreased from \$1.75/s to \$1.65/s -- Fixed issue with nested for loops in Netscript (stupid Javascript references) -- Added 'scp' command to Terminal and Netscript -- Slightly nerfed Hacknet Node Kernel DNI and Hacknet Node Core DNI Augmentations -- Increased TOR Router cost to \$200k - -## v0.16.0 - -- New Script Editor interface -- Rebalanced hacknet node - Increased base production but halved the multiplier from additional cores. This should boost its early-game production but nerf its late-game production -- Player now starts with 8GB of RAM on home computer -- 'scan-analyze' terminal command displays RAM on servers -- Slightly buffed the amount of money the player steals when hacking servers (by about ~8%) -- Time to execute grow() now depends on hacking skill and server security, rather than taking a flat 2 minutes. -- Clicking outside of a pop-up dialog box will now close it -- BruteSSH.exe takes 33% less time to create -- 'iron-gym' and 'max-hardware' servers now have 2GB of RAM -- Buffed job salaries across the board -- Updated Tutorial -- Created a Hacknet Node API for Netscript that allows you to access and upgrade your Hacknet Nodes. See the Netscript documentation for more details. WARNING The old upgradeHacknetNode() and getNumHacknetNodes() functions waere removed so any script that has these will no longer work - -## v0.15.0 - -- Slightly reduced production multiplier for Hacknet Node RAM -- Faction pages now scroll -- Slightly increased amount of money gained from hacking -- Added 'alias' command -- Added 'scan-analyze' terminal command - used to get basic hacking info about all immediate network connections -- Fixed bugs with upgradeHacknetNode() and purchaseHacknetNode() commands -- Added getNumHacknetNodes() and hasRootAccess(hostname/ip) commands to Netscript -- Increased Cost of university classes/gym -- You can now see what an Augmentation does and its price even while its locked diff --git a/src/Documentation/doc/index.md b/src/Documentation/doc/index.md index 63b0c103c..fc8310802 100644 --- a/src/Documentation/doc/index.md +++ b/src/Documentation/doc/index.md @@ -48,6 +48,8 @@ - [Game Frozen or Stuck?](programming/game_frozen.md) - [Tools & Resources](help/tools_and_resources.md) - [Changelog](changelog.md) +- [Changelog - Legacy v1](changelog-v1.md) +- [Changelog - Legacy v0](changelog-v0.md) ## Migration diff --git a/src/Documentation/pages.ts b/src/Documentation/pages.ts index fd5ffad59..d6afd0846 100644 --- a/src/Documentation/pages.ts +++ b/src/Documentation/pages.ts @@ -45,19 +45,21 @@ import file42 from "!!raw-loader!./doc/basic/stats.md"; import file43 from "!!raw-loader!./doc/basic/stockmarket.md"; import file44 from "!!raw-loader!./doc/basic/terminal.md"; import file45 from "!!raw-loader!./doc/basic/world.md"; -import file46 from "!!raw-loader!./doc/changelog.md"; -import file47 from "!!raw-loader!./doc/help/bitnode_order.md"; -import file48 from "!!raw-loader!./doc/help/getting_started.md"; -import file49 from "!!raw-loader!./doc/help/tools_and_resources.md"; -import file50 from "!!raw-loader!./doc/index.md"; -import file51 from "!!raw-loader!./doc/migrations/ns2.md"; -import file52 from "!!raw-loader!./doc/migrations/v1.md"; -import file53 from "!!raw-loader!./doc/migrations/v2.md"; -import file54 from "!!raw-loader!./doc/programming/game_frozen.md"; -import file55 from "!!raw-loader!./doc/programming/go_algorithms.md"; -import file56 from "!!raw-loader!./doc/programming/hackingalgorithms.md"; -import file57 from "!!raw-loader!./doc/programming/learn.md"; -import file58 from "!!raw-loader!./doc/programming/remote_api.md"; +import file46 from "!!raw-loader!./doc/changelog-v0.md"; +import file47 from "!!raw-loader!./doc/changelog-v1.md"; +import file48 from "!!raw-loader!./doc/changelog.md"; +import file49 from "!!raw-loader!./doc/help/bitnode_order.md"; +import file50 from "!!raw-loader!./doc/help/getting_started.md"; +import file51 from "!!raw-loader!./doc/help/tools_and_resources.md"; +import file52 from "!!raw-loader!./doc/index.md"; +import file53 from "!!raw-loader!./doc/migrations/ns2.md"; +import file54 from "!!raw-loader!./doc/migrations/v1.md"; +import file55 from "!!raw-loader!./doc/migrations/v2.md"; +import file56 from "!!raw-loader!./doc/programming/game_frozen.md"; +import file57 from "!!raw-loader!./doc/programming/go_algorithms.md"; +import file58 from "!!raw-loader!./doc/programming/hackingalgorithms.md"; +import file59 from "!!raw-loader!./doc/programming/learn.md"; +import file60 from "!!raw-loader!./doc/programming/remote_api.md"; interface Document { default: string; @@ -109,16 +111,18 @@ AllPages["basic/stats.md"] = file42; AllPages["basic/stockmarket.md"] = file43; AllPages["basic/terminal.md"] = file44; AllPages["basic/world.md"] = file45; -AllPages["changelog.md"] = file46; -AllPages["help/bitnode_order.md"] = file47; -AllPages["help/getting_started.md"] = file48; -AllPages["help/tools_and_resources.md"] = file49; -AllPages["index.md"] = file50; -AllPages["migrations/ns2.md"] = file51; -AllPages["migrations/v1.md"] = file52; -AllPages["migrations/v2.md"] = file53; -AllPages["programming/game_frozen.md"] = file54; -AllPages["programming/go_algorithms.md"] = file55; -AllPages["programming/hackingalgorithms.md"] = file56; -AllPages["programming/learn.md"] = file57; -AllPages["programming/remote_api.md"] = file58; +AllPages["changelog-v0.md"] = file46; +AllPages["changelog-v1.md"] = file47; +AllPages["changelog.md"] = file48; +AllPages["help/bitnode_order.md"] = file49; +AllPages["help/getting_started.md"] = file50; +AllPages["help/tools_and_resources.md"] = file51; +AllPages["index.md"] = file52; +AllPages["migrations/ns2.md"] = file53; +AllPages["migrations/v1.md"] = file54; +AllPages["migrations/v2.md"] = file55; +AllPages["programming/game_frozen.md"] = file56; +AllPages["programming/go_algorithms.md"] = file57; +AllPages["programming/hackingalgorithms.md"] = file58; +AllPages["programming/learn.md"] = file59; +AllPages["programming/remote_api.md"] = file60; From 16b9ad21ea3ada1b5d6ea541b5b5e3deb1aa6c37 Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Sat, 8 Jun 2024 03:21:26 +0700 Subject: [PATCH 28/43] MISC: Set copyright line for Electron app (#1371) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 83b5d786e..0b33f6271 100644 --- a/package.json +++ b/package.json @@ -119,7 +119,7 @@ "watch": "webpack --watch --mode production", "watch:dev": "webpack --watch --mode development", "electron": "bash ./tools/package-electron.sh", - "electron:packager-all": "electron-packager .package bitburner --platform all --arch x64,armv7l,arm64,mips64el --out .build --overwrite --icon .package/icon.png", + "electron:packager-all": "electron-packager .package bitburner --platform all --arch x64,armv7l,arm64,mips64el --out .build --overwrite --icon .package/icon.png --app-copyright \"Copyright (C) 2024 Bitburner\"", "preversion": "npm install && npm run test", "version": "sh ./tools/build-release.sh && git add --all", "postversion": "git push -u origin dev && git push --tags", From 70383d90852ccb4b1aaf3fec4965f69884b89e33 Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Sat, 8 Jun 2024 03:23:04 +0700 Subject: [PATCH 29/43] MISC: Change error message when spawning on an invalid server (#1370) --- src/NetscriptFunctions.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index a9e63df53..36388e631 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -737,11 +737,11 @@ export const ns: InternalAPI = { const args = helpers.scriptArgs(ctx, _args); setTimeout(() => { const scriptServer = GetServer(ctx.workerScript.hostname); - if (scriptServer == null) { - throw helpers.errorMessage(ctx, "Could not find server. This is a bug. Report to dev"); + if (scriptServer === null) { + throw helpers.errorMessage(ctx, `Cannot find server ${ctx.workerScript.hostname}`); } - return runScriptFromScript("spawn", scriptServer, path, args, ctx.workerScript, runOpts); + runScriptFromScript("spawn", scriptServer, path, args, ctx.workerScript, runOpts); }, runOpts.spawnDelay); helpers.log(ctx, () => `Will execute '${path}' in ${runOpts.spawnDelay} milliseconds`); From d9efea0fe60e07b7f4e1ba685541034927c3049e Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Sat, 8 Jun 2024 03:24:19 +0700 Subject: [PATCH 30/43] SLEEVES: Clarify augmentation condition (#1369) --- src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx b/src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx index f6254eb6b..0b1e13aa2 100644 --- a/src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx +++ b/src/PersonObjects/Sleeve/ui/SleeveAugmentationsModal.tsx @@ -27,12 +27,13 @@ export function SleeveAugmentationsModal(props: IProps): React.ReactElement { - You can purchase Augmentations for your Duplicate Sleeves. These Augmentations have the same effect as they - would for you. You can only purchase Augmentations that you have unlocked through Factions. + You can purchase augmentations for your Sleeves. These augmentations have the same effect as they would for + you. You can only purchase augmentations that you unlocked through factions. If an augmentation is useless for + Sleeves, it will not be available. Sleeves can install an augmentation without its prerequisites.

    - When purchasing an Augmentation for a Duplicate Sleeve, they are immediately installed. This means that the - Duplicate Sleeve will immediately lose all of its stat experience. + When purchasing an augmentation for a Sleeve, it is immediately installed. This means that the Sleeve will + immediately lose all of its stat experience.

    Augmentations will appear below as they become available. From 8b3206e1c66c7a4bb2cb42893b0fe8295bdbfced Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Sat, 8 Jun 2024 03:34:47 +0700 Subject: [PATCH 31/43] BLADEBURNER: Add Stop button and refactor code (#1363) --- src/Bladeburner/ui/ActionHeader.tsx | 55 +++++++++++++++++++++++ src/Bladeburner/ui/BlackOpElem.tsx | 55 +++++------------------ src/Bladeburner/ui/BlackOpPage.tsx | 8 ++-- src/Bladeburner/ui/ContractElem.tsx | 32 ++----------- src/Bladeburner/ui/GeneralActionElem.tsx | 37 ++------------- src/Bladeburner/ui/OperationElem.tsx | 57 ++++++------------------ src/Bladeburner/ui/OperationPage.tsx | 4 +- src/Bladeburner/ui/StartButton.tsx | 6 ++- src/Bladeburner/ui/StopButton.tsx | 6 ++- src/Bladeburner/ui/TeamSizeButton.tsx | 2 +- 10 files changed, 104 insertions(+), 158 deletions(-) create mode 100644 src/Bladeburner/ui/ActionHeader.tsx diff --git a/src/Bladeburner/ui/ActionHeader.tsx b/src/Bladeburner/ui/ActionHeader.tsx new file mode 100644 index 000000000..51caf9733 --- /dev/null +++ b/src/Bladeburner/ui/ActionHeader.tsx @@ -0,0 +1,55 @@ +import type { Bladeburner } from "../Bladeburner"; +import type { Action } from "../Types"; + +import React from "react"; +import { Box, Typography } from "@mui/material"; +import { CopyableText } from "../../ui/React/CopyableText"; +import { createProgressBarText } from "../../utils/helpers/createProgressBarText"; +import { StartButton } from "./StartButton"; +import { StopButton } from "./StopButton"; +import { TeamSizeButton } from "./TeamSizeButton"; + +import { formatNumberNoSuffix } from "../../ui/formatNumber"; +import { BlackOperation, Operation } from "../Actions"; + +interface ActionHeaderProps { + bladeburner: Bladeburner; + action: Action; + rerender: () => void; +} +export function ActionHeader({ bladeburner, action, rerender }: ActionHeaderProps): React.ReactElement { + const isActive = action.name === bladeburner.action?.name; + const computedActionTimeCurrent = Math.min( + bladeburner.actionTimeCurrent + bladeburner.actionTimeOverflow, + bladeburner.actionTimeToComplete, + ); + const allowTeam = action instanceof Operation || action instanceof BlackOperation; + + if (isActive) { + return ( + <> + + + + + + (IN PROGRESS - {formatNumberNoSuffix(computedActionTimeCurrent, 0)} /{" "} + {formatNumberNoSuffix(bladeburner.actionTimeToComplete, 0)}) + + + {createProgressBarText({ + progress: computedActionTimeCurrent / bladeburner.actionTimeToComplete, + })} + + + ); + } + + return ( + + + + {allowTeam && } + + ); +} diff --git a/src/Bladeburner/ui/BlackOpElem.tsx b/src/Bladeburner/ui/BlackOpElem.tsx index fdf524313..5eed70a7a 100644 --- a/src/Bladeburner/ui/BlackOpElem.tsx +++ b/src/Bladeburner/ui/BlackOpElem.tsx @@ -7,72 +7,41 @@ import { Paper, Typography } from "@mui/material"; import { Player } from "@player"; import { formatNumberNoSuffix } from "../../ui/formatNumber"; import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions"; -import { createProgressBarText } from "../../utils/helpers/createProgressBarText"; -import { TeamSizeButton } from "./TeamSizeButton"; -import { CopyableText } from "../../ui/React/CopyableText"; import { SuccessChance } from "./SuccessChance"; -import { StartButton } from "./StartButton"; import { useRerender } from "../../ui/React/hooks"; +import { ActionHeader } from "./ActionHeader"; interface BlackOpElemProps { bladeburner: Bladeburner; - blackOp: BlackOperation; + action: BlackOperation; } -export function BlackOpElem({ bladeburner, blackOp }: BlackOpElemProps): React.ReactElement { +export function BlackOpElem({ bladeburner, action }: BlackOpElemProps): React.ReactElement { const rerender = useRerender(); - const isCompleted = bladeburner.numBlackOpsComplete > blackOp.n; + const isCompleted = bladeburner.numBlackOpsComplete > action.n; if (isCompleted) { return ( - {blackOp.name} (COMPLETED) + {action.name} (COMPLETED) ); } - const isActive = bladeburner.action?.name === blackOp.name; - const actionTime = blackOp.getActionTime(bladeburner, Player); - const hasReqdRank = bladeburner.rank >= blackOp.reqdRank; - const computedActionTimeCurrent = Math.min( - bladeburner.actionTimeCurrent + bladeburner.actionTimeOverflow, - bladeburner.actionTimeToComplete, - ); + const actionTime = action.getActionTime(bladeburner, Player); + const hasRequiredRank = bladeburner.rank >= action.reqdRank; return ( - {isActive ? ( - <> - - - (IN PROGRESS - {formatNumberNoSuffix(computedActionTimeCurrent, 0)} /{" "} - {formatNumberNoSuffix(bladeburner.actionTimeToComplete, 0)}) - - - {createProgressBarText({ - progress: computedActionTimeCurrent / bladeburner.actionTimeToComplete, - })} - - - ) : ( - <> - - - - - - )} - +
    + {action.desc}
    - {blackOp.desc} -
    -
    - - Required Rank: {formatNumberNoSuffix(blackOp.reqdRank, 0)} + + Required Rank: {formatNumberNoSuffix(action.reqdRank, 0)}
    - +
    Time Required: {convertTimeMsToTimeElapsedString(actionTime * 1000)}
    diff --git a/src/Bladeburner/ui/BlackOpPage.tsx b/src/Bladeburner/ui/BlackOpPage.tsx index c0d5aadcc..b53b379c4 100644 --- a/src/Bladeburner/ui/BlackOpPage.tsx +++ b/src/Bladeburner/ui/BlackOpPage.tsx @@ -1,6 +1,6 @@ import type { Bladeburner } from "../Bladeburner"; -import * as React from "react"; +import React from "react"; import { Button, Typography } from "@mui/material"; import { FactionName } from "@enums"; import { BlackOpElem } from "./BlackOpElem"; @@ -14,7 +14,7 @@ interface BlackOpPageProps { } export function BlackOpPage({ bladeburner }: BlackOpPageProps): React.ReactElement { - const blackOps = blackOpsArray.slice(0, bladeburner.numBlackOpsComplete + 1).reverse(); + const blackOperations = blackOpsArray.slice(0, bladeburner.numBlackOpsComplete + 1).reverse(); return ( <> @@ -38,8 +38,8 @@ export function BlackOpPage({ bladeburner }: BlackOpPageProps): React.ReactEleme ) : ( <> - {blackOps.map((blackOp) => ( - + {blackOperations.map((blackOperation) => ( + ))} )} diff --git a/src/Bladeburner/ui/ContractElem.tsx b/src/Bladeburner/ui/ContractElem.tsx index f587f5d5b..8ad66dfc7 100644 --- a/src/Bladeburner/ui/ContractElem.tsx +++ b/src/Bladeburner/ui/ContractElem.tsx @@ -2,18 +2,16 @@ import type { Bladeburner } from "../Bladeburner"; import type { Contract } from "../Actions/Contract"; import React from "react"; -import { createProgressBarText } from "../../utils/helpers/createProgressBarText"; import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions"; import { Player } from "@player"; import { SuccessChance } from "./SuccessChance"; -import { CopyableText } from "../../ui/React/CopyableText"; import { ActionLevel } from "./ActionLevel"; import { Autolevel } from "./Autolevel"; -import { StartButton } from "./StartButton"; -import { formatNumberNoSuffix, formatBigNumber } from "../../ui/formatNumber"; +import { formatBigNumber } from "../../ui/formatNumber"; import { Paper, Typography } from "@mui/material"; import { useRerender } from "../../ui/React/hooks"; import { getEnumHelper } from "../../utils/EnumHelper"; +import { ActionHeader } from "./ActionHeader"; interface ContractElemProps { bladeburner: Bladeburner; @@ -25,38 +23,14 @@ export function ContractElem({ bladeburner, action }: ContractElemProps): React. // Temp special return if (!getEnumHelper("BladeContractName").isMember(action.name)) return <>; const isActive = action.name === bladeburner.action?.name; - const computedActionTimeCurrent = Math.min( - bladeburner.actionTimeCurrent + bladeburner.actionTimeOverflow, - bladeburner.actionTimeToComplete, - ); const actionTime = action.getActionTime(bladeburner, Player); return ( - {isActive ? ( - <> - - - (IN PROGRESS - {formatNumberNoSuffix(computedActionTimeCurrent, 0)} /{" "} - {formatNumberNoSuffix(bladeburner.actionTimeToComplete, 0)}) - - - {createProgressBarText({ - progress: computedActionTimeCurrent / bladeburner.actionTimeToComplete, - })} - - - ) : ( - <> - - - - )} -
    +

    -
    {action.desc}
    diff --git a/src/Bladeburner/ui/GeneralActionElem.tsx b/src/Bladeburner/ui/GeneralActionElem.tsx index d35a72d9e..006b479bf 100644 --- a/src/Bladeburner/ui/GeneralActionElem.tsx +++ b/src/Bladeburner/ui/GeneralActionElem.tsx @@ -2,15 +2,12 @@ import type { Bladeburner } from "../Bladeburner"; import type { GeneralAction } from "../Actions/GeneralAction"; import React from "react"; -import { createProgressBarText } from "../../utils/helpers/createProgressBarText"; import { formatNumberNoSuffix } from "../../ui/formatNumber"; import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions"; import { Player } from "@player"; -import { CopyableText } from "../../ui/React/CopyableText"; -import { StartButton } from "./StartButton"; -import { StopButton } from "./StopButton"; -import { Box, Paper, Typography } from "@mui/material"; +import { Paper, Typography } from "@mui/material"; import { useRerender } from "../../ui/React/hooks"; +import { ActionHeader } from "./ActionHeader"; interface GeneralActionElemProps { bladeburner: Bladeburner; @@ -19,44 +16,16 @@ interface GeneralActionElemProps { export function GeneralActionElem({ bladeburner, action }: GeneralActionElemProps): React.ReactElement { const rerender = useRerender(); - const isActive = action.name === bladeburner.action?.name; - const computedActionTimeCurrent = Math.min( - bladeburner.actionTimeCurrent + bladeburner.actionTimeOverflow, - bladeburner.actionTimeToComplete, - ); const actionTime = action.getActionTime(bladeburner, Player); const successChance = action.name === "Recruitment" ? Math.max(0, Math.min(bladeburner.getRecruitmentSuccessChance(Player), 1)) : -1; return ( - {isActive ? ( - <> - - - - - - (IN PROGRESS - {formatNumberNoSuffix(computedActionTimeCurrent, 0)} /{" "} - {formatNumberNoSuffix(bladeburner.actionTimeToComplete, 0)}) - - - {createProgressBarText({ - progress: computedActionTimeCurrent / bladeburner.actionTimeToComplete, - })} - - - ) : ( - - - - - )} -
    +
    {action.desc}
    -
    Time Required: {convertTimeMsToTimeElapsedString(actionTime * 1000)} {successChance !== -1 && ( diff --git a/src/Bladeburner/ui/OperationElem.tsx b/src/Bladeburner/ui/OperationElem.tsx index 487456410..83244ea4d 100644 --- a/src/Bladeburner/ui/OperationElem.tsx +++ b/src/Bladeburner/ui/OperationElem.tsx @@ -5,76 +5,47 @@ import React from "react"; import { Paper, Typography } from "@mui/material"; import { Player } from "@player"; -import { createProgressBarText } from "../../utils/helpers/createProgressBarText"; import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions"; import { SuccessChance } from "./SuccessChance"; import { ActionLevel } from "./ActionLevel"; import { Autolevel } from "./Autolevel"; -import { StartButton } from "./StartButton"; -import { TeamSizeButton } from "./TeamSizeButton"; -import { CopyableText } from "../../ui/React/CopyableText"; -import { formatNumberNoSuffix, formatBigNumber } from "../../ui/formatNumber"; +import { formatBigNumber } from "../../ui/formatNumber"; import { useRerender } from "../../ui/React/hooks"; import { BladeActionType } from "@enums"; +import { ActionHeader } from "./ActionHeader"; interface OperationElemProps { bladeburner: Bladeburner; - operation: Operation; + action: Operation; } -export function OperationElem({ bladeburner, operation }: OperationElemProps): React.ReactElement { +export function OperationElem({ bladeburner, action }: OperationElemProps): React.ReactElement { const rerender = useRerender(); - const isActive = - bladeburner.action?.type === BladeActionType.operation && operation.name === bladeburner.action?.name; - const computedActionTimeCurrent = Math.min( - bladeburner.actionTimeCurrent + bladeburner.actionTimeOverflow, - bladeburner.actionTimeToComplete, - ); - const actionTime = operation.getActionTime(bladeburner, Player); + const isActive = bladeburner.action?.type === BladeActionType.operation && action.name === bladeburner.action?.name; + const actionTime = action.getActionTime(bladeburner, Player); return ( - {isActive ? ( - <> - - (IN PROGRESS - {formatNumberNoSuffix(computedActionTimeCurrent, 0)}{" "} - / {formatNumberNoSuffix(bladeburner.actionTimeToComplete, 0)}) - - - {createProgressBarText({ - progress: computedActionTimeCurrent / bladeburner.actionTimeToComplete, - })} - - - ) : ( - <> - - - - - )} -
    -
    - - +
    +
    - {operation.desc} + {action.desc}

    - +
    Time Required: {convertTimeMsToTimeElapsedString(actionTime * 1000)}
    - Operations remaining: {formatBigNumber(Math.floor(operation.count))} + Operations remaining: {formatBigNumber(Math.floor(action.count))}
    - Successes: {formatBigNumber(operation.successes)} + Successes: {formatBigNumber(action.successes)}
    - Failures: {formatBigNumber(operation.failures)} + Failures: {formatBigNumber(action.failures)}

    - +
    ); } diff --git a/src/Bladeburner/ui/OperationPage.tsx b/src/Bladeburner/ui/OperationPage.tsx index 4559dcee6..8682cf2bf 100644 --- a/src/Bladeburner/ui/OperationPage.tsx +++ b/src/Bladeburner/ui/OperationPage.tsx @@ -1,6 +1,6 @@ import type { Bladeburner } from "../Bladeburner"; -import * as React from "react"; +import React from "react"; import { OperationElem } from "./OperationElem"; import { Typography } from "@mui/material"; @@ -30,7 +30,7 @@ export function OperationPage({ bladeburner }: OperationPageProps): React.ReactE difficult, but grant more rank and experience.
    {operations.map((operation) => ( - + ))} ); diff --git a/src/Bladeburner/ui/StartButton.tsx b/src/Bladeburner/ui/StartButton.tsx index d307ed4db..2c7109919 100644 --- a/src/Bladeburner/ui/StartButton.tsx +++ b/src/Bladeburner/ui/StartButton.tsx @@ -20,7 +20,11 @@ export function StartButton({ bladeburner, action, rerender }: StartButtonProps) } return ( - + Start ); diff --git a/src/Bladeburner/ui/StopButton.tsx b/src/Bladeburner/ui/StopButton.tsx index 75bf88f41..58d4764c4 100644 --- a/src/Bladeburner/ui/StopButton.tsx +++ b/src/Bladeburner/ui/StopButton.tsx @@ -13,5 +13,9 @@ export function StopButton({ bladeburner, rerender }: StopButtonProps): React.Re rerender(); } - return ; + return ( + + ); } diff --git a/src/Bladeburner/ui/TeamSizeButton.tsx b/src/Bladeburner/ui/TeamSizeButton.tsx index 76913c9a4..bb1cf4ab1 100644 --- a/src/Bladeburner/ui/TeamSizeButton.tsx +++ b/src/Bladeburner/ui/TeamSizeButton.tsx @@ -15,7 +15,7 @@ export function TeamSizeButton({ action, bladeburner }: TeamSizeButtonProps): Re return ( <> - setOpen(false)} action={action} bladeburner={bladeburner} /> From ebf08d5d1fad269b296abc0d5801eba3755f6341 Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Sat, 8 Jun 2024 03:41:42 +0700 Subject: [PATCH 32/43] BLADEBURNER: Improve terminal logging (#1361) --- src/Bladeburner/Bladeburner.ts | 68 ++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/src/Bladeburner/Bladeburner.ts b/src/Bladeburner/Bladeburner.ts index ebbb3a240..922a40fe8 100644 --- a/src/Bladeburner/Bladeburner.ts +++ b/src/Bladeburner/Bladeburner.ts @@ -17,7 +17,7 @@ import { } from "@enums"; import { getKeyList } from "../utils/helpers/getKeyList"; import { constructorsForReviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver"; -import { formatNumberNoSuffix } from "../ui/formatNumber"; +import { formatHp, formatNumberNoSuffix, formatSleeveShock } from "../ui/formatNumber"; import { Skills } from "./data/Skills"; import { City } from "./City"; import { Player } from "@player"; @@ -46,6 +46,8 @@ import { clampInteger, clampNumber } from "../utils/helpers/clampNumber"; import { parseCommand } from "../Terminal/Parser"; import { BlackOperations } from "./data/BlackOperations"; import { GeneralActions } from "./data/GeneralActions"; +import { PlayerObject } from "../PersonObjects/Player/PlayerObject"; +import { Sleeve } from "../PersonObjects/Sleeve/Sleeve"; export const BladeburnerPromise: PromisePair = { promise: null, resolve: null }; @@ -854,6 +856,22 @@ export class Bladeburner { } completeAction(person: Person, actionIdent: ActionIdentifier, isPlayer = true): WorkStats { + const currentHp = person.hp.current; + const getExtraLogAfterTakingDamage = (damage: number) => { + let extraLog = ""; + if (currentHp <= damage) { + if (person instanceof PlayerObject) { + extraLog += ` ${person.whoAmI()} was hospitalized. Current HP is ${formatHp(person.hp.current)}.`; + } else if (person instanceof Sleeve) { + extraLog += ` ${person.whoAmI()} was shocked. Current shock is ${formatSleeveShock( + person.shock, + )}. Current HP is ${formatHp(person.hp.current)}.`; + } + } else { + extraLog += ` HP reduced from ${formatHp(currentHp)} to ${formatHp(person.hp.current)}.`; + } + return extraLog; + }; let retValue = newWorkStats(); const action = this.getActionObject(actionIdent); switch (action.type) { @@ -899,12 +917,12 @@ export class Bladeburner { this.changeRank(person, gain); if (isOperation && this.logging.ops) { this.log( - `${person.whoAmI()}: ${action.name} successfully completed! Gained ${formatBigNumber(gain)} rank`, + `${person.whoAmI()}: ${action.name} successfully completed! Gained ${formatBigNumber(gain)} rank.`, ); } else if (!isOperation && this.logging.contracts) { this.log( `${person.whoAmI()}: ${action.name} contract successfully completed! Gained ` + - `${formatBigNumber(gain)} rank and ${formatMoney(moneyGain)}`, + `${formatBigNumber(gain)} rank and ${formatMoney(moneyGain)}.`, ); } } @@ -930,15 +948,15 @@ export class Bladeburner { } let logLossText = ""; if (loss > 0) { - logLossText += "Lost " + formatNumberNoSuffix(loss, 3) + " rank. "; + logLossText += ` Lost ${formatNumberNoSuffix(loss, 3)} rank.`; } if (damage > 0) { - logLossText += "Took " + formatNumberNoSuffix(damage, 0) + " damage."; + logLossText += ` Took ${formatNumberNoSuffix(damage, 0)} damage.${getExtraLogAfterTakingDamage(damage)}`; } if (isOperation && this.logging.ops) { - this.log(`${person.whoAmI()}: ` + action.name + " failed! " + logLossText); + this.log(`${person.whoAmI()}: ${action.name} failed!${logLossText}`); } else if (!isOperation && this.logging.contracts) { - this.log(`${person.whoAmI()}: ` + action.name + " contract failed! " + logLossText); + this.log(`${person.whoAmI()}: ${action.name} contract failed!${logLossText}`); } isOperation ? this.completeOperation(false) : this.completeContract(false, action); } @@ -977,7 +995,9 @@ export class Bladeburner { teamLossMax = Math.ceil(teamCount / 2); if (this.logging.blackops) { - this.log(`${person.whoAmI()}: ${action.name} successful! Gained ${formatNumberNoSuffix(rankGain, 1)} rank`); + this.log( + `${person.whoAmI()}: ${action.name} successful! Gained ${formatNumberNoSuffix(rankGain, 1)} rank.`, + ); } } else { retValue = this.getActionStats(action, person, false); @@ -1003,7 +1023,7 @@ export class Bladeburner { `${person.whoAmI()}: ${action.name} failed! Lost ${formatNumberNoSuffix( rankLoss, 1, - )} rank and took ${formatNumberNoSuffix(damage, 0)} damage`, + )} rank. Took ${formatNumberNoSuffix(damage, 0)} damage.${getExtraLogAfterTakingDamage(damage)}`, ); } } @@ -1026,7 +1046,7 @@ export class Bladeburner { this.teamLost += losses; if (this.logging.blackops) { this.log( - `${person.whoAmI()}: You lost ${formatNumberNoSuffix(losses, 0)} team members during ${action.name}`, + `${person.whoAmI()}: You lost ${formatNumberNoSuffix(losses, 0)} team members during ${action.name}.`, ); } } @@ -1059,7 +1079,7 @@ export class Bladeburner { formatExp(agiExpGain) + " agi exp, " + formatBigNumber(staminaGain) + - " max stamina", + " max stamina.", ); } break; @@ -1089,7 +1109,7 @@ export class Bladeburner { `${person.whoAmI()}: ` + `Field analysis completed. Gained ${formatBigNumber(rankGain)} rank, ` + `${formatExp(hackingExpGain)} hacking exp, and ` + - `${formatExp(charismaExpGain)} charisma exp`, + `${formatExp(charismaExpGain)} charisma exp.`, ); } break; @@ -1105,7 +1125,7 @@ export class Bladeburner { `${person.whoAmI()}: ` + "Successfully recruited a team member! Gained " + formatExp(expGain) + - " charisma exp", + " charisma exp.", ); } } else { @@ -1116,7 +1136,7 @@ export class Bladeburner { `${person.whoAmI()}: ` + "Failed to recruit a team member. Gained " + formatExp(expGain) + - " charisma exp", + " charisma exp.", ); } } @@ -1132,7 +1152,7 @@ export class Bladeburner { this.log( `${person.whoAmI()}: Diplomacy completed. Chaos levels in the current city fell by ${formatPercent( 1 - eff, - )}`, + )}.`, ); } break; @@ -1140,14 +1160,22 @@ export class Bladeburner { case BladeGeneralActionName.hyperbolicRegen: { person.regenerateHp(BladeburnerConstants.HrcHpGain); + const currentStamina = this.stamina; const staminaGain = this.maxStamina * (BladeburnerConstants.HrcStaminaGain / 100); this.stamina = Math.min(this.maxStamina, this.stamina + staminaGain); if (this.logging.general) { - this.log( - `${person.whoAmI()}: Rested in Hyperbolic Regeneration Chamber. Restored ${ - BladeburnerConstants.HrcHpGain - } HP and gained ${formatStamina(staminaGain)} stamina`, - ); + let extraLog = ""; + if (Player.hp.current > currentHp) { + extraLog += ` Restored ${formatHp(BladeburnerConstants.HrcHpGain)} HP. Current HP is ${formatHp( + Player.hp.current, + )}.`; + } + if (this.stamina > currentStamina) { + extraLog += ` Restored ${formatStamina(staminaGain)} stamina. Current stamina is ${formatStamina( + this.stamina, + )}.`; + } + this.log(`${person.whoAmI()}: Rested in Hyperbolic Regeneration Chamber.${extraLog}`); } break; } From abcd6c545a29928aa98d028c9fba64c95a3e8725 Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Sat, 8 Jun 2024 08:04:08 +0700 Subject: [PATCH 33/43] BLADEBURNER: Remove obsolete fix (#1367) --- src/Bladeburner/Bladeburner.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Bladeburner/Bladeburner.ts b/src/Bladeburner/Bladeburner.ts index 922a40fe8..f80f741f1 100644 --- a/src/Bladeburner/Bladeburner.ts +++ b/src/Bladeburner/Bladeburner.ts @@ -117,7 +117,6 @@ export class Bladeburner { } calculateStaminaPenalty(): number { - if (this.stamina === this.maxStamina) return 1; return Math.min(1, this.stamina / (0.5 * this.maxStamina)); } @@ -1286,13 +1285,16 @@ export class Bladeburner { calculateMaxStamina(): void { const baseStamina = Math.pow(this.getEffectiveSkillLevel(Player, "agility"), 0.8); + // Min value of maxStamina is an arbitrarily small positive value. It must not be 0 to avoid NaN stamina penalty. const maxStamina = clampNumber( (baseStamina + this.staminaBonus) * this.getSkillMult(BladeMultName.stamina) * Player.mults.bladeburner_max_stamina, - 0, + 1e-9, ); - if (this.maxStamina === maxStamina) return; + if (this.maxStamina === maxStamina) { + return; + } // If max stamina changed, adjust stamina accordingly const oldMax = this.maxStamina; this.maxStamina = maxStamina; @@ -1459,6 +1461,16 @@ export class Bladeburner { loadOperationsData(operationsData, bladeburner.operations); // Regenerate skill multiplier data, which is not included in savedata bladeburner.updateSkillMultipliers(); + // If stamina or maxStamina is invalid, we set both of them to 1 and recalculate them. + if ( + !Number.isFinite(bladeburner.stamina) || + !Number.isFinite(bladeburner.maxStamina) || + bladeburner.maxStamina === 0 + ) { + bladeburner.stamina = 1; + bladeburner.maxStamina = 1; + bladeburner.calculateMaxStamina(); + } return bladeburner; } } From b8f03cb50b4669d8fbadf0da8219757a99c1285d Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Sun, 9 Jun 2024 03:51:05 +0700 Subject: [PATCH 34/43] BLADEBURNER: Remove unused code (#1368) --- src/Bladeburner/ui/ContractElem.tsx | 3 --- src/utils/EnumHelper.ts | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Bladeburner/ui/ContractElem.tsx b/src/Bladeburner/ui/ContractElem.tsx index 8ad66dfc7..d92423f6d 100644 --- a/src/Bladeburner/ui/ContractElem.tsx +++ b/src/Bladeburner/ui/ContractElem.tsx @@ -10,7 +10,6 @@ import { Autolevel } from "./Autolevel"; import { formatBigNumber } from "../../ui/formatNumber"; import { Paper, Typography } from "@mui/material"; import { useRerender } from "../../ui/React/hooks"; -import { getEnumHelper } from "../../utils/EnumHelper"; import { ActionHeader } from "./ActionHeader"; interface ContractElemProps { @@ -20,8 +19,6 @@ interface ContractElemProps { export function ContractElem({ bladeburner, action }: ContractElemProps): React.ReactElement { const rerender = useRerender(); - // Temp special return - if (!getEnumHelper("BladeContractName").isMember(action.name)) return <>; const isActive = action.name === bladeburner.action?.name; const actionTime = action.getActionTime(bladeburner, Player); diff --git a/src/utils/EnumHelper.ts b/src/utils/EnumHelper.ts index 97f657441..350574cac 100644 --- a/src/utils/EnumHelper.ts +++ b/src/utils/EnumHelper.ts @@ -26,7 +26,7 @@ class EnumHelper & st this.valueSet = new Set(this.valueArray); this.fuzzMap = new Map(this.valueArray.map((val) => [val.toLowerCase().replace(/[ -]+/g, ""), val])); } - /** Provide a boolean indication for whether a */ + /** Provide a boolean indication for whether a value is a member of an enum */ isMember(toValidate: unknown): toValidate is EnumMember { // Asserting that Set.has actually takes in arbitrary values, which it does. return (this.valueSet.has as (value: unknown) => boolean)(toValidate); From a354867fc4f08cb4b692ad1d9a5dc125f5100c8c Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Sun, 9 Jun 2024 03:52:10 +0700 Subject: [PATCH 35/43] MISC: Refactor code of traveling and going to location (#1365) --- src/Locations/ui/CompanyLocation.tsx | 2 +- src/Locations/ui/TravelAgencyRoot.tsx | 13 +++++-------- src/Locations/ui/TravelConfirmationModal.tsx | 4 ++-- src/NetscriptFunctions/Singularity.ts | 18 ++++++++---------- src/NetscriptFunctions/Sleeve.ts | 6 +++++- .../Player/PlayerObjectGeneralMethods.ts | 15 +++++++++------ src/PersonObjects/Sleeve/Sleeve.ts | 8 ++++++-- src/PersonObjects/Sleeve/ui/TravelModal.tsx | 6 ++---- 8 files changed, 38 insertions(+), 34 deletions(-) diff --git a/src/Locations/ui/CompanyLocation.tsx b/src/Locations/ui/CompanyLocation.tsx index 1d69b3ff7..ca8a0b442 100644 --- a/src/Locations/ui/CompanyLocation.tsx +++ b/src/Locations/ui/CompanyLocation.tsx @@ -57,7 +57,7 @@ export function CompanyLocation(props: IProps): React.ReactElement { */ const currentPosition = jobTitle ? CompanyPositions[jobTitle] : null; - Player.location = companyNameAsLocationName(props.companyName); + Player.gotoLocation(companyNameAsLocationName(props.companyName)); function startInfiltration(e: React.MouseEvent): void { if (!e.isTrusted) { diff --git a/src/Locations/ui/TravelAgencyRoot.tsx b/src/Locations/ui/TravelAgencyRoot.tsx index 97389b778..b2784559d 100644 --- a/src/Locations/ui/TravelAgencyRoot.tsx +++ b/src/Locations/ui/TravelAgencyRoot.tsx @@ -24,14 +24,12 @@ import Button from "@mui/material/Button"; import { useRerender } from "../../ui/React/hooks"; function travel(to: CityName): void { - const cost = CONSTANTS.TravelCost; - if (!Player.canAfford(cost)) { + if (!Player.travel(to)) { return; } - - Player.loseMoney(cost, "other"); - Player.travel(to); - if (!Settings.SuppressTravelConfirmation) dialogBoxCreate(`You are now in ${to}!`); + if (!Settings.SuppressTravelConfirmation) { + dialogBoxCreate(`You are now in ${to}!`); + } Router.toPage(Page.City); } @@ -41,8 +39,7 @@ export function TravelAgencyRoot(): React.ReactElement { useRerender(1000); function startTravel(city: CityName): void { - const cost = CONSTANTS.TravelCost; - if (!Player.canAfford(cost)) { + if (!Player.canAfford(CONSTANTS.TravelCost)) { return; } if (Settings.SuppressTravelConfirmation) { diff --git a/src/Locations/ui/TravelConfirmationModal.tsx b/src/Locations/ui/TravelConfirmationModal.tsx index 5a16822d0..ee8bdd04d 100644 --- a/src/Locations/ui/TravelConfirmationModal.tsx +++ b/src/Locations/ui/TravelConfirmationModal.tsx @@ -14,7 +14,6 @@ interface IProps { } export function TravelConfirmationModal(props: IProps): React.ReactElement { - const cost = CONSTANTS.TravelCost; function travel(): void { props.travel(); } @@ -22,7 +21,8 @@ export function TravelConfirmationModal(props: IProps): React.ReactElement { return ( - Would you like to travel to {props.city}? The trip will cost . + Would you like to travel to {props.city}? The trip will cost{" "} + .

    diff --git a/src/NetscriptFunctions/Singularity.ts b/src/NetscriptFunctions/Singularity.ts index e0628ceae..cde24fea3 100644 --- a/src/NetscriptFunctions/Singularity.ts +++ b/src/NetscriptFunctions/Singularity.ts @@ -269,7 +269,7 @@ export function NetscriptSingularity(): InternalAPI { ); return false; } - Player.location = LocationName.Sector12RothmanUniversity; + Player.gotoLocation(LocationName.Sector12RothmanUniversity); break; case LocationName.VolhavenZBInstituteOfTechnology.toLowerCase(): if (Player.city != CityName.Volhaven) { @@ -279,7 +279,7 @@ export function NetscriptSingularity(): InternalAPI { ); return false; } - Player.location = LocationName.VolhavenZBInstituteOfTechnology; + Player.gotoLocation(LocationName.VolhavenZBInstituteOfTechnology); break; default: helpers.log(ctx, () => `Invalid university name: '${universityName}'.`); @@ -327,7 +327,7 @@ export function NetscriptSingularity(): InternalAPI { ); return false; } - Player.location = LocationName.AevumCrushFitnessGym; + Player.gotoLocation(LocationName.AevumCrushFitnessGym); break; case LocationName.AevumSnapFitnessGym.toLowerCase(): if (Player.city != CityName.Aevum) { @@ -338,7 +338,7 @@ export function NetscriptSingularity(): InternalAPI { ); return false; } - Player.location = LocationName.AevumSnapFitnessGym; + Player.gotoLocation(LocationName.AevumSnapFitnessGym); break; case LocationName.Sector12IronGym.toLowerCase(): if (Player.city != CityName.Sector12) { @@ -349,7 +349,7 @@ export function NetscriptSingularity(): InternalAPI { ); return false; } - Player.location = LocationName.Sector12IronGym; + Player.gotoLocation(LocationName.Sector12IronGym); break; case LocationName.Sector12PowerhouseGym.toLowerCase(): if (Player.city != CityName.Sector12) { @@ -360,7 +360,7 @@ export function NetscriptSingularity(): InternalAPI { ); return false; } - Player.location = LocationName.Sector12PowerhouseGym; + Player.gotoLocation(LocationName.Sector12PowerhouseGym); break; case LocationName.VolhavenMilleniumFitnessGym.toLowerCase(): if (Player.city != CityName.Volhaven) { @@ -371,7 +371,7 @@ export function NetscriptSingularity(): InternalAPI { ); return false; } - Player.location = LocationName.VolhavenMilleniumFitnessGym; + Player.gotoLocation(LocationName.VolhavenMilleniumFitnessGym); break; default: helpers.log(ctx, () => `Invalid gym name: ${gymName}. gymWorkout() failed`); @@ -401,12 +401,10 @@ export function NetscriptSingularity(): InternalAPI { case CityName.NewTokyo: case CityName.Ishima: case CityName.Volhaven: - if (Player.money < CONSTANTS.TravelCost) { + if (!Player.travel(cityName)) { helpers.log(ctx, () => "Not enough money to travel."); return false; } - Player.loseMoney(CONSTANTS.TravelCost, "other"); - Player.city = cityName; helpers.log(ctx, () => `Traveled to ${cityName}`); Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 50000); return true; diff --git a/src/NetscriptFunctions/Sleeve.ts b/src/NetscriptFunctions/Sleeve.ts index 253a09d3b..24113c9e4 100644 --- a/src/NetscriptFunctions/Sleeve.ts +++ b/src/NetscriptFunctions/Sleeve.ts @@ -79,7 +79,11 @@ export function NetscriptSleeve(): InternalAPI { const cityName = getEnumHelper("CityName").nsGetMember(ctx, _cityName); checkSleeveAPIAccess(ctx); checkSleeveNumber(ctx, sleeveNumber); - return Player.sleeves[sleeveNumber].travel(cityName); + if (!Player.sleeves[sleeveNumber].travel(cityName)) { + helpers.log(ctx, () => "Not enough money to travel."); + return false; + } + return true; }, setToCompanyWork: (ctx) => (_sleeveNumber, _companyName) => { const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); diff --git a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts index 62e45e4f9..ac00f6532 100644 --- a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts +++ b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts @@ -531,20 +531,23 @@ export function gainCodingContractReward( } } -export function travel(this: PlayerObject, to: CityName): boolean { - if (Cities[to] == null) { - console.warn(`Player.travel() called with invalid city: ${to}`); +export function travel(this: PlayerObject, cityName: CityName): boolean { + if (Cities[cityName] == null) { + throw new Error(`Player.travel() was called with an invalid city: ${cityName}`); + } + if (!this.canAfford(CONSTANTS.TravelCost)) { return false; } - this.city = to; + + this.loseMoney(CONSTANTS.TravelCost, "other"); + this.city = cityName; return true; } export function gotoLocation(this: PlayerObject, to: LocationName): boolean { if (Locations[to] == null) { - console.warn(`Player.gotoLocation() called with invalid location: ${to}`); - return false; + throw new Error(`Player.gotoLocation() was called with an invalid location: ${to}`); } this.location = to; diff --git a/src/PersonObjects/Sleeve/Sleeve.ts b/src/PersonObjects/Sleeve/Sleeve.ts index 9b48ab889..69a4d37c3 100644 --- a/src/PersonObjects/Sleeve/Sleeve.ts +++ b/src/PersonObjects/Sleeve/Sleeve.ts @@ -44,6 +44,7 @@ import { SleeveCrimeWork } from "./Work/SleeveCrimeWork"; import * as sleeveMethods from "./SleeveMethods"; import { calculateIntelligenceBonus } from "../formulas/intelligence"; import { getEnumHelper } from "../../utils/EnumHelper"; +import { Cities } from "../../Locations/Cities"; export class Sleeve extends Person implements SleevePerson { currentWork: SleeveWork | null = null; @@ -255,13 +256,16 @@ export class Sleeve extends Person implements SleevePerson { } /** Travel to another City. Costs money from player */ - travel(newCity: CityName): boolean { + travel(cityName: CityName): boolean { + if (Cities[cityName] == null) { + throw new Error(`Sleeve.travel() was called with an invalid city: ${cityName}`); + } if (!Player.canAfford(CONSTANTS.TravelCost)) { return false; } Player.loseMoney(CONSTANTS.TravelCost, "sleeves"); - this.city = newCity; + this.city = cityName; return true; } diff --git a/src/PersonObjects/Sleeve/ui/TravelModal.tsx b/src/PersonObjects/Sleeve/ui/TravelModal.tsx index 76cec4276..2c7e78f1d 100644 --- a/src/PersonObjects/Sleeve/ui/TravelModal.tsx +++ b/src/PersonObjects/Sleeve/ui/TravelModal.tsx @@ -1,6 +1,5 @@ import React from "react"; import { Button, Typography } from "@mui/material"; -import { Player } from "@player"; import { CityName } from "@enums"; import { Sleeve } from "../Sleeve"; import { CONSTANTS } from "../../../Constants"; @@ -19,11 +18,10 @@ interface IProps { export function TravelModal(props: IProps): React.ReactElement { function travel(city: string): void { - if (!Player.canAfford(CONSTANTS.TravelCost)) { + if (!props.sleeve.travel(city as CityName)) { dialogBoxCreate("You cannot afford to have this sleeve travel to another city"); + return; } - props.sleeve.city = city as CityName; - Player.loseMoney(CONSTANTS.TravelCost, "sleeves"); props.sleeve.stopWork(); props.rerender(); props.onClose(); From a0fc9cc71335475a1b5246a16b68884084a0c591 Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Sun, 9 Jun 2024 03:54:44 +0700 Subject: [PATCH 36/43] UI: Automatically show Bitverse UI if BN is finished (#1358) --- src/Achievements/Achievements.ts | 90 ++++++++++++--------------- src/BitNode/BitNodeUtils.ts | 11 ++++ src/Bladeburner/ui/BlackOpPage.tsx | 16 ++++- src/NetscriptFunctions/Singularity.ts | 4 +- src/ui/GameRoot.tsx | 19 ++++-- 5 files changed, 83 insertions(+), 57 deletions(-) create mode 100644 src/BitNode/BitNodeUtils.ts diff --git a/src/Achievements/Achievements.ts b/src/Achievements/Achievements.ts index 7b37cf9de..eff510dbe 100644 --- a/src/Achievements/Achievements.ts +++ b/src/Achievements/Achievements.ts @@ -19,7 +19,6 @@ import { HacknetNode } from "../Hacknet/HacknetNode"; import { HacknetServer } from "../Hacknet/HacknetServer"; import { Player } from "@player"; import { GetAllServers, GetServer } from "../Server/AllServers"; -import { SpecialServers } from "../Server/data/SpecialServers"; import { Server } from "../Server/Server"; import { Router } from "../ui/GameRoot"; import { Page } from "../ui/Router"; @@ -30,7 +29,7 @@ import { workerScripts } from "../Netscript/WorkerScripts"; import { getRecordValues } from "../Types/Record"; import { ServerConstants } from "../Server/data/Constants"; -import { blackOpsArray } from "../Bladeburner/data/BlackOperations"; +import { isBitNodeFinished } from "../BitNode/BitNodeUtils"; // Unable to correctly cast the JSON data into AchievementDataJson type otherwise... const achievementData = ((data)).achievements; @@ -61,15 +60,8 @@ export interface AchievementData { Description: string; } -function bitNodeFinishedState(): boolean { - const wd = GetServer(SpecialServers.WorldDaemon); - if (!(wd instanceof Server)) return false; - if (wd.backdoorInstalled) return true; - return Player.bladeburner !== null && Player.bladeburner.numBlackOpsComplete >= blackOpsArray.length; -} - -function hasAccessToSF(bn: number): boolean { - return Player.bitNodeN === bn || Player.sourceFileLvl(bn) > 0; +function canAccessBitNodeFeature(bitNode: number): boolean { + return Player.bitNodeN === bitNode || Player.sourceFileLvl(bitNode) > 0; } function knowsAboutBitverse(): boolean { @@ -338,25 +330,25 @@ export const achievements: Record = { GANG: { ...achievementData.GANG, Icon: "GANG", - Visible: () => hasAccessToSF(2), + Visible: () => canAccessBitNodeFeature(2), Condition: () => Player.gang !== null, }, FULL_GANG: { ...achievementData.FULL_GANG, Icon: "GANGMAX", - Visible: () => hasAccessToSF(2), + Visible: () => canAccessBitNodeFeature(2), Condition: () => Player.gang !== null && Player.gang.members.length === GangConstants.MaximumGangMembers, }, GANG_TERRITORY: { ...achievementData.GANG_TERRITORY, Icon: "GANG100%", - Visible: () => hasAccessToSF(2), + Visible: () => canAccessBitNodeFeature(2), Condition: () => Player.gang !== null && AllGangs[Player.gang.facName].territory >= 0.999, }, GANG_MEMBER_POWER: { ...achievementData.GANG_MEMBER_POWER, Icon: "GANG10000", - Visible: () => hasAccessToSF(2), + Visible: () => canAccessBitNodeFeature(2), Condition: () => Player.gang !== null && Player.gang.members.some( @@ -367,19 +359,19 @@ export const achievements: Record = { CORPORATION: { ...achievementData.CORPORATION, Icon: "CORP", - Visible: () => hasAccessToSF(3), + Visible: () => canAccessBitNodeFeature(3), Condition: () => Player.corporation !== null, }, CORPORATION_BRIBE: { ...achievementData.CORPORATION_BRIBE, Icon: "CORPLOBBY", - Visible: () => hasAccessToSF(3), + Visible: () => canAccessBitNodeFeature(3), Condition: () => !!Player.corporation && Player.corporation.unlocks.has(CorpUnlockName.GovernmentPartnership), }, CORPORATION_PROD_1000: { ...achievementData.CORPORATION_PROD_1000, Icon: "CORP1000", - Visible: () => hasAccessToSF(3), + Visible: () => canAccessBitNodeFeature(3), Condition: () => { if (!Player.corporation) return false; for (const division of Player.corporation.divisions.values()) { @@ -391,7 +383,7 @@ export const achievements: Record = { CORPORATION_EMPLOYEE_3000: { ...achievementData.CORPORATION_EMPLOYEE_3000, Icon: "CORPCITY", - Visible: () => hasAccessToSF(3), + Visible: () => canAccessBitNodeFeature(3), Condition: (): boolean => { if (!Player.corporation) return false; for (const division of Player.corporation.divisions.values()) { @@ -406,7 +398,7 @@ export const achievements: Record = { Icon: "CORPRE", Name: "Own the land", Description: "Expand to the Real Estate division.", - Visible: () => hasAccessToSF(3), + Visible: () => canAccessBitNodeFeature(3), Condition: () => { if (!Player.corporation) return false; for (const division of Player.corporation.divisions.values()) { @@ -418,26 +410,26 @@ export const achievements: Record = { INTELLIGENCE_255: { ...achievementData.INTELLIGENCE_255, Icon: "INT255", - Visible: () => hasAccessToSF(5), + Visible: () => canAccessBitNodeFeature(5), Condition: () => Player.skills.intelligence >= 255, }, BLADEBURNER_DIVISION: { ...achievementData.BLADEBURNER_DIVISION, Icon: "BLADE", - Visible: () => hasAccessToSF(6), + Visible: () => canAccessBitNodeFeature(6), Condition: () => Player.bladeburner !== null, }, BLADEBURNER_OVERCLOCK: { ...achievementData.BLADEBURNER_OVERCLOCK, Icon: "BLADEOVERCLOCK", - Visible: () => hasAccessToSF(6), + Visible: () => canAccessBitNodeFeature(6), Condition: () => Player.bladeburner?.getSkillLevel(BladeSkillName.overclock) === Skills[BladeSkillName.overclock].maxLvl, }, BLADEBURNER_UNSPENT_100000: { ...achievementData.BLADEBURNER_UNSPENT_100000, Icon: "BLADE100K", - Visible: () => hasAccessToSF(6), + Visible: () => canAccessBitNodeFeature(6), Condition: () => Player.bladeburner !== null && Player.bladeburner.skillPoints >= 100000, }, "4S": { @@ -448,21 +440,21 @@ export const achievements: Record = { FIRST_HACKNET_SERVER: { ...achievementData.FIRST_HACKNET_SERVER, Icon: "HASHNET", - Visible: () => hasAccessToSF(9), + Visible: () => canAccessBitNodeFeature(9), Condition: () => hasHacknetServers() && Player.hacknetNodes.length > 0, AdditionalUnlock: [achievementData.FIRST_HACKNET_NODE.ID], }, ALL_HACKNET_SERVER: { ...achievementData.ALL_HACKNET_SERVER, Icon: "HASHNETALL", - Visible: () => hasAccessToSF(9), + Visible: () => canAccessBitNodeFeature(9), Condition: () => hasHacknetServers() && Player.hacknetNodes.length === HacknetServerConstants.MaxServers, AdditionalUnlock: [achievementData["30_HACKNET_NODE"].ID], }, MAX_HACKNET_SERVER: { ...achievementData.MAX_HACKNET_SERVER, Icon: "HASHNETALL", - Visible: () => hasAccessToSF(9), + Visible: () => canAccessBitNodeFeature(9), Condition: (): boolean => { if (!hasHacknetServers()) return false; for (const h of Player.hacknetNodes) { @@ -484,14 +476,14 @@ export const achievements: Record = { HACKNET_SERVER_1B: { ...achievementData.HACKNET_SERVER_1B, Icon: "HASHNETMONEY", - Visible: () => hasAccessToSF(9), + Visible: () => canAccessBitNodeFeature(9), Condition: () => hasHacknetServers() && Player.moneySourceB.hacknet >= 1e9, AdditionalUnlock: [achievementData.HACKNET_NODE_10M.ID], }, MAX_CACHE: { ...achievementData.MAX_CACHE, Icon: "HASHNETCAP", - Visible: () => hasAccessToSF(9), + Visible: () => canAccessBitNodeFeature(9), Condition: () => hasHacknetServers() && Player.hashManager.hashes === Player.hashManager.capacity && @@ -500,7 +492,7 @@ export const achievements: Record = { SLEEVE_8: { ...achievementData.SLEEVE_8, Icon: "SLEEVE8", - Visible: () => hasAccessToSF(10), + Visible: () => canAccessBitNodeFeature(10), Condition: () => Player.sleeves.length === 8 && Player.sourceFileLvl(10) === 3, }, INDECISIVE: { @@ -523,7 +515,7 @@ export const achievements: Record = { ...achievementData.FAST_BN, Icon: "2DAYS", Visible: knowsAboutBitverse, - Condition: () => bitNodeFinishedState() && Player.playtimeSinceLastBitnode < 1000 * 60 * 60 * 24 * 2, + Condition: () => isBitNodeFinished() && Player.playtimeSinceLastBitnode < 1000 * 60 * 60 * 24 * 2, }, CHALLENGE_BN1: { ...achievementData.CHALLENGE_BN1, @@ -531,57 +523,57 @@ export const achievements: Record = { Visible: knowsAboutBitverse, Condition: () => Player.bitNodeN === 1 && - bitNodeFinishedState() && + isBitNodeFinished() && Player.getHomeComputer().maxRam <= 128 && Player.getHomeComputer().cpuCores === 1, }, CHALLENGE_BN2: { ...achievementData.CHALLENGE_BN2, Icon: "BN2+", - Visible: () => hasAccessToSF(2), - Condition: () => Player.bitNodeN === 2 && bitNodeFinishedState() && Player.gang === null, + Visible: () => canAccessBitNodeFeature(2), + Condition: () => Player.bitNodeN === 2 && isBitNodeFinished() && Player.gang === null, }, CHALLENGE_BN3: { ...achievementData.CHALLENGE_BN3, Icon: "BN3+", - Visible: () => hasAccessToSF(3), - Condition: () => Player.bitNodeN === 3 && bitNodeFinishedState() && Player.corporation === null, + Visible: () => canAccessBitNodeFeature(3), + Condition: () => Player.bitNodeN === 3 && isBitNodeFinished() && Player.corporation === null, }, CHALLENGE_BN6: { ...achievementData.CHALLENGE_BN6, Icon: "BN6+", - Visible: () => hasAccessToSF(6), - Condition: () => Player.bitNodeN === 6 && bitNodeFinishedState() && Player.bladeburner === null, + Visible: () => canAccessBitNodeFeature(6), + Condition: () => Player.bitNodeN === 6 && isBitNodeFinished() && Player.bladeburner === null, }, CHALLENGE_BN7: { ...achievementData.CHALLENGE_BN7, Icon: "BN7+", - Visible: () => hasAccessToSF(7), - Condition: () => Player.bitNodeN === 7 && bitNodeFinishedState() && Player.bladeburner === null, + Visible: () => canAccessBitNodeFeature(7), + Condition: () => Player.bitNodeN === 7 && isBitNodeFinished() && Player.bladeburner === null, }, CHALLENGE_BN8: { ...achievementData.CHALLENGE_BN8, Icon: "BN8+", - Visible: () => hasAccessToSF(8), - Condition: () => Player.bitNodeN === 8 && bitNodeFinishedState() && !Player.has4SData && !Player.has4SDataTixApi, + Visible: () => canAccessBitNodeFeature(8), + Condition: () => Player.bitNodeN === 8 && isBitNodeFinished() && !Player.has4SData && !Player.has4SDataTixApi, }, CHALLENGE_BN9: { ...achievementData.CHALLENGE_BN9, Icon: "BN9+", - Visible: () => hasAccessToSF(9), + Visible: () => canAccessBitNodeFeature(9), Condition: () => Player.bitNodeN === 9 && - bitNodeFinishedState() && + isBitNodeFinished() && Player.moneySourceB.hacknet === 0 && Player.moneySourceB.hacknet_expenses === 0, }, CHALLENGE_BN10: { ...achievementData.CHALLENGE_BN10, Icon: "BN10+", - Visible: () => hasAccessToSF(10), + Visible: () => canAccessBitNodeFeature(10), Condition: () => Player.bitNodeN === 10 && - bitNodeFinishedState() && + isBitNodeFinished() && !Player.sleeves.some( (s) => s.augmentations.length > 0 || @@ -596,7 +588,7 @@ export const achievements: Record = { CHALLENGE_BN12: { ...achievementData.CHALLENGE_BN12, Icon: "BN12+", - Visible: () => hasAccessToSF(12), + Visible: () => canAccessBitNodeFeature(12), Condition: () => Player.sourceFileLvl(12) >= 50, }, BYPASS: { @@ -657,10 +649,10 @@ export const achievements: Record = { CHALLENGE_BN13: { ...achievementData.CHALLENGE_BN13, Icon: "BN13+", - Visible: () => hasAccessToSF(13), + Visible: () => canAccessBitNodeFeature(13), Condition: () => Player.bitNodeN === 13 && - bitNodeFinishedState() && + isBitNodeFinished() && !Player.augmentations.some((a) => a.name === AugmentationName.StaneksGift1), }, DEVMENU: { diff --git a/src/BitNode/BitNodeUtils.ts b/src/BitNode/BitNodeUtils.ts new file mode 100644 index 000000000..65eb15fad --- /dev/null +++ b/src/BitNode/BitNodeUtils.ts @@ -0,0 +1,11 @@ +import { GetServer } from "../Server/AllServers"; +import { Server } from "../Server/Server"; +import { SpecialServers } from "../Server/data/SpecialServers"; + +export function isBitNodeFinished(): boolean { + const wd = GetServer(SpecialServers.WorldDaemon); + if (!(wd instanceof Server)) { + throw new Error("WorldDaemon is not a normal server. This is a bug. Please contact developers."); + } + return wd.backdoorInstalled; +} diff --git a/src/Bladeburner/ui/BlackOpPage.tsx b/src/Bladeburner/ui/BlackOpPage.tsx index b53b379c4..f35c3ff11 100644 --- a/src/Bladeburner/ui/BlackOpPage.tsx +++ b/src/Bladeburner/ui/BlackOpPage.tsx @@ -8,11 +8,23 @@ import { Router } from "../../ui/GameRoot"; import { Page } from "../../ui/Router"; import { CorruptableText } from "../../ui/React/CorruptableText"; import { blackOpsArray } from "../data/BlackOperations"; +import { GetServer } from "../../Server/AllServers"; +import { SpecialServers } from "../../Server/data/SpecialServers"; +import { Server } from "../../Server/Server"; interface BlackOpPageProps { bladeburner: Bladeburner; } +function finishBitNode() { + const wd = GetServer(SpecialServers.WorldDaemon); + if (!(wd instanceof Server)) { + throw new Error("WorldDaemon is not a normal server. This is a bug. Please contact developers."); + } + wd.backdoorInstalled = true; + Router.toPage(Page.BitVerse, { flume: false, quick: false }); +} + export function BlackOpPage({ bladeburner }: BlackOpPageProps): React.ReactElement { const blackOperations = blackOpsArray.slice(0, bladeburner.numBlackOpsComplete + 1).reverse(); @@ -33,8 +45,8 @@ export function BlackOpPage({ bladeburner }: BlackOpPageProps): React.ReactEleme losses.
    {bladeburner.numBlackOpsComplete >= blackOpsArray.length ? ( - ) : ( <> diff --git a/src/NetscriptFunctions/Singularity.ts b/src/NetscriptFunctions/Singularity.ts index cde24fea3..b401fb1ed 100644 --- a/src/NetscriptFunctions/Singularity.ts +++ b/src/NetscriptFunctions/Singularity.ts @@ -1121,7 +1121,9 @@ export function NetscriptSingularity(): InternalAPI { if (cbScript === null) throw helpers.errorMessage(ctx, `Could not resolve file path: ${_cbScript}`); const wd = GetServer(SpecialServers.WorldDaemon); - if (!(wd instanceof Server)) throw new Error("WorldDaemon was not a normal server. This is a bug contact dev."); + if (!(wd instanceof Server)) { + throw new Error("WorldDaemon is not a normal server. This is a bug. Please contact developers."); + } const hackingRequirements = () => { if (Player.skills.hacking < wd.requiredHackingSkill) return false; if (!wd.hasAdminRights) return false; diff --git a/src/ui/GameRoot.tsx b/src/ui/GameRoot.tsx index 1bb400fa2..5d1c95811 100644 --- a/src/ui/GameRoot.tsx +++ b/src/ui/GameRoot.tsx @@ -72,6 +72,7 @@ import { MathJaxContext } from "better-react-mathjax"; import { useRerender } from "./React/hooks"; import { HistoryProvider } from "./React/Documentation"; import { GoRoot } from "../Go/ui/GoRoot"; +import { isBitNodeFinished } from "../BitNode/BitNodeUtils"; const htmlLocation = location; @@ -108,16 +109,24 @@ export let Router: IRouter = { }, }; -function determineStartPage() { - if (RecoveryMode) return Page.Recovery; - if (Player.currentWork !== null) return Page.Work; - return Page.Terminal; +function determineStartPage(): PageWithContext { + if (RecoveryMode) { + return { page: Page.Recovery }; + } + if (isBitNodeFinished()) { + // Go to BitVerse UI without animation. + return { page: Page.BitVerse, flume: false, quick: true }; + } + if (Player.currentWork !== null) { + return { page: Page.Work }; + } + return { page: Page.Terminal }; } export function GameRoot(): React.ReactElement { const { classes } = useStyles(); - const [pages, setPages] = useState(() => [{ page: determineStartPage() }]); + const [pages, setPages] = useState(() => [determineStartPage()]); const pageWithContext = pages[0]; const setNextPage = (pageWithContext: PageWithContext) => From 995294a770a7352dda2ef80619fd3e84410749c8 Mon Sep 17 00:00:00 2001 From: Albert Llop Date: Mon, 10 Jun 2024 01:34:53 +0200 Subject: [PATCH 37/43] BUGFIX: bladeburner.getActionRepGain: mark level param as optional in signature (#1375) --- markdown/bitburner.bladeburner.getactionrepgain.md | 4 ++-- src/ScriptEditor/NetscriptDefinitions.d.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/markdown/bitburner.bladeburner.getactionrepgain.md b/markdown/bitburner.bladeburner.getactionrepgain.md index 1ca00295e..6caabcaeb 100644 --- a/markdown/bitburner.bladeburner.getactionrepgain.md +++ b/markdown/bitburner.bladeburner.getactionrepgain.md @@ -9,7 +9,7 @@ Get the reputation gain of an action. **Signature:** ```typescript -getActionRepGain(type: string, name: string, level: number): number; +getActionRepGain(type: string, name: string, level?: number): number; ``` ## Parameters @@ -18,7 +18,7 @@ getActionRepGain(type: string, name: string, level: number): number; | --- | --- | --- | | type | string | Type of action. | | name | string | Name of action. Must be an exact match. | -| level | number | Optional number. Action level at which to calculate the gain. Will be the action's current level if not given. | +| level | number | _(Optional)_ Optional number. Action level at which to calculate the gain. Will be the action's current level if not given. | **Returns:** diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index bcfb207a2..f816e66d5 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -3132,7 +3132,7 @@ export interface Bladeburner { * @param level - Optional number. Action level at which to calculate the gain. Will be the action's current level if not given. * @returns Average Bladeburner reputation gain for successfully completing the specified action. */ - getActionRepGain(type: string, name: string, level: number): number; + getActionRepGain(type: string, name: string, level?: number): number; /** * Get action count remaining. From ba7d45362f02d975a74b1cdc2c6e51a3471df4c0 Mon Sep 17 00:00:00 2001 From: Albert Llop Date: Mon, 10 Jun 2024 01:39:01 +0200 Subject: [PATCH 38/43] bladeburner.getTeamSize: fix signature and documentation (#1383) --- markdown/bitburner.bladeburner.getteamsize.md | 8 ++++---- src/ScriptEditor/NetscriptDefinitions.d.ts | 6 ++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/markdown/bitburner.bladeburner.getteamsize.md b/markdown/bitburner.bladeburner.getteamsize.md index 37c87b530..02811fa95 100644 --- a/markdown/bitburner.bladeburner.getteamsize.md +++ b/markdown/bitburner.bladeburner.getteamsize.md @@ -9,15 +9,15 @@ Get team size. **Signature:** ```typescript -getTeamSize(type: string, name: string): number; +getTeamSize(type?: string, name?: string): number; ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| type | string | Type of action. | -| name | string | Name of action. Must be an exact match. | +| type | string | _(Optional)_ Type of action. | +| name | string | _(Optional)_ Name of action. Must be an exact match. | **Returns:** @@ -29,7 +29,7 @@ Number of Bladeburner team members that were assigned to the specified action. RAM cost: 4 GB -Returns the number of Bladeburner team members you have assigned to the specified action. +Returns the number of available Bladeburner team members. You can also pass the type and name of an action to get the number of Bladeburner team members you have assigned to the specified action. Setting a team is only applicable for Operations and BlackOps. This function will return 0 for other action types. diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index f816e66d5..1d47d472e 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -3321,7 +3321,9 @@ export interface Bladeburner { * @remarks * RAM cost: 4 GB * - * Returns the number of Bladeburner team members you have assigned to the specified action. + * Returns the number of available Bladeburner team members. + * You can also pass the type and name of an action to get the number of + * Bladeburner team members you have assigned to the specified action. * * Setting a team is only applicable for Operations and BlackOps. This function will return 0 for other action types. * @@ -3329,7 +3331,7 @@ export interface Bladeburner { * @param name - Name of action. Must be an exact match. * @returns Number of Bladeburner team members that were assigned to the specified action. */ - getTeamSize(type: string, name: string): number; + getTeamSize(type?: string, name?: string): number; /** * Set team size. From 9a2bb16548ab1e91f11b09c3c5d1aff795e27872 Mon Sep 17 00:00:00 2001 From: catloversg <152669316+catloversg@users.noreply.github.com> Date: Mon, 10 Jun 2024 06:39:56 +0700 Subject: [PATCH 39/43] MISC: Fix wrong help text of cd command (#1376) --- src/Terminal/HelpText.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Terminal/HelpText.ts b/src/Terminal/HelpText.ts index a63d053d6..2de92ba29 100644 --- a/src/Terminal/HelpText.ts +++ b/src/Terminal/HelpText.ts @@ -148,8 +148,7 @@ export const HelpTexts: Record = { cd: [ "Usage: cd [dir]", " ", - "Change to the specified directory. Note that this works even for directories that don't exist. If you ", - "change to a directory that does not exist, it will not be 'created'. Examples:", + "Change to the specified directory. You cannot change to a directory that does not exist. Examples:", " ", " cd scripts/hacking", " ", From 7b3265346d6b8ab22b4f9fda90bd40e80eb803aa Mon Sep 17 00:00:00 2001 From: muesli4brekkies <110121045+muesli4brekkies@users.noreply.github.com> Date: Mon, 10 Jun 2024 00:49:34 +0100 Subject: [PATCH 40/43] ACCESSIBILITY: Wire cutting infil now prints colours of wire along the wire (#1380) --- src/Infiltration/ui/WireCuttingGame.tsx | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/Infiltration/ui/WireCuttingGame.tsx b/src/Infiltration/ui/WireCuttingGame.tsx index f70d82175..425773ea6 100644 --- a/src/Infiltration/ui/WireCuttingGame.tsx +++ b/src/Infiltration/ui/WireCuttingGame.tsx @@ -4,7 +4,6 @@ import { Box, Paper, Typography } from "@mui/material"; import { AugmentationName } from "@enums"; import { Player } from "@player"; import { Settings } from "../../Settings/Settings"; -import { KEY } from "../../utils/helpers/keyCodes"; import { random } from "../utils"; import { interpolate } from "./Difficulty"; import { GameTimer } from "./GameTimer"; @@ -32,19 +31,17 @@ const difficulties: { Impossible: { timer: 4000, wiresmin: 9, wiresmax: 9, rules: 4 }, }; -const types = [KEY.PIPE, KEY.DOT, KEY.FORWARD_SLASH, KEY.HYPHEN, "█", KEY.HASH]; - const colors = ["red", "#FFC107", "blue", "white"]; const colorNames: Record = { - red: "red", - "#FFC107": "yellow", - blue: "blue", - white: "white", + red: "RED", + "#FFC107": "YELLOW", + blue: "BLUE", + white: "WHITE", }; interface Wire { - wireType: string; + wireType: string[]; colors: string[]; } @@ -142,7 +139,7 @@ export function WireCuttingGame({ onSuccess, onFailure, difficulty }: IMinigameP
    ); })} - {new Array(8).fill(0).map((_, i) => ( + {new Array(11).fill(0).map((_, i) => ( {wires.map((wire, j) => { if ((i === 3 || i === 4) && cutWires[j]) { @@ -153,7 +150,7 @@ export function WireCuttingGame({ onSuccess, onFailure, difficulty }: IMinigameP hasAugment && !isCorrectWire ? Settings.theme.disabled : wire.colors[i % wire.colors.length]; return ( - |{wire.wireType}| + |{wire.wireType[i % wire.wireType.length]}| ); })} @@ -172,7 +169,7 @@ function randomPositionQuestion(wires: Wire[]): Question { toString: (): string => { return `Cut wires number ${index + 1}.`; }, - shouldCut: (wire: Wire, i: number): boolean => { + shouldCut: (_wire: Wire, i: number): boolean => { return index === i; }, }; @@ -209,8 +206,9 @@ function generateWires(difficulty: Difficulty): Wire[] { if (Math.random() < 0.15) { wireColors.push(colors[Math.floor(Math.random() * colors.length)]); } + const wireType = [...wireColors.map((color) => colorNames[color]).join("")]; wires.push({ - wireType: types[Math.floor(Math.random() * types.length)], + wireType, colors: wireColors, }); } From f25756916a511e20096b403b6c2c6296b2ac8e9f Mon Sep 17 00:00:00 2001 From: G4mingJon4s <40526179+G4mingJon4s@users.noreply.github.com> Date: Wed, 12 Jun 2024 10:21:27 +0200 Subject: [PATCH 41/43] GANG: added effective text to gang UI gains (#1379) --- src/Gang/ui/GangStats.tsx | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Gang/ui/GangStats.tsx b/src/Gang/ui/GangStats.tsx index f2cbd1cee..67ad3409f 100644 --- a/src/Gang/ui/GangStats.tsx +++ b/src/Gang/ui/GangStats.tsx @@ -14,6 +14,7 @@ import { useGang } from "./Context"; import Typography from "@mui/material/Typography"; import Tooltip from "@mui/material/Tooltip"; import Box from "@mui/material/Box"; +import { GangConstants } from "../data/Constants"; export function GangStats(): React.ReactElement { const gang = useGang(); @@ -40,7 +41,10 @@ export function GangStats(): React.ReactElement { } > - Respect: {formatRespect(gang.respect)} ({formatRespect(5 * gang.respectGainRate)} / sec) + Respect: {formatRespect(gang.respect)} ({formatRespect(5 * gang.respectGainRate)} / sec){" "} + {gang.storedCycles > 2 * GangConstants.maxCyclesToProcess + ? `[Effective Gain: ${formatRespect(5 * gang.respectGainRate * GangConstants.maxCyclesToProcess)} / sec]` + : ""}
    @@ -55,7 +59,10 @@ export function GangStats(): React.ReactElement { } > - Wanted Level: {formatWanted(gang.wanted)} ({formatWanted(5 * gang.wantedGainRate)} / sec) + Wanted Level: {formatWanted(gang.wanted)} ({formatWanted(5 * gang.wantedGainRate)} / sec){" "} + {gang.storedCycles > 2 * GangConstants.maxCyclesToProcess + ? `[Effective Gain: ${formatWanted(5 * gang.wantedGainRate * GangConstants.maxCyclesToProcess)} / sec]` + : ""} @@ -69,7 +76,14 @@ export function GangStats(): React.ReactElement { - Money gain rate: + Money gain rate: {" "} + {gang.storedCycles > 2 * GangConstants.maxCyclesToProcess ? "[Effective Gain:" : ""}{" "} + {gang.storedCycles > 2 * GangConstants.maxCyclesToProcess ? ( + + ) : ( + "" + )} + {gang.storedCycles > 2 * GangConstants.maxCyclesToProcess ? "]" : ""} From ab80ee66c8ac6f8ada5744319ac4f2f0887c247f Mon Sep 17 00:00:00 2001 From: G4mingJon4s <40526179+G4mingJon4s@users.noreply.github.com> Date: Wed, 12 Jun 2024 10:24:10 +0200 Subject: [PATCH 42/43] EDITOR: re-added vim notifications and register view (#1382) --- src/ScriptEditor/ui/StatusBar.tsx | 57 ++++++++++++++++++++++++++++--- src/ui/React/Modal.tsx | 7 ++-- 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/src/ScriptEditor/ui/StatusBar.tsx b/src/ScriptEditor/ui/StatusBar.tsx index 521ad6096..cb98cd280 100644 --- a/src/ScriptEditor/ui/StatusBar.tsx +++ b/src/ScriptEditor/ui/StatusBar.tsx @@ -1,4 +1,5 @@ import { Input, Typography } from "@mui/material"; +import { Modal } from "../../ui/React/Modal"; import { styled } from "@mui/material/styles"; import type { editor } from "monaco-editor"; import React from "react"; @@ -36,6 +37,9 @@ export class StatusBar { showInput = false; inputValue = ""; buffer = ""; + notification = ""; + showRegisters = false; + registers: Record = {}; rerender: () => void; @@ -131,9 +135,39 @@ export class StatusBar { this.node.current = null; }; - // this is used to show notifications. In game, these won't be rendered, so the function is empty. - showNotification(__text: HTMLElement) { - return; + parseRegisters = (html: HTMLElement) => { + this.registers = {}; + + const registerValues = html.innerText.split("\n").filter((s) => s.startsWith('"')); + for (const registerValue of registerValues) { + const name = registerValue[1]; + const value = registerValue.slice(2).trim(); + this.registers[name] = value; + } + console.log(this.registers); + }; + // this is used to show notifications. + // The package passes a new HTMLElement, but we only want to show the text. + showNotification(html: HTMLElement) { + // Registers are too big for the status bar, so we show them in a modal. + if (html.innerText.startsWith("----------Registers----------\n\n") && html.innerText.length > 31) { + this.parseRegisters(html); + this.showRegisters = true; + return this.update(); + } + if (html.innerText.startsWith("----------Registers----------\n\n")) this.notification = "Registers are empty"; + else this.notification = html.innerText; + + const currentNotification = this.notification; + + setTimeout(() => { + // don't update if the notification has changed in the meantime + if (this.notification !== currentNotification) return; + this.notification = ""; + this.update(); + }, 5000); + + this.update(); } update = () => { @@ -177,8 +211,22 @@ export class StatusBar { }; StatusBar(): React.ReactElement { + const registers = Object.entries(this.registers).map(([name, value]) => `[${name}]: ${value.slice(0, 100)}`); + return ( + { + this.showRegisters = false; + this.update(); + }} + removeFocus={false} + > + {registers.map((registers) => ( + {registers} + ))} + {this.mode} {this.showInput && ( @@ -188,9 +236,10 @@ export class StatusBar { onKeyUp={this.keyUp} onKeyDown={this.keyDown} autoFocus={true} + sx={{ mr: 4 }} /> )} - {!this.showInput &&
    } + {this.notification} {this.buffer} diff --git a/src/ui/React/Modal.tsx b/src/ui/React/Modal.tsx index bb1c065e0..2d0995b45 100644 --- a/src/ui/React/Modal.tsx +++ b/src/ui/React/Modal.tsx @@ -43,9 +43,10 @@ interface ModalProps { onClose: () => void; children: React.ReactNode; sx?: SxProps; + removeFocus?: boolean; } -export const Modal = ({ open, onClose, children, sx }: ModalProps): React.ReactElement => { +export const Modal = ({ open, onClose, children, sx, removeFocus = true }: ModalProps): React.ReactElement => { const { classes } = useStyles(); const [content, setContent] = useState(children); useEffect(() => { @@ -55,10 +56,10 @@ export const Modal = ({ open, onClose, children, sx }: ModalProps): React.ReactE return ( Date: Wed, 12 Jun 2024 15:24:57 +0700 Subject: [PATCH 43/43] BLADEBURNER: Fix wrong tooltip description in ActionLevel (#1384) --- src/Bladeburner/ui/ActionLevel.tsx | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/Bladeburner/ui/ActionLevel.tsx b/src/Bladeburner/ui/ActionLevel.tsx index 9210f565a..59e15620f 100644 --- a/src/Bladeburner/ui/ActionLevel.tsx +++ b/src/Bladeburner/ui/ActionLevel.tsx @@ -7,6 +7,7 @@ import ArrowDropUpIcon from "@mui/icons-material/ArrowDropUp"; import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown"; import { BladeburnerConstants } from "../data/Constants"; +import { Contract } from "../Actions"; interface ActionLevelProps { action: LevelableAction; @@ -18,6 +19,11 @@ interface ActionLevelProps { export function ActionLevel({ action, isActive, bladeburner, rerender }: ActionLevelProps): React.ReactElement { const canIncrease = action.level < action.maxLevel; const canDecrease = action.level > 1; + const successesNeededForNextLevel = action.getSuccessesNeededForNextLevel( + action instanceof Contract + ? BladeburnerConstants.ContractSuccessesPerLevel + : BladeburnerConstants.OperationSuccessesPerLevel, + ); function increaseLevel(): void { if (!canIncrease) return; @@ -36,21 +42,7 @@ export function ActionLevel({ action, isActive, bladeburner, rerender }: ActionL return ( - - {action.getSuccessesNeededForNextLevel(BladeburnerConstants.ContractSuccessesPerLevel)} successes needed - for next level - - ) : ( - - {action.getSuccessesNeededForNextLevel(BladeburnerConstants.OperationSuccessesPerLevel)} successes - needed for next level - - ) - } - > + {successesNeededForNextLevel} successes needed for next level}> Level: {action.level} / {action.maxLevel}