merge base

This commit is contained in:
phyzical 2022-04-13 18:50:42 +08:00
commit 6b48ff8f21
172 changed files with 5885 additions and 3696 deletions

@ -1,3 +1,3 @@
last 4 versions
last 8 versions
not dead
not ie <= 11

@ -353,6 +353,7 @@ module.exports = {
"no-useless-constructor": [
"off", // Valid for typescript due to property ctor shorthand
],
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/ban-ts-ignore": "off",
"@typescript-eslint/camelcase": "off",

71
.github/workflows/ci-pr.yml vendored Normal file

@ -0,0 +1,71 @@
name: CI Pull Request
on:
# Triggers the workflow on pull request events but only for the dev branch, checking only diffs
pull_request:
branches: [dev]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js 16.13.1
uses: actions/setup-node@v2
with:
node-version: 16.13.1
cache: "npm"
- name: Install npm dependencies
run: npm ci
- name: Build the production app
run: npm run build
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Use Node.js 16.13.1
uses: actions/setup-node@v2
with:
node-version: 16.13.1
cache: "npm"
- name: Install npm dependencies
run: npm ci
- name: Run linter
run: npm run lint:report-diff
prettier:
name: Prettier
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Use Node.js 16.13.1
uses: actions/setup-node@v2
with:
node-version: 16.13.1
cache: "npm"
- name: Install npm dependencies
run: npm ci
- name: Run prettier check
run: npm run format:report-diff
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js 16.13.1
uses: actions/setup-node@v2
with:
node-version: 16.13.1
cache: "npm"
- name: Install npm dependencies
run: npm ci
- name: Run tests
run: npm run test

@ -1,11 +1,9 @@
name: CI
on:
# Triggers the workflow on push or pull request events but only for the dev branch
# Triggers the workflow on push events but only for the dev branch
push:
branches: [dev]
pull_request:
branches: [dev]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

3
.npmrc Normal file

@ -0,0 +1,3 @@
# Default "npm version" commit message
# See: https://stackoverflow.com/a/34606092
message=":bookmark: Build v%s"

165
dist/bitburner.d.ts vendored

@ -3,7 +3,7 @@
*/
export declare interface ActiveFragment {
id: number;
avgCharge: number;
highestCharge: number;
numCharge: number;
rotation: number;
x: number;
@ -182,7 +182,7 @@ export declare interface BitNodeMultipliers {
/** Influences the maximum allowed RAM for a purchased server */
PurchasedServerMaxRam: number;
/** Influences cost of any purchased server at or above 128GB */
PurchasedServerSoftCap: number;
PurchasedServerSoftcap: number;
/** Influences the minimum favor the player must have with a faction before they can donate to gain rep. */
RepToDonateToFaction: number;
/** Influences how much the money on a server can be reduced when a script performs a hack against it. */
@ -709,10 +709,10 @@ export declare interface CharacterInfo {
factions: string[];
/** Current health points */
hp: number;
/** Array of all companies at which you have jobs */
company: string[];
/** Array of all jobs */
jobs: string[];
/** Array of job positions for all companies you are employed at. Same order as 'jobs' */
jobTitle: string[];
jobTitles: string[];
/** Maximum health points */
maxHp: number;
/** Boolean indicating whether or not you have a tor router */
@ -737,6 +737,18 @@ export declare interface CharacterInfo {
workRepGain: number;
/** Money earned so far from work, if applicable */
workMoneyGain: number;
/** total hacking exp */
hackingExp: number;
/** total strength exp */
strengthExp: number;
/** total defense exp */
defenseExp: number;
/** total dexterity exp */
dexterityExp: number;
/** total agility exp */
agilityExp: number;
/** total charisma exp */
charismaExp: number;
}
/**
@ -747,6 +759,10 @@ export declare interface CharacterMult {
agility: number;
/** Agility exp */
agilityExp: number;
/** Charisma stat */
charisma: number;
/** Charisma exp */
charismaExp: number;
/** Company reputation */
companyRep: number;
/** Money earned from crimes */
@ -1177,6 +1193,8 @@ export declare type FilenameOrPID = number | string;
* @public
*/
export declare interface Formulas {
/** Reputation formulas */
reputation: ReputationFormulas;
/** Skills formulas */
skills: SkillsFormulas;
/** Hacking formulas */
@ -2101,7 +2119,7 @@ export declare interface Hacknet {
* // NS1:
* var upgradeName = "Sell for Corporation Funds";
* if (hacknet.numHashes() > hacknet.hashCost(upgradeName)) {
* hacknet.spendHashes(upgName);
* hacknet.spendHashes(upgradeName);
* }
* ```
* @example
@ -2109,7 +2127,7 @@ export declare interface Hacknet {
* // NS2:
* const upgradeName = "Sell for Corporation Funds";
* if (ns.hacknet.numHashes() > ns.hacknet.hashCost(upgradeName)) {
* ns.hacknet.spendHashes(upgName);
* ns.hacknet.spendHashes(upgradeName);
* }
* ```
* @param upgName - Name of the upgrade of Hacknet Node.
@ -2442,6 +2460,10 @@ export declare interface Material {
qty: number;
/** Quality of the material */
qlt: number;
/** Demand for the material, only present if "Market Research - Demand" unlocked */
dmd: number | undefined;
/** Competition for the material, only present if "Market Research - Competition" unlocked */
cmp: number | undefined;
/** Amount of material produced */
prod: number;
/** Amount of material sold */
@ -2574,7 +2596,7 @@ export declare interface NodeStats {
* {@link https://bitburner.readthedocs.io/en/latest/netscript/netscriptjs.html| ns2 in-game docs}
* <hr>
*/
export declare interface NS extends Singularity {
export declare interface NS {
/**
* Namespace for hacknet functions.
* @remarks RAM cost: 4 GB
@ -2635,6 +2657,12 @@ export declare interface NS extends Singularity {
*/
readonly ui: UserInterface;
/**
* Namespace for singularity functions.
* RAM cost: 0 GB
*/
readonly singularity: Singularity;
/**
* Namespace for grafting functions.
* @remarks
@ -2825,9 +2853,10 @@ export declare interface NS extends Singularity {
* Returns the security increase that would occur if a hack with this many threads happened.
*
* @param threads - Amount of threads that will be used.
* @param hostname - Hostname of the target server. The number of threads is limited to the number needed to hack the servers maximum amount of money.
* @returns The security increase.
*/
hackAnalyzeSecurity(threads: number): number;
hackAnalyzeSecurity(threads: number, hostname?: string): number;
/**
* Get the chance of successfully hacking a server.
@ -2912,7 +2941,7 @@ export declare interface NS extends Singularity {
* ```
* @returns
*/
sleep(millis: number): Promise<void>;
sleep(millis: number): Promise<true>;
/**
* Suspends the script for n milliseconds. Doesn't block with concurrent calls.
@ -2922,7 +2951,7 @@ export declare interface NS extends Singularity {
* @param millis - Number of milliseconds to sleep.
* @returns
*/
asleep(millis: number): Promise<void>;
asleep(millis: number): Promise<true>;
/**
* Prints one or move values or variables to the scripts logs.
@ -3051,6 +3080,27 @@ export declare interface NS extends Singularity {
*/
getScriptLogs(fn?: string, host?: string, ...args: any[]): string[];
/**
* Get an array of recently killed scripts across all servers.
* @remarks
* RAM cost: 0.2 GB
*
* The most recently killed script is the first element in the array.
* Note that there is a maximum number of recently killed scripts which are tracked.
* This is configurable in the game's options as `Recently killed scripts size`.
*
* @example
* ```ts
* let recentScripts = ns.getRecentScripts();
* let mostRecent = recentScripts.shift()
* if (mostRecent)
* ns.tprint(mostRecent.logs.join('\n'))
* ```
*
* @returns Array with information about previously killed scripts.
*/
getRecentScripts(): RecentScript[];
/**
* Open the tail window of a script.
* @remarks
@ -3941,7 +3991,7 @@ export declare interface NS extends Singularity {
* @param args - Arguments to identify the script
* @returns The info about the running script if found, and null otherwise.
*/
getRunningScript(filename?: FilenameOrPID, hostname?: string, ...args: (string | number)[]): RunningScript;
getRunningScript(filename?: FilenameOrPID, hostname?: string, ...args: (string | number)[]): RunningScript | null;
/**
* Get cost of purchasing a server.
@ -4453,7 +4503,7 @@ export declare interface NS extends Singularity {
* @param variant - Type of toast, must be one of success, info, warning, error. Defaults to success.
* @param duration - Duration of toast in ms. Can also be `null` to create a persistent toast. Defaults to 2000
*/
toast(msg: any, variant?: string, duration?: number | null): void;
toast(msg: any, variant?: ToastVariantValues, duration?: number | null): void;
/**
* Download a file from the internet.
@ -4648,6 +4698,13 @@ export declare interface NS extends Singularity {
* RAM cost: 0.2 GB
*/
getSharePower(): number;
enums: NSEnums;
}
/** @public */
export declare interface NSEnums {
toast: typeof ToastVariant;
}
/**
@ -4671,8 +4728,10 @@ export declare interface Office {
maxMor: number;
/** Name of all the employees */
employees: string[];
/** Positions of the employees */
/** Production of the employees */
employeeProd: EmployeeJobs;
/** Positions of the employees */
employeeJobs: EmployeeJobs;
}
/**
@ -4947,10 +5006,14 @@ export declare interface ProcessInfo {
export declare interface Product {
/** Name of the product */
name: string;
/** Demand for the product */
dmd: number;
/** Competition for the product */
cmp: number;
/** Demand for the product, only present if "Market Research - Demand" unlocked */
dmd: number | undefined;
/** Competition for the product, only present if "Market Research - Competition" unlocked */
cmp: number | undefined;
/** Product Rating */
rat: number;
/** Product Properties. The data is \{qlt, per, dur, rel, aes, fea\} */
properties: { [key: string]: number };
/** Production cost */
pCost: number;
/** Sell cost, can be "MP+5" */
@ -4963,24 +5026,66 @@ export declare interface Product {
developmentProgress: number;
}
/**
* @public
*/
export declare interface RecentScript extends RunningScript {
/** Timestamp of when the script was killed */
timeOfDeath: Date;
}
/**
* Reputation formulas
* @public
*/
export declare interface ReputationFormulas {
/**
* Calculate the total required amount of faction reputation to reach a target favor.
* @param favor - target faction favor.
* @returns The calculated faction reputation required.
*/
calculateFavorToRep(favor: number): number;
/**
* Calculate the resulting faction favor of a total amount of reputation.
* (Faction favor is gained whenever you install an Augmentation.)
* @param rep - amount of reputation.
* @returns The calculated faction favor.
*/
calculateRepToFavor(rep: number): number;
}
/**
* @public
*/
export declare interface RunningScript {
/** Arguments the script was called with */
args: string[];
/** Filename of the script */
filename: string;
/**
* Script logs as an array. The newest log entries are at the bottom.
* Timestamps, if enabled, are placed inside `[brackets]` at the start of each line.
**/
logs: string[];
/** Total amount of hacking experience earned from this script when offline */
offlineExpGained: number;
/** Total amount of money made by this script when offline */
offlineMoneyMade: number;
/** Offline running time of the script, in seconds **/
/** Number of seconds that the script has been running offline */
offlineRunningTime: number;
/** Total amount of hacking experience earned from this script when online */
onlineExpGained: number;
/** Total amount of money made by this script when online */
onlineMoneyMade: number;
/** Online running time of the script, in seconds **/
/** Number of seconds that this script has been running online */
onlineRunningTime: number;
/** Process ID. Must be an integer */
pid: number;
/** How much RAM this script uses for ONE thread */
ramUsage: number;
/** Hostname of the server on which this script runs */
server: string;
/** Number of threads that this script runs with */
threads: number;
}
@ -5750,11 +5855,8 @@ export declare interface Singularity {
* Hospitalize the player.
* @remarks
* RAM cost: 0.25 GB * 16/4/1
*
*
* @returns The cost of the hospitalization.
*/
hospitalize(): number;
hospitalize(): void;
/**
* Soft reset the game.
@ -6028,9 +6130,9 @@ export declare interface Sleeve {
* @param sleeveNumber - Index of the sleeve to work for the faction.
* @param factionName - Name of the faction to work for.
* @param factionWorkType - Name of the action to perform for this faction.
* @returns True if the sleeve started working on this faction, false otherwise.
* @returns True if the sleeve started working on this faction, false otherwise, can also throw on errors
*/
setToFactionWork(sleeveNumber: number, factionName: string, factionWorkType: string): boolean;
setToFactionWork(sleeveNumber: number, factionName: string, factionWorkType: string): boolean | undefined;
/**
* Set a sleeve to work for a company.
@ -6729,6 +6831,17 @@ export declare interface TIX {
purchaseTixApi(): boolean;
}
/** @public */
export declare enum ToastVariant {
SUCCESS = "success",
WARNING = "warning",
ERROR = "error",
INFO = "info",
}
/** @public */
export declare type ToastVariantValues = `${ToastVariant}`;
/**
* User Interface API.
* @public

4
dist/main.bundle.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

42
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -5,10 +5,10 @@ Grafting
Grafting is an experimental process through which you can obtain the benefits of
Augmentations, without needing to reboot your body.
In order to graft, you must first purchase a blueprint for and craft the Augmentation.
This can be done at VitaLife in New Tokyo, where you'll find a shady researcher with
questionable connections. Once you purchase a blueprint, you will start crafting the
Augmentation, and it will be grafted to your body once complete.
Grafting can be done at VitaLife in New Tokyo, where you'll find a shady researcher with
questionable connections. From there, you can spend a sum of money to begin grafting
Augmentations. This will take some time. When done, the Augmentation will be applied to
your character without needing to install.
Be warned, some who have tested grafting have reported an unidentified malware. Dubbed
"Entropy", this virus seems to grow in potency as more Augmentations are grafted,

@ -93,9 +93,15 @@ The list contains the name of (i.e. the value returned by
| Subarray with Maximum Sum | | Given an array of integers, find the contiguous subarray (containing |
| | | at least one number) which has the largest sum and return that sum. |
+------------------------------------+------------------------------------------------------------------------------------------+
| Total Ways to Sum | | Given a number, how many different ways can that number be written as |
| Total Ways to Sum | | Given a number, how many different distinct ways can that number be written as |
| | | a sum of at least two positive integers? |
+------------------------------------+------------------------------------------------------------------------------------------+
| Total Ways to Sum II | | You are given an array with two elements. The first element is an integer n. |
| | | The second element is an array of numbers representing the set of available integers. |
| | | How many different distinct ways can that number n be written as |
| | | a sum of integers contained in the given set? |
| | | You may use each integer in the set zero or more times. |
+------------------------------------+------------------------------------------------------------------------------------------+
| Spiralize Matrix | | Given an array of array of numbers representing a 2D matrix, return the |
| | | elements of that matrix in clockwise spiral order. |
| | | |
@ -115,6 +121,16 @@ The list contains the name of (i.e. the value returned by
| | | Assuming you are initially positioned at the start of the array, determine |
| | | whether you are able to reach the last index of the array. |
+------------------------------------+------------------------------------------------------------------------------------------+
| Array Jumping Game II | | You are given an array of integers where each element represents the |
| | | maximum possible jump distance from that position. For example, if you |
| | | are at position i and your maximum jump length is n, then you can jump |
| | | to any position from i to i+n. |
| | | |
| | | Assuming you are initially positioned at the start of the array, determine |
| | | the minimum number of jumps to reach the end of the array. |
| | | |
| | | If it's impossible to reach the end, then the answer should be 0. |
+------------------------------------+------------------------------------------------------------------------------------------+
| Merge Overlapping Intervals | | Given an array of intervals, merge all overlapping intervals. An interval |
| | | is an array with two numbers, where the first number is always less than |
| | | the second (e.g. [1, 5]). |
@ -196,6 +212,23 @@ The list contains the name of (i.e. the value returned by
| | | |
| | | Determine how many unique paths there are from start to finish. |
+------------------------------------+------------------------------------------------------------------------------------------+
| Shortest Path in a Grid | | You are given a 2D array of numbers (array of array of numbers) representing |
| | | a grid. The 2D array contains 1's and 0's, where 1 represents an obstacle and |
| | | 0 represents a free space. |
| | | |
| | | Assume you are initially positioned in top-left corner of that grid and that you |
| | | are trying to reach the bottom-right corner. In each step, you may move to the up, |
| | | down, left or right. Furthermore, you cannot move onto spaces which have obstacles. |
| | | |
| | | Determine if paths exist from start to destination, and find the shortest one. |
| | | |
| | | Examples: |
| | | [[0,1,0,0,0], |
| | | [0,0,0,1,0]] -> "DRRURRD" |
| | | [[0,1], |
| | | [1,0]] -> "" |
| | | |
+------------------------------------+------------------------------------------------------------------------------------------+
| Sanitize Parentheses in Expression | | Given a string with parentheses and letters, remove the minimum number of invalid |
| | | parentheses in order to validate the string. If there are multiple minimal ways |
| | | to validate the string, provide all of the possible results. |

@ -22,109 +22,96 @@ function error_process(err, error_callback) {
if (err && error_callback) error_callback(err);
}
greenworks.ugcGetItems = function (options, ugc_matching_type, ugc_query_type, success_callback, error_callback) {
if (typeof options !== "object") {
error_callback = success_callback;
success_callback = ugc_query_type;
ugc_query_type = ugc_matching_type;
ugc_matching_type = options;
options = {
app_id: greenworks.getAppId(),
page_num: 1,
};
}
greenworks._ugcGetItems(options, ugc_matching_type, ugc_query_type, success_callback, error_callback);
};
if (greenworks) {
greenworks.ugcGetItems = function (options, ugc_matching_type, ugc_query_type, success_callback, error_callback) {
if (typeof options !== "object") {
error_callback = success_callback;
success_callback = ugc_query_type;
ugc_query_type = ugc_matching_type;
ugc_matching_type = options;
options = {
app_id: greenworks.getAppId(),
page_num: 1,
};
}
greenworks._ugcGetItems(options, ugc_matching_type, ugc_query_type, success_callback, error_callback);
};
greenworks.ugcGetUserItems = function (
options,
ugc_matching_type,
ugc_list_sort_order,
ugc_list,
success_callback,
error_callback,
) {
if (typeof options !== "object") {
error_callback = success_callback;
success_callback = ugc_list;
ugc_list = ugc_list_sort_order;
ugc_list_sort_order = ugc_matching_type;
ugc_matching_type = options;
options = {
app_id: greenworks.getAppId(),
page_num: 1,
};
}
greenworks._ugcGetUserItems(
greenworks.ugcGetUserItems = function (
options,
ugc_matching_type,
ugc_list_sort_order,
ugc_list,
success_callback,
error_callback,
);
};
) {
if (typeof options !== "object") {
error_callback = success_callback;
success_callback = ugc_list;
ugc_list = ugc_list_sort_order;
ugc_list_sort_order = ugc_matching_type;
ugc_matching_type = options;
options = {
app_id: greenworks.getAppId(),
page_num: 1,
};
}
greenworks._ugcGetUserItems(
options,
ugc_matching_type,
ugc_list_sort_order,
ugc_list,
success_callback,
error_callback,
);
};
greenworks.ugcSynchronizeItems = function (options, sync_dir, success_callback, error_callback) {
if (typeof options !== "object") {
error_callback = success_callback;
success_callback = sync_dir;
sync_dir = options;
options = {
app_id: greenworks.getAppId(),
page_num: 1,
};
}
greenworks._ugcSynchronizeItems(options, sync_dir, success_callback, error_callback);
};
greenworks.ugcSynchronizeItems = function (options, sync_dir, success_callback, error_callback) {
if (typeof options !== "object") {
error_callback = success_callback;
success_callback = sync_dir;
sync_dir = options;
options = {
app_id: greenworks.getAppId(),
page_num: 1,
};
}
greenworks._ugcSynchronizeItems(options, sync_dir, success_callback, error_callback);
};
greenworks.publishWorkshopFile = function (
options,
file_path,
image_path,
title,
description,
success_callback,
error_callback,
) {
if (typeof options !== "object") {
error_callback = success_callback;
success_callback = description;
description = title;
title = image_path;
image_path = file_path;
file_path = options;
options = {
app_id: greenworks.getAppId(),
tags: [],
};
}
greenworks._publishWorkshopFile(options, file_path, image_path, title, description, success_callback, error_callback);
};
greenworks.publishWorkshopFile = function (
options,
file_path,
image_path,
title,
description,
success_callback,
error_callback,
) {
if (typeof options !== "object") {
error_callback = success_callback;
success_callback = description;
description = title;
title = image_path;
image_path = file_path;
file_path = options;
options = {
app_id: greenworks.getAppId(),
tags: [],
};
}
greenworks._publishWorkshopFile(
options,
file_path,
image_path,
title,
description,
success_callback,
error_callback,
);
};
greenworks.updatePublishedWorkshopFile = function (
options,
published_file_handle,
file_path,
image_path,
title,
description,
success_callback,
error_callback,
) {
if (typeof options !== "object") {
error_callback = success_callback;
success_callback = description;
description = title;
title = image_path;
image_path = file_path;
file_path = published_file_handle;
published_file_handle = options;
options = {
tags: [], // No tags are set
};
}
greenworks._updatePublishedWorkshopFile(
greenworks.updatePublishedWorkshopFile = function (
options,
published_file_handle,
file_path,
@ -133,161 +120,184 @@ greenworks.updatePublishedWorkshopFile = function (
description,
success_callback,
error_callback,
);
};
) {
if (typeof options !== "object") {
error_callback = success_callback;
success_callback = description;
description = title;
title = image_path;
image_path = file_path;
file_path = published_file_handle;
published_file_handle = options;
options = {
tags: [], // No tags are set
};
}
greenworks._updatePublishedWorkshopFile(
options,
published_file_handle,
file_path,
image_path,
title,
description,
success_callback,
error_callback,
);
};
// An utility function for publish related APIs.
// It processes remains steps after saving files to Steam Cloud.
function file_share_process(file_name, image_name, next_process_func, error_callback, progress_callback) {
if (progress_callback) progress_callback("Completed on saving files on Steam Cloud.");
greenworks.fileShare(
// An utility function for publish related APIs.
// It processes remains steps after saving files to Steam Cloud.
function file_share_process(file_name, image_name, next_process_func, error_callback, progress_callback) {
if (progress_callback) progress_callback("Completed on saving files on Steam Cloud.");
greenworks.fileShare(
file_name,
function () {
greenworks.fileShare(
image_name,
function () {
next_process_func();
},
function (err) {
error_process(err, error_callback);
},
);
},
function (err) {
error_process(err, error_callback);
},
);
}
// Publishing user generated content(ugc) to Steam contains following steps:
// 1. Save file and image to Steam Cloud.
// 2. Share the file and image.
// 3. publish the file to workshop.
greenworks.ugcPublish = function (
file_name,
function () {
greenworks.fileShare(
title,
description,
image_name,
success_callback,
error_callback,
progress_callback,
) {
var publish_file_process = function () {
if (progress_callback) progress_callback("Completed on sharing files.");
greenworks.publishWorkshopFile(
file_name,
image_name,
function () {
next_process_func();
title,
description,
function (publish_file_id) {
success_callback(publish_file_id);
},
function (err) {
error_process(err, error_callback);
},
);
},
function (err) {
error_process(err, error_callback);
},
);
};
greenworks.saveFilesToCloud(
[file_name, image_name],
function () {
file_share_process(file_name, image_name, publish_file_process, error_callback, progress_callback);
},
function (err) {
error_process(err, error_callback);
},
);
};
// Update publish ugc steps:
// 1. Save new file and image to Steam Cloud.
// 2. Share file and images.
// 3. Update published file.
greenworks.ugcPublishUpdate = function (
published_file_id,
file_name,
title,
description,
image_name,
success_callback,
error_callback,
progress_callback,
) {
var update_published_file_process = function () {
if (progress_callback) progress_callback("Completed on sharing files.");
greenworks.updatePublishedWorkshopFile(
published_file_id,
file_name,
image_name,
title,
description,
function () {
success_callback();
},
function (err) {
error_process(err, error_callback);
},
);
};
greenworks.saveFilesToCloud(
[file_name, image_name],
function () {
file_share_process(file_name, image_name, update_published_file_process, error_callback, progress_callback);
},
function (err) {
error_process(err, error_callback);
},
);
};
// Greenworks Utils APIs implmentation.
greenworks.Utils.move = function (source_dir, target_dir, success_callback, error_callback) {
fs.rename(source_dir, target_dir, function (err) {
if (err) {
if (error_callback) error_callback(err);
return;
}
if (success_callback) success_callback();
});
};
greenworks.init = function () {
if (this.initAPI()) return true;
if (!this.isSteamRunning()) throw new Error("Steam initialization failed. Steam is not running.");
var appId;
try {
appId = fs.readFileSync("steam_appid.txt", "utf8");
} catch (e) {
throw new Error(
"Steam initialization failed. Steam is running," +
"but steam_appid.txt is missing. Expected to find it in: " +
require("path").resolve("steam_appid.txt"),
);
}
if (!/^\d+ *\r?\n?$/.test(appId)) {
throw new Error(
"Steam initialization failed. " +
"steam_appid.txt appears to be invalid; " +
"it should contain a numeric ID: " +
appId,
);
}
throw new Error(
"Steam initialization failed, but Steam is running, " +
"and steam_appid.txt is present and valid." +
"Maybe that's not really YOUR app ID? " +
appId.trim(),
);
};
var EventEmitter = require("events").EventEmitter;
greenworks.__proto__ = EventEmitter.prototype;
EventEmitter.call(greenworks);
greenworks._steam_events.on = function () {
greenworks.emit.apply(greenworks, arguments);
};
process.versions["greenworks"] = greenworks._version;
}
// Publishing user generated content(ugc) to Steam contains following steps:
// 1. Save file and image to Steam Cloud.
// 2. Share the file and image.
// 3. publish the file to workshop.
greenworks.ugcPublish = function (
file_name,
title,
description,
image_name,
success_callback,
error_callback,
progress_callback,
) {
var publish_file_process = function () {
if (progress_callback) progress_callback("Completed on sharing files.");
greenworks.publishWorkshopFile(
file_name,
image_name,
title,
description,
function (publish_file_id) {
success_callback(publish_file_id);
},
function (err) {
error_process(err, error_callback);
},
);
};
greenworks.saveFilesToCloud(
[file_name, image_name],
function () {
file_share_process(file_name, image_name, publish_file_process, error_callback, progress_callback);
},
function (err) {
error_process(err, error_callback);
},
);
};
// Update publish ugc steps:
// 1. Save new file and image to Steam Cloud.
// 2. Share file and images.
// 3. Update published file.
greenworks.ugcPublishUpdate = function (
published_file_id,
file_name,
title,
description,
image_name,
success_callback,
error_callback,
progress_callback,
) {
var update_published_file_process = function () {
if (progress_callback) progress_callback("Completed on sharing files.");
greenworks.updatePublishedWorkshopFile(
published_file_id,
file_name,
image_name,
title,
description,
function () {
success_callback();
},
function (err) {
error_process(err, error_callback);
},
);
};
greenworks.saveFilesToCloud(
[file_name, image_name],
function () {
file_share_process(file_name, image_name, update_published_file_process, error_callback, progress_callback);
},
function (err) {
error_process(err, error_callback);
},
);
};
// Greenworks Utils APIs implmentation.
greenworks.Utils.move = function (source_dir, target_dir, success_callback, error_callback) {
fs.rename(source_dir, target_dir, function (err) {
if (err) {
if (error_callback) error_callback(err);
return;
}
if (success_callback) success_callback();
});
};
greenworks.init = function () {
if (this.initAPI()) return true;
if (!this.isSteamRunning()) throw new Error("Steam initialization failed. Steam is not running.");
var appId;
try {
appId = fs.readFileSync("steam_appid.txt", "utf8");
} catch (e) {
throw new Error(
"Steam initialization failed. Steam is running," +
"but steam_appid.txt is missing. Expected to find it in: " +
require("path").resolve("steam_appid.txt"),
);
}
if (!/^\d+ *\r?\n?$/.test(appId)) {
throw new Error(
"Steam initialization failed. " +
"steam_appid.txt appears to be invalid; " +
"it should contain a numeric ID: " +
appId,
);
}
throw new Error(
"Steam initialization failed, but Steam is running, " +
"and steam_appid.txt is present and valid." +
"Maybe that's not really YOUR app ID? " +
appId.trim(),
);
};
var EventEmitter = require("events").EventEmitter;
greenworks.__proto__ = EventEmitter.prototype;
EventEmitter.call(greenworks);
greenworks._steam_events.on = function () {
greenworks.emit.apply(greenworks, arguments);
};
process.versions["greenworks"] = greenworks._version;
module.exports = greenworks;

@ -25,7 +25,7 @@ process.on("uncaughtException", function () {
// We want to fail gracefully if we cannot connect to Steam
try {
if (greenworks.init()) {
if (greenworks && greenworks.init()) {
log.info("Steam API has been initialized.");
} else {
const error = "Steam API has failed to initialize.";

@ -8,6 +8,39 @@ const storage = require("./storage");
const config = new Config();
function getMenu(window) {
const canZoomIn = utils.getZoomFactor() <= 2;
const zoomIn = () => {
const currentZoom = utils.getZoomFactor();
const newZoom = currentZoom + 0.1;
if (newZoom <= 2.0) {
utils.setZoomFactor(window, newZoom);
refreshMenu(window);
} else {
log.log("Max zoom out");
utils.writeToast(window, "Cannot zoom in anymore", "warning");
}
};
const canZoomOut = utils.getZoomFactor() >= 0.5;
const zoomOut = () => {
const currentZoom = utils.getZoomFactor();
const newZoom = currentZoom - 0.1;
if (newZoom >= 0.5) {
utils.setZoomFactor(window, newZoom);
refreshMenu(window);
} else {
log.log("Max zoom in");
utils.writeToast(window, "Cannot zoom out anymore", "warning");
}
};
const canResetZoom = utils.getZoomFactor() !== 1;
const resetZoom = () => {
utils.setZoomFactor(window, 1);
refreshMenu(window);
log.log("Reset zoom");
};
return Menu.buildFromTemplate([
{
label: "File",
@ -289,45 +322,45 @@ function getMenu(window) {
submenu: [
{
label: "Zoom In",
enabled: utils.getZoomFactor() <= 2,
enabled: canZoomIn,
accelerator: "CommandOrControl+numadd",
click: () => {
const currentZoom = utils.getZoomFactor();
const newZoom = currentZoom + 0.1;
if (newZoom <= 2.0) {
utils.setZoomFactor(window, newZoom);
refreshMenu(window);
} else {
log.log("Max zoom out");
utils.writeToast(window, "Cannot zoom in anymore", "warning");
}
},
click: zoomIn,
},
{
label: "Zoom In (non numpad)",
enabled: canZoomIn,
visible: false,
accelerator: "CommandOrControl+Plus",
acceleratorWorksWhenHidden: true,
click: zoomIn,
},
{
label: "Zoom Out",
enabled: utils.getZoomFactor() >= 0.5,
enabled: canZoomOut,
accelerator: "CommandOrControl+numsub",
click: () => {
const currentZoom = utils.getZoomFactor();
const newZoom = currentZoom - 0.1;
if (newZoom >= 0.5) {
utils.setZoomFactor(window, newZoom);
refreshMenu(window);
} else {
log.log("Max zoom in");
utils.writeToast(window, "Cannot zoom out anymore", "warning");
}
},
click: zoomOut,
},
{
label: "Zoom Out (non numpad)",
enabled: canZoomOut,
accelerator: "CommandOrControl+-",
visible: false,
acceleratorWorksWhenHidden: true,
click: zoomOut,
},
{
label: "Reset Zoom",
enabled: utils.getZoomFactor() !== 1,
enabled: canResetZoom,
accelerator: "CommandOrControl+num0",
click: () => {
utils.setZoomFactor(window, 1);
refreshMenu(window);
log.log("Reset zoom");
},
click: resetZoom,
},
{
label: "Reset Zoom (non numpad)",
enabled: canResetZoom,
accelerator: "CommandOrControl+0",
visible: false,
acceleratorWorksWhenHidden: true,
click: resetZoom,
},
],
},

@ -1,12 +1,12 @@
{
"name": "bitburner",
"version": "1.0.0",
"version": "1.6.3",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "bitburner",
"version": "1.0.0",
"version": "1.6.3",
"dependencies": {
"electron-config": "^2.0.0",
"electron-log": "^4.4.4",

@ -1,6 +1,6 @@
{
"name": "bitburner",
"version": "1.0.0",
"version": "1.6.3",
"description": "A cyberpunk-themed programming incremental game",
"main": "main.js",
"author": "Daniel Xie & Olivier Gagnon",

@ -73,5 +73,5 @@
<link rel="shortcut icon" href="favicon.ico"></head>
<body>
<div id="root"/>
<script type="text/javascript" src="dist/vendor.bundle.js"></script><script type="text/javascript" src="main.bundle.js"></script></body>
<script type="text/javascript" src="dist/vendor.bundle.js"></script><script type="text/javascript" src="dist/main.bundle.js"></script></body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,11 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [ActiveFragment](./bitburner.activefragment.md) &gt; [avgCharge](./bitburner.activefragment.avgcharge.md)
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [ActiveFragment](./bitburner.activefragment.md) &gt; [highestCharge](./bitburner.activefragment.highestcharge.md)
## ActiveFragment.avgCharge property
## ActiveFragment.highestCharge property
<b>Signature:</b>
```typescript
avgCharge: number;
highestCharge: number;
```

@ -15,7 +15,7 @@ export interface ActiveFragment
| Property | Type | Description |
| --- | --- | --- |
| [avgCharge](./bitburner.activefragment.avgcharge.md) | number | |
| [highestCharge](./bitburner.activefragment.highestcharge.md) | number | |
| [id](./bitburner.activefragment.id.md) | number | |
| [numCharge](./bitburner.activefragment.numcharge.md) | number | |
| [rotation](./bitburner.activefragment.rotation.md) | number | |

@ -49,7 +49,7 @@ export interface BitNodeMultipliers
| [PurchasedServerCost](./bitburner.bitnodemultipliers.purchasedservercost.md) | number | Influence how much it costs to purchase a server |
| [PurchasedServerLimit](./bitburner.bitnodemultipliers.purchasedserverlimit.md) | number | Influences the maximum number of purchased servers you can have |
| [PurchasedServerMaxRam](./bitburner.bitnodemultipliers.purchasedservermaxram.md) | number | Influences the maximum allowed RAM for a purchased server |
| [PurchasedServerSoftCap](./bitburner.bitnodemultipliers.purchasedserversoftcap.md) | number | Influences cost of any purchased server at or above 128GB |
| [PurchasedServerSoftcap](./bitburner.bitnodemultipliers.purchasedserversoftcap.md) | number | Influences cost of any purchased server at or above 128GB |
| [RepToDonateToFaction](./bitburner.bitnodemultipliers.reptodonatetofaction.md) | number | Influences the minimum favor the player must have with a faction before they can donate to gain rep. |
| [ScriptHackMoney](./bitburner.bitnodemultipliers.scripthackmoney.md) | number | Influences how much the money on a server can be reduced when a script performs a hack against it. |
| [ScriptHackMoneyGain](./bitburner.bitnodemultipliers.scripthackmoneygain.md) | number | Influences how much of the money stolen by a scripted hack will be added to the player's money. |

@ -1,13 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [BitNodeMultipliers](./bitburner.bitnodemultipliers.md) &gt; [PurchasedServerSoftCap](./bitburner.bitnodemultipliers.purchasedserversoftcap.md)
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [BitNodeMultipliers](./bitburner.bitnodemultipliers.md) &gt; [PurchasedServerSoftcap](./bitburner.bitnodemultipliers.purchasedserversoftcap.md)
## BitNodeMultipliers.PurchasedServerSoftCap property
## BitNodeMultipliers.PurchasedServerSoftcap property
Influences cost of any purchased server at or above 128GB
<b>Signature:</b>
```typescript
PurchasedServerSoftCap: number;
PurchasedServerSoftcap: number;
```

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [CharacterInfo](./bitburner.characterinfo.md) &gt; [agilityExp](./bitburner.characterinfo.agilityexp.md)
## CharacterInfo.agilityExp property
total agility exp
<b>Signature:</b>
```typescript
agilityExp: number;
```

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [CharacterInfo](./bitburner.characterinfo.md) &gt; [charismaExp](./bitburner.characterinfo.charismaexp.md)
## CharacterInfo.charismaExp property
total charisma exp
<b>Signature:</b>
```typescript
charismaExp: number;
```

@ -1,13 +0,0 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [CharacterInfo](./bitburner.characterinfo.md) &gt; [company](./bitburner.characterinfo.company.md)
## CharacterInfo.company property
Array of all companies at which you have jobs
<b>Signature:</b>
```typescript
company: string[];
```

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [CharacterInfo](./bitburner.characterinfo.md) &gt; [defenseExp](./bitburner.characterinfo.defenseexp.md)
## CharacterInfo.defenseExp property
total defense exp
<b>Signature:</b>
```typescript
defenseExp: number;
```

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [CharacterInfo](./bitburner.characterinfo.md) &gt; [dexterityExp](./bitburner.characterinfo.dexterityexp.md)
## CharacterInfo.dexterityExp property
total dexterity exp
<b>Signature:</b>
```typescript
dexterityExp: number;
```

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [CharacterInfo](./bitburner.characterinfo.md) &gt; [hackingExp](./bitburner.characterinfo.hackingexp.md)
## CharacterInfo.hackingExp property
total hacking exp
<b>Signature:</b>
```typescript
hackingExp: number;
```

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [CharacterInfo](./bitburner.characterinfo.md) &gt; [jobs](./bitburner.characterinfo.jobs.md)
## CharacterInfo.jobs property
Array of all jobs
<b>Signature:</b>
```typescript
jobs: string[];
```

@ -1,13 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [CharacterInfo](./bitburner.characterinfo.md) &gt; [jobTitle](./bitburner.characterinfo.jobtitle.md)
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [CharacterInfo](./bitburner.characterinfo.md) &gt; [jobTitles](./bitburner.characterinfo.jobtitles.md)
## CharacterInfo.jobTitle property
## CharacterInfo.jobTitles property
Array of job positions for all companies you are employed at. Same order as 'jobs'
<b>Signature:</b>
```typescript
jobTitle: string[];
jobTitles: string[];
```

@ -15,14 +15,20 @@ export interface CharacterInfo
| Property | Type | Description |
| --- | --- | --- |
| [agilityExp](./bitburner.characterinfo.agilityexp.md) | number | total agility exp |
| [bitnode](./bitburner.characterinfo.bitnode.md) | number | Current BitNode number |
| [charismaExp](./bitburner.characterinfo.charismaexp.md) | number | total charisma exp |
| [city](./bitburner.characterinfo.city.md) | string | Name of city you are currently in |
| [company](./bitburner.characterinfo.company.md) | string\[\] | Array of all companies at which you have jobs |
| [defenseExp](./bitburner.characterinfo.defenseexp.md) | number | total defense exp |
| [dexterityExp](./bitburner.characterinfo.dexterityexp.md) | number | total dexterity exp |
| [factions](./bitburner.characterinfo.factions.md) | string\[\] | Array of factions you are currently a member of |
| [hackingExp](./bitburner.characterinfo.hackingexp.md) | number | total hacking exp |
| [hp](./bitburner.characterinfo.hp.md) | number | Current health points |
| [jobTitle](./bitburner.characterinfo.jobtitle.md) | string\[\] | Array of job positions for all companies you are employed at. Same order as 'jobs' |
| [jobs](./bitburner.characterinfo.jobs.md) | string\[\] | Array of all jobs |
| [jobTitles](./bitburner.characterinfo.jobtitles.md) | string\[\] | Array of job positions for all companies you are employed at. Same order as 'jobs' |
| [maxHp](./bitburner.characterinfo.maxhp.md) | number | Maximum health points |
| [mult](./bitburner.characterinfo.mult.md) | [CharacterMult](./bitburner.charactermult.md) | Object with many of the player's multipliers from Augmentations/Source Files |
| [strengthExp](./bitburner.characterinfo.strengthexp.md) | number | total strength exp |
| [timeWorked](./bitburner.characterinfo.timeworked.md) | number | Timed worked in ms |
| [tor](./bitburner.characterinfo.tor.md) | boolean | Boolean indicating whether or not you have a tor router |
| [workAgiExpGain](./bitburner.characterinfo.workagiexpgain.md) | number | Agi experience earned so far from work |

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [CharacterInfo](./bitburner.characterinfo.md) &gt; [strengthExp](./bitburner.characterinfo.strengthexp.md)
## CharacterInfo.strengthExp property
total strength exp
<b>Signature:</b>
```typescript
strengthExp: number;
```

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [CharacterMult](./bitburner.charactermult.md) &gt; [charisma](./bitburner.charactermult.charisma.md)
## CharacterMult.charisma property
Charisma stat
<b>Signature:</b>
```typescript
charisma: number;
```

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [CharacterMult](./bitburner.charactermult.md) &gt; [charismaExp](./bitburner.charactermult.charismaexp.md)
## CharacterMult.charismaExp property
Charisma exp
<b>Signature:</b>
```typescript
charismaExp: number;
```

@ -17,6 +17,8 @@ export interface CharacterMult
| --- | --- | --- |
| [agility](./bitburner.charactermult.agility.md) | number | Agility stat |
| [agilityExp](./bitburner.charactermult.agilityexp.md) | number | Agility exp |
| [charisma](./bitburner.charactermult.charisma.md) | number | Charisma stat |
| [charismaExp](./bitburner.charactermult.charismaexp.md) | number | Charisma exp |
| [companyRep](./bitburner.charactermult.companyrep.md) | number | Company reputation |
| [crimeMoney](./bitburner.charactermult.crimemoney.md) | number | Money earned from crimes |
| [crimeSuccess](./bitburner.charactermult.crimesuccess.md) | number | Crime success chance |

@ -24,5 +24,6 @@ You need Formulas.exe on your home computer to use this API.
| [hacking](./bitburner.formulas.hacking.md) | [HackingFormulas](./bitburner.hackingformulas.md) | Hacking formulas |
| [hacknetNodes](./bitburner.formulas.hacknetnodes.md) | [HacknetNodesFormulas](./bitburner.hacknetnodesformulas.md) | Hacknet Nodes formulas |
| [hacknetServers](./bitburner.formulas.hacknetservers.md) | [HacknetServersFormulas](./bitburner.hacknetserversformulas.md) | Hacknet Servers formulas |
| [reputation](./bitburner.formulas.reputation.md) | [ReputationFormulas](./bitburner.reputationformulas.md) | Reputation formulas |
| [skills](./bitburner.formulas.skills.md) | [SkillsFormulas](./bitburner.skillsformulas.md) | Skills formulas |

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [Formulas](./bitburner.formulas.md) &gt; [reputation](./bitburner.formulas.reputation.md)
## Formulas.reputation property
Reputation formulas
<b>Signature:</b>
```typescript
reputation: ReputationFormulas;
```

@ -39,7 +39,7 @@ Returns the number of hashes required for the specified upgrade. The name of the
// NS1:
var upgradeName = "Sell for Corporation Funds";
if (hacknet.numHashes() > hacknet.hashCost(upgradeName)) {
hacknet.spendHashes(upgName);
hacknet.spendHashes(upgradeName);
}
```
@ -50,7 +50,7 @@ if (hacknet.numHashes() > hacknet.hashCost(upgradeName)) {
// NS2:
const upgradeName = "Sell for Corporation Funds";
if (ns.hacknet.numHashes() > ns.hacknet.hashCost(upgradeName)) {
ns.hacknet.spendHashes(upgName);
ns.hacknet.spendHashes(upgradeName);
}
```

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [Material](./bitburner.material.md) &gt; [cmp](./bitburner.material.cmp.md)
## Material.cmp property
Competition for the material, only present if "Market Research - Competition" unlocked
<b>Signature:</b>
```typescript
cmp: number | undefined;
```

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [Material](./bitburner.material.md) &gt; [dmd](./bitburner.material.dmd.md)
## Material.dmd property
Demand for the material, only present if "Market Research - Demand" unlocked
<b>Signature:</b>
```typescript
dmd: number | undefined;
```

@ -16,6 +16,8 @@ interface Material
| Property | Type | Description |
| --- | --- | --- |
| [cmp](./bitburner.material.cmp.md) | number \| undefined | Competition for the material, only present if "Market Research - Competition" unlocked |
| [dmd](./bitburner.material.dmd.md) | number \| undefined | Demand for the material, only present if "Market Research - Demand" unlocked |
| [name](./bitburner.material.name.md) | string | Name of the material |
| [prod](./bitburner.material.prod.md) | number | Amount of material produced |
| [qlt](./bitburner.material.qlt.md) | number | Quality of the material |

@ -10,6 +10,7 @@
| --- | --- |
| [OrderTypes](./bitburner.ordertypes.md) | |
| [PositionTypes](./bitburner.positiontypes.md) | |
| [ToastVariant](./bitburner.toastvariant.md) | |
## Interfaces
@ -59,12 +60,15 @@
| [NetscriptPort](./bitburner.netscriptport.md) | Object representing a port. A port is a serialized queue. |
| [NodeStats](./bitburner.nodestats.md) | Object representing all the values related to a hacknet node. |
| [NS](./bitburner.ns.md) | Collection of all functions passed to scripts |
| [NSEnums](./bitburner.nsenums.md) | |
| [Office](./bitburner.office.md) | Office for a division in a city. |
| [OfficeAPI](./bitburner.officeapi.md) | Corporation Office API |
| [Player](./bitburner.player.md) | |
| [PlayerSkills](./bitburner.playerskills.md) | Short summary of the players skills. |
| [ProcessInfo](./bitburner.processinfo.md) | A single process on a server. |
| [Product](./bitburner.product.md) | Product in a warehouse |
| [RecentScript](./bitburner.recentscript.md) | |
| [ReputationFormulas](./bitburner.reputationformulas.md) | Reputation formulas |
| [RunningScript](./bitburner.runningscript.md) | |
| [Server](./bitburner.server.md) | A single server. |
| [Singularity](./bitburner.singularity.md) | Singularity API |
@ -88,4 +92,5 @@
| Type Alias | Description |
| --- | --- |
| [FilenameOrPID](./bitburner.filenameorpid.md) | |
| [ToastVariantValues](./bitburner.toastvariantvalues.md) | |

@ -9,7 +9,7 @@ Suspends the script for n milliseconds. Doesn't block with concurrent calls.
<b>Signature:</b>
```typescript
asleep(millis: number): Promise<void>;
asleep(millis: number): Promise<true>;
```
## Parameters
@ -20,7 +20,7 @@ asleep(millis: number): Promise<void>;
<b>Returns:</b>
Promise&lt;void&gt;
Promise&lt;true&gt;
## Remarks

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [NS](./bitburner.ns.md) &gt; [enums](./bitburner.ns.enums.md)
## NS.enums property
<b>Signature:</b>
```typescript
enums: NSEnums;
```

@ -0,0 +1,35 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [NS](./bitburner.ns.md) &gt; [getRecentScripts](./bitburner.ns.getrecentscripts.md)
## NS.getRecentScripts() method
Get an array of recently killed scripts across all servers.
<b>Signature:</b>
```typescript
getRecentScripts(): RecentScript[];
```
<b>Returns:</b>
[RecentScript](./bitburner.recentscript.md)<!-- -->\[\]
Array with information about previously killed scripts.
## Remarks
RAM cost: 0.2 GB
The most recently killed script is the first element in the array. Note that there is a maximum number of recently killed scripts which are tracked. This is configurable in the game's options as `Recently killed scripts size`<!-- -->.
## Example
```ts
let recentScripts = ns.getRecentScripts();
let mostRecent = recentScripts.shift()
if (mostRecent)
ns.tprint(mostRecent.logs.join('\n'))
```

@ -9,7 +9,7 @@ Get general info about a running script.
<b>Signature:</b>
```typescript
getRunningScript(filename?: FilenameOrPID, hostname?: string, ...args: (string | number)[]): RunningScript;
getRunningScript(filename?: FilenameOrPID, hostname?: string, ...args: (string | number)[]): RunningScript | null;
```
## Parameters
@ -22,7 +22,7 @@ getRunningScript(filename?: FilenameOrPID, hostname?: string, ...args: (string |
<b>Returns:</b>
[RunningScript](./bitburner.runningscript.md)
[RunningScript](./bitburner.runningscript.md) \| null
The info about the running script if found, and null otherwise.

@ -9,7 +9,7 @@ Get the security increase for a number of thread.
<b>Signature:</b>
```typescript
hackAnalyzeSecurity(threads: number): number;
hackAnalyzeSecurity(threads: number, hostname?: string): number;
```
## Parameters
@ -17,6 +17,7 @@ hackAnalyzeSecurity(threads: number): number;
| Parameter | Type | Description |
| --- | --- | --- |
| threads | number | Amount of threads that will be used. |
| hostname | string | Hostname of the target server. The number of threads is limited to the number needed to hack the servers maximum amount of money. |
<b>Returns:</b>

@ -9,9 +9,8 @@ Collection of all functions passed to scripts
<b>Signature:</b>
```typescript
export interface NS extends Singularity
export interface NS
```
<b>Extends:</b> [Singularity](./bitburner.singularity.md)
## Remarks
@ -45,10 +44,12 @@ export async function main(ns) {
| [bladeburner](./bitburner.ns.bladeburner.md) | [Bladeburner](./bitburner.bladeburner.md) | Namespace for bladeburner functions. |
| [codingcontract](./bitburner.ns.codingcontract.md) | [CodingContract](./bitburner.codingcontract.md) | Namespace for codingcontract functions. |
| [corporation](./bitburner.ns.corporation.md) | [Corporation](./bitburner.corporation.md) | Namespace for corporation functions. RAM cost: 0 GB |
| [enums](./bitburner.ns.enums.md) | [NSEnums](./bitburner.nsenums.md) | |
| [formulas](./bitburner.ns.formulas.md) | [Formulas](./bitburner.formulas.md) | Namespace for formulas functions. |
| [gang](./bitburner.ns.gang.md) | [Gang](./bitburner.gang.md) | Namespace for gang functions. |
| [grafting](./bitburner.ns.grafting.md) | [Grafting](./bitburner.grafting.md) | Namespace for grafting functions. |
| [hacknet](./bitburner.ns.hacknet.md) | [Hacknet](./bitburner.hacknet.md) | Namespace for hacknet functions. |
| [singularity](./bitburner.ns.singularity.md) | [Singularity](./bitburner.singularity.md) | Namespace for singularity functions. RAM cost: 0 GB |
| [sleeve](./bitburner.ns.sleeve.md) | [Sleeve](./bitburner.sleeve.md) | Namespace for sleeve functions. |
| [stanek](./bitburner.ns.stanek.md) | [Stanek](./bitburner.stanek.md) | Namespace for stanek functions. RAM cost: 0 GB |
| [stock](./bitburner.ns.stock.md) | [TIX](./bitburner.tix.md) | Namespace for stock functions. |
@ -88,6 +89,7 @@ export async function main(ns) {
| [getPurchasedServerLimit()](./bitburner.ns.getpurchasedserverlimit.md) | Returns the maximum number of servers you can purchase. |
| [getPurchasedServerMaxRam()](./bitburner.ns.getpurchasedservermaxram.md) | Returns the maximum RAM that a purchased server can have. |
| [getPurchasedServers()](./bitburner.ns.getpurchasedservers.md) | Returns an array with the hostnames of all of the servers you have purchased. |
| [getRecentScripts()](./bitburner.ns.getrecentscripts.md) | Get an array of recently killed scripts across all servers. |
| [getRunningScript(filename, hostname, args)](./bitburner.ns.getrunningscript.md) | Get general info about a running script. |
| [getScriptExpGain()](./bitburner.ns.getscriptexpgain.md) | Get the exp gain of a script. |
| [getScriptExpGain(script, host, args)](./bitburner.ns.getscriptexpgain_1.md) | Get the exp gain of a script. |
@ -117,7 +119,7 @@ export async function main(ns) {
| [hack(host, opts)](./bitburner.ns.hack.md) | Steal a servers money. |
| [hackAnalyze(host)](./bitburner.ns.hackanalyze.md) | Get the part of money stolen with a single thread. |
| [hackAnalyzeChance(host)](./bitburner.ns.hackanalyzechance.md) | Get the chance of successfully hacking a server. |
| [hackAnalyzeSecurity(threads)](./bitburner.ns.hackanalyzesecurity.md) | Get the security increase for a number of thread. |
| [hackAnalyzeSecurity(threads, hostname)](./bitburner.ns.hackanalyzesecurity.md) | Get the security increase for a number of thread. |
| [hackAnalyzeThreads(host, hackAmount)](./bitburner.ns.hackanalyzethreads.md) | Predict the effect of hack. |
| [hasRootAccess(host)](./bitburner.ns.hasrootaccess.md) | Check if your have root access on a server. |
| [httpworm(host)](./bitburner.ns.httpworm.md) | Runs HTTPWorm.exe on a server. |

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [NS](./bitburner.ns.md) &gt; [singularity](./bitburner.ns.singularity.md)
## NS.singularity property
Namespace for singularity functions. RAM cost: 0 GB
<b>Signature:</b>
```typescript
readonly singularity: Singularity;
```

@ -9,7 +9,7 @@ Suspends the script for n milliseconds.
<b>Signature:</b>
```typescript
sleep(millis: number): Promise<void>;
sleep(millis: number): Promise<true>;
```
## Parameters
@ -20,7 +20,7 @@ sleep(millis: number): Promise<void>;
<b>Returns:</b>
Promise&lt;void&gt;
Promise&lt;true&gt;
## Remarks

@ -9,7 +9,7 @@ Queue a toast (bottom-right notification).
<b>Signature:</b>
```typescript
toast(msg: any, variant?: string, duration?: number | null): void;
toast(msg: any, variant?: ToastVariantValues, duration?: number | null): void;
```
## Parameters
@ -17,7 +17,7 @@ toast(msg: any, variant?: string, duration?: number | null): void;
| Parameter | Type | Description |
| --- | --- | --- |
| msg | any | Message in the toast. |
| variant | string | Type of toast, must be one of success, info, warning, error. Defaults to success. |
| variant | [ToastVariantValues](./bitburner.toastvariantvalues.md) | Type of toast, must be one of success, info, warning, error. Defaults to success. |
| duration | number \| null | Duration of toast in ms. Can also be <code>null</code> to create a persistent toast. Defaults to 2000 |
<b>Returns:</b>

@ -0,0 +1,19 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [NSEnums](./bitburner.nsenums.md)
## NSEnums interface
<b>Signature:</b>
```typescript
export interface NSEnums
```
## Properties
| Property | Type | Description |
| --- | --- | --- |
| [toast](./bitburner.nsenums.toast.md) | typeof [ToastVariant](./bitburner.toastvariant.md) | |

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [NSEnums](./bitburner.nsenums.md) &gt; [toast](./bitburner.nsenums.toast.md)
## NSEnums.toast property
<b>Signature:</b>
```typescript
toast: typeof ToastVariant;
```

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [Office](./bitburner.office.md) &gt; [employeeJobs](./bitburner.office.employeejobs.md)
## Office.employeeJobs property
Positions of the employees
<b>Signature:</b>
```typescript
employeeJobs: EmployeeJobs;
```

@ -4,7 +4,7 @@
## Office.employeeProd property
Positions of the employees
Production of the employees
<b>Signature:</b>

@ -16,7 +16,8 @@ interface Office
| Property | Type | Description |
| --- | --- | --- |
| [employeeProd](./bitburner.office.employeeprod.md) | [EmployeeJobs](./bitburner.employeejobs.md) | Positions of the employees |
| [employeeJobs](./bitburner.office.employeejobs.md) | [EmployeeJobs](./bitburner.employeejobs.md) | Positions of the employees |
| [employeeProd](./bitburner.office.employeeprod.md) | [EmployeeJobs](./bitburner.employeejobs.md) | Production of the employees |
| [employees](./bitburner.office.employees.md) | string\[\] | Name of all the employees |
| [loc](./bitburner.office.loc.md) | string | City of the office |
| [maxEne](./bitburner.office.maxene.md) | number | Maximum amount of energy of the employees |

@ -4,10 +4,10 @@
## Product.cmp property
Competition for the product
Competition for the product, only present if "Market Research - Competition" unlocked
<b>Signature:</b>
```typescript
cmp: number;
cmp: number | undefined;
```

@ -4,10 +4,10 @@
## Product.dmd property
Demand for the product
Demand for the product, only present if "Market Research - Demand" unlocked
<b>Signature:</b>
```typescript
dmd: number;
dmd: number | undefined;
```

@ -17,10 +17,12 @@ interface Product
| Property | Type | Description |
| --- | --- | --- |
| [cityData](./bitburner.product.citydata.md) | { \[key: string\]: number\[\] } | Data refers to the production, sale, and quantity of the products These values are specific to a city For each city, the data is \[qty, prod, sell\] |
| [cmp](./bitburner.product.cmp.md) | number | Competition for the product |
| [cmp](./bitburner.product.cmp.md) | number \| undefined | Competition for the product, only present if "Market Research - Competition" unlocked |
| [developmentProgress](./bitburner.product.developmentprogress.md) | number | Creation progress - A number between 0-100 representing percentage |
| [dmd](./bitburner.product.dmd.md) | number | Demand for the product |
| [dmd](./bitburner.product.dmd.md) | number \| undefined | Demand for the product, only present if "Market Research - Demand" unlocked |
| [name](./bitburner.product.name.md) | string | Name of the product |
| [pCost](./bitburner.product.pcost.md) | number | Production cost |
| [properties](./bitburner.product.properties.md) | { \[key: string\]: number } | Product Properties. The data is {<!-- -->qlt, per, dur, rel, aes, fea<!-- -->} |
| [rat](./bitburner.product.rat.md) | number | Product Rating |
| [sCost](./bitburner.product.scost.md) | string \| number | Sell cost, can be "MP+5" |

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [Product](./bitburner.product.md) &gt; [properties](./bitburner.product.properties.md)
## Product.properties property
Product Properties. The data is {<!-- -->qlt, per, dur, rel, aes, fea<!-- -->}
<b>Signature:</b>
```typescript
properties: { [key: string]: number };
```

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [Product](./bitburner.product.md) &gt; [rat](./bitburner.product.rat.md)
## Product.rat property
Product Rating
<b>Signature:</b>
```typescript
rat: number;
```

@ -0,0 +1,20 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [RecentScript](./bitburner.recentscript.md)
## RecentScript interface
<b>Signature:</b>
```typescript
export interface RecentScript extends RunningScript
```
<b>Extends:</b> [RunningScript](./bitburner.runningscript.md)
## Properties
| Property | Type | Description |
| --- | --- | --- |
| [timeOfDeath](./bitburner.recentscript.timeofdeath.md) | Date | Timestamp of when the script was killed |

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [RecentScript](./bitburner.recentscript.md) &gt; [timeOfDeath](./bitburner.recentscript.timeofdeath.md)
## RecentScript.timeOfDeath property
Timestamp of when the script was killed
<b>Signature:</b>
```typescript
timeOfDeath: Date;
```

@ -0,0 +1,26 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [ReputationFormulas](./bitburner.reputationformulas.md) &gt; [calculateFavorToRep](./bitburner.reputationformulas.calculatefavortorep.md)
## ReputationFormulas.calculateFavorToRep() method
Calculate the total required amount of faction reputation to reach a target favor.
<b>Signature:</b>
```typescript
calculateFavorToRep(favor: number): number;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| favor | number | target faction favor. |
<b>Returns:</b>
number
The calculated faction reputation required.

@ -0,0 +1,26 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [ReputationFormulas](./bitburner.reputationformulas.md) &gt; [calculateRepToFavor](./bitburner.reputationformulas.calculatereptofavor.md)
## ReputationFormulas.calculateRepToFavor() method
Calculate the resulting faction favor of a total amount of reputation. (Faction favor is gained whenever you install an Augmentation.)
<b>Signature:</b>
```typescript
calculateRepToFavor(rep: number): number;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| rep | number | amount of reputation. |
<b>Returns:</b>
number
The calculated faction favor.

@ -0,0 +1,21 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [ReputationFormulas](./bitburner.reputationformulas.md)
## ReputationFormulas interface
Reputation formulas
<b>Signature:</b>
```typescript
interface ReputationFormulas
```
## Methods
| Method | Description |
| --- | --- |
| [calculateFavorToRep(favor)](./bitburner.reputationformulas.calculatefavortorep.md) | Calculate the total required amount of faction reputation to reach a target favor. |
| [calculateRepToFavor(rep)](./bitburner.reputationformulas.calculatereptofavor.md) | Calculate the resulting faction favor of a total amount of reputation. (Faction favor is gained whenever you install an Augmentation.) |

@ -4,6 +4,8 @@
## RunningScript.args property
Arguments the script was called with
<b>Signature:</b>
```typescript

@ -4,6 +4,8 @@
## RunningScript.filename property
Filename of the script
<b>Signature:</b>
```typescript

@ -4,6 +4,8 @@
## RunningScript.logs property
Script logs as an array. The newest log entries are at the bottom. Timestamps, if enabled, are placed inside `[brackets]` at the start of each line.
<b>Signature:</b>
```typescript

@ -8,24 +8,24 @@
<b>Signature:</b>
```typescript
interface RunningScript
export interface RunningScript
```
## Properties
| Property | Type | Description |
| --- | --- | --- |
| [args](./bitburner.runningscript.args.md) | string\[\] | |
| [filename](./bitburner.runningscript.filename.md) | string | |
| [logs](./bitburner.runningscript.logs.md) | string\[\] | |
| [offlineExpGained](./bitburner.runningscript.offlineexpgained.md) | number | |
| [offlineMoneyMade](./bitburner.runningscript.offlinemoneymade.md) | number | |
| [offlineRunningTime](./bitburner.runningscript.offlinerunningtime.md) | number | Offline running time of the script, in seconds \* |
| [onlineExpGained](./bitburner.runningscript.onlineexpgained.md) | number | |
| [onlineMoneyMade](./bitburner.runningscript.onlinemoneymade.md) | number | |
| [onlineRunningTime](./bitburner.runningscript.onlinerunningtime.md) | number | Online running time of the script, in seconds \* |
| [pid](./bitburner.runningscript.pid.md) | number | |
| [ramUsage](./bitburner.runningscript.ramusage.md) | number | |
| [server](./bitburner.runningscript.server.md) | string | |
| [threads](./bitburner.runningscript.threads.md) | number | |
| [args](./bitburner.runningscript.args.md) | string\[\] | Arguments the script was called with |
| [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 |
| [offlineMoneyMade](./bitburner.runningscript.offlinemoneymade.md) | number | Total amount of money made by this script when offline |
| [offlineRunningTime](./bitburner.runningscript.offlinerunningtime.md) | number | Number of seconds that the script has been running offline |
| [onlineExpGained](./bitburner.runningscript.onlineexpgained.md) | number | Total amount of hacking experience earned from this script when online |
| [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 |
| [server](./bitburner.runningscript.server.md) | string | Hostname of the server on which this script runs |
| [threads](./bitburner.runningscript.threads.md) | number | Number of threads that this script runs with |

@ -4,6 +4,8 @@
## RunningScript.offlineExpGained property
Total amount of hacking experience earned from this script when offline
<b>Signature:</b>
```typescript

@ -4,6 +4,8 @@
## RunningScript.offlineMoneyMade property
Total amount of money made by this script when offline
<b>Signature:</b>
```typescript

@ -4,7 +4,7 @@
## RunningScript.offlineRunningTime property
Offline running time of the script, in seconds \*
Number of seconds that the script has been running offline
<b>Signature:</b>

@ -4,6 +4,8 @@
## RunningScript.onlineExpGained property
Total amount of hacking experience earned from this script when online
<b>Signature:</b>
```typescript

@ -4,6 +4,8 @@
## RunningScript.onlineMoneyMade property
Total amount of money made by this script when online
<b>Signature:</b>
```typescript

@ -4,7 +4,7 @@
## RunningScript.onlineRunningTime property
Online running time of the script, in seconds \*
Number of seconds that this script has been running online
<b>Signature:</b>

@ -4,6 +4,8 @@
## RunningScript.pid property
Process ID. Must be an integer
<b>Signature:</b>
```typescript

@ -4,6 +4,8 @@
## RunningScript.ramUsage property
How much RAM this script uses for ONE thread
<b>Signature:</b>
```typescript

@ -4,6 +4,8 @@
## RunningScript.server property
Hostname of the server on which this script runs
<b>Signature:</b>
```typescript

@ -4,6 +4,8 @@
## RunningScript.threads property
Number of threads that this script runs with
<b>Signature:</b>
```typescript

@ -9,13 +9,11 @@ Hospitalize the player.
<b>Signature:</b>
```typescript
hospitalize(): number;
hospitalize(): void;
```
<b>Returns:</b>
number
The cost of the hospitalization.
void
## Remarks

@ -9,7 +9,7 @@ Set a sleeve to work for a faction.
<b>Signature:</b>
```typescript
setToFactionWork(sleeveNumber: number, factionName: string, factionWorkType: string): boolean;
setToFactionWork(sleeveNumber: number, factionName: string, factionWorkType: string): boolean | undefined;
```
## Parameters
@ -22,9 +22,9 @@ setToFactionWork(sleeveNumber: number, factionName: string, factionWorkType: str
<b>Returns:</b>
boolean
boolean \| undefined
True if the sleeve started working on this faction, false otherwise.
True if the sleeve started working on this faction, false otherwise, can also throw on errors
## Remarks

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [ToastVariant](./bitburner.toastvariant.md)
## ToastVariant enum
<b>Signature:</b>
```typescript
export enum ToastVariant
```
## Enumeration Members
| Member | Value | Description |
| --- | --- | --- |
| ERROR | <code>&quot;error&quot;</code> | |
| INFO | <code>&quot;info&quot;</code> | |
| SUCCESS | <code>&quot;success&quot;</code> | |
| WARNING | <code>&quot;warning&quot;</code> | |

@ -0,0 +1,14 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [ToastVariantValues](./bitburner.toastvariantvalues.md)
## ToastVariantValues type
<b>Signature:</b>
```typescript
export type ToastVariantValues = `${ToastVariant}`;
```
<b>References:</b> [ToastVariant](./bitburner.toastvariant.md)

68
package-lock.json generated

@ -1,12 +1,12 @@
{
"name": "bitburner",
"version": "1.5.0",
"version": "1.6.3",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "bitburner",
"version": "1.5.0",
"version": "1.6.3",
"hasInstallScript": true,
"license": "SEE LICENSE IN license.txt",
"dependencies": {
@ -69,7 +69,7 @@
"babel-jest": "^27.0.6",
"babel-loader": "^8.0.5",
"cypress": "^8.3.1",
"electron": "^14.0.2",
"electron": "^14.2.4",
"electron-packager": "^15.4.0",
"eslint": "^7.24.0",
"file-loader": "^6.2.0",
@ -5965,13 +5965,19 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001265",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001265.tgz",
"integrity": "sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
}
"version": "1.0.30001328",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001328.tgz",
"integrity": "sha512-Ue55jHkR/s4r00FLNiX+hGMMuwml/QGqqzVeMQ5thUewznU2EdULFvI3JR7JJid6OrjJNfFvHY2G2dIjmRaDDQ==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
}
]
},
"node_modules/caseless": {
"version": "0.12.0",
@ -7821,9 +7827,9 @@
"dev": true
},
"node_modules/electron": {
"version": "14.0.2",
"resolved": "https://registry.npmjs.org/electron/-/electron-14.0.2.tgz",
"integrity": "sha512-LIJj795cfggUtLHIM84lseE7LC0kAs/HNVXoDFPTjtYzQikPX9XAIMI1BTJcod3j+U1ZXsayk9N4M3M890WD3w==",
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/electron/-/electron-14.2.4.tgz",
"integrity": "sha512-uskCIp+fpohqVYtM2Q28rbXLqGjZ6sWYylXcX6N+K8jR8kR2eHuDMIkO8DzWrTsqA6t4UNAzn+bJnA3VfIIjQw==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
@ -15190,9 +15196,9 @@
}
},
"node_modules/minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
},
"node_modules/mixin-deep": {
"version": "1.3.2",
@ -16484,9 +16490,9 @@
}
},
"node_modules/plist": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/plist/-/plist-3.0.4.tgz",
"integrity": "sha512-ksrr8y9+nXOxQB2osVNqrgvX/XQPOXaU4BQMKjYq8PvaY1U18mo+fKgBSwzK+luSyinOuPae956lSVcBwxlAMg==",
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz",
"integrity": "sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA==",
"dev": true,
"dependencies": {
"base64-js": "^1.5.1",
@ -26994,9 +27000,9 @@
"dev": true
},
"caniuse-lite": {
"version": "1.0.30001265",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001265.tgz",
"integrity": "sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw=="
"version": "1.0.30001328",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001328.tgz",
"integrity": "sha512-Ue55jHkR/s4r00FLNiX+hGMMuwml/QGqqzVeMQ5thUewznU2EdULFvI3JR7JJid6OrjJNfFvHY2G2dIjmRaDDQ=="
},
"caseless": {
"version": "0.12.0",
@ -28515,9 +28521,9 @@
"dev": true
},
"electron": {
"version": "14.0.2",
"resolved": "https://registry.npmjs.org/electron/-/electron-14.0.2.tgz",
"integrity": "sha512-LIJj795cfggUtLHIM84lseE7LC0kAs/HNVXoDFPTjtYzQikPX9XAIMI1BTJcod3j+U1ZXsayk9N4M3M890WD3w==",
"version": "14.2.4",
"resolved": "https://registry.npmjs.org/electron/-/electron-14.2.4.tgz",
"integrity": "sha512-uskCIp+fpohqVYtM2Q28rbXLqGjZ6sWYylXcX6N+K8jR8kR2eHuDMIkO8DzWrTsqA6t4UNAzn+bJnA3VfIIjQw==",
"dev": true,
"requires": {
"@electron/get": "^1.0.1",
@ -34244,9 +34250,9 @@
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="
},
"mixin-deep": {
"version": "1.3.2",
@ -35264,9 +35270,9 @@
}
},
"plist": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/plist/-/plist-3.0.4.tgz",
"integrity": "sha512-ksrr8y9+nXOxQB2osVNqrgvX/XQPOXaU4BQMKjYq8PvaY1U18mo+fKgBSwzK+luSyinOuPae956lSVcBwxlAMg==",
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz",
"integrity": "sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA==",
"dev": true,
"requires": {
"base64-js": "^1.5.1",

@ -1,7 +1,7 @@
{
"name": "bitburner",
"license": "SEE LICENSE IN license.txt",
"version": "1.6.0",
"version": "1.6.3",
"main": "electron-main.js",
"author": {
"name": "Daniel Xie & Olivier Gagnon"
@ -70,7 +70,7 @@
"babel-jest": "^27.0.6",
"babel-loader": "^8.0.5",
"cypress": "^8.3.1",
"electron": "^14.0.2",
"electron": "^14.2.4",
"electron-packager": "^15.4.0",
"eslint": "^7.24.0",
"file-loader": "^6.2.0",
@ -109,26 +109,31 @@
"doc": "npx api-extractor run && npx api-documenter markdown && rm input/bitburner.api.json && rm -r input",
"format": "prettier --write .",
"format:report": "prettier -c .",
"format:report-diff": "bash -c 'if [[ $(git diff --name-only --diff-filter=ACMRTUXB origin/dev | grep -E \"(.js$|.jsx$|.ts$|.tsx$)\" | wc -c) -ne 0 ]]; then prettier -c $(git diff --name-only --diff-filter=ACMRTUXB origin/dev | grep -E \"(.js$|.jsx$|.ts$|.tsx$)\" | xargs); fi'",
"start": "http-server -p 8000",
"start:dev": "webpack-dev-server --progress --env.devServer --mode development",
"start:dev-fast": "webpack-dev-server --progress --env.devServer --mode development --fast true",
"start:container": "webpack-dev-server --progress --env.devServer --mode development --env.runInContainer",
"build": "webpack --mode production",
"build:dev": "webpack --mode development",
"lint": "eslint --fix . --ext js,jsx,ts,tsx",
"lint:report": "eslint --ext js,jsx,ts,tsx .",
"lint": "eslint --fix --ext js,jsx,ts,tsx --max-warnings 0 .",
"lint:report": "eslint --ext js,jsx,ts,tsx --max-warnings 0 .",
"lint:report-diff": "eslint --max-warnings 0 $(git diff --name-only --diff-filter=ACMRTUXB origin/dev | grep -E \"(.js$|.jsx$|.ts$|.tsx$)\" | xargs)",
"preinstall": "node ./tools/engines-check/engines-check.js",
"postinstall": "cd electron && npm install",
"test": "jest",
"test:watch": "jest --watch",
"watch": "webpack --watch --mode production",
"watch:dev": "webpack --watch --mode development",
"electron": "sh ./package.sh",
"electron": "sh ./tools/package-electron.sh",
"electron:packager": "electron-packager .package bitburner --all --out .build --overwrite --icon .package/icon.png --no-prune",
"electron:packager-all": "electron-packager .package bitburner --all --out .build --overwrite --icon .package/icon.png",
"electron:packager-win": "electron-packager .package bitburner --platform win32 --arch x64 --out .build --overwrite --icon .package/icon.png",
"electron:packager-mac": "electron-packager .package bitburner --platform darwin --arch x64 --out .build --overwrite --icon .package/icon.png",
"electron:packager-linux": "electron-packager .package bitburner --platform linux --arch x64 --out .build --overwrite --icon .package/icon.png",
"allbuild": "npm run build && npm run electron && git add --all && git commit -m \"allbuild commit $(git rev-parse --short HEAD)\" && git push -f -u origin dev"
"allbuild": "npm run build && npm run electron && git add --all && git commit -m \"allbuild commit $(git rev-parse --short HEAD)\" && git push -f -u origin dev",
"preversion": "npm install && npm run test",
"version": "sh ./tools/build-release.sh && git add --all",
"postversion": "git push -u origin dev && git push --tags"
}
}

@ -1,31 +0,0 @@
#!/bin/sh
# Clear out any files remaining from old builds
rm -rf .package
mkdir -p .package/dist/src/ThirdParty || true
mkdir -p .package/src/ThirdParty || true
mkdir -p .package/node_modules || true
cp index.html .package
cp -r electron/* .package
cp -r dist/ext .package/dist
cp -r dist/icons .package/dist
cp -r dist/images .package/dist
# The js files.
cp dist/vendor.bundle.js .package/dist/vendor.bundle.js
cp main.bundle.js .package/main.bundle.js
# Source maps
cp dist/vendor.bundle.js.map .package/dist/vendor.bundle.js.map
cp main.bundle.js.map .package/main.bundle.js.map
# Install electron sub-dependencies
cd electron
npm install
cd ..
BUILD_PLATFORM="${1:-"all"}"
# And finally build the app.
npm run electron:packager-$BUILD_PLATFORM

@ -2,7 +2,6 @@
import * as React from "react";
import { IMap } from "../types";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { Faction } from "../Faction/Faction";
import { Factions } from "../Faction/Factions";
import { numeralWrapper } from "../ui/numeralFormat";
@ -141,7 +140,7 @@ function generateStatsDescription(mults: IMap<number>, programs?: string[], star
desc = (
<>
{desc}
<br />+{f(mults.charisma_mult - 1)} Charisma skill
<br />+{f(mults.charisma_mult - 1)} charisma skill
</>
);
}
@ -464,8 +463,8 @@ export class Augmentation {
this.info = params.info;
this.prereqs = params.prereqs ? params.prereqs : [];
this.baseRepRequirement = params.repCost * BitNodeMultipliers.AugmentationRepCost;
this.baseCost = params.moneyCost * BitNodeMultipliers.AugmentationMoneyCost;
this.baseRepRequirement = params.repCost;
this.baseCost = params.moneyCost;
this.startingCost = this.baseCost;
this.startingRepRequirement = this.baseRepRequirement;
this.factions = params.factions;

@ -22,6 +22,7 @@ import {
initUnstableCircadianModulator,
} from "./data/AugmentationCreator";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { Router } from "../ui/GameRoot";
export function AddToAugmentations(aug: Augmentation): void {
const name = aug.name;
@ -157,6 +158,12 @@ function applyAugmentation(aug: IPlayerOwnedAugmentation, reapply = false): void
}
}
// Special logic for Congruity Implant
if (aug.name === AugmentationNames.CongruityImplant && !reapply) {
Player.entropy = 0;
Player.applyEntropy(Player.entropy);
}
// Push onto Player's Augmentation list
if (!reapply) {
const ownedAug = new PlayerOwnedAugmentation(aug.name);
@ -164,8 +171,8 @@ function applyAugmentation(aug: IPlayerOwnedAugmentation, reapply = false): void
}
}
function installAugmentations(): boolean {
if (Player.queuedAugmentations.length == 0) {
function installAugmentations(force?: boolean): boolean {
if (Player.queuedAugmentations.length == 0 && !force) {
dialogBoxCreate("You have not purchased any Augmentations to install!");
return false;
}
@ -195,13 +202,16 @@ function installAugmentations(): boolean {
augmentationList += aug.name + level + "<br>";
}
Player.queuedAugmentations = [];
dialogBoxCreate(
"You slowly drift to sleep as scientists put you under in order " +
"to install the following Augmentations:<br>" +
augmentationList +
"<br>You wake up in your home...you feel different...",
);
if (!force) {
dialogBoxCreate(
"You slowly drift to sleep as scientists put you under in order " +
"to install the following Augmentations:<br>" +
augmentationList +
"<br>You wake up in your home...you feel different...",
);
}
prestigeAugmentation();
Router.toTerminal();
return true;
}

@ -1641,6 +1641,25 @@ export const initGeneralAugmentations = (): Augmentation[] => [
),
factions: [FactionNames.TianDiHui],
}),
// Grafting-exclusive Augmentation
new Augmentation({
name: AugmentationNames.CongruityImplant,
repCost: Infinity,
moneyCost: 50e12,
info: (
<>
Developed by a pioneer in Grafting research, this implant generates pulses of stability which seem to have a
nullifying effect versus the Entropy virus.
<br />
<br />
<b>Note:</b> For unknown reasons, the lowercase <code>n</code> appears to be an integral component to its
functionality.
</>
),
stats: <>This Augmentation removes the Entropy virus, and prevents it from affecting you again.</>,
factions: [],
}),
];
export const initBladeburnerAugmentations = (): Augmentation[] => [

@ -91,6 +91,7 @@ export enum AugmentationNames {
BionicArms = "Bionic Arms",
SNA = "Social Negotiation Assistant (S.N.A)",
HydroflameLeftArm = "Hydroflame Left Arm",
CongruityImplant = "nickofolas Congruity Implant",
EsperEyewear = "EsperTech Bladeburner Eyewear",
EMS4Recombination = "EMS-4 Recombination",
OrionShoulder = "ORION-MKIV Shoulder",

@ -7,7 +7,7 @@ import React, { useState, useEffect } from "react";
import { InstalledAugmentations } from "./InstalledAugmentations";
import { PlayerMultipliers } from "./PlayerMultipliers";
import { PurchasedAugmentations } from "./PurchasedAugmentations";
import { SourceFiles } from "./SourceFiles";
import { SourceFilesElement } from "./SourceFiles";
import { canGetBonus } from "../../ExportBonus";
import { use } from "../../ui/Context";
@ -16,8 +16,55 @@ import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
import Tooltip from "@mui/material/Tooltip";
import Box from "@mui/material/Box";
import Paper from "@mui/material/Paper";
import Container from "@mui/material/Container";
import { Settings } from "../../Settings/Settings";
import { ConfirmationModal } from "../../ui/React/ConfirmationModal";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { AugmentationNames } from "../data/AugmentationNames";
import { Augmentations } from "../Augmentations";
import { CONSTANTS } from "../../Constants";
import { formatNumber } from "../../utils/StringHelperFunctions";
import { Info } from "@mui/icons-material";
interface NFGDisplayProps {
player: IPlayer;
}
const NeuroFluxDisplay = ({ player }: NFGDisplayProps): React.ReactElement => {
const level = player.augmentations.find((e) => e.name === AugmentationNames.NeuroFluxGovernor)?.level ?? 0;
return level > 0 ? (
<Paper sx={{ p: 1 }}>
<Typography variant="h5" color={Settings.theme.info}>
NeuroFlux Governor - Level {level}
</Typography>
<Typography color={Settings.theme.info}>{Augmentations[AugmentationNames.NeuroFluxGovernor].stats}</Typography>
</Paper>
) : (
<></>
);
};
interface EntropyDisplayProps {
player: IPlayer;
}
const EntropyDisplay = ({ player }: EntropyDisplayProps): React.ReactElement => {
return player.entropy > 0 ? (
<Paper sx={{ p: 1 }}>
<Typography variant="h5" color={Settings.theme.error}>
Entropy Virus - Level {player.entropy}
</Typography>
<Typography color={Settings.theme.error}>
<b>All multipliers decreased by:</b> {formatNumber((1 - CONSTANTS.EntropyEffect ** player.entropy) * 100, 3)}%
(multiplicative)
</Typography>
</Paper>
) : (
<></>
);
};
interface IProps {
exportGameFn: () => void;
@ -55,81 +102,113 @@ export function AugmentationsRoot(props: IProps): React.ReactElement {
}
return (
<>
<Container disableGutters maxWidth="lg" sx={{ mx: 0 }}>
<Typography variant="h4">Augmentations</Typography>
<Box mx={2}>
<Typography>
Below is a list of all Augmentations you have purchased but not yet installed. Click the button below to
install them.
</Typography>
<Typography>WARNING: Installing your Augmentations resets most of your progress, including:</Typography>
<br />
<Typography>- Stats/Skill levels and Experience</Typography>
<Typography>- Money</Typography>
<Typography>- Scripts on every computer but your home computer</Typography>
<Typography>- Purchased servers</Typography>
<Typography>- Hacknet Nodes</Typography>
<Typography>- Faction/Company reputation</Typography>
<Typography>- Stocks</Typography>
<br />
<Typography>
Installing Augmentations lets you start over with the perks and benefits granted by all of the Augmentations
you have ever installed. Also, you will keep any scripts and RAM/Core upgrades on your home computer (but you
will lose all programs besides NUKE.exe)
</Typography>
<Box sx={{ mb: 1 }}>
<Paper sx={{ p: 1 }}>
<Typography variant="h5" color="primary" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
Purchased Augmentations
<Tooltip
title={
<>
<Typography>
Below is a list of all Augmentations you have purchased but not yet installed. Click the button
below to install them.
</Typography>
<Typography>
WARNING: Installing your Augmentations resets most of your progress, including:
</Typography>
<br />
<Typography>- Stats/Skill levels and Experience</Typography>
<Typography>- Money</Typography>
<Typography>- Scripts on every computer but your home computer</Typography>
<Typography>- Purchased servers</Typography>
<Typography>- Hacknet Nodes</Typography>
<Typography>- Faction/Company reputation</Typography>
<Typography>- Stocks</Typography>
<br />
<Typography>
Installing Augmentations lets you start over with the perks and benefits granted by all of the
Augmentations you have ever installed. Also, you will keep any scripts and RAM/Core upgrades on your
home computer (but you will lose all programs besides NUKE.exe)
</Typography>
</>
}
>
<Info sx={{ ml: 1, mb: 0.5 }} color="info" />
</Tooltip>
</Typography>
<ConfirmationModal
open={installOpen}
onClose={() => setInstallOpen(false)}
onConfirm={props.installAugmentationsFn}
confirmationText={
<>
Installing will reset
<br />
<br />- money
<br />- skill / experience
<br />- every server except home
<br />- factions and reputation
<br />
<br />
You will keep:
<br />
<br />- All scripts on home
<br />- home ram and cores
<br />
<br />
It is recommended to install several Augmentations at once. Preferably everything from any faction of
your choosing.
</>
}
/>
<Box sx={{ display: "grid", width: "100%", gridTemplateColumns: "1fr 1fr" }}>
<Tooltip title={<Typography>'I never asked for this'</Typography>}>
<span>
<Button sx={{ width: "100%" }} disabled={player.queuedAugmentations.length === 0} onClick={doInstall}>
Install Augmentations
</Button>
</span>
</Tooltip>
<Tooltip title={<Typography>It's always a good idea to backup/export your save!</Typography>}>
<Button sx={{ width: "100%" }} onClick={doExport} color="error">
Backup Save {exportBonusStr()}
</Button>
</Tooltip>
</Box>
</Paper>
{player.queuedAugmentations.length > 0 ? (
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 3fr" }}>
<PurchasedAugmentations />
<PlayerMultipliers />
</Box>
) : (
<Paper sx={{ p: 1 }}>
<Typography>No Augmentations have been purchased yet</Typography>
</Paper>
)}
</Box>
<Typography variant="h4" color="primary">
Purchased Augmentations
</Typography>
<Box mx={2}>
<Tooltip title={<Typography>'I never asked for this'</Typography>}>
<span>
<Button disabled={player.queuedAugmentations.length === 0} onClick={doInstall}>
Install Augmentations
</Button>
</span>
</Tooltip>
<ConfirmationModal
open={installOpen}
onClose={() => setInstallOpen(false)}
onConfirm={props.installAugmentationsFn}
confirmationText={
<>
Installing will reset
<br />
<br />- money
<br />- skill / experience
<br />- every server except home
<br />- factions and reputation
<br />
<br />
You will keep:
<br />
<br />- All scripts on home
<br />- home ram and cores
<br />
<br />
It is recommended to install several Augmentations at once. Preferably everything from any faction of your
choosing.
</>
}
/>
<Tooltip title={<Typography>It's always a good idea to backup/export your save!</Typography>}>
<Button sx={{ mx: 2 }} onClick={doExport} color="error">
Backup Save {exportBonusStr()}
</Button>
</Tooltip>
<PurchasedAugmentations />
<Box
sx={{
my: 1,
display: "grid",
gridTemplateColumns: `repeat(${
+!!((player.augmentations.find((e) => e.name === AugmentationNames.NeuroFluxGovernor)?.level ?? 0) > 0) +
+!!(player.entropy > 0)
}, 1fr)`,
gap: 1,
}}
>
<NeuroFluxDisplay player={player} />
<EntropyDisplay player={player} />
</Box>
<Typography variant="h4">Installed Augmentations</Typography>
<Box mx={2}>
<Typography>
List of all Augmentations that have been installed. You have gained the effects of these.
</Typography>
<Box>
<InstalledAugmentations />
</Box>
<PlayerMultipliers />
<SourceFiles />
</>
<SourceFilesElement />
</Container>
);
}

@ -5,28 +5,23 @@
* It also contains 'configuration' buttons that allow you to change how the
* Augs/SF's are displayed
*/
import { Box, ListItemButton, Paper, Typography } from "@mui/material";
import Button from "@mui/material/Button";
import List from "@mui/material/List";
import Tooltip from "@mui/material/Tooltip";
import React, { useState } from "react";
import { AugmentationAccordion } from "../../ui/React/AugmentationAccordion";
import { Augmentations } from "../Augmentations";
import { AugmentationNames } from "../data/AugmentationNames";
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
import { Settings } from "../../Settings/Settings";
import { use } from "../../ui/Context";
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
import Button from "@mui/material/Button";
import Tooltip from "@mui/material/Tooltip";
import List from "@mui/material/List";
import { ExpandLess, ExpandMore } from "@mui/icons-material";
import { Box, Paper, ListItemButton, ListItemText, Typography, Collapse } from "@mui/material";
import { CONSTANTS } from "../../Constants";
import { formatNumber } from "../../utils/StringHelperFunctions";
import { Augmentations } from "../Augmentations";
import { AugmentationNames } from "../data/AugmentationNames";
export function InstalledAugmentations(): React.ReactElement {
const setRerender = useState(true)[1];
const player = use.Player();
const sourceAugs = player.augmentations.slice().filter((aug) => aug.name !== AugmentationNames.NeuroFluxGovernor);
const sourceAugs = player.augmentations.slice();
const [selectedAug, setSelectedAug] = useState(sourceAugs[0]);
if (Settings.OwnedAugmentationsOrder === OwnedAugmentationsOrderSetting.Alphabetically) {
sourceAugs.sort((aug1, aug2) => {
@ -49,59 +44,60 @@ export function InstalledAugmentations(): React.ReactElement {
}
return (
<>
<Tooltip title={"Sorts the Augmentations alphabetically in numeral order"}>
<Button onClick={sortInOrder}>Sort in Order</Button>
</Tooltip>
<Tooltip title={"Sorts the Augmentations based on when you acquired them (same as default)"}>
<Button sx={{ mx: 2 }} onClick={sortByAcquirementTime}>
Sort by Acquirement Time
</Button>
</Tooltip>
<List dense>
{player.entropy > 0 &&
(() => {
const [open, setOpen] = useState(false);
return (
<Box component={Paper}>
<ListItemButton onClick={() => setOpen((old) => !old)}>
<ListItemText
primary={
<Typography color={Settings.theme.hp} style={{ whiteSpace: "pre-wrap" }}>
Entropy Virus - Level {player.entropy}
</Typography>
}
/>
{open ? (
<ExpandLess sx={{ color: Settings.theme.hp }} />
) : (
<ExpandMore sx={{ color: Settings.theme.hp }} />
)}
<Box sx={{ width: "100%" }}>
<Paper sx={{ p: 1 }}>
<Typography variant="h5">Installed Augmentations</Typography>
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
<Tooltip title={"Sorts the Augmentations alphabetically in numeral order"}>
<Button sx={{ width: "100%" }} onClick={sortInOrder}>
Sort in Order
</Button>
</Tooltip>
<Tooltip title={"Sorts the Augmentations based on when you acquired them (same as default)"}>
<Button sx={{ width: "100%" }} onClick={sortByAcquirementTime}>
Sort by Time of Acquirement
</Button>
</Tooltip>
</Box>
</Paper>
{sourceAugs.length > 0 ? (
<Paper sx={{ display: "grid", gridTemplateColumns: "1fr 3fr" }}>
<Box>
<List sx={{ height: 400, overflowY: "scroll", borderRight: `1px solid ${Settings.theme.welllight}` }}>
{sourceAugs.map((k, i) => (
<ListItemButton key={i + 1} onClick={() => setSelectedAug(k)} selected={selectedAug === k}>
<Typography>{k.name}</Typography>
</ListItemButton>
<Collapse in={open} unmountOnExit>
<Box m={4}>
<Typography color={Settings.theme.hp}>
<b>All multipliers decreased by:</b>{" "}
{formatNumber((1 - CONSTANTS.EntropyEffect ** player.entropy) * 100, 3)}% (multiplicative)
</Typography>
</Box>
</Collapse>
</Box>
);
})()}
))}
</List>
</Box>
<Box sx={{ m: 1 }}>
<Typography variant="h6" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
{selectedAug.name}
</Typography>
<Typography sx={{ maxHeight: 350, overflowY: "scroll" }}>
{(() => {
const aug = Augmentations[selectedAug.name];
{sourceAugs.map((e) => {
const aug = Augmentations[e.name];
let level = null;
if (e.name === AugmentationNames.NeuroFluxGovernor) {
level = e.level;
}
return <AugmentationAccordion key={aug.name} aug={aug} level={level} />;
})}
</List>
</>
const info = typeof aug.info === "string" ? <span>{aug.info}</span> : aug.info;
const tooltip = (
<>
{info}
<br />
<br />
{aug.stats}
</>
);
return tooltip;
})()}
</Typography>
</Box>
</Paper>
) : (
<Paper sx={{ p: 1 }}>
<Typography>No Augmentations have been installed yet</Typography>
</Paper>
)}
</Box>
);
}

@ -1,20 +1,22 @@
/**
* React component for displaying the player's multipliers on the Augmentation UI page
*/
import { DoubleArrow } from "@mui/icons-material";
import { List, ListItem, ListItemText, Paper, Typography } from "@mui/material";
import * as React from "react";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { Player } from "../../Player";
import { Settings } from "../../Settings/Settings";
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
import { numeralWrapper } from "../../ui/numeralFormat";
import { Augmentations } from "../Augmentations";
import { Table, TableCell } from "../../ui/React/Table";
import TableBody from "@mui/material/TableBody";
import TableRow from "@mui/material/TableRow";
import Typography from "@mui/material/Typography";
import Box from "@mui/material/Box";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
function calculateAugmentedStats(): any {
const augP: any = {};
interface IAugmentedStats {
[index: string]: number;
}
function calculateAugmentedStats(): IAugmentedStats {
const augP: IAugmentedStats = {};
for (const aug of Player.queuedAugmentations) {
const augObj = Augmentations[aug.name];
for (const mult of Object.keys(augObj.mults)) {
@ -25,311 +27,284 @@ function calculateAugmentedStats(): any {
return augP;
}
function Improvements({ r, m }: { r: number; m: number }): React.ReactElement {
if (r) {
return (
<>
<TableCell key="2">
<Typography>&nbsp;{"=>"}&nbsp;</Typography>
</TableCell>
<TableCell key="3">
<Typography>
{numeralWrapper.formatPercentage(r)} <BN5Stat base={r} mult={m} />
</Typography>
</TableCell>
</>
);
}
return <></>;
}
interface IBN5StatsProps {
interface IBitNodeModifiedStatsProps {
base: number;
mult: number;
color: string;
}
function BN5Stat(props: IBN5StatsProps): React.ReactElement {
if (props.mult === 1) return <></>;
return <>({numeralWrapper.formatPercentage(props.base * props.mult)})</>;
}
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 || SourceFileFlags[5] === 0)
return <Typography color={props.color}>{numeralWrapper.formatPercentage(props.base)}</Typography>;
function MultiplierTable({ rows }: { rows: [string, number, number, number][] }): React.ReactElement {
return (
<Table size="small" padding="none">
<TableBody>
{rows.map((r: any) => (
<TableRow key={r[0]}>
<TableCell key="0">
<Typography noWrap>{r[0]} multiplier:&nbsp;</Typography>
</TableCell>
<TableCell key="1" style={{ textAlign: "right" }}>
<Typography noWrap>
{numeralWrapper.formatPercentage(r[1])} <BN5Stat base={r[1]} mult={r[3]} />
</Typography>
</TableCell>
<Improvements r={r[2]} m={r[3]} />
</TableRow>
))}
</TableBody>
</Table>
<Typography color={props.color}>
<span style={{ opacity: 0.5 }}>{numeralWrapper.formatPercentage(props.base)}</span>{" "}
{numeralWrapper.formatPercentage(props.base * props.mult)}
</Typography>
);
}
type MultiplierListItemData = [
multiplier: string,
currentValue: number,
augmentedValue: number,
bitNodeMultiplier: number,
color: string,
];
interface IMultiplierListProps {
rows: MultiplierListItemData[];
}
function MultiplierList(props: IMultiplierListProps): React.ReactElement {
const listItems = props.rows
.map((data) => {
const [multiplier, currentValue, augmentedValue, bitNodeMultiplier, color] = data;
if (!isNaN(augmentedValue)) {
return (
<ListItem key={multiplier} disableGutters sx={{ py: 0 }}>
<ListItemText
sx={{ my: 0.1 }}
primary={
<Typography color={color}>
<b>{multiplier}</b>
</Typography>
}
secondary={
<span style={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
<BitNodeModifiedStats base={currentValue} mult={bitNodeMultiplier} color={color} />
<DoubleArrow fontSize="small" color="success" sx={{ mb: 0.5, mx: 1 }} />
<BitNodeModifiedStats base={augmentedValue} mult={bitNodeMultiplier} color={Settings.theme.success} />
</span>
}
disableTypography
/>
</ListItem>
);
}
return;
})
.filter((i) => i !== undefined);
return listItems.length > 0 ? <List disablePadding>{listItems}</List> : <></>;
}
export function PlayerMultipliers(): React.ReactElement {
const mults = calculateAugmentedStats();
function BladeburnerMults(): React.ReactElement {
if (!Player.canAccessBladeburner()) return <></>;
return (
<>
<MultiplierTable
rows={[
[
"Bladeburner Success Chance",
Player.bladeburner_success_chance_mult,
Player.bladeburner_success_chance_mult * mults.bladeburner_success_chance_mult,
1,
],
[
"Bladeburner Max Stamina",
Player.bladeburner_max_stamina_mult,
Player.bladeburner_max_stamina_mult * mults.bladeburner_max_stamina_mult,
1,
],
[
"Bladeburner Stamina Gain",
Player.bladeburner_stamina_gain_mult,
Player.bladeburner_stamina_gain_mult * mults.bladeburner_stamina_gain_mult,
1,
],
[
"Bladeburner Field Analysis",
Player.bladeburner_analysis_mult,
Player.bladeburner_analysis_mult * mults.bladeburner_analysis_mult,
1,
],
]}
/>
<br />
</>
// Column data is a bit janky, so it's set up here to allow for
// easier logic in setting up the layout
const leftColData: MultiplierListItemData[] = [
...[
["Hacking Chance ", Player.hacking_chance_mult, Player.hacking_chance_mult * mults.hacking_chance_mult, 1],
["Hacking Speed ", Player.hacking_speed_mult, Player.hacking_speed_mult * mults.hacking_speed_mult, 1],
["Hacking Money ", Player.hacking_money_mult, Player.hacking_money_mult * mults.hacking_money_mult, 1],
["Hacking Growth ", Player.hacking_grow_mult, Player.hacking_grow_mult * mults.hacking_grow_mult, 1],
[
"Hacking Level ",
Player.hacking_mult,
Player.hacking_mult * mults.hacking_mult,
BitNodeMultipliers.HackingLevelMultiplier,
],
[
"Hacking Experience ",
Player.hacking_exp_mult,
Player.hacking_exp_mult * mults.hacking_exp_mult,
BitNodeMultipliers.HackExpGain,
],
].map((data): MultiplierListItemData => (data as any).concat([Settings.theme.hack])),
...[
[
"Strength Level ",
Player.strength_mult,
Player.strength_mult * mults.strength_mult,
BitNodeMultipliers.StrengthLevelMultiplier,
],
["Strength Experience ", Player.strength_exp_mult, Player.strength_exp_mult * mults.strength_exp_mult, 1],
[
"Defense Level ",
Player.defense_mult,
Player.defense_mult * mults.defense_mult,
BitNodeMultipliers.DefenseLevelMultiplier,
],
["Defense Experience ", Player.defense_exp_mult, Player.defense_exp_mult * mults.defense_exp_mult, 1],
[
"Dexterity Level ",
Player.dexterity_mult,
Player.dexterity_mult * mults.dexterity_mult,
BitNodeMultipliers.DexterityLevelMultiplier,
],
["Dexterity Experience ", Player.dexterity_exp_mult, Player.dexterity_exp_mult * mults.dexterity_exp_mult, 1],
[
"Agility Level ",
Player.agility_mult,
Player.agility_mult * mults.agility_mult,
BitNodeMultipliers.AgilityLevelMultiplier,
],
["Agility Experience ", Player.agility_exp_mult, Player.agility_exp_mult * mults.agility_exp_mult, 1],
].map((data): MultiplierListItemData => (data as any).concat([Settings.theme.combat])),
[
"Charisma Level ",
Player.charisma_mult,
Player.charisma_mult * mults.charisma_mult,
BitNodeMultipliers.CharismaLevelMultiplier,
Settings.theme.cha,
],
[
"Charisma Experience ",
Player.charisma_exp_mult,
Player.charisma_exp_mult * mults.charisma_exp_mult,
1,
Settings.theme.cha,
],
];
const rightColData: MultiplierListItemData[] = [
...[
[
"Hacknet Node production ",
Player.hacknet_node_money_mult,
Player.hacknet_node_money_mult * mults.hacknet_node_money_mult,
BitNodeMultipliers.HacknetNodeMoney,
],
[
"Hacknet Node purchase cost ",
Player.hacknet_node_purchase_cost_mult,
Player.hacknet_node_purchase_cost_mult * mults.hacknet_node_purchase_cost_mult,
1,
],
[
"Hacknet Node RAM upgrade cost ",
Player.hacknet_node_ram_cost_mult,
Player.hacknet_node_ram_cost_mult * mults.hacknet_node_ram_cost_mult,
1,
],
[
"Hacknet Node Core purchase cost ",
Player.hacknet_node_core_cost_mult,
Player.hacknet_node_core_cost_mult * mults.hacknet_node_core_cost_mult,
1,
],
[
"Hacknet Node level upgrade cost ",
Player.hacknet_node_level_cost_mult,
Player.hacknet_node_level_cost_mult * mults.hacknet_node_level_cost_mult,
1,
],
["Company reputation gain ", Player.company_rep_mult, Player.company_rep_mult * mults.company_rep_mult, 1],
[
"Faction reputation gain ",
Player.faction_rep_mult,
Player.faction_rep_mult * mults.faction_rep_mult,
BitNodeMultipliers.FactionWorkRepGain,
],
].map((data): MultiplierListItemData => (data as any).concat([Settings.theme.primary])),
[
"Salary ",
Player.work_money_mult,
Player.work_money_mult * mults.work_money_mult,
BitNodeMultipliers.CompanyWorkMoney,
Settings.theme.money,
],
[
"Crime success ",
Player.crime_success_mult,
Player.crime_success_mult * mults.crime_success_mult,
1,
Settings.theme.combat,
],
[
"Crime money ",
Player.crime_money_mult,
Player.crime_money_mult * mults.crime_money_mult,
BitNodeMultipliers.CrimeMoney,
Settings.theme.money,
],
];
if (Player.canAccessBladeburner()) {
rightColData.push(
...[
[
"Bladeburner Success Chance",
Player.bladeburner_success_chance_mult,
Player.bladeburner_success_chance_mult * mults.bladeburner_success_chance_mult,
1,
],
[
"Bladeburner Max Stamina",
Player.bladeburner_max_stamina_mult,
Player.bladeburner_max_stamina_mult * mults.bladeburner_max_stamina_mult,
1,
],
[
"Bladeburner Stamina Gain",
Player.bladeburner_stamina_gain_mult,
Player.bladeburner_stamina_gain_mult * mults.bladeburner_stamina_gain_mult,
1,
],
[
"Bladeburner Field Analysis",
Player.bladeburner_analysis_mult,
Player.bladeburner_analysis_mult * mults.bladeburner_analysis_mult,
1,
],
].map((data): MultiplierListItemData => (data as any).concat([Settings.theme.primary])),
);
}
function InfiltrationMults(): React.ReactElement {
return (
<>
<MultiplierTable
rows={[
[
"Infiltrator Rep reward",
Player.infiltration_rep_mult,
Player.infiltration_rep_mult * mults.infiltration_rep_mult,
1,
],
[
"Infiltration sell",
Player.infiltration_sell_mult,
Player.infiltration_sell_mult * mults.infiltration_sell_mult,
1,
],
[
"Infiltration trade",
Player.infiltration_trade_mult,
Player.infiltration_trade_mult * mults.infiltration_trade_mult,
1,
],
[
"Infiltration minigame timer",
Player.infiltration_timer_mult,
Player.infiltration_timer_mult * mults.infiltration_timer_mult,
1,
],
[
"Infiltration minigame health reduction",
Player.infiltration_health_reduction_mult,
-1 * (1 - Player.infiltration_health_reduction_mult * mults.infiltration_health_reduction_mult),
1,
],
]}
/>
<br />
</>
);
}
rightColData.push(
...[
[
"Infiltrator Rep reward",
Player.infiltration_rep_mult,
Player.infiltration_rep_mult * mults.infiltration_rep_mult,
1,
],
[
"Infiltration sell",
Player.infiltration_sell_mult,
Player.infiltration_sell_mult * mults.infiltration_sell_mult,
1,
],
[
"Infiltration trade",
Player.infiltration_trade_mult,
Player.infiltration_trade_mult * mults.infiltration_trade_mult,
1,
],
[
"Infiltration minigame timer",
Player.infiltration_timer_mult,
Player.infiltration_timer_mult * mults.infiltration_timer_mult,
1,
],
[
"Infiltration minigame health reduction",
Player.infiltration_health_reduction_mult,
-1 * (1 - Player.infiltration_health_reduction_mult * mults.infiltration_health_reduction_mult),
1,
],
].map((data): MultiplierListItemData => (data as any).concat([Settings.theme.primary])),
);
const hasLeftImprovements = +!!(leftColData.filter((item) => item[2] !== 0).length > 0),
hasRightImprovements = +!!(rightColData.filter((item) => item[2] !== 0).length > 0);
return (
<>
<Typography variant="h4">Multipliers</Typography>
<Box mx={2}>
<MultiplierTable
rows={[
["Hacking Chance ", Player.hacking_chance_mult, Player.hacking_chance_mult * mults.hacking_chance_mult, 1],
["Hacking Speed ", Player.hacking_speed_mult, Player.hacking_speed_mult * mults.hacking_speed_mult, 1],
["Hacking Money ", Player.hacking_money_mult, Player.hacking_money_mult * mults.hacking_money_mult, 1],
["Hacking Growth ", Player.hacking_grow_mult, Player.hacking_grow_mult * mults.hacking_grow_mult, 1],
]}
/>
<br />
<MultiplierTable
rows={[
[
"Hacking Level ",
Player.hacking_mult,
Player.hacking_mult * mults.hacking_mult,
BitNodeMultipliers.HackingLevelMultiplier,
],
[
"Hacking Experience ",
Player.hacking_exp_mult,
Player.hacking_exp_mult * mults.hacking_exp_mult,
BitNodeMultipliers.HackExpGain,
],
]}
/>
<br />
<MultiplierTable
rows={[
[
"Strength Level ",
Player.strength_mult,
Player.strength_mult * mults.strength_mult,
BitNodeMultipliers.StrengthLevelMultiplier,
],
["Strength Experience ", Player.strength_exp_mult, Player.strength_exp_mult * mults.strength_exp_mult, 1],
]}
/>
<br />
<MultiplierTable
rows={[
[
"Defense Level ",
Player.defense_mult,
Player.defense_mult * mults.defense_mult,
BitNodeMultipliers.DefenseLevelMultiplier,
],
["Defense Experience ", Player.defense_exp_mult, Player.defense_exp_mult * mults.defense_exp_mult, 1],
]}
/>
<br />
<MultiplierTable
rows={[
[
"Dexterity Level ",
Player.dexterity_mult,
Player.dexterity_mult * mults.dexterity_mult,
BitNodeMultipliers.DexterityLevelMultiplier,
],
[
"Dexterity Experience ",
Player.dexterity_exp_mult,
Player.dexterity_exp_mult * mults.dexterity_exp_mult,
1,
],
]}
/>
<br />
<MultiplierTable
rows={[
[
"Agility Level ",
Player.agility_mult,
Player.agility_mult * mults.agility_mult,
BitNodeMultipliers.AgilityLevelMultiplier,
],
["Agility Experience ", Player.agility_exp_mult, Player.agility_exp_mult * mults.agility_exp_mult, 1],
]}
/>
<br />
<MultiplierTable
rows={[
[
"Charisma Level ",
Player.charisma_mult,
Player.charisma_mult * mults.charisma_mult,
BitNodeMultipliers.CharismaLevelMultiplier,
],
["Charisma Experience ", Player.charisma_exp_mult, Player.charisma_exp_mult * mults.charisma_exp_mult, 1],
]}
/>
<br />
<MultiplierTable
rows={[
[
"Hacknet Node production ",
Player.hacknet_node_money_mult,
Player.hacknet_node_money_mult * mults.hacknet_node_money_mult,
BitNodeMultipliers.HacknetNodeMoney,
],
[
"Hacknet Node purchase cost ",
Player.hacknet_node_purchase_cost_mult,
Player.hacknet_node_purchase_cost_mult * mults.hacknet_node_purchase_cost_mult,
1,
],
[
"Hacknet Node RAM upgrade cost ",
Player.hacknet_node_ram_cost_mult,
Player.hacknet_node_ram_cost_mult * mults.hacknet_node_ram_cost_mult,
1,
],
[
"Hacknet Node Core purchase cost ",
Player.hacknet_node_core_cost_mult,
Player.hacknet_node_core_cost_mult * mults.hacknet_node_core_cost_mult,
1,
],
[
"Hacknet Node level upgrade cost ",
Player.hacknet_node_level_cost_mult,
Player.hacknet_node_level_cost_mult * mults.hacknet_node_level_cost_mult,
1,
],
]}
/>
<br />
<MultiplierTable
rows={[
["Company reputation gain ", Player.company_rep_mult, Player.company_rep_mult * mults.company_rep_mult, 1],
[
"Faction reputation gain ",
Player.faction_rep_mult,
Player.faction_rep_mult * mults.faction_rep_mult,
BitNodeMultipliers.FactionWorkRepGain,
],
[
"Salary ",
Player.work_money_mult,
Player.work_money_mult * mults.work_money_mult,
BitNodeMultipliers.CompanyWorkMoney,
],
]}
/>
<br />
<MultiplierTable
rows={[
["Crime success ", Player.crime_success_mult, Player.crime_success_mult * mults.crime_success_mult, 1],
[
"Crime money ",
Player.crime_money_mult,
Player.crime_money_mult * mults.crime_money_mult,
BitNodeMultipliers.CrimeMoney,
],
]}
/>
<br />
<BladeburnerMults />
<InfiltrationMults />
</Box>
</>
<Paper
sx={{
p: 1,
maxHeight: 400,
overflowY: "scroll",
display: "grid",
gridTemplateColumns: `repeat(${hasLeftImprovements + hasRightImprovements}, 1fr)`,
}}
>
<MultiplierList rows={leftColData} />
<MultiplierList rows={rightColData} />
</Paper>
);
}

@ -2,14 +2,11 @@
* React component for displaying all of the player's purchased (but not installed)
* Augmentations on the Augmentations UI.
*/
import { List, ListItemText, Paper, Tooltip, Typography } from "@mui/material";
import * as React from "react";
import { Player } from "../../Player";
import { Augmentations } from "../Augmentations";
import { AugmentationNames } from "../data/AugmentationNames";
import { Player } from "../../Player";
import { AugmentationAccordion } from "../../ui/React/AugmentationAccordion";
import List from "@mui/material/List";
export function PurchasedAugmentations(): React.ReactElement {
const augs: React.ReactElement[] = [];
@ -23,14 +20,48 @@ export function PurchasedAugmentations(): React.ReactElement {
}
for (let i = 0; i < Player.queuedAugmentations.length; i++) {
const ownedAug = Player.queuedAugmentations[i];
let displayName = ownedAug.name;
if (ownedAug.name === AugmentationNames.NeuroFluxGovernor && i !== nfgIndex) continue;
const aug = Augmentations[ownedAug.name];
let level = null;
if (ownedAug.name === AugmentationNames.NeuroFluxGovernor) {
level = ownedAug.level;
displayName += ` - Level ${level}`;
}
augs.push(<AugmentationAccordion key={aug.name} aug={aug} level={level} />);
augs.push(
<Tooltip
title={
<Typography>
{(() => {
const info = typeof aug.info === "string" ? <span>{aug.info}</span> : aug.info;
const tooltip = (
<>
{info}
<br />
<br />
{aug.stats}
</>
);
return tooltip;
})()}
</Typography>
}
enterNextDelay={500}
key={displayName}
>
<ListItemText sx={{ px: 2, py: 1 }} primary={displayName} />
</Tooltip>,
);
}
return <List dense>{augs}</List>;
return (
<Paper sx={{ py: 1, maxHeight: 400, overflowY: "scroll" }}>
<List sx={{ height: 400, overflowY: "scroll" }} disablePadding>
{augs}
</List>
</Paper>
);
}

@ -1,21 +1,159 @@
import React from "react";
import { SourceFileMinus1 } from "./SourceFileMinus1";
import { OwnedSourceFiles } from "./OwnedSourceFiles";
import List from "@mui/material/List";
import Typography from "@mui/material/Typography";
import { ListItemButton, ListItemText, Paper } from "@mui/material";
import Box from "@mui/material/Box";
import List from "@mui/material/List";
import Typography from "@mui/material/Typography";
import React, { useState } from "react";
import { Exploit, ExploitName } from "../../Exploits/Exploit";
import { Player } from "../../Player";
import { OwnedAugmentationsOrderSetting } from "../../Settings/SettingEnums";
import { Settings } from "../../Settings/Settings";
import { SourceFile } from "../../SourceFile/SourceFile";
import { SourceFiles } from "../../SourceFile/SourceFiles";
interface SfMinus1 {
info: React.ReactElement;
n: number;
name: string;
lvl: number;
}
const safeGetSf = (sfNum: number): SourceFile | SfMinus1 | null => {
if (sfNum === -1) {
const sfMinus1: SfMinus1 = {
info: (
<>
This Source-File can only be acquired with obscure knowledge of the game, javascript, and the web ecosystem.
<br />
<br />
It increases all of the player's multipliers by 0.1%
<br />
<br />
You have found the following exploits:
<br />
<br />
{Player.exploits.map((c: Exploit) => (
<React.Fragment key={c}>
* {ExploitName(c)}
<br />
</React.Fragment>
))}
</>
),
lvl: Player.exploits.length,
n: -1,
name: "Source-File -1: Exploits in the BitNodes",
};
return sfMinus1;
}
const srcFileKey = "SourceFile" + sfNum;
const sfObj = SourceFiles[srcFileKey];
if (sfObj == null) {
console.error(`Invalid source file number: ${sfNum}`);
return null;
}
return sfObj;
};
const getMaxLevel = (sfObj: SourceFile | SfMinus1): string | number => {
let maxLevel;
switch (sfObj.n) {
case 12:
maxLevel = "∞";
break;
case -1:
maxLevel = Object.keys(Exploit).length;
break;
default:
maxLevel = "3";
}
return maxLevel;
};
export function SourceFilesElement(): React.ReactElement {
const sourceSfs = Player.sourceFiles.slice();
const exploits = Player.exploits;
// Create a fake SF for -1, if "owned"
if (exploits.length > 0) {
sourceSfs.unshift({
n: -1,
lvl: exploits.length,
});
}
if (Settings.OwnedAugmentationsOrder === OwnedAugmentationsOrderSetting.Alphabetically) {
sourceSfs.sort((sf1, sf2) => {
return sf1.n - sf2.n;
});
}
if (sourceSfs.length === 0) {
return <></>;
}
const [selectedSf, setSelectedSf] = useState(sourceSfs[0]);
export function SourceFiles(): React.ReactElement {
return (
<>
<Typography variant="h4">Source Files</Typography>
<Box mx={2}>
<List dense>
<SourceFileMinus1 />
<OwnedSourceFiles />
</List>
</Box>
</>
<Box sx={{ width: "100%", mt: 1 }}>
<Paper sx={{ p: 1 }}>
<Typography variant="h5">Source Files</Typography>
</Paper>
<Paper sx={{ display: "grid", gridTemplateColumns: "1fr 3fr" }}>
<Box>
<List
sx={{ height: 400, overflowY: "scroll", borderRight: `1px solid ${Settings.theme.welllight}` }}
disablePadding
>
{sourceSfs.map((e, i) => {
const sfObj = safeGetSf(e.n);
if (!sfObj) return;
const maxLevel = getMaxLevel(sfObj);
return (
<ListItemButton
key={i + 1}
onClick={() => setSelectedSf(e)}
selected={selectedSf.n === e.n}
sx={{ py: 0 }}
>
<ListItemText
disableTypography
primary={<Typography>{sfObj.name}</Typography>}
secondary={
<Typography>
Level {e.lvl} / {maxLevel}
</Typography>
}
/>
</ListItemButton>
);
})}
</List>
</Box>
<Box sx={{ m: 1 }}>
<Typography variant="h6" sx={{ display: "flex", alignItems: "center", flexWrap: "wrap" }}>
{safeGetSf(selectedSf.n)?.name}
</Typography>
<Typography sx={{ maxHeight: 350, overflowY: "scroll" }}>
{(() => {
const sfObj = safeGetSf(selectedSf.n);
if (!sfObj) return;
const maxLevel = getMaxLevel(sfObj);
return (
<>
Level {selectedSf.lvl} / {maxLevel}
<br />
<br />
{sfObj.info}
</>
);
})()}
</Typography>
</Box>
</Paper>
</Box>
);
}

@ -2,7 +2,7 @@ import React, { useState } from "react";
import { SourceFileFlags } from "../../SourceFile/SourceFileFlags";
import { IRouter } from "../../ui/Router";
import { BitNodes } from "../BitNode";
import { enterBitNode, setRedPillFlag } from "../../RedPill";
import { enterBitNode } from "../../RedPill";
import { PortalModal } from "./PortalModal";
import { CinematicText } from "../../ui/React/CinematicText";
import { use } from "../../ui/Context";
@ -123,7 +123,6 @@ interface IProps {
}
export function BitverseRoot(props: IProps): React.ReactElement {
setRedPillFlag(true);
const player = use.Player();
const enter = enterBitNode;
const destroyed = player.bitNodeN;

@ -276,7 +276,7 @@ export const CONSTANTS: {
CodingContractBaseCompanyRepGain: 4000,
CodingContractBaseMoneyGain: 75e6,
// Augmentation crafting multipliers
// Augmentation grafting multipliers
AugmentationGraftingCostMult: 3,
AugmentationGraftingTimeBase: 3600000,

Some files were not shown because too many files have changed in this diff Show More