mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-16 14:28:36 +02:00
Compare commits
124 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
633da38301 | ||
|
|
3c29757827 | ||
|
|
960fe5aa8b | ||
|
|
922f0bfcc5 | ||
|
|
e66a8e319f | ||
|
|
3fafa23f28 | ||
|
|
b1c1fc24a9 | ||
|
|
32eb6324fd | ||
|
|
61ec7dde80 | ||
|
|
9c9a69f2e2 | ||
|
|
1c20a24079 | ||
|
|
06d742a7f3 | ||
|
|
357cc568e9 | ||
|
|
21e984bda6 | ||
|
|
f620ec889c | ||
|
|
f162faf60a | ||
|
|
031b8b9cbb | ||
|
|
64933419d6 | ||
|
|
b597746343 | ||
|
|
abdf5f52cd | ||
|
|
dc057d05fc | ||
|
|
cef789eb7c | ||
|
|
fd8eae5cf5 | ||
|
|
bf8c15332e | ||
|
|
819f877370 | ||
|
|
67cdd57728 | ||
|
|
5a8f0e99af | ||
|
|
0d8cc54c99 | ||
|
|
c0036b03d4 | ||
|
|
48bebeea2b | ||
|
|
49668f10b2 | ||
|
|
847d45f4f4 | ||
|
|
a62bdcafef | ||
|
|
337fa4e274 | ||
|
|
eff834bfe9 | ||
|
|
99b22a221c | ||
|
|
4382f860db | ||
|
|
7a39a93fa9 | ||
|
|
ceb58bc6b3 | ||
|
|
f6de21ea18 | ||
|
|
4936d14639 | ||
|
|
a780880531 | ||
|
|
e9347fca76 | ||
|
|
417d420793 | ||
|
|
a12056a898 | ||
|
|
bec6e82d7f | ||
|
|
805ca06922 | ||
|
|
344054f10d | ||
|
|
39b18e7659 | ||
|
|
2198a02152 | ||
|
|
e76e254c3e | ||
|
|
ab80ee66c8 | ||
|
|
f25756916a | ||
|
|
7b3265346d | ||
|
|
9a2bb16548 | ||
|
|
ba7d45362f | ||
|
|
995294a770 | ||
|
|
a0fc9cc713 | ||
|
|
a354867fc4 | ||
|
|
b8f03cb50b | ||
|
|
abcd6c545a | ||
|
|
ebf08d5d1f | ||
|
|
8b3206e1c6 | ||
|
|
d9efea0fe6 | ||
|
|
70383d9085 | ||
|
|
16b9ad21ea | ||
|
|
e782b6fd7c | ||
|
|
e64247571d | ||
|
|
7b3cf48453 | ||
|
|
481938a2fb | ||
|
|
463d4cdb1d | ||
|
|
cf48d666f5 | ||
|
|
30a6419b11 | ||
|
|
304a918cc9 | ||
|
|
eeab6df718 | ||
|
|
fe3e8fb348 | ||
|
|
d9e8161a64 | ||
|
|
653d531d0a | ||
|
|
bd5c502f53 | ||
|
|
5f6a5c8785 | ||
|
|
7321d64383 | ||
|
|
2316bf5b69 | ||
|
|
c42d4143c9 | ||
|
|
18ae6ce215 | ||
|
|
101914b660 | ||
|
|
3afafe4454 | ||
|
|
cb92643c7e | ||
|
|
e622b9b904 | ||
|
|
d9f04203cf | ||
|
|
2f7950b49c | ||
|
|
1f08724fea | ||
|
|
a28bb4bd99 | ||
|
|
f40d4f8e92 | ||
|
|
76ce2f9955 | ||
|
|
2ee548a140 | ||
|
|
54d099e552 | ||
|
|
bd6585617c | ||
|
|
f439352438 | ||
|
|
c2a56a6150 | ||
|
|
b8d3109158 | ||
|
|
bed66f980f | ||
|
|
e674a177d6 | ||
|
|
53f187fb89 | ||
|
|
ee4471e22c | ||
|
|
4b5e0b1f6a | ||
|
|
bf5c43daa2 | ||
|
|
30cdaa1a7a | ||
|
|
48a7eb364f | ||
|
|
70521c9156 | ||
|
|
efd4152eed | ||
|
|
23445a917d | ||
|
|
8703da4ab6 | ||
|
|
7f8757b536 | ||
|
|
b42f775493 | ||
|
|
30c04f8152 | ||
|
|
81a707123e | ||
|
|
cfa941ce58 | ||
|
|
c82b2e15a0 | ||
|
|
fe14d4fef3 | ||
|
|
08eb60d21b | ||
|
|
7ed64cbc9c | ||
|
|
819e9f3448 | ||
|
|
7bb36ec111 | ||
|
|
fe7e1c86bc |
93
dist/OFL.txt
vendored
Normal file
93
dist/OFL.txt
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
https://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
30
electron/fileError.html
Normal file
30
electron/fileError.html
Normal file
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Bitburner</title>
|
||||
<style>
|
||||
body {
|
||||
background-color: black;
|
||||
color: #0c0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h1>Attempts to access local files outside the normal game environment will be directed to this file.</h1>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1 +0,0 @@
|
||||
Attempts to access local files outside the normal game environment will be directed to this file.
|
||||
@@ -29,6 +29,7 @@ const debounce = require("lodash/debounce");
|
||||
const Store = require("electron-store");
|
||||
const store = new Store();
|
||||
const path = require("path");
|
||||
const { realpathSync } = require("fs");
|
||||
const { fileURLToPath } = require("url");
|
||||
|
||||
log.transports.file.level = store.get("file-log-level", "info");
|
||||
@@ -201,13 +202,18 @@ app.on("ready", async () => {
|
||||
// Intercept file protocol requests and only let valid requests through
|
||||
protocol.interceptFileProtocol("file", ({ url, method }, callback) => {
|
||||
const filePath = fileURLToPath(url);
|
||||
const relativePath = path.relative(__dirname, filePath);
|
||||
//only provide html files in same directory, or anything in dist
|
||||
if ((method === "GET" && relativePath.startsWith("dist")) || relativePath.match(/^[a-zA-Z-_]*\.html/)) {
|
||||
return callback(filePath);
|
||||
const realPath = realpathSync(filePath);
|
||||
const relativePath = path.relative(__dirname, realPath);
|
||||
// Only allow access to files in "dist" folder or html files in the same directory
|
||||
if (method === "GET" && (relativePath.startsWith("dist") || relativePath.match(/^[a-zA-Z-_]*\.html/))) {
|
||||
callback(realPath);
|
||||
return;
|
||||
}
|
||||
log.error(`Tried to access a page outside the sandbox. Url: ${url}. Method: ${method}.`);
|
||||
callback(path.join(__dirname, "fileError.txt"));
|
||||
log.error(
|
||||
`Tried to access a page outside the sandbox. Url: ${url}. FilePath: ${filePath}. RealPath: ${realPath}.` +
|
||||
` __dirname: ${__dirname}. RelativePath: ${relativePath}. Method: ${method}.`,
|
||||
);
|
||||
callback(path.join(__dirname, "fileError.html"));
|
||||
});
|
||||
|
||||
log.info("Application is ready!");
|
||||
|
||||
4
electron/package-lock.json
generated
4
electron/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "bitburner",
|
||||
"version": "2.6.1",
|
||||
"version": "2.6.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "bitburner",
|
||||
"version": "2.6.1",
|
||||
"version": "2.6.2",
|
||||
"dependencies": {
|
||||
"electron-log": "^4.4.8",
|
||||
"electron-store": "^8.1.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "bitburner",
|
||||
"version": "2.6.1",
|
||||
"version": "2.6.2",
|
||||
"description": "A cyberpunk-themed programming incremental game",
|
||||
"main": "main.js",
|
||||
"author": "Daniel Xie, hydroflame, et al.",
|
||||
|
||||
@@ -192,9 +192,9 @@ async function pushSaveDataToSteamCloud(saveData, currentPlayerId) {
|
||||
*
|
||||
* Instead of implementing it, the old code (encoding in base64) is used here for backward compatibility.
|
||||
*/
|
||||
const content = saveData.toString("base64");
|
||||
log.debug(`Uncompressed: ${saveData.length} bytes`);
|
||||
log.debug(`Compressed: ${content.length} bytes`);
|
||||
const content = Buffer.from(saveData).toString("base64");
|
||||
log.debug(`saveData: ${saveData.length} bytes`);
|
||||
log.debug(`Base64 string of saveData: ${content.length} bytes`);
|
||||
log.debug(`Saving to Steam Cloud as ${steamSaveName}`);
|
||||
|
||||
try {
|
||||
|
||||
11
markdown/bitburner.autocompletedata.enums.md
Normal file
11
markdown/bitburner.autocompletedata.enums.md
Normal file
@@ -0,0 +1,11 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [AutocompleteData](./bitburner.autocompletedata.md) > [enums](./bitburner.autocompletedata.enums.md)
|
||||
|
||||
## AutocompleteData.enums property
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
enums: NSEnums;
|
||||
```
|
||||
@@ -16,6 +16,7 @@ interface AutocompleteData
|
||||
|
||||
| Property | Modifiers | Type | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| [enums](./bitburner.autocompletedata.enums.md) | | [NSEnums](./bitburner.nsenums.md) | |
|
||||
| [scripts](./bitburner.autocompletedata.scripts.md) | | string\[\] | |
|
||||
| [servers](./bitburner.autocompletedata.servers.md) | | string\[\] | |
|
||||
| [txts](./bitburner.autocompletedata.txts.md) | | string\[\] | |
|
||||
|
||||
@@ -9,7 +9,7 @@ Get estimate success chance of an action.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getActionEstimatedSuccessChance(type: string, name: string): [number, number];
|
||||
getActionEstimatedSuccessChance(type: string, name: string, sleeveNumber?: number): [number, number];
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -18,6 +18,7 @@ getActionEstimatedSuccessChance(type: string, name: string): [number, number];
|
||||
| --- | --- | --- |
|
||||
| type | string | Type of action. |
|
||||
| name | string | Name of action. Must be an exact match. |
|
||||
| sleeveNumber | number | _(Optional)_ Optional. Index of the sleeve to retrieve information. |
|
||||
|
||||
**Returns:**
|
||||
|
||||
|
||||
@@ -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:**
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ You have to be employed in the Bladeburner division and be in BitNode-7 or have
|
||||
| [getActionCountRemaining(type, name)](./bitburner.bladeburner.getactioncountremaining.md) | Get action count remaining. |
|
||||
| [getActionCurrentLevel(type, name)](./bitburner.bladeburner.getactioncurrentlevel.md) | Get the current level of an action. |
|
||||
| [getActionCurrentTime()](./bitburner.bladeburner.getactioncurrenttime.md) | Get the time elapsed on current action. |
|
||||
| [getActionEstimatedSuccessChance(type, name)](./bitburner.bladeburner.getactionestimatedsuccesschance.md) | Get estimate success chance of an action. |
|
||||
| [getActionEstimatedSuccessChance(type, name, sleeveNumber)](./bitburner.bladeburner.getactionestimatedsuccesschance.md) | Get estimate success chance of an action. |
|
||||
| [getActionMaxLevel(type, name)](./bitburner.bladeburner.getactionmaxlevel.md) | Get the maximum level of an action. |
|
||||
| [getActionRepGain(type, name, level)](./bitburner.bladeburner.getactionrepgain.md) | Get the reputation gain of an action. |
|
||||
| [getActionSuccesses(type, name)](./bitburner.bladeburner.getactionsuccesses.md) | Get action successes. |
|
||||
|
||||
@@ -36,9 +36,11 @@ Attempts to solve the Coding Contract with the provided solution.
|
||||
|
||||
|
||||
```js
|
||||
const reward = codingcontract.attempt(yourSolution, filename, hostname);
|
||||
const reward = ns.codingcontract.attempt(yourSolution, filename, hostname);
|
||||
if (reward) {
|
||||
ns.tprint(`Contract solved successfully! Reward: ${reward}`)
|
||||
} else ns.tprint("Failed to solve contract.")
|
||||
ns.tprint(`Contract solved successfully! Reward: ${reward}`);
|
||||
} else {
|
||||
ns.tprint("Failed to solve contract.");
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ The amount of real time spent asleep between updates can vary due to "bonus time
|
||||
```js
|
||||
while (true) {
|
||||
const prevState = await ns.corporation.nextUpdate();
|
||||
const nextState = ns.corporation.getCorporation().state;
|
||||
const nextState = ns.corporation.getCorporation().nextState;
|
||||
ns.print(`Corporation finished with ${prevState}, next will be ${nextState}.`);
|
||||
// Manage the Corporation
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
21
markdown/bitburner.go.getmovehistory.md
Normal file
21
markdown/bitburner.go.getmovehistory.md
Normal file
@@ -0,0 +1,21 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[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:
|
||||
|
||||
\[<br/> "XX.O.",<br/> "X..OO",<br/> ".XO..",<br/> "XXO.\#",<br/> ".XO.\#",<br/> \]
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getMoveHistory(): string[][];
|
||||
```
|
||||
**Returns:**
|
||||
|
||||
string\[\]\[\]
|
||||
|
||||
@@ -30,7 +30,7 @@ makeMove(
|
||||
|
||||
Promise<{ type: "move" \| "pass" \| "gameOver"; x: number \| null; y: number \| null; }>
|
||||
|
||||
a promise that contains if your move was valid and successful, the opponent move's x and y coordinates (or pass) in response, or an indication if the game has ended
|
||||
a promise that contains the opponent move's x and y coordinates (or pass) in response, or an indication if the game has ended
|
||||
|
||||
## Remarks
|
||||
|
||||
|
||||
@@ -26,9 +26,10 @@ export interface Go
|
||||
| [getBoardState()](./bitburner.go.getboardstate.md) | <p>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.)</p><p>For example, a 5x5 board might look like this:</p><p>\[<br/> "XX.O.",<br/> "X..OO",<br/> ".XO..",<br/> "XXO.\#",<br/> ".XO.\#",<br/> \]</p><p>Each string represents a vertical column on the board, and each character in the string represents a point.</p><p>Traditional notation for Go is e.g. "B,1" referring to second ("B") column, first rank. This is the equivalent of index \[1\]\[0\].</p><p>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.</p> |
|
||||
| [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) | <p>Returns all the prior moves in the current game, as an array of simple board states.</p><p>For example, a single 5x5 prior move board might look like this:</p><p>\[<br/> "XX.O.",<br/> "X..OO",<br/> ".XO..",<br/> "XXO.\#",<br/> ".XO.\#",<br/> \]</p> |
|
||||
| [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. |
|
||||
| [passTurn()](./bitburner.go.passturn.md) | <p>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.</p><p>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.</p> |
|
||||
| [resetBoardState(opponent, boardSize)](./bitburner.go.resetboardstate.md) | <p>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.</p><p>Note that some factions will have a few routers on the subnet at this state.</p><p>opponent is "Netburners" or "Slum Snakes" or "The Black Hand" or "Tetrads" or "Daedalus" or "Illuminati" or "????????????",</p> |
|
||||
| [resetBoardState(opponent, boardSize)](./bitburner.go.resetboardstate.md) | <p>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.</p><p>Note that some factions will have a few routers on the subnet at this state.</p><p>opponent is "Netburners" or "Slum Snakes" or "The Black Hand" or "Tetrads" or "Daedalus" or "Illuminati" or "????????????" or "No AI",</p> |
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ passTurn(): Promise<{
|
||||
|
||||
Promise<{ type: "move" \| "pass" \| "gameOver"; x: number \| null; y: number \| null; }>
|
||||
|
||||
a promise that contains if your move was valid and successful, the opponent move's x and y coordinates (or pass) in response, or an indication if the game has ended
|
||||
a promise that contains the opponent move's x and y coordinates (or pass) in response, or an indication if the game has ended
|
||||
|
||||
## Remarks
|
||||
|
||||
|
||||
@@ -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:**
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Grafting.getAugmentationGraftTime() method
|
||||
|
||||
Retrieves the time required to graft an aug.
|
||||
Retrieves the time required to graft an aug. Do not use this value to determine when the ongoing grafting finishes. The ongoing grafting is affected by current intelligence level and focus bonus. You should use [waitForOngoingGrafting](./bitburner.grafting.waitforongoinggrafting.md) for that purpose.
|
||||
|
||||
**Signature:**
|
||||
|
||||
@@ -22,7 +22,7 @@ getAugmentationGraftTime(augName: string): number;
|
||||
|
||||
number
|
||||
|
||||
The time required, in millis, to graft the named augmentation.
|
||||
The time required, in milliseconds, to graft the named augmentation.
|
||||
|
||||
## Exceptions
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Grafting.graftAugmentation() method
|
||||
|
||||
Begins grafting the named aug. You must be in New Tokyo to use this.
|
||||
Begins grafting the named aug. You must be in New Tokyo to use this. When you call this API, the current work (grafting or other actions) will be canceled.
|
||||
|
||||
**Signature:**
|
||||
|
||||
|
||||
@@ -21,7 +21,8 @@ This API requires Source-File 10 to use.
|
||||
| Method | Description |
|
||||
| --- | --- |
|
||||
| [getAugmentationGraftPrice(augName)](./bitburner.grafting.getaugmentationgraftprice.md) | Retrieve the grafting cost of an aug. |
|
||||
| [getAugmentationGraftTime(augName)](./bitburner.grafting.getaugmentationgrafttime.md) | Retrieves the time required to graft an aug. |
|
||||
| [getAugmentationGraftTime(augName)](./bitburner.grafting.getaugmentationgrafttime.md) | Retrieves the time required to graft an aug. Do not use this value to determine when the ongoing grafting finishes. The ongoing grafting is affected by current intelligence level and focus bonus. You should use [waitForOngoingGrafting](./bitburner.grafting.waitforongoinggrafting.md) for that purpose. |
|
||||
| [getGraftableAugmentations()](./bitburner.grafting.getgraftableaugmentations.md) | Retrieves a list of Augmentations that can be grafted. |
|
||||
| [graftAugmentation(augName, focus)](./bitburner.grafting.graftaugmentation.md) | Begins grafting the named aug. You must be in New Tokyo to use this. |
|
||||
| [graftAugmentation(augName, focus)](./bitburner.grafting.graftaugmentation.md) | Begins grafting the named aug. You must be in New Tokyo to use this. When you call this API, the current work (grafting or other actions) will be canceled. |
|
||||
| [waitForOngoingGrafting()](./bitburner.grafting.waitforongoinggrafting.md) | Wait until the ongoing grafting finishes or is canceled. |
|
||||
|
||||
|
||||
23
markdown/bitburner.grafting.waitforongoinggrafting.md
Normal file
23
markdown/bitburner.grafting.waitforongoinggrafting.md
Normal file
@@ -0,0 +1,23 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Grafting](./bitburner.grafting.md) > [waitForOngoingGrafting](./bitburner.grafting.waitforongoinggrafting.md)
|
||||
|
||||
## Grafting.waitForOngoingGrafting() method
|
||||
|
||||
Wait until the ongoing grafting finishes or is canceled.
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
waitForOngoingGrafting(): Promise<void>;
|
||||
```
|
||||
**Returns:**
|
||||
|
||||
Promise<void>
|
||||
|
||||
A promise that resolves when the current grafting finishes or is canceled. If there is no current work, the promise resolves immediately. If the current work is not a grafting work, the promise rejects immediately.
|
||||
|
||||
## Remarks
|
||||
|
||||
RAM cost: 1 GB
|
||||
|
||||
11
markdown/bitburner.graftingtask.completion.md
Normal file
11
markdown/bitburner.graftingtask.completion.md
Normal file
@@ -0,0 +1,11 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [GraftingTask](./bitburner.graftingtask.md) > [completion](./bitburner.graftingtask.completion.md)
|
||||
|
||||
## GraftingTask.completion property
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
completion: Promise<void>;
|
||||
```
|
||||
@@ -21,6 +21,7 @@ An object representing the current grafting status
|
||||
| Property | Modifiers | Type | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| [augmentation](./bitburner.graftingtask.augmentation.md) | | string | |
|
||||
| [completion](./bitburner.graftingtask.completion.md) | | Promise<void> | |
|
||||
| [cyclesWorked](./bitburner.graftingtask.cyclesworked.md) | | number | |
|
||||
| [type](./bitburner.graftingtask.type.md) | | "GRAFTING" | |
|
||||
|
||||
|
||||
@@ -9,14 +9,14 @@ Get all infiltrations with difficulty, location and rewards.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getInfiltration(location: string): InfiltrationLocation;
|
||||
getInfiltration(location: LocationName | `${LocationName}`): InfiltrationLocation;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| location | string | |
|
||||
| location | [LocationName](./bitburner.locationname.md) \| \`${[LocationName](./bitburner.locationname.md)<!-- -->}\` | |
|
||||
|
||||
**Returns:**
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## NS.disableLog() method
|
||||
|
||||
Disables logging for the given function.
|
||||
Disables logging for the given NS function.
|
||||
|
||||
**Signature:**
|
||||
|
||||
@@ -16,7 +16,7 @@ disableLog(fn: string): void;
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| fn | string | Name of function for which to disable logging. |
|
||||
| fn | string | Name of the NS function for which to disable logging. |
|
||||
|
||||
**Returns:**
|
||||
|
||||
@@ -30,3 +30,11 @@ Logging can be disabled for all functions by passing `ALL` as the argument.
|
||||
|
||||
For specific interfaces, use the form "namespace.functionName". (e.g. "ui.setTheme")
|
||||
|
||||
## Example
|
||||
|
||||
|
||||
```js
|
||||
ns.disableLog("hack"); // Disable logging for `ns.hack()`
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## NS.enableLog() method
|
||||
|
||||
Enable logging for a certain function.
|
||||
Enables logging for the given NS function.
|
||||
|
||||
**Signature:**
|
||||
|
||||
@@ -16,7 +16,7 @@ enableLog(fn: string): void;
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| fn | string | Name of function for which to enable logging. |
|
||||
| fn | string | Name of the NS function for which to enable logging. |
|
||||
|
||||
**Returns:**
|
||||
|
||||
@@ -26,5 +26,13 @@ void
|
||||
|
||||
RAM cost: 0 GB
|
||||
|
||||
Re-enables logging for the given function. If `ALL` is passed into this function as an argument, then it will revert the effects of disableLog(`ALL`<!-- -->).
|
||||
Re-enables logging for the given function. If `ALL` is passed into this function as an argument, it will revert the effect of disableLog("ALL").
|
||||
|
||||
## Example
|
||||
|
||||
|
||||
```js
|
||||
ns.enableLog("hack"); // Enable logging for `ns.hack()`
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -49,19 +49,19 @@ export async function main(ns) {
|
||||
ns.tprint(data);
|
||||
}
|
||||
|
||||
// [home ~/]> run example.js
|
||||
// [home /]> run example.js
|
||||
// {"_":[],"delay":0,"server":"foodnstuff","exclude":[],"help":false,"v":false}
|
||||
// [home ~/]> run example.js --delay 3000
|
||||
// [home /]> run example.js --delay 3000
|
||||
// {"_":[],"delay":3000,"server":"foodnstuff","exclude":[],"help":false,"v":false}
|
||||
// [home ~/]> run example.js --delay 3000 --server harakiri-sushi
|
||||
// [home /]> run example.js --delay 3000 --server harakiri-sushi
|
||||
// {"_":[],"delay":3000,"server":"harakiri-sushi","exclude":[],"help":false,"v":false}
|
||||
// [home ~/]> run example.js --delay 3000 --server harakiri-sushi hello world
|
||||
// [home /]> run example.js --delay 3000 --server harakiri-sushi hello world
|
||||
// {"_":["hello","world"],"delay":3000,"server":"harakiri-sushi","exclude":[],"help":false,"v":false}
|
||||
// [home ~/]> run example.js --delay 3000 --server harakiri-sushi hello world --exclude a --exclude b
|
||||
// [home /]> run example.js --delay 3000 --server harakiri-sushi hello world --exclude a --exclude b
|
||||
// {"_":["hello","world"],"delay":3000,"server":"harakiri-sushi","exclude":["a","b"],"help":false,"v":false}
|
||||
// [home ~/]> run example.js --help
|
||||
// [home /]> run example.js --help
|
||||
// {"_":[],"delay":0,"server":"foodnstuff","exclude":[],"help":true,"v":false}
|
||||
// [home ~/]> run example.js -v
|
||||
// [home /]> run example.js -v
|
||||
// {"_":[],"delay":0,"server":"foodnstuff","exclude":[],"help":false,"v":true}
|
||||
```
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ Returns an object containing the Player’s hacking related multipliers. These m
|
||||
|
||||
```js
|
||||
const mults = ns.getHackingMultipliers();
|
||||
print(`chance: ${mults.chance}`);
|
||||
print(`growth: ${mults.growth}`);
|
||||
ns.tprint(`chance: ${mults.chance}`);
|
||||
ns.tprint(`growth: ${mults.growth}`);
|
||||
```
|
||||
|
||||
|
||||
@@ -36,6 +36,6 @@ Returns the cost to purchase a server with the specified amount of ram.
|
||||
```js
|
||||
const ram = 2 ** 20;
|
||||
const cost = ns.getPurchasedServerCost(ram);
|
||||
ns.tprint(`A purchased server with ${ns.formatRam(ram)} costs ${ns.formatMoney(cost)}`);
|
||||
ns.tprint(`A purchased server with ${ns.formatRam(ram)} costs $${ns.formatNumber(cost)}`);
|
||||
```
|
||||
|
||||
|
||||
@@ -26,10 +26,10 @@ The most recently killed script is the first element in the array. Note that the
|
||||
## Example
|
||||
|
||||
|
||||
```ts
|
||||
```js
|
||||
let recentScripts = ns.getRecentScripts();
|
||||
let mostRecent = recentScripts.shift()
|
||||
let mostRecent = recentScripts.shift();
|
||||
if (mostRecent)
|
||||
ns.tprint(mostRecent.logs.join('\n'))
|
||||
ns.tprint(mostRecent.logs.join('\n'));
|
||||
```
|
||||
|
||||
|
||||
@@ -26,6 +26,6 @@ RAM cost: 1 GB
|
||||
const resetInfo = ns.getResetInfo();
|
||||
const lastAugReset = resetInfo.lastAugReset;
|
||||
ns.tprint(`The last augmentation reset was: ${new Date(lastAugReset)}`);
|
||||
ns.tprint(`It has been ${Date.now() - lastAugReset}ms since the last augmentation reset.`);
|
||||
ns.tprint(`It has been ${Date.now() - lastAugReset} ms since the last augmentation reset.`);
|
||||
```
|
||||
|
||||
|
||||
@@ -54,6 +54,6 @@ The grow() command requires root access to the target server, but there is no re
|
||||
|
||||
```js
|
||||
let currentMoney = ns.getServerMoneyAvailable("n00dles");
|
||||
currentMoney *= await ns.grow("foodnstuff");
|
||||
currentMoney *= await ns.grow("n00dles");
|
||||
```
|
||||
|
||||
|
||||
@@ -34,12 +34,12 @@ This function returns the decimal number of script threads you need when running
|
||||
## Example
|
||||
|
||||
|
||||
```ts
|
||||
```js
|
||||
// Calculate threadcount of a single hack that would take $100k from n00dles
|
||||
const hackThreads = hackAnalyzeThreads("n00dles", 1e5);
|
||||
const hackThreads = ns.hackAnalyzeThreads("n00dles", 1e5);
|
||||
|
||||
// Launching a script requires an integer thread count. The below would take less than the targeted $100k.
|
||||
ns.run("noodleHack.js", Math.floor(hackThreads))
|
||||
ns.run("noodleHack.js", Math.floor(hackThreads));
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## NS.isLogEnabled() method
|
||||
|
||||
Checks the status of the logging for the given function.
|
||||
Checks the status of the logging for the given NS function.
|
||||
|
||||
**Signature:**
|
||||
|
||||
@@ -22,9 +22,17 @@ isLogEnabled(fn: string): boolean;
|
||||
|
||||
boolean
|
||||
|
||||
Returns a boolean indicating whether or not logging is enabled for that function (or `ALL`<!-- -->).
|
||||
Returns a boolean indicating whether or not logging is enabled for that NS function (or `ALL`<!-- -->).
|
||||
|
||||
## Remarks
|
||||
|
||||
RAM cost: 0 GB
|
||||
|
||||
## Example
|
||||
|
||||
|
||||
```js
|
||||
ns.print(ns.isLogEnabled("hack")); // Check if logging is enabled for `ns.hack()`
|
||||
|
||||
```
|
||||
|
||||
|
||||
@@ -63,8 +63,8 @@ export async function main(ns) {
|
||||
| [clearPort(portNumber)](./bitburner.ns.clearport.md) | Clear data from a port. |
|
||||
| [closeTail(pid)](./bitburner.ns.closetail.md) | Close the tail window of a script. |
|
||||
| [deleteServer(host)](./bitburner.ns.deleteserver.md) | Delete a purchased server. |
|
||||
| [disableLog(fn)](./bitburner.ns.disablelog.md) | Disables logging for the given function. |
|
||||
| [enableLog(fn)](./bitburner.ns.enablelog.md) | Enable logging for a certain function. |
|
||||
| [disableLog(fn)](./bitburner.ns.disablelog.md) | Disables logging for the given NS function. |
|
||||
| [enableLog(fn)](./bitburner.ns.enablelog.md) | Enables logging for the given NS function. |
|
||||
| [exec(script, hostname, threadOrOptions, args)](./bitburner.ns.exec.md) | Start another script on any server. |
|
||||
| [exit()](./bitburner.ns.exit.md) | Terminates the current script immediately. |
|
||||
| [fileExists(filename, host)](./bitburner.ns.fileexists.md) | Check if a file exists. |
|
||||
@@ -125,7 +125,7 @@ export async function main(ns) {
|
||||
| [hasRootAccess(host)](./bitburner.ns.hasrootaccess.md) | Check if you have root access on a server. |
|
||||
| [hasTorRouter()](./bitburner.ns.hastorrouter.md) | Returns whether the player has access to the darkweb. |
|
||||
| [httpworm(host)](./bitburner.ns.httpworm.md) | Runs HTTPWorm.exe on a server. |
|
||||
| [isLogEnabled(fn)](./bitburner.ns.islogenabled.md) | Checks the status of the logging for the given function. |
|
||||
| [isLogEnabled(fn)](./bitburner.ns.islogenabled.md) | Checks the status of the logging for the given NS function. |
|
||||
| [isRunning(script, host, args)](./bitburner.ns.isrunning.md) | Check if a script is running. |
|
||||
| [kill(pid)](./bitburner.ns.kill.md) | Terminate the script with the provided PID. |
|
||||
| [kill(filename, hostname, args)](./bitburner.ns.kill_1.md) | Terminate the script(s) with the provided filename, hostname, and script arguments. |
|
||||
@@ -143,6 +143,7 @@ export async function main(ns) {
|
||||
| [prompt(txt, options)](./bitburner.ns.prompt.md) | Prompt the player with an input modal. |
|
||||
| [ps(host)](./bitburner.ns.ps.md) | List running scripts on a server. |
|
||||
| [purchaseServer(hostname, ram)](./bitburner.ns.purchaseserver.md) | Purchase a server. |
|
||||
| [ramOverride(ram)](./bitburner.ns.ramoverride.md) | Change the current static RAM allocation of the script. |
|
||||
| [read(filename)](./bitburner.ns.read.md) | Read content of a file. |
|
||||
| [readPort(portNumber)](./bitburner.ns.readport.md) | Read data from a port. |
|
||||
| [relaysmtp(host)](./bitburner.ns.relaysmtp.md) | Runs relaySMTP.exe on a server. |
|
||||
|
||||
@@ -42,7 +42,7 @@ ns.printf("I'm %d seconds old.", age);
|
||||
ns.printf("My age in binary is %b.", age);
|
||||
ns.printf("My age in scientific notation is %e.", age);
|
||||
ns.printf("In %d seconds, I'll be %s.", 6, "Byte");
|
||||
ns.printf("Am I a nibble? %t", (4 == age));
|
||||
ns.printf("Am I a nibble? %t", (4 === age));
|
||||
ns.tail();
|
||||
```
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ Returns an array with general information about all scripts running on the speci
|
||||
|
||||
```js
|
||||
const ps = ns.ps("home");
|
||||
for (let script of ps) {
|
||||
for (const script of ps) {
|
||||
ns.tprint(`${script.filename} ${script.threads}`);
|
||||
ns.tprint(script.args);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ Returns the hostname of the newly purchased server as a string. If the function
|
||||
// Attempt to purchase 5 servers with 64GB of ram each
|
||||
const ram = 64;
|
||||
const prefix = "pserv-";
|
||||
for (i = 0; i < 5; ++i) {
|
||||
for (let i = 0; i < 5; ++i) {
|
||||
ns.purchaseServer(prefix + i, ram);
|
||||
}
|
||||
```
|
||||
|
||||
34
markdown/bitburner.ns.ramoverride.md
Normal file
34
markdown/bitburner.ns.ramoverride.md
Normal file
@@ -0,0 +1,34 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [NS](./bitburner.ns.md) > [ramOverride](./bitburner.ns.ramoverride.md)
|
||||
|
||||
## NS.ramOverride() method
|
||||
|
||||
Change the current static RAM allocation of the script.
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
ramOverride(ram?: number): number;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| ram | number | _(Optional)_ The new RAM limit to set. |
|
||||
|
||||
**Returns:**
|
||||
|
||||
number
|
||||
|
||||
The new static RAM limit, which will be the old one if it wasn't changed. This means you can use no parameters to check the current ram limit.
|
||||
|
||||
## Remarks
|
||||
|
||||
RAM cost: 0 GB
|
||||
|
||||
This acts analagously to the ramOverride parameter in runOptions, but for changing RAM in the current running script. The static RAM allocation (the amount of RAM used by ONE thread) will be adjusted to the given value, if possible. This can fail if the number is less than the current dynamic RAM limit, or if adjusting upward would require more RAM than is available on the server.
|
||||
|
||||
RAM usage will be rounded to the nearest hundredth of a GB, which is the granularity of all RAM calculations.
|
||||
|
||||
@@ -51,6 +51,6 @@ ns.run("foo.js");
|
||||
ns.run("foo.js", {threads: 5});
|
||||
|
||||
//This next example will run ‘foo.js’ single-threaded, and will pass the string ‘foodnstuff’ into the script as an argument:
|
||||
ns.run("foo.js", 1, 'foodnstuff');
|
||||
ns.run("foo.js", 1, "foodnstuff");
|
||||
```
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ RAM cost: 0 GB
|
||||
|
||||
```js
|
||||
// This will count from 1 to 10 in your terminal, with one number every 5 seconds
|
||||
for (var i = 1; i <= 10; i++) {
|
||||
for (let i = 1; i <= 10; ++i) {
|
||||
ns.tprint(i);
|
||||
await ns.sleep(5000);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ RAM cost: 2 GB
|
||||
|
||||
Terminates the current script, and then after a defined delay it will execute the newly-specified script. The purpose of this function is to execute a new script without being constrained by the RAM usage of the current one. This function can only be used to run scripts on the local server.
|
||||
|
||||
The delay specified can be 0; in this case the new script will synchronously replace the old one. (There will not be any opportunity for other scripts to use up the RAM in-between.)
|
||||
|
||||
Because this function immediately terminates the script, it does not have a return value.
|
||||
|
||||
Running this function with 0 or fewer threads will cause a runtime error.
|
||||
@@ -39,6 +41,6 @@ Running this function with 0 or fewer threads will cause a runtime error.
|
||||
|
||||
```js
|
||||
//The following example will execute the script ‘foo.js’ with 10 threads, in 500 milliseconds and the arguments ‘foodnstuff’ and 90:
|
||||
ns.spawn('foo.js', {threads: 10, spawnDelay: 500}, 'foodnstuff', 90);
|
||||
ns.spawn("foo.js", {threads: 10, spawnDelay: 500}, "foodnstuff", 90);
|
||||
```
|
||||
|
||||
|
||||
@@ -31,3 +31,5 @@ RAM cost: 0 GB
|
||||
|
||||
Write data to the given Netscript port.
|
||||
|
||||
There is a limit on the maximum number of ports, but you won't reach that limit in normal situations. If you do, it usually means that there is a bug in your script that leaks port data. A port is freed when it does not have any data in its underlying queue. `ns.clearPort` deletes all data on a port. `ns.readPort` reads the first element in the port's queue, then removes it from the queue.
|
||||
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
location: string;
|
||||
location: LocationName;
|
||||
```
|
||||
|
||||
@@ -20,7 +20,7 @@ interface Player extends Person
|
||||
| [factions](./bitburner.player.factions.md) | | string\[\] | |
|
||||
| [jobs](./bitburner.player.jobs.md) | | Partial<Record<[CompanyName](./bitburner.companyname.md)<!-- -->, [JobName](./bitburner.jobname.md)<!-- -->>> | |
|
||||
| [karma](./bitburner.player.karma.md) | | number | |
|
||||
| [location](./bitburner.player.location.md) | | string | |
|
||||
| [location](./bitburner.player.location.md) | | [LocationName](./bitburner.locationname.md) | |
|
||||
| [money](./bitburner.player.money.md) | | number | |
|
||||
| [numPeopleKilled](./bitburner.player.numpeoplekilled.md) | | number | |
|
||||
| [totalPlaytime](./bitburner.player.totalplaytime.md) | | number | |
|
||||
|
||||
15
markdown/bitburner.runningscript.dynamicramusage.md
Normal file
15
markdown/bitburner.runningscript.dynamicramusage.md
Normal file
@@ -0,0 +1,15 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [RunningScript](./bitburner.runningscript.md) > [dynamicRamUsage](./bitburner.runningscript.dynamicramusage.md)
|
||||
|
||||
## RunningScript.dynamicRamUsage property
|
||||
|
||||
The dynamic RAM usage of (one thread of) this script instance. Does not affect overall RAM consumption (ramUsage is for that), but rather shows how much of the reserved RAM is currently in use via all the ns functions the script has called. Initially 1.6GB, this increases as new functions are called.
|
||||
|
||||
Only set for scripts that are still running.
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
dynamicRamUsage: number | undefined;
|
||||
```
|
||||
@@ -16,6 +16,7 @@ interface RunningScript
|
||||
| Property | Modifiers | Type | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| [args](./bitburner.runningscript.args.md) | | [ScriptArg](./bitburner.scriptarg.md)<!-- -->\[\] | Arguments the script was called with |
|
||||
| [dynamicRamUsage](./bitburner.runningscript.dynamicramusage.md) | | number \| undefined | <p>The dynamic RAM usage of (one thread of) this script instance. Does not affect overall RAM consumption (ramUsage is for that), but rather shows how much of the reserved RAM is currently in use via all the ns functions the script has called. Initially 1.6GB, this increases as new functions are called.</p><p>Only set for scripts that are still running.</p> |
|
||||
| [filename](./bitburner.runningscript.filename.md) | | string | Filename of the script |
|
||||
| [logs](./bitburner.runningscript.logs.md) | | string\[\] | Script logs as an array. The newest log entries are at the bottom. Timestamps, if enabled, are placed inside <code>[brackets]</code> at the start of each line. |
|
||||
| [offlineExpGained](./bitburner.runningscript.offlineexpgained.md) | | number | Total amount of hacking experience earned from this script when offline |
|
||||
@@ -25,7 +26,7 @@ interface RunningScript
|
||||
| [onlineMoneyMade](./bitburner.runningscript.onlinemoneymade.md) | | number | Total amount of money made by this script when online |
|
||||
| [onlineRunningTime](./bitburner.runningscript.onlinerunningtime.md) | | number | Number of seconds that this script has been running online |
|
||||
| [pid](./bitburner.runningscript.pid.md) | | number | Process ID. Must be an integer |
|
||||
| [ramUsage](./bitburner.runningscript.ramusage.md) | | number | How much RAM this script uses for ONE thread |
|
||||
| [ramUsage](./bitburner.runningscript.ramusage.md) | | number | How much RAM this script uses for ONE thread. Also known as "static RAM usage," this value does not change once the script is started, unless you call ns.ramOverride(). |
|
||||
| [server](./bitburner.runningscript.server.md) | | string | Hostname of the server on which this script runs |
|
||||
| [tailProperties](./bitburner.runningscript.tailproperties.md) | | [TailProperties](./bitburner.tailproperties.md) \| null | Properties of the tail window, or null if it is not shown |
|
||||
| [temporary](./bitburner.runningscript.temporary.md) | | boolean | Whether this RunningScript is excluded from saves |
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## RunningScript.ramUsage property
|
||||
|
||||
How much RAM this script uses for ONE thread
|
||||
How much RAM this script uses for ONE thread. Also known as "static RAM usage," this value does not change once the script is started, unless you call ns.ramOverride().
|
||||
|
||||
**Signature:**
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ interface RunOptions
|
||||
| Property | Modifiers | Type | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| [preventDuplicates?](./bitburner.runoptions.preventduplicates.md) | | boolean | _(Optional)_ Should we fail to run if another instance is running with the exact same arguments? This used to be the default behavior, now defaults to false. |
|
||||
| [ramOverride?](./bitburner.runoptions.ramoverride.md) | | number | <p>_(Optional)_ The RAM allocation to launch each thread of the script with.</p><p>Lowering this will <i>not</i> automatically let you get away with using less RAM: the dynamic RAM check enforces that all [NS](./bitburner.ns.md) functions actually called incur their cost. However, if you know that certain functions that are statically present (and thus included in the static RAM cost) will never be called in a particular circumstance, you can use this to avoid paying for them.</p><p>You can also use this to <i>increase</i> the RAM if the static RAM checker has missed functions that you need to call.</p><p>Must be greater-or-equal to the base RAM cost. Defaults to the statically calculated cost.</p> |
|
||||
| [ramOverride?](./bitburner.runoptions.ramoverride.md) | | number | <p>_(Optional)_ The RAM allocation to launch each thread of the script with.</p><p>Lowering this will <i>not</i> automatically let you get away with using less RAM: the dynamic RAM check enforces that all [NS](./bitburner.ns.md) functions actually called incur their cost. However, if you know that certain functions that are statically present (and thus included in the static RAM cost) will never be called in a particular circumstance, you can use this to avoid paying for them.</p><p>You can also use this to <i>increase</i> the RAM if the static RAM checker has missed functions that you need to call.</p><p>Must be greater-or-equal to the base RAM cost. Will be rounded to the nearest hundredth-of-a-GB, which is the granularity of all RAM calculations. Defaults to the statically calculated cost.</p> |
|
||||
| [temporary?](./bitburner.runoptions.temporary.md) | | boolean | _(Optional)_ Whether this script is excluded from saves, defaults to false |
|
||||
| [threads?](./bitburner.runoptions.threads.md) | | number | _(Optional)_ Number of threads that the script will run with, defaults to 1 |
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ Lowering this will <i>not</i> automatically let you get away with using less RAM
|
||||
|
||||
You can also use this to <i>increase</i> the RAM if the static RAM checker has missed functions that you need to call.
|
||||
|
||||
Must be greater-or-equal to the base RAM cost. Defaults to the statically calculated cost.
|
||||
Must be greater-or-equal to the base RAM cost. Will be rounded to the nearest hundredth-of-a-GB, which is the granularity of all RAM calculations. Defaults to the statically calculated cost.
|
||||
|
||||
**Signature:**
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ Note that creating a program using this function has the same hacking level requ
|
||||
|
||||
```js
|
||||
const programName = "BruteSSH.exe";
|
||||
const success = ns.createProgram(programName);
|
||||
if (!success) ns.tprint("ERROR: Failed to start working on ${programName}")
|
||||
const success = ns.singularity.createProgram(programName);
|
||||
if (!success) ns.tprint(`ERROR: Failed to start working on ${programName}`);
|
||||
```
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ If the program does not exist, an error is thrown.
|
||||
|
||||
```js
|
||||
const programName = "BruteSSH.exe";
|
||||
const cost = ns.getDarkwebProgramCost(programName);
|
||||
if (cost > 0) ns.tprint(`${programName} costs ${ns.formatMoney(cost)}`);
|
||||
const cost = ns.singularity.getDarkwebProgramCost(programName);
|
||||
if (cost > 0) ns.tprint(`${programName} costs $${ns.formatNumber(cost)}`);
|
||||
```
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ This function allows the player to get a list of programs available for purchase
|
||||
|
||||
|
||||
```js
|
||||
const programs = ns.getDarkwebPrograms();
|
||||
ns.tprint(`Available programs are: ${programs.split(", ")}`);
|
||||
const programs = ns.singularity.getDarkwebPrograms();
|
||||
ns.tprint(`Available programs are: ${programs}`);
|
||||
```
|
||||
|
||||
|
||||
@@ -32,7 +32,8 @@ RAM cost: 3 GB \* 16/4/1
|
||||
|
||||
|
||||
```js
|
||||
ns.singularity.getFactionInviteRequirements("The Syndicate")
|
||||
ns.singularity.getFactionInviteRequirements("The Syndicate");
|
||||
|
||||
[
|
||||
{ "type": "someCondition", "conditions": [
|
||||
{ "type": "city", "city": "Aevum" },
|
||||
@@ -49,7 +50,10 @@ ns.singularity.getFactionInviteRequirements("The Syndicate")
|
||||
},
|
||||
{ "type": "money", "money": 10000000 },
|
||||
{ "type": "skills", "skills": { "hacking": 200 } },
|
||||
{ "type": "skills", "skills": { "strength": 200, "defense": 200, "dexterity": 200, "agility": 200 } },
|
||||
{ "type": "skills", "skills": { "strength": 200 } },
|
||||
{ "type": "skills", "skills": { "defense": 200 } },
|
||||
{ "type": "skills", "skills": { "dexterity": 200 } },
|
||||
{ "type": "skills", "skills": { "agility": 200 } },
|
||||
{ "type": "karma", "karma": -90 }
|
||||
]
|
||||
```
|
||||
|
||||
32
markdown/bitburner.singularity.getfactionworktypes.md
Normal file
32
markdown/bitburner.singularity.getfactionworktypes.md
Normal file
@@ -0,0 +1,32 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Singularity](./bitburner.singularity.md) > [getFactionWorkTypes](./bitburner.singularity.getfactionworktypes.md)
|
||||
|
||||
## Singularity.getFactionWorkTypes() method
|
||||
|
||||
Get the work types of a faction.
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getFactionWorkTypes(faction: string): FactionWorkType[];
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| faction | string | Name of the faction. |
|
||||
|
||||
**Returns:**
|
||||
|
||||
[FactionWorkType](./bitburner.factionworktype.md)<!-- -->\[\]
|
||||
|
||||
The work types of the faction.
|
||||
|
||||
## Remarks
|
||||
|
||||
RAM cost: 1 GB \* 16/4/1
|
||||
|
||||
This function returns an array containing the work types of the specified faction.
|
||||
|
||||
@@ -9,14 +9,14 @@ Go to a location.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
goToLocation(locationName: string): boolean;
|
||||
goToLocation(locationName: LocationName | `${LocationName}`): boolean;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| locationName | string | Name of the location. |
|
||||
| locationName | [LocationName](./bitburner.locationname.md) \| \`${[LocationName](./bitburner.locationname.md)<!-- -->}\` | Name of the location. |
|
||||
|
||||
**Returns:**
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ This API requires Source-File 4 to use. The RAM cost of all these functions is m
|
||||
| [getFactionFavorGain(faction)](./bitburner.singularity.getfactionfavorgain.md) | Get faction favor gain. |
|
||||
| [getFactionInviteRequirements(faction)](./bitburner.singularity.getfactioninviterequirements.md) | List conditions for being invited to a faction. |
|
||||
| [getFactionRep(faction)](./bitburner.singularity.getfactionrep.md) | Get faction reputation. |
|
||||
| [getFactionWorkTypes(faction)](./bitburner.singularity.getfactionworktypes.md) | Get the work types of a faction. |
|
||||
| [getOwnedAugmentations(purchased)](./bitburner.singularity.getownedaugmentations.md) | Get a list of owned augmentation. |
|
||||
| [getOwnedSourceFiles()](./bitburner.singularity.getownedsourcefiles.md) | Get a list of acquired Source-Files. |
|
||||
| [getUpgradeHomeCoresCost()](./bitburner.singularity.getupgradehomecorescost.md) | Get the price of upgrading home cores. |
|
||||
|
||||
@@ -34,8 +34,8 @@ This function allows you to automatically purchase programs. You MUST have a TOR
|
||||
|
||||
|
||||
```js
|
||||
const programName = "BruteSSH.exe"
|
||||
const success = ns.purchaseProgram(programName);
|
||||
if (!success) ns.tprint("ERROR: Failed to purchase ${programName}")
|
||||
const programName = "BruteSSH.exe";
|
||||
const success = ns.singularity.purchaseProgram(programName);
|
||||
if (!success) ns.tprint(`ERROR: Failed to purchase ${programName}`);
|
||||
```
|
||||
|
||||
|
||||
@@ -42,6 +42,6 @@ const factionName = "CyberSec";
|
||||
const workType = "hacking";
|
||||
|
||||
let success = ns.singularity.workForFaction(factionName, workType);
|
||||
if (!success) ns.tprint(`ERROR: Failed to start work for ${factionName} with work type ${workType}.`)
|
||||
if (!success) ns.tprint(`ERROR: Failed to start work for ${factionName} with work type ${workType}.`);
|
||||
```
|
||||
|
||||
|
||||
@@ -37,5 +37,5 @@ If you are not in BitNode-10, then you must have Source-File 10 in order to use
|
||||
| [setToShockRecovery(sleeveNumber)](./bitburner.sleeve.settoshockrecovery.md) | Set a sleeve to shock recovery. |
|
||||
| [setToSynchronize(sleeveNumber)](./bitburner.sleeve.settosynchronize.md) | Set a sleeve to synchronize. |
|
||||
| [setToUniversityCourse(sleeveNumber, university, className)](./bitburner.sleeve.settouniversitycourse.md) | Set a sleeve to take a class at a university. |
|
||||
| [travel(sleeveNumber, city)](./bitburner.sleeve.travel.md) | Make a sleeve travel to another city. |
|
||||
| [travel(sleeveNumber, city)](./bitburner.sleeve.travel.md) | Make a sleeve travel to another city. The cost for using this function is the same as for a player. |
|
||||
|
||||
|
||||
@@ -34,12 +34,12 @@ Return a boolean indicating whether or not this action was set successfully (fal
|
||||
## Example
|
||||
|
||||
|
||||
```ts
|
||||
```js
|
||||
// Assigns the first sleeve to Homicide.
|
||||
ns.sleeve.setToCommitCrime(0, "Homicide");
|
||||
|
||||
// Assigns the second sleeve to Grand Theft Auto, using enum
|
||||
const crimes = ns.enums.CrimeType;
|
||||
ns.sleeve.setToCommitCrime(1, crimes.grandTheftAuto)
|
||||
ns.sleeve.setToCommitCrime(1, crimes.grandTheftAuto);
|
||||
```
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Sleeve.travel() method
|
||||
|
||||
Make a sleeve travel to another city.
|
||||
Make a sleeve travel to another city. The cost for using this function is the same as for a player.
|
||||
|
||||
**Signature:**
|
||||
|
||||
|
||||
@@ -16,5 +16,5 @@ interface SpawnOptions extends RunOptions
|
||||
|
||||
| Property | Modifiers | Type | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| [spawnDelay?](./bitburner.spawnoptions.spawndelay.md) | | number | _(Optional)_ Number of milliseconds to delay before spawning script, defaults to 10000 (10s). Must be a positive integer. |
|
||||
| [spawnDelay?](./bitburner.spawnoptions.spawndelay.md) | | number | _(Optional)_ Number of milliseconds to delay before spawning script, defaults to 10000 (10s). Must be a non-negative integer. If 0, the script will be spawned synchronously. |
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## SpawnOptions.spawnDelay property
|
||||
|
||||
Number of milliseconds to delay before spawning script, defaults to 10000 (10s). Must be a positive integer.
|
||||
Number of milliseconds to delay before spawning script, defaults to 10000 (10s). Must be a non-negative integer. If 0, the script will be spawned synchronously.
|
||||
|
||||
**Signature:**
|
||||
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
location: string;
|
||||
location: LocationName | `${LocationName}`;
|
||||
```
|
||||
|
||||
@@ -22,6 +22,6 @@ An object representing the current study task
|
||||
| --- | --- | --- | --- |
|
||||
| [classType](./bitburner.studytask.classtype.md) | | string | |
|
||||
| [cyclesWorked](./bitburner.studytask.cyclesworked.md) | | number | |
|
||||
| [location](./bitburner.studytask.location.md) | | string | |
|
||||
| [location](./bitburner.studytask.location.md) | | [LocationName](./bitburner.locationname.md) \| \`${[LocationName](./bitburner.locationname.md)<!-- -->}\` | |
|
||||
| [type](./bitburner.studytask.type.md) | | "CLASS" | |
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ Object containing information for all the Limit and Stop Orders you have in the
|
||||
|
||||
RAM cost: 2.5 GB This is an object containing information for all the Limit and Stop Orders you have in the stock market. For each symbol you have a position in, the returned object will have a key with that symbol's name. The object's properties are each an array of [StockOrderObject](./bitburner.stockorderobject.md) The object has the following structure:
|
||||
|
||||
```ts
|
||||
```js
|
||||
{
|
||||
string1: [ // Array of orders for this stock
|
||||
{
|
||||
@@ -46,7 +46,7 @@ The “Order type” property can have one of the following four values: "Limit
|
||||
## Example
|
||||
|
||||
|
||||
```ts
|
||||
```js
|
||||
"If you do not have orders in Nova Medical (NVMD), then the returned object will not have a “NVMD” property."
|
||||
{
|
||||
ECP: [
|
||||
|
||||
@@ -30,7 +30,7 @@ RAM cost: 0 GB
|
||||
|
||||
Usage example (NS2)
|
||||
|
||||
```ts
|
||||
```js
|
||||
const styles = ns.ui.getStyles();
|
||||
styles.fontFamily = 'Comic Sans Ms';
|
||||
ns.ui.setStyles(styles);
|
||||
|
||||
@@ -30,7 +30,7 @@ RAM cost: 0 GB
|
||||
|
||||
Usage example (NS2)
|
||||
|
||||
```ts
|
||||
```js
|
||||
const theme = ns.ui.getTheme();
|
||||
theme.primary = '#ff5500';
|
||||
ns.ui.setTheme(theme);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
gymGains(person: Person, gymType: GymType | `${GymType}`, locationName: string): WorkStats;
|
||||
gymGains(person: Person, gymType: GymType | `${GymType}`, locationName: LocationName | `${LocationName}`): WorkStats;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@@ -16,7 +16,7 @@ gymGains(person: Person, gymType: GymType | `${GymType}`, locationName: string):
|
||||
| --- | --- | --- |
|
||||
| person | [Person](./bitburner.person.md) | |
|
||||
| gymType | [GymType](./bitburner.gymtype.md) \| \`${[GymType](./bitburner.gymtype.md)<!-- -->}\` | |
|
||||
| locationName | string | |
|
||||
| locationName | [LocationName](./bitburner.locationname.md) \| \`${[LocationName](./bitburner.locationname.md)<!-- -->}\` | |
|
||||
|
||||
**Returns:**
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
universityGains(
|
||||
person: Person,
|
||||
classType: UniversityClassType | `${UniversityClassType}`,
|
||||
locationName: string,
|
||||
locationName: LocationName | `${LocationName}`,
|
||||
): WorkStats;
|
||||
```
|
||||
|
||||
@@ -20,7 +20,7 @@ universityGains(
|
||||
| --- | --- | --- |
|
||||
| person | [Person](./bitburner.person.md) | |
|
||||
| classType | [UniversityClassType](./bitburner.universityclasstype.md) \| \`${[UniversityClassType](./bitburner.universityclasstype.md)<!-- -->}\` | |
|
||||
| locationName | string | |
|
||||
| locationName | [LocationName](./bitburner.locationname.md) \| \`${[LocationName](./bitburner.locationname.md)<!-- -->}\` | |
|
||||
|
||||
**Returns:**
|
||||
|
||||
|
||||
130
package-lock.json
generated
130
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "bitburner",
|
||||
"version": "2.6.1",
|
||||
"version": "2.6.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "bitburner",
|
||||
"version": "2.6.1",
|
||||
"version": "2.6.2",
|
||||
"hasInstallScript": true,
|
||||
"license": "SEE LICENSE IN license.txt",
|
||||
"dependencies": {
|
||||
@@ -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",
|
||||
@@ -5945,13 +5946,14 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/body-parser": {
|
||||
"version": "1.20.1",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
|
||||
"integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
|
||||
"version": "1.20.2",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
|
||||
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bytes": "3.1.2",
|
||||
"content-type": "~1.0.4",
|
||||
"content-type": "~1.0.5",
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"destroy": "1.2.0",
|
||||
@@ -5959,7 +5961,7 @@
|
||||
"iconv-lite": "0.4.24",
|
||||
"on-finished": "2.4.1",
|
||||
"qs": "6.11.0",
|
||||
"raw-body": "2.5.1",
|
||||
"raw-body": "2.5.2",
|
||||
"type-is": "~1.6.18",
|
||||
"unpipe": "1.0.0"
|
||||
},
|
||||
@@ -5973,6 +5975,7 @@
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
@@ -5982,6 +5985,7 @@
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
@@ -5990,7 +5994,8 @@
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/bonjour-service": {
|
||||
"version": "1.1.1",
|
||||
@@ -6028,12 +6033,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
"fill-range": "^7.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -6598,6 +6604,7 @@
|
||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
|
||||
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
@@ -6609,10 +6616,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cookie": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
|
||||
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
@@ -8232,17 +8240,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/express": {
|
||||
"version": "4.18.2",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
|
||||
"integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==",
|
||||
"version": "4.19.2",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
|
||||
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.8",
|
||||
"array-flatten": "1.1.1",
|
||||
"body-parser": "1.20.1",
|
||||
"body-parser": "1.20.2",
|
||||
"content-disposition": "0.5.4",
|
||||
"content-type": "~1.0.4",
|
||||
"cookie": "0.5.0",
|
||||
"cookie": "0.6.0",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
@@ -8484,10 +8493,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
@@ -8634,9 +8644,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.3",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
|
||||
"integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==",
|
||||
"version": "1.15.6",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
||||
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -8644,6 +8654,7 @@
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
@@ -8900,20 +8911,6 @@
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
@@ -9810,6 +9807,7 @@
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
},
|
||||
@@ -10305,6 +10303,7 @@
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
@@ -12502,14 +12501,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/katex": {
|
||||
"version": "0.16.9",
|
||||
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.9.tgz",
|
||||
"integrity": "sha512-fsSYjWS0EEOwvy81j3vRA8TEAhQhKiqO+FQaKWp0m39qwOzHVBgAUBIXWj1pB+O2W3fIpNa6Y9KSKCVbfPhyAQ==",
|
||||
"version": "0.16.10",
|
||||
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.10.tgz",
|
||||
"integrity": "sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
"https://opencollective.com/katex",
|
||||
"https://github.com/sponsors/katex"
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"commander": "^8.3.0"
|
||||
},
|
||||
@@ -13126,6 +13126,7 @@
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
@@ -14925,6 +14926,7 @@
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"side-channel": "^1.0.4"
|
||||
},
|
||||
@@ -14997,10 +14999,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/raw-body": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
|
||||
"integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
|
||||
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bytes": "3.1.2",
|
||||
"http-errors": "2.0.0",
|
||||
@@ -15016,6 +15019,7 @@
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
@@ -16787,6 +16791,7 @@
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
@@ -16896,6 +16901,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",
|
||||
@@ -16934,6 +16963,7 @@
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"media-typer": "0.3.0",
|
||||
"mime-types": "~2.1.24"
|
||||
@@ -17998,9 +18028,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.14.2",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz",
|
||||
"integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==",
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
|
||||
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
|
||||
13
package.json
13
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "bitburner",
|
||||
"license": "SEE LICENSE IN license.txt",
|
||||
"version": "2.6.1",
|
||||
"version": "2.6.2",
|
||||
"main": "electron-main.js",
|
||||
"author": {
|
||||
"name": "Daniel Xie, hydroflame, et al."
|
||||
@@ -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"
|
||||
@@ -118,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",
|
||||
|
||||
@@ -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 = (<AchievementDataJson>(<unknown>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<string, Achievement> = {
|
||||
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<string, Achievement> = {
|
||||
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<string, Achievement> = {
|
||||
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<string, Achievement> = {
|
||||
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<string, Achievement> = {
|
||||
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<string, Achievement> = {
|
||||
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<string, Achievement> = {
|
||||
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<string, Achievement> = {
|
||||
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<string, Achievement> = {
|
||||
...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<string, Achievement> = {
|
||||
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<string, Achievement> = {
|
||||
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<string, Achievement> = {
|
||||
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: {
|
||||
|
||||
@@ -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 (
|
||||
<div className={classes.root} style={{ width: "90%" }}>
|
||||
<Typography variant="h4">Achievements</Typography>
|
||||
|
||||
@@ -195,6 +195,12 @@ export class Augmentation {
|
||||
// The Player/Person classes
|
||||
mults: Multipliers = defaultMultipliers();
|
||||
|
||||
// Amount of money given to the Player when prestiging with this augmentation.
|
||||
startingMoney: number;
|
||||
|
||||
// Array of programs to be given to the player when prestiging with this augmentation.
|
||||
programs: CompletedProgramName[];
|
||||
|
||||
// Factions that offer this aug.
|
||||
factions: FactionName[] = [];
|
||||
|
||||
@@ -219,6 +225,9 @@ export class Augmentation {
|
||||
if (mult) this.mults[multName] = mult;
|
||||
}
|
||||
|
||||
this.startingMoney = params.startingMoney ?? 0;
|
||||
this.programs = params.programs ?? [];
|
||||
|
||||
if (params.stats === undefined)
|
||||
this.stats = generateStatsDescription(this.mults, params.programs, params.startingMoney);
|
||||
else this.stats = params.stats;
|
||||
|
||||
@@ -13,11 +13,26 @@ import { Page } from "../ui/Router";
|
||||
import { mergeMultipliers } from "../PersonObjects/Multipliers";
|
||||
import { currentNodeMults } from "../BitNode/BitNodeMultipliers";
|
||||
|
||||
const soaAugmentationNames = [
|
||||
AugmentationName.BeautyOfAphrodite,
|
||||
AugmentationName.ChaosOfDionysus,
|
||||
AugmentationName.FloodOfPoseidon,
|
||||
AugmentationName.HuntOfArtemis,
|
||||
AugmentationName.KnowledgeOfApollo,
|
||||
AugmentationName.MightOfAres,
|
||||
AugmentationName.TrickeryOfHermes,
|
||||
AugmentationName.WKSharmonizer,
|
||||
AugmentationName.WisdomOfAthena,
|
||||
];
|
||||
|
||||
export function getBaseAugmentationPriceMultiplier(): number {
|
||||
return CONSTANTS.MultipleAugMultiplier * [1, 0.96, 0.94, 0.93][Player.sourceFileLvl(11)];
|
||||
}
|
||||
export function getGenericAugmentationPriceMultiplier(): number {
|
||||
return Math.pow(getBaseAugmentationPriceMultiplier(), Player.queuedAugmentations.length);
|
||||
const queuedNonSoAAugmentationList = Player.queuedAugmentations.filter((augmentation) => {
|
||||
return !soaAugmentationNames.includes(augmentation.name);
|
||||
});
|
||||
return Math.pow(getBaseAugmentationPriceMultiplier(), queuedNonSoAAugmentationList.length);
|
||||
}
|
||||
|
||||
export function applyAugmentation(aug: PlayerOwnedAugmentation, reapply = false): void {
|
||||
@@ -111,7 +126,7 @@ export function getAugCost(aug: Augmentation): AugmentationCosts {
|
||||
const multiplier = Math.pow(CONSTANTS.NeuroFluxGovernorLevelMult, aug.getLevel());
|
||||
repCost = aug.baseRepRequirement * multiplier * currentNodeMults.AugmentationRepCost;
|
||||
moneyCost = aug.baseCost * multiplier * currentNodeMults.AugmentationMoneyCost;
|
||||
moneyCost *= getBaseAugmentationPriceMultiplier() ** Player.queuedAugmentations.length;
|
||||
moneyCost *= getGenericAugmentationPriceMultiplier();
|
||||
break;
|
||||
}
|
||||
// SOA Augments use a unique cost method
|
||||
@@ -124,17 +139,6 @@ export function getAugCost(aug: Augmentation): AugmentationCosts {
|
||||
case AugmentationName.TrickeryOfHermes:
|
||||
case AugmentationName.WKSharmonizer:
|
||||
case AugmentationName.WisdomOfAthena: {
|
||||
const soaAugmentationNames = [
|
||||
AugmentationName.BeautyOfAphrodite,
|
||||
AugmentationName.ChaosOfDionysus,
|
||||
AugmentationName.FloodOfPoseidon,
|
||||
AugmentationName.HuntOfArtemis,
|
||||
AugmentationName.KnowledgeOfApollo,
|
||||
AugmentationName.MightOfAres,
|
||||
AugmentationName.TrickeryOfHermes,
|
||||
AugmentationName.WKSharmonizer,
|
||||
AugmentationName.WisdomOfAthena,
|
||||
];
|
||||
const soaAugCount = soaAugmentationNames.filter((augName) => Player.hasAugmentation(augName)).length;
|
||||
moneyCost = aug.baseCost * Math.pow(CONSTANTS.SoACostMult, soaAugCount);
|
||||
repCost = aug.baseRepRequirement * Math.pow(CONSTANTS.SoARepMult, soaAugCount);
|
||||
|
||||
@@ -1013,9 +1013,9 @@ export const Augmentations: Record<AugmentationName, Augmentation> = (() => {
|
||||
moneyCost: 1e6,
|
||||
info:
|
||||
"Extra-ocular neurons taken from old martial art master. Injecting them gives the user the ability to " +
|
||||
"predict the enemy's attack before they even know it themselves.",
|
||||
"predict the enemy's movement.",
|
||||
stats:
|
||||
"This augmentation makes the Slash minigame easier by showing you via an indicator when the slash is coming.",
|
||||
"This augmentation makes the Slash minigame easier by showing you via an indicator when the sentinel is distracted.",
|
||||
isSpecial: true,
|
||||
factions: [FactionName.ShadowsOfAnarchy],
|
||||
},
|
||||
|
||||
@@ -28,9 +28,10 @@ function customFormatPercent(value: number): string {
|
||||
}
|
||||
|
||||
function BitNodeModifiedStats(props: IBitNodeModifiedStatsProps): React.ReactElement {
|
||||
// If player doesn't have SF5 or if the property isn't affected by BitNode mults
|
||||
if (props.mult === 1 || Player.sourceFileLvl(5) === 0)
|
||||
// If the player doesn't have access to SF5 feature or if the property isn't affected by BitNode mults
|
||||
if (props.mult === 1 || (Player.bitNodeN !== 5 && Player.sourceFileLvl(5) === 0)) {
|
||||
return <Typography color={props.color}>{customFormatPercent(props.base)}</Typography>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Typography color={props.color}>
|
||||
|
||||
@@ -36,23 +36,21 @@ export function initBitNodes() {
|
||||
"The original BitNode",
|
||||
(
|
||||
<>
|
||||
The first BitNode created by the Enders to imprison the minds of humans. It became the prototype and
|
||||
testing-grounds for all of the BitNodes that followed.
|
||||
This is the first BitNode created by the Enders to imprison the minds of humans. It became the prototype and
|
||||
testing ground for all of the BitNodes that followed.
|
||||
<br />
|
||||
<br />
|
||||
This is the first BitNode that you play through. It has no special modifications or mechanics.
|
||||
<br />
|
||||
<br />
|
||||
Destroying this BitNode will give you Source-File 1, or if you already have this Source-File it will upgrade its
|
||||
level up to a maximum of 3. This Source-File lets the player start with 32GB of RAM on his/her home computer
|
||||
when entering a new BitNode, and also increases all of the player's multipliers by:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: 16%
|
||||
<br />
|
||||
Level 2: 24%
|
||||
<br />
|
||||
Level 3: 28%
|
||||
Destroying this BitNode will give you Source-File 1, or if you already have this Source-File, it will upgrade
|
||||
its level up to a maximum of 3. This Source-File lets the player start with 32GB of RAM on their home computer
|
||||
when entering a new BitNode and increases all of the player's multipliers by:
|
||||
<ul>
|
||||
<li>Level 1: 16%</li>
|
||||
<li>Level 2: 24%</li>
|
||||
<li>Level 3: 28%</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
);
|
||||
@@ -60,36 +58,30 @@ export function initBitNodes() {
|
||||
2,
|
||||
0,
|
||||
"Rise of the Underworld",
|
||||
"From the shadows, they rose", //Gangs
|
||||
"From the shadows, they rose",
|
||||
(
|
||||
<>
|
||||
From the shadows, they rose.
|
||||
<br />
|
||||
<br />
|
||||
Organized crime groups quickly filled the void of power left behind from the collapse of Western government in
|
||||
the 2050s. As society and civilization broke down, people quickly succumbed to the innate human impulse of evil
|
||||
and savagery. The organized crime factions quickly rose to the top of the modern world.
|
||||
<br />
|
||||
<br />
|
||||
Certain Factions ({FactionName.SlumSnakes}, {FactionName.Tetrads}, {FactionName.TheSyndicate},{" "}
|
||||
{FactionName.TheDarkArmy}, {FactionName.SpeakersForTheDead}, {FactionName.NiteSec}, {FactionName.TheBlackHand}
|
||||
) give the player the ability to form and manage their own gang, which can earn the player money and reputation
|
||||
with the corresponding Faction. Gangs offer more Augmentations than Factions, and in BitNode-2 offer a way to
|
||||
destroy the BitNode.
|
||||
Certain factions ({FactionName.SlumSnakes}, {FactionName.Tetrads}, {FactionName.TheSyndicate},{" "}
|
||||
{FactionName.TheDarkArmy}, {FactionName.SpeakersForTheDead}, {FactionName.NiteSec}, and{" "}
|
||||
{FactionName.TheBlackHand}) give the player the ability to form and manage their own gang, which can earn the
|
||||
player money and reputation with the corresponding faction. The gang faction offers more augmentations than
|
||||
other factions, and in BitNode-2, it offers a way to destroy the BitNode.
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
Destroying this BitNode will give you Source-File 2, or if you already have this Source-File it will upgrade its
|
||||
level up to a maximum of 3. This Source-File allows you to form gangs in other BitNodes once your karma
|
||||
Destroying this BitNode will give you Source-File 2, or if you already have this Source-File, it will upgrade
|
||||
its level up to a maximum of 3. This Source-File allows you to form gangs in other BitNodes once your karma
|
||||
decreases to a certain value. It also increases your crime success rate, crime money, and charisma multipliers
|
||||
by:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: 24%
|
||||
<br />
|
||||
Level 2: 36%
|
||||
<br />
|
||||
Level 3: 42%
|
||||
<ul>
|
||||
<li>Level 1: 24%</li>
|
||||
<li>Level 2: 36%</li>
|
||||
<li>Level 3: 42%</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
);
|
||||
@@ -103,25 +95,24 @@ export function initBitNodes() {
|
||||
Our greatest illusion is that a healthy society can revolve around a single-minded pursuit of wealth.
|
||||
<br />
|
||||
<br />
|
||||
Sometime in the early 21st century economic and political globalization turned the world into a corporatocracy,
|
||||
Sometime in the early 21st century, economic and political globalization turned the world into a corporatocracy,
|
||||
and it never looked back. Now, the privileged elite will happily bankrupt their own countrymen, decimate their
|
||||
own community, and evict their neighbors from houses in their desperate bid to increase their wealth.
|
||||
<br />
|
||||
<br />
|
||||
In this BitNode you can create and manage your own corporation. Running a successful corporation has the
|
||||
potential of generating massive profits.
|
||||
In this BitNode, you can create and manage your own corporation. Running a successful corporation has the
|
||||
potential to generate massive profits.
|
||||
<br />
|
||||
<br />
|
||||
Destroying this BitNode will give you Source-File 3, or if you already have this Source-File it will upgrade its
|
||||
level up to a maximum of 3. This Source-File lets you create corporations on other BitNodes (although some
|
||||
Destroying this BitNode will give you Source-File 3, or if you already have this Source-File, it will upgrade
|
||||
its level up to a maximum of 3. This Source-File lets you create corporations on other BitNodes (although some
|
||||
BitNodes will disable this mechanic) and level 3 permanently unlocks the full API. This Source-File also
|
||||
increases your charisma and company salary multipliers by:
|
||||
<br />
|
||||
Level 1: 8%
|
||||
<br />
|
||||
Level 2: 12%
|
||||
<br />
|
||||
Level 3: 14%
|
||||
<ul>
|
||||
<li>Level 1: 8%</li>
|
||||
<li>Level 2: 12%</li>
|
||||
<li>Level 3: 14%</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
);
|
||||
@@ -132,24 +123,23 @@ export function initBitNodes() {
|
||||
"The Man and the Machine",
|
||||
(
|
||||
<>
|
||||
The Singularity has arrived. The human race is gone, replaced by artificially superintelligent beings that are
|
||||
more machine than man. <br />
|
||||
The Singularity has arrived. The human race is gone, replaced by artificially super intelligent beings that are
|
||||
more machine than man.
|
||||
<br />
|
||||
<br />
|
||||
In this BitNode you will gain access to a new set of Netscript Functions known as Singularity Functions. These
|
||||
In this BitNode, you will gain access to a new set of Netscript functions known as Singularity functions. These
|
||||
functions allow you to control most aspects of the game through scripts, including working for
|
||||
factions/companies, purchasing/installing Augmentations, and creating programs.
|
||||
factions/companies, purchasing/installing augmentations, and creating programs.
|
||||
<br />
|
||||
<br />
|
||||
Destroying this BitNode will give you Source-File 4, or if you already have this Source-File it will upgrade its
|
||||
level up to a maximum of 3. This Source-File lets you access and use the Singularity Functions in other
|
||||
Destroying this BitNode will give you Source-File 4, or if you already have this Source-File, it will upgrade
|
||||
its level up to a maximum of 3. This Source-File lets you access and use the Singularity functions in other
|
||||
BitNodes. Each level of this Source-File reduces the RAM cost of singularity functions:
|
||||
<br />
|
||||
Level 1: 16x
|
||||
<br />
|
||||
Level 2: 4x
|
||||
<br />
|
||||
Level 3: 1x
|
||||
<ul>
|
||||
<li>Level 1: 16x</li>
|
||||
<li>Level 2: 4x</li>
|
||||
<li>Level 3: 1x</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
);
|
||||
@@ -165,21 +155,20 @@ export function initBitNodes() {
|
||||
that couldn't be modeled by 1's and 0's. They were wrong.
|
||||
<br />
|
||||
<br />
|
||||
Destroying this BitNode will give you Source-File 5, or if you already have this Source-File it will upgrade its
|
||||
level up to a maximum of 3. This Source-File grants you a special new stat called Intelligence. Intelligence is
|
||||
unique because it is permanent and persistent (it never gets reset back to 1). However gaining Intelligence
|
||||
Destroying this BitNode will give you Source-File 5, or if you already have this Source-File, it will upgrade
|
||||
its level up to a maximum of 3. This Source-File grants you a special new stat called Intelligence. Intelligence
|
||||
is unique because it is permanent and persistent (it never gets reset back to 1). However, gaining Intelligence
|
||||
experience is much slower than other stats. Higher Intelligence levels will boost your production for many
|
||||
actions in the game. <br />
|
||||
actions in the game.
|
||||
<br />
|
||||
<br />
|
||||
In addition, this Source-File will unlock the getBitNodeMultipliers() Netscript function and let you start with
|
||||
Formulas.exe, and will also raise all of your hacking-related multipliers by:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: 8%
|
||||
<br />
|
||||
Level 2: 12%
|
||||
<br />
|
||||
Level 3: 14%
|
||||
<ul>
|
||||
<li>Level 1: 8%</li>
|
||||
<li>Level 2: 12%</li>
|
||||
<li>Level 3: 14%</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
);
|
||||
@@ -192,26 +181,24 @@ export function initBitNodes() {
|
||||
<>
|
||||
In the middle of the 21st century, {FactionName.OmniTekIncorporated} began designing and manufacturing advanced
|
||||
synthetic androids, or Synthoids for short. They achieved a major technological breakthrough in the sixth
|
||||
generation of their Synthoid design, called MK-VI, by developing a hyperintelligent AI. Many argue that this was
|
||||
the first sentient AI ever created. This resulted in Synthoid models that were stronger, faster, and more
|
||||
generation of their Synthoid design, called MK-VI, by developing a hyper-intelligent AI. Many argue that this
|
||||
was the first sentient AI ever created. This resulted in Synthoid models that were stronger, faster, and more
|
||||
intelligent than the humans that had created them.
|
||||
<br />
|
||||
<br />
|
||||
In this BitNode you will be able to access the {FactionName.Bladeburners} Division at the NSA, which provides a
|
||||
In this BitNode, you will be able to access the {FactionName.Bladeburners} division at the NSA, which provides a
|
||||
new mechanic for progression.
|
||||
<br />
|
||||
<br />
|
||||
Destroying this BitNode will give you Source-File 6, or if you already have this Source-File it will upgrade its
|
||||
level up to a maximum of 3. This Source-File allows you to access the NSA's {FactionName.Bladeburners} Division
|
||||
in other BitNodes. In addition, this Source-File will raise both the level and experience gain rate of all your
|
||||
combat stats by:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: 8%
|
||||
<br />
|
||||
Level 2: 12%
|
||||
<br />
|
||||
Level 3: 14%
|
||||
Destroying this BitNode will give you Source-File 6, or if you already have this Source-File, it will upgrade
|
||||
its level up to a maximum of 3. This Source-File allows you to access the NSA's {FactionName.Bladeburners}{" "}
|
||||
division in other BitNodes. In addition, this Source-File will raise both the level and experience gain rate of
|
||||
all your combat stats by:
|
||||
<ul>
|
||||
<li>Level 1: 8%</li>
|
||||
<li>Level 2: 12%</li>
|
||||
<li>Level 3: 14%</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
);
|
||||
@@ -225,25 +212,23 @@ export function initBitNodes() {
|
||||
In the middle of the 21st century, you were doing cutting-edge work at {FactionName.OmniTekIncorporated} as part
|
||||
of the AI design team for advanced synthetic androids, or Synthoids for short. You helped achieve a major
|
||||
technological breakthrough in the sixth generation of the company's Synthoid design, called MK-VI, by developing
|
||||
a hyperintelligent AI. Many argue that this was the first sentient AI ever created. This resulted in Synthoid
|
||||
a hyper-intelligent AI. Many argue that this was the first sentient AI ever created. This resulted in Synthoid
|
||||
models that were stronger, faster, and more intelligent than the humans that had created them.
|
||||
<br />
|
||||
<br />
|
||||
In this BitNode you will be able to access the {FactionName.Bladeburners} API, which allows you to access{" "}
|
||||
In this BitNode, you will be able to access the {FactionName.Bladeburners} API, which allows you to access{" "}
|
||||
{FactionName.Bladeburners} functionality through Netscript.
|
||||
<br />
|
||||
<br />
|
||||
Destroying this BitNode will give you Source-File 7, or if you already have this Source-File it will upgrade its
|
||||
level up to a maximum of 3. This Source-File allows you to access the {FactionName.Bladeburners} Netscript API
|
||||
in other BitNodes. In addition, this Source-File will increase all of your {FactionName.Bladeburners}{" "}
|
||||
Destroying this BitNode will give you Source-File 7, or if you already have this Source-File, it will upgrade
|
||||
its level up to a maximum of 3. This Source-File allows you to access the {FactionName.Bladeburners} Netscript
|
||||
API in other BitNodes. In addition, this Source-File will increase all of your {FactionName.Bladeburners}{" "}
|
||||
multipliers by:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: 8%
|
||||
<br />
|
||||
Level 2: 12%
|
||||
<br />
|
||||
Level 3: 14%
|
||||
<ul>
|
||||
<li>Level 1: 8%</li>
|
||||
<li>Level 2: 12%</li>
|
||||
<li>Level 3: 14%</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
);
|
||||
@@ -258,33 +243,24 @@ export function initBitNodes() {
|
||||
<br />
|
||||
<br />
|
||||
In this BitNode:
|
||||
<br />
|
||||
<br />
|
||||
You start with $250 million
|
||||
<br />
|
||||
You start with a WSE membership and access to the TIX API
|
||||
<br />
|
||||
You are able to short stocks and place different types of orders (limit/stop)
|
||||
<br />
|
||||
<br />
|
||||
Destroying this BitNode will give you Source-File 8, or if you already have this Source-File it will upgrade its
|
||||
level up to a maximum of 3. This Source-File grants the following benefits:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: Permanent access to WSE and TIX API
|
||||
<br />
|
||||
Level 2: Ability to short stocks in other BitNodes
|
||||
<br />
|
||||
Level 3: Ability to use limit/stop orders in other BitNodes
|
||||
<br />
|
||||
<br />
|
||||
<ul>
|
||||
<li>You start with $250 million.</li>
|
||||
<li>You start with a WSE membership and access to the TIX API.</li>
|
||||
<li>You can short stocks and place different types of orders (limit/stop).</li>
|
||||
</ul>
|
||||
Destroying this BitNode will give you Source-File 8, or if you already have this Source-File, it will upgrade
|
||||
its level up to a maximum of 3. This Source-File grants the following benefits:
|
||||
<ul>
|
||||
<li>Level 1: Permanent access to WSE and TIX API</li>
|
||||
<li>Level 2: Ability to short stocks in other BitNodes</li>
|
||||
<li>Level 3: Ability to use limit/stop orders in other BitNodes</li>
|
||||
</ul>
|
||||
This Source-File also increases your hacking growth multipliers by:
|
||||
<br />
|
||||
Level 1: 12%
|
||||
<br />
|
||||
Level 2: 18%
|
||||
<br />
|
||||
Level 3: 21%
|
||||
<ul>
|
||||
<li>Level 1: 12%</li>
|
||||
<li>Level 2: 18%</li>
|
||||
<li>Level 3: 21%</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
);
|
||||
@@ -297,36 +273,31 @@ export function initBitNodes() {
|
||||
<>
|
||||
When {FactionName.FulcrumSecretTechnologies} released their open-source Linux distro Chapeau, it quickly became
|
||||
the OS of choice for the underground hacking community. Chapeau became especially notorious for powering the
|
||||
Hacknet, a global, decentralized network used for nefarious purposes. {FactionName.FulcrumSecretTechnologies}{" "}
|
||||
quickly abandoned the project and dissociated themselves from it.
|
||||
Hacknet, which is a global, decentralized network used for nefarious purposes.{" "}
|
||||
{FactionName.FulcrumSecretTechnologies} quickly abandoned the project and dissociated themselves from it.
|
||||
<br />
|
||||
<br />
|
||||
This BitNode unlocks the Hacknet Server, an upgraded version of the Hacknet Node. Hacknet Servers generate
|
||||
hashes, which can be spent on a variety of different upgrades.
|
||||
<br />
|
||||
<br />
|
||||
Destroying this BitNode will give you Source-File 9, or if you already have this Source-File it will upgrade its
|
||||
level up to a maximum of 3. This Source-File grants the following benefits:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: Permanently unlocks the Hacknet Server in other BitNodes
|
||||
<br />
|
||||
Level 2: You start with 128GB of RAM on your home computer when entering a new BitNode
|
||||
<br />
|
||||
Level 3: Grants a highly-upgraded Hacknet Server when entering a new BitNode
|
||||
This BitNode unlocks the Hacknet Server, which is an upgraded version of the Hacknet Node. Hacknet Servers
|
||||
generate hashes, which can be spent on a variety of different upgrades.
|
||||
<br />
|
||||
<br />
|
||||
Destroying this BitNode will give you Source-File 9, or if you already have this Source-File, it will upgrade
|
||||
its level up to a maximum of 3. This Source-File grants the following benefits:
|
||||
<ul>
|
||||
<li>Level 1: Permanently unlocks the Hacknet Server in other BitNodes</li>
|
||||
<li>Level 2: You start with 128GB of RAM on your home computer when entering a new BitNode</li>
|
||||
<li>Level 3: Grants a highly-upgraded Hacknet Server when entering a new BitNode</li>
|
||||
</ul>
|
||||
(Note that the Level 3 effect of this Source-File only applies when entering a new BitNode, NOT when installing
|
||||
Augmentations)
|
||||
augmentations)
|
||||
<br />
|
||||
<br />
|
||||
This Source-File also increases hacknet production and reduces hacknet costs by:
|
||||
<br />
|
||||
Level 1: 12%
|
||||
<br />
|
||||
Level 2: 18%
|
||||
<br />
|
||||
Level 3: 21%
|
||||
<ul>
|
||||
<li>Level 1: 12%</li>
|
||||
<li>Level 2: 18%</li>
|
||||
<li>Level 3: 21%</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
);
|
||||
@@ -343,21 +314,20 @@ export function initBitNodes() {
|
||||
achieved immortality - at least for those that could afford it.
|
||||
<br />
|
||||
<br />
|
||||
This BitNode unlocks Sleeve and grafting technologies. Sleeve technology allows you to:
|
||||
<br />
|
||||
<br />
|
||||
1. Grafting: Visit VitaLife in New Tokyo to be able to obtain Augmentations without needing to install
|
||||
<br />
|
||||
2. Duplicate Sleeves: Duplicate your consciousness into Synthoids, allowing you to perform different tasks
|
||||
synchronously.
|
||||
<br />
|
||||
<br />
|
||||
Grafting technology allows you to graft Augmentations, which is an alternative way of installing Augmentations.
|
||||
<br />
|
||||
<br />
|
||||
Destroying this BitNode will give you Source-File 10, or if you already have this Source-File it will upgrade
|
||||
its level up to a maximum of 3. This Source-File unlocks Sleeve technology, and the Grafting API in other
|
||||
BitNodes. Each level of this Source-File also grants you a Duplicate Sleeve
|
||||
This BitNode unlocks Sleeve and Grafting technology:
|
||||
<ul>
|
||||
<li>
|
||||
Sleeve: Duplicate your consciousness into Synthoids, allowing you to perform different tasks asynchronously.
|
||||
You cannot buy Sleeves outside this BitNode.
|
||||
</li>
|
||||
<li>
|
||||
Grafting: Visit VitaLife in New Tokyo to get access to this technology. It allows you to graft
|
||||
augmentations, which is an alternative way of installing augmentations.
|
||||
</li>
|
||||
</ul>
|
||||
Destroying this BitNode will give you Source-File 10, or if you already have this Source-File, it will upgrade
|
||||
its level up to a maximum of 3. This Source-File unlocks Sleeve and Grafting API in other BitNodes. Each level
|
||||
of this Source-File also grants you a Sleeve.
|
||||
</>
|
||||
),
|
||||
);
|
||||
@@ -369,9 +339,9 @@ export function initBitNodes() {
|
||||
(
|
||||
<>
|
||||
The 2050s was defined by the massive amounts of violent civil unrest and anarchic rebellion that rose all around
|
||||
the world. It was this period of disorder that eventually lead to the governmental reformation of many global
|
||||
the world. It was this period of disorder that eventually led to the governmental reformation of many global
|
||||
superpowers, most notably the USA and China. But just as the world was slowly beginning to recover from these
|
||||
dark times, financial catastrophe hit.
|
||||
dark times, financial catastrophes hit.
|
||||
<br />
|
||||
<br />
|
||||
In many countries, the high cost of trying to deal with the civil disorder bankrupted the governments. In all of
|
||||
@@ -380,27 +350,21 @@ export function initBitNodes() {
|
||||
the world is slowly crumbling in the middle of the biggest economic crisis of all time.
|
||||
<br />
|
||||
<br />
|
||||
Destroying this BitNode will give you Source-File 11, or if you already have this Source-File it will upgrade
|
||||
Destroying this BitNode will give you Source-File 11, or if you already have this Source-File, it will upgrade
|
||||
its level up to a maximum of 3. This Source-File makes it so that company favor increases BOTH the player's
|
||||
salary and reputation gain rate at that company by 1% per favor (rather than just the reputation gain). This
|
||||
Source-File also increases the player's company salary and reputation gain multipliers by:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: 32%
|
||||
<br />
|
||||
Level 2: 48%
|
||||
<br />
|
||||
Level 3: 56%
|
||||
<br />
|
||||
<br />
|
||||
It also reduces the price increase for every aug bought by:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: 4%
|
||||
<br />
|
||||
Level 2: 6%
|
||||
<br />
|
||||
Level 3: 7%
|
||||
<ul>
|
||||
<li>Level 1: 32%</li>
|
||||
<li>Level 2: 48%</li>
|
||||
<li>Level 3: 56%</li>
|
||||
</ul>
|
||||
It also reduces the price increase for every augmentation bought by:
|
||||
<ul>
|
||||
<li>Level 1: 4%</li>
|
||||
<li>Level 2: 6%</li>
|
||||
<li>Level 3: 7%</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
);
|
||||
@@ -411,13 +375,13 @@ export function initBitNodes() {
|
||||
"Repeat.",
|
||||
(
|
||||
<>
|
||||
To iterate is human, to recurse divine.
|
||||
To iterate is human; to recurse, divine.
|
||||
<br />
|
||||
<br />
|
||||
Every time this BitNode is destroyed, it becomes slightly harder. Destroying this BitNode will give you
|
||||
Source-File 12, or if you already have this Source-File it will upgrade its level. There is no maximum level for
|
||||
Source-File 12. Each level of Source-File 12 lets you start any BitNodes with NeuroFlux Governor equal to the
|
||||
level of this source file.
|
||||
Source-File 12, or if you already have this Source-File, it will upgrade its level. There is no maximum level
|
||||
for Source-File 12. Each level of Source-File 12 lets you start any BitNodes with NeuroFlux Governor equal to
|
||||
the level of this source file.
|
||||
</>
|
||||
),
|
||||
);
|
||||
@@ -428,15 +392,15 @@ export function initBitNodes() {
|
||||
"1 step back, 2 steps forward",
|
||||
(
|
||||
<>
|
||||
With the invention of Augmentations in the 2040s a religious group known as the{" "}
|
||||
With the invention of augmentations in the 2040s, a religious group known as the{" "}
|
||||
{FactionName.ChurchOfTheMachineGod} has rallied far more support than anyone would have hoped.
|
||||
<br />
|
||||
<br />
|
||||
Their leader, Allison "Mother" Stanek is said to have created her own Augmentation whose power goes beyond any
|
||||
Their leader, Allison "Mother" Stanek is said to have created her own augmentation whose power goes beyond any
|
||||
other. Find her in {CityName.Chongqing} and gain her trust.
|
||||
<br />
|
||||
<br />
|
||||
Destroying this BitNode will give you Source-File 13, or if you already have this Source-File it will upgrade
|
||||
Destroying this BitNode will give you Source-File 13, or if you already have this Source-File, it will upgrade
|
||||
its level up to a maximum of 3. This Source-File lets the {FactionName.ChurchOfTheMachineGod} appear in other
|
||||
BitNodes.
|
||||
<br />
|
||||
@@ -459,24 +423,19 @@ export function initBitNodes() {
|
||||
networks by controlling the open space in the 'net!
|
||||
<br />
|
||||
<br />
|
||||
Destroying this BitNode will give you Source-File 14, or if you already have this Source-File it will upgrade
|
||||
Destroying this BitNode will give you Source-File 14, or if you already have this Source-File, it will upgrade
|
||||
its level up to a maximum of 3. This Source-File grants the following benefits:
|
||||
<br />
|
||||
<br />
|
||||
Level 1: 100% increased stat multipliers from Node Power
|
||||
<br />
|
||||
Level 2: Permanently unlocks the go.cheat API
|
||||
<br />
|
||||
Level 3: 25% additive increased success rate for the go.cheat API
|
||||
<br />
|
||||
<br />
|
||||
<ul>
|
||||
<li>Level 1: 100% increased stat multipliers from Node Power</li>
|
||||
<li>Level 2: Permanently unlocks the go.cheat API</li>
|
||||
<li>Level 3: 25% additive increased success rate for the go.cheat API</li>
|
||||
</ul>
|
||||
This Source-File also increases the maximum favor you can gain for each faction from IPvGO to:
|
||||
<br />
|
||||
Level 1: 80
|
||||
<br />
|
||||
Level 2: 100
|
||||
<br />
|
||||
Level 3: 120
|
||||
<ul>
|
||||
<li>Level 1: 80</li>
|
||||
<li>Level 2: 100</li>
|
||||
<li>Level 3: 120</li>
|
||||
</ul>
|
||||
</>
|
||||
),
|
||||
);
|
||||
|
||||
@@ -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<keyof BitNodeMultipliers, number> = {}) {
|
||||
for (const [key, value] of getRecordEntries(a)) this[key] = value;
|
||||
for (const [key, value] of getRecordEntries(a)) this[key] = clampNumber(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
11
src/BitNode/BitNodeUtils.ts
Normal file
11
src/BitNode/BitNodeUtils.ts
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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</>;
|
||||
|
||||
@@ -28,19 +28,18 @@ export function PortalModal(props: IProps): React.ReactElement {
|
||||
<Typography variant="h4">
|
||||
BitNode-{props.n}: {bitNode.name}
|
||||
</Typography>
|
||||
<Typography variant="h5">{bitNode.desc}</Typography>
|
||||
<br />
|
||||
<Typography>
|
||||
Source-File Level: {props.level} / {maxSourceFileLevel}
|
||||
</Typography>
|
||||
<br />
|
||||
<br />
|
||||
<Typography> Difficulty: {["easy", "normal", "hard"][bitNode.difficulty]}</Typography>
|
||||
<br />
|
||||
<br />
|
||||
<Typography>{bitNode.info}</Typography>
|
||||
<Typography component="div">{bitNode.info}</Typography>
|
||||
<BitnodeMultiplierDescription n={props.n} level={newLevel} />
|
||||
<br />
|
||||
<br />
|
||||
<Button
|
||||
aria-label={`enter-bitnode-${bitNode.number.toString()}`}
|
||||
autoFocus={true}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { BladeburnerConstants } from "../data/Constants";
|
||||
import { calculateIntelligenceBonus } from "../../PersonObjects/formulas/intelligence";
|
||||
import { BladeMultName } from "../Enums";
|
||||
import { getRecordKeys } from "../../Types/Record";
|
||||
import { clampNumber } from "../../utils/helpers/clampNumber";
|
||||
|
||||
export interface ActionParams {
|
||||
desc: string;
|
||||
@@ -146,9 +147,16 @@ export abstract class ActionClass {
|
||||
let high = real + diff;
|
||||
const city = bladeburner.getCurrentCity();
|
||||
let r = city.pop / city.popEst;
|
||||
if (Number.isNaN(r)) r = 0;
|
||||
if (r < 1) low *= r;
|
||||
else high *= r;
|
||||
if (Number.isNaN(r)) {
|
||||
r = 0;
|
||||
}
|
||||
if (r < 1) {
|
||||
low *= r;
|
||||
} else {
|
||||
// We need to "clamp" r with "clampNumber" (not "clamp"), otherwise (high *= r) may be NaN. This happens when the
|
||||
// action is Raid, popEst=0, and comms=0.
|
||||
high *= clampNumber(r);
|
||||
}
|
||||
return [clamp(low), clamp(high)];
|
||||
}
|
||||
|
||||
|
||||
@@ -34,18 +34,20 @@ export class BlackOperation extends ActionClass {
|
||||
if (bladeburner.rank < this.reqdRank) return { error: "Insufficient rank" };
|
||||
return { available: true };
|
||||
}
|
||||
// To be implemented by subtypes
|
||||
|
||||
getActionTimePenalty(): number {
|
||||
return 1.5;
|
||||
}
|
||||
|
||||
getPopulationSuccessFactor(/*inst: Bladeburner, params: ISuccessChanceParams*/): number {
|
||||
getPopulationSuccessFactor(): number {
|
||||
return 1;
|
||||
}
|
||||
|
||||
getChaosSuccessFactor(/*inst: Bladeburner, params: ISuccessChanceParams*/): number {
|
||||
getChaosSuccessFactor(): number {
|
||||
return 1;
|
||||
}
|
||||
|
||||
getTeamSuccessBonus = operationTeamSuccessBonus;
|
||||
|
||||
getActionTypeSkillSuccessBonus = operationSkillSuccessBonus;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ export class Operation extends LevelableActionClass {
|
||||
|
||||
// These functions are shared between operations and blackops, so they are defined outside of Operation
|
||||
getTeamSuccessBonus = operationTeamSuccessBonus;
|
||||
|
||||
getActionTypeSkillSuccessBonus = operationSkillSuccessBonus;
|
||||
|
||||
getChaosSuccessFactor(inst: Bladeburner /*, params: ISuccessChanceParams*/): number {
|
||||
@@ -45,7 +46,9 @@ export class Operation extends LevelableActionClass {
|
||||
return 1;
|
||||
}
|
||||
getSuccessChance(inst: Bladeburner, person: Person, params: SuccessChanceParams) {
|
||||
if (this.name == BladeOperationName.raid && inst.getCurrentCity().comms <= 0) return 0;
|
||||
if (this.name === BladeOperationName.raid && inst.getCurrentCity().comms <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return ActionClass.prototype.getSuccessChance.call(this, inst, person, params);
|
||||
}
|
||||
|
||||
@@ -57,6 +60,7 @@ export class Operation extends LevelableActionClass {
|
||||
toJSON(): IReviverValue {
|
||||
return this.save("Operation", "teamCount");
|
||||
}
|
||||
|
||||
loadData(loadedObject: Operation): void {
|
||||
this.teamCount = clampInteger(loadedObject.teamCount, 0);
|
||||
LevelableActionClass.prototype.loadData.call(this, loadedObject);
|
||||
@@ -73,6 +77,7 @@ constructorsForReviver.Operation = Operation;
|
||||
export const operationSkillSuccessBonus = (inst: Bladeburner) => {
|
||||
return inst.getSkillMult(BladeMultName.successChanceOperation);
|
||||
};
|
||||
|
||||
export function operationTeamSuccessBonus(this: Operation | BlackOperation, inst: Bladeburner) {
|
||||
if (this.teamCount && this.teamCount > 0) {
|
||||
this.teamCount = Math.min(this.teamCount, inst.teamSize);
|
||||
|
||||
@@ -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<number> = { promise: null, resolve: null };
|
||||
|
||||
@@ -115,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));
|
||||
}
|
||||
|
||||
@@ -124,7 +125,7 @@ export class Bladeburner {
|
||||
startAction(actionId: ActionIdentifier | null): Attempt<{ message: string }> {
|
||||
if (!actionId) {
|
||||
this.resetAction();
|
||||
return { success: true, message: "Stopped current bladeburner action" };
|
||||
return { success: true, message: "Stopped current Bladeburner action" };
|
||||
}
|
||||
if (!Player.hasAugmentation(AugmentationName.BladesSimulacrum, true)) Player.finishWork(true);
|
||||
const action = this.getActionObject(actionId);
|
||||
@@ -854,6 +855,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 +916,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 +947,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 +994,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 +1022,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 +1045,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 +1078,7 @@ export class Bladeburner {
|
||||
formatExp(agiExpGain) +
|
||||
" agi exp, " +
|
||||
formatBigNumber(staminaGain) +
|
||||
" max stamina",
|
||||
" max stamina.",
|
||||
);
|
||||
}
|
||||
break;
|
||||
@@ -1089,7 +1108,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 +1124,7 @@ export class Bladeburner {
|
||||
`${person.whoAmI()}: ` +
|
||||
"Successfully recruited a team member! Gained " +
|
||||
formatExp(expGain) +
|
||||
" charisma exp",
|
||||
" charisma exp.",
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -1116,7 +1135,7 @@ export class Bladeburner {
|
||||
`${person.whoAmI()}: ` +
|
||||
"Failed to recruit a team member. Gained " +
|
||||
formatExp(expGain) +
|
||||
" charisma exp",
|
||||
" charisma exp.",
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1132,7 +1151,7 @@ export class Bladeburner {
|
||||
this.log(
|
||||
`${person.whoAmI()}: Diplomacy completed. Chaos levels in the current city fell by ${formatPercent(
|
||||
1 - eff,
|
||||
)}`,
|
||||
)}.`,
|
||||
);
|
||||
}
|
||||
break;
|
||||
@@ -1140,14 +1159,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;
|
||||
}
|
||||
@@ -1258,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;
|
||||
@@ -1431,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;
|
||||
}
|
||||
}
|
||||
|
||||
91
src/Bladeburner/ui/ActionHeader.tsx
Normal file
91
src/Bladeburner/ui/ActionHeader.tsx
Normal file
@@ -0,0 +1,91 @@
|
||||
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";
|
||||
import { BladeburnerConstants } from "../data/Constants";
|
||||
import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
||||
|
||||
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 remainingSeconds = Math.max(
|
||||
bladeburner.actionTimeToComplete - bladeburner.actionTimeCurrent + bladeburner.actionTimeOverflow,
|
||||
0,
|
||||
);
|
||||
const remainingBonusSeconds = Math.floor(bladeburner.storedCycles / BladeburnerConstants.CyclesPerSecond);
|
||||
/**
|
||||
* Bladeburner is processed every second. Each time it's processed, we use (up to) 4 bonus seconds and process it as
|
||||
* if (up to) 5 seconds passed.
|
||||
* For example, with 20 bonus seconds, we need 5 seconds to use up all those bonus seconds. After 5 seconds, we used
|
||||
* up 20 bonus seconds and processed Bladeburner as if 25 seconds had passed.
|
||||
*/
|
||||
const effectiveBonusSeconds = (remainingBonusSeconds / 4) * 5;
|
||||
let eta;
|
||||
if (remainingSeconds <= effectiveBonusSeconds) {
|
||||
// If we have enough effectiveBonusSeconds, ETA is (remainingSeconds / 5).
|
||||
eta = Math.floor(remainingSeconds / 5);
|
||||
} else {
|
||||
/**
|
||||
* For example, let's say we start the "Training" action with 20 bonus seconds: remainingSeconds=30;remainingBonusSeconds=20.
|
||||
* After 5 seconds (remainingBonusSeconds / 4), we processed Bladeburner as if 25 seconds (effectiveBonusSeconds)
|
||||
* had passed. We still need 5 more seconds (30 - 25 = remainingTime - effectiveBonusSeconds) to complete the action
|
||||
* at normal speed.
|
||||
*
|
||||
* ETA = remainingBonusSeconds / 4 + remainingTime - effectiveBonusSeconds
|
||||
* = remainingBonusSeconds / 4 + remainingTime - ((remainingBonusSeconds / 4) * 5)
|
||||
* = remainingTime - remainingBonusSeconds
|
||||
*/
|
||||
eta = remainingSeconds - remainingBonusSeconds;
|
||||
}
|
||||
|
||||
const allowTeam = action instanceof Operation || action instanceof BlackOperation;
|
||||
|
||||
if (isActive) {
|
||||
return (
|
||||
<>
|
||||
<Box display="flex" flexDirection="row" alignItems="center">
|
||||
<CopyableText value={action.name} />
|
||||
<StopButton bladeburner={bladeburner} rerender={rerender} />
|
||||
</Box>
|
||||
<Typography>
|
||||
(IN PROGRESS - {formatNumberNoSuffix(computedActionTimeCurrent, 0)} /{" "}
|
||||
{formatNumberNoSuffix(bladeburner.actionTimeToComplete, 0)})
|
||||
</Typography>
|
||||
<Box display="flex" flexDirection="row" alignItems="center">
|
||||
<Typography>
|
||||
{createProgressBarText({
|
||||
progress: computedActionTimeCurrent / bladeburner.actionTimeToComplete,
|
||||
})}
|
||||
</Typography>
|
||||
<Typography marginLeft="1rem">Remaining time: {convertTimeMsToTimeElapsedString(eta * 1000)}</Typography>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box display="flex" flexDirection="row" alignItems="center">
|
||||
<CopyableText value={action.name} />
|
||||
<StartButton bladeburner={bladeburner} action={action} rerender={rerender} />
|
||||
{allowTeam && <TeamSizeButton bladeburner={bladeburner} action={action} />}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -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 (
|
||||
<Box display="flex" flexDirection="row" alignItems="center">
|
||||
<Box display="flex">
|
||||
<Tooltip
|
||||
title={
|
||||
action.constructor.name === "Contract" ? (
|
||||
<Typography>
|
||||
{action.getSuccessesNeededForNextLevel(BladeburnerConstants.ContractSuccessesPerLevel)} successes needed
|
||||
for next level
|
||||
</Typography>
|
||||
) : (
|
||||
<Typography>
|
||||
{action.getSuccessesNeededForNextLevel(BladeburnerConstants.OperationSuccessesPerLevel)} successes
|
||||
needed for next level
|
||||
</Typography>
|
||||
)
|
||||
}
|
||||
>
|
||||
<Tooltip title={<Typography>{successesNeededForNextLevel} successes needed for next level</Typography>}>
|
||||
<Typography>
|
||||
Level: {action.level} / {action.maxLevel}
|
||||
</Typography>
|
||||
|
||||
@@ -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 (
|
||||
<Paper sx={{ my: 1, p: 1 }}>
|
||||
<Typography>{blackOp.name} (COMPLETED)</Typography>
|
||||
<Typography>{action.name} (COMPLETED)</Typography>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
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 (
|
||||
<Paper sx={{ my: 1, p: 1 }}>
|
||||
{isActive ? (
|
||||
<>
|
||||
<CopyableText value={blackOp.name} />
|
||||
<Typography>
|
||||
(IN PROGRESS - {formatNumberNoSuffix(computedActionTimeCurrent, 0)} /{" "}
|
||||
{formatNumberNoSuffix(bladeburner.actionTimeToComplete, 0)})
|
||||
</Typography>
|
||||
<Typography>
|
||||
{createProgressBarText({
|
||||
progress: computedActionTimeCurrent / bladeburner.actionTimeToComplete,
|
||||
})}
|
||||
</Typography>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<CopyableText value={blackOp.name} />
|
||||
|
||||
<StartButton bladeburner={bladeburner} action={blackOp} rerender={rerender} />
|
||||
<TeamSizeButton action={blackOp} bladeburner={bladeburner} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<ActionHeader bladeburner={bladeburner} action={action} rerender={rerender}></ActionHeader>
|
||||
<br />
|
||||
<Typography whiteSpace={"pre-wrap"}>{action.desc}</Typography>
|
||||
<br />
|
||||
<Typography whiteSpace={"pre-wrap"}>{blackOp.desc}</Typography>
|
||||
<br />
|
||||
<br />
|
||||
<Typography color={hasReqdRank ? "primary" : "error"}>
|
||||
Required Rank: {formatNumberNoSuffix(blackOp.reqdRank, 0)}
|
||||
<Typography color={hasRequiredRank ? "primary" : "error"}>
|
||||
Required Rank: {formatNumberNoSuffix(action.reqdRank, 0)}
|
||||
</Typography>
|
||||
<br />
|
||||
<Typography>
|
||||
<SuccessChance action={blackOp} bladeburner={bladeburner} />
|
||||
<SuccessChance action={action} bladeburner={bladeburner} />
|
||||
<br />
|
||||
Time Required: {convertTimeMsToTimeElapsedString(actionTime * 1000)}
|
||||
</Typography>
|
||||
|
||||
@@ -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";
|
||||
@@ -8,13 +8,25 @@ 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 blackOps = blackOpsArray.slice(0, bladeburner.numBlackOpsComplete + 1);
|
||||
const blackOperations = blackOpsArray.slice(0, bladeburner.numBlackOpsComplete + 1).reverse();
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -33,13 +45,13 @@ export function BlackOpPage({ bladeburner }: BlackOpPageProps): React.ReactEleme
|
||||
losses.
|
||||
</Typography>
|
||||
{bladeburner.numBlackOpsComplete >= blackOpsArray.length ? (
|
||||
<Button sx={{ my: 1, p: 1 }} onClick={() => Router.toPage(Page.BitVerse, { flume: false, quick: false })}>
|
||||
<CorruptableText content="Destroy w0rld_d34mon" spoiler={false}></CorruptableText>
|
||||
<Button sx={{ my: 1, p: 1 }} onClick={finishBitNode}>
|
||||
<CorruptableText content="Destroy w0r1d_d43m0n" spoiler={false}></CorruptableText>
|
||||
</Button>
|
||||
) : (
|
||||
<>
|
||||
{blackOps.map((blackOp) => (
|
||||
<BlackOpElem key={blackOp.name} bladeburner={bladeburner} blackOp={blackOp} />
|
||||
{blackOperations.map((blackOperation) => (
|
||||
<BlackOpElem key={blackOperation.name} bladeburner={bladeburner} action={blackOperation} />
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -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<HTMLInputElement>(null);
|
||||
useRerender(1000);
|
||||
|
||||
@@ -2,18 +2,15 @@ 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;
|
||||
@@ -22,41 +19,15 @@ 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 computedActionTimeCurrent = Math.min(
|
||||
bladeburner.actionTimeCurrent + bladeburner.actionTimeOverflow,
|
||||
bladeburner.actionTimeToComplete,
|
||||
);
|
||||
const actionTime = action.getActionTime(bladeburner, Player);
|
||||
|
||||
return (
|
||||
<Paper sx={{ my: 1, p: 1 }}>
|
||||
{isActive ? (
|
||||
<>
|
||||
<CopyableText value={action.name} />
|
||||
<Typography>
|
||||
(IN PROGRESS - {formatNumberNoSuffix(computedActionTimeCurrent, 0)} /{" "}
|
||||
{formatNumberNoSuffix(bladeburner.actionTimeToComplete, 0)})
|
||||
</Typography>
|
||||
<Typography>
|
||||
{createProgressBarText({
|
||||
progress: computedActionTimeCurrent / bladeburner.actionTimeToComplete,
|
||||
})}
|
||||
</Typography>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<CopyableText value={action.name} />
|
||||
<StartButton bladeburner={bladeburner} action={action} rerender={rerender} />
|
||||
</>
|
||||
)}
|
||||
<br />
|
||||
<ActionHeader bladeburner={bladeburner} action={action} rerender={rerender}></ActionHeader>
|
||||
<br />
|
||||
<ActionLevel action={action} bladeburner={bladeburner} isActive={isActive} rerender={rerender} />
|
||||
<br />
|
||||
<br />
|
||||
<Typography whiteSpace={"pre-wrap"}>
|
||||
{action.desc}
|
||||
<br />
|
||||
|
||||
@@ -2,14 +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 { 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;
|
||||
@@ -18,41 +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 (
|
||||
<Paper sx={{ my: 1, p: 1 }}>
|
||||
{isActive ? (
|
||||
<>
|
||||
<CopyableText value={action.name} />
|
||||
<Typography>
|
||||
(IN PROGRESS - {formatNumberNoSuffix(computedActionTimeCurrent, 0)} /{" "}
|
||||
{formatNumberNoSuffix(bladeburner.actionTimeToComplete, 0)})
|
||||
</Typography>
|
||||
<Typography>
|
||||
{createProgressBarText({
|
||||
progress: computedActionTimeCurrent / bladeburner.actionTimeToComplete,
|
||||
})}
|
||||
</Typography>
|
||||
</>
|
||||
) : (
|
||||
<Box display="flex" flexDirection="row" alignItems="center">
|
||||
<CopyableText value={action.name} />
|
||||
<StartButton bladeburner={bladeburner} action={action} rerender={rerender} />
|
||||
</Box>
|
||||
)}
|
||||
<br />
|
||||
<ActionHeader bladeburner={bladeburner} action={action} rerender={rerender}></ActionHeader>
|
||||
<br />
|
||||
<Typography>{action.desc}</Typography>
|
||||
<br />
|
||||
<br />
|
||||
<Typography>
|
||||
Time Required: {convertTimeMsToTimeElapsedString(actionTime * 1000)}
|
||||
{successChance !== -1 && (
|
||||
|
||||
@@ -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 (
|
||||
<Paper sx={{ my: 1, p: 1 }}>
|
||||
{isActive ? (
|
||||
<>
|
||||
<Typography>
|
||||
<CopyableText value={operation.name} /> (IN PROGRESS - {formatNumberNoSuffix(computedActionTimeCurrent, 0)}{" "}
|
||||
/ {formatNumberNoSuffix(bladeburner.actionTimeToComplete, 0)})
|
||||
</Typography>
|
||||
<Typography>
|
||||
{createProgressBarText({
|
||||
progress: computedActionTimeCurrent / bladeburner.actionTimeToComplete,
|
||||
})}
|
||||
</Typography>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<CopyableText value={operation.name} />
|
||||
<StartButton bladeburner={bladeburner} action={operation} rerender={rerender} />
|
||||
<TeamSizeButton action={operation} bladeburner={bladeburner} />
|
||||
</>
|
||||
)}
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<ActionLevel action={operation} bladeburner={bladeburner} isActive={isActive} rerender={rerender} />
|
||||
<ActionHeader bladeburner={bladeburner} action={action} rerender={rerender}></ActionHeader>
|
||||
<br />
|
||||
<ActionLevel action={action} bladeburner={bladeburner} isActive={isActive} rerender={rerender} />
|
||||
<br />
|
||||
<Typography whiteSpace={"pre-wrap"}>
|
||||
{operation.desc}
|
||||
{action.desc}
|
||||
<br />
|
||||
<br />
|
||||
<SuccessChance action={operation} bladeburner={bladeburner} />
|
||||
<SuccessChance action={action} bladeburner={bladeburner} />
|
||||
<br />
|
||||
Time Required: {convertTimeMsToTimeElapsedString(actionTime * 1000)}
|
||||
<br />
|
||||
Operations remaining: {formatBigNumber(Math.floor(operation.count))}
|
||||
Operations remaining: {formatBigNumber(Math.floor(action.count))}
|
||||
<br />
|
||||
Successes: {formatBigNumber(operation.successes)}
|
||||
Successes: {formatBigNumber(action.successes)}
|
||||
<br />
|
||||
Failures: {formatBigNumber(operation.failures)}
|
||||
Failures: {formatBigNumber(action.failures)}
|
||||
</Typography>
|
||||
<br />
|
||||
<Autolevel rerender={rerender} action={operation} />
|
||||
<Autolevel rerender={rerender} action={action} />
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user