Merge pull request #3432 from danielyxie/dev

keeping up to date
This commit is contained in:
hydroflame 2022-04-13 12:37:41 -04:00 committed by GitHub
commit af95f0bfaf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
131 changed files with 3382 additions and 2166 deletions

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"

170
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 */
@ -1755,6 +1773,18 @@ export declare interface Grafting {
*/
getAugmentationGraftTime(augName: string): number;
/**
* Retrieves a list of Augmentations that can be grafted.
* @remarks
* RAM cost: 5 GB
*
* Note that this function returns a list of currently graftable Augmentations,
* based off of the Augmentations that you already own.
*
* @returns An array of graftable Augmentations.
*/
getGraftableAugmentations(): string[];
/**
* Begins grafting the named aug. You must be in New Tokyo to use this.
* @remarks
@ -2442,6 +2472,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 +2608,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 +2669,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
@ -2883,9 +2923,11 @@ export declare interface NS extends Singularity {
* Returns the security increase that would occur if a grow with this many threads happened.
*
* @param threads - Amount of threads that will be used.
* @param hostname - Optional. Hostname of the target server. The number of threads is limited to the number needed to hack the servers maximum amount of money.
* @param cores - Optional. The number of cores of the server that would run grow.
* @returns The security increase.
*/
growthAnalyzeSecurity(threads: number): number;
growthAnalyzeSecurity(threads: number, hostname?: string, cores?: number): number;
/**
* Suspends the script for n milliseconds.
@ -2913,7 +2955,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.
@ -2923,7 +2965,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.
@ -3052,6 +3094,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
@ -3942,7 +4005,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.
@ -4454,7 +4517,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.
@ -4649,6 +4712,13 @@ export declare interface NS extends Singularity {
* RAM cost: 0.2 GB
*/
getSharePower(): number;
enums: NSEnums;
}
/** @public */
export declare interface NSEnums {
toast: typeof ToastVariant;
}
/**
@ -4950,10 +5020,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" */
@ -4966,24 +5040,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;
}
@ -5753,11 +5869,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.
@ -6031,9 +6144,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.
@ -6732,6 +6845,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

@ -66,7 +66,7 @@ documentation_title = '{0} Documentation'.format(project)
# The short X.Y version.
version = '1.6'
# The full version, including alpha/beta/rc tags.
release = '1.6.3'
release = '1.6.4'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

@ -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.4",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "bitburner",
"version": "1.0.0",
"version": "1.6.4",
"dependencies": {
"electron-config": "^2.0.0",
"electron-log": "^4.4.4",

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

@ -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;
```

@ -0,0 +1,25 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [bitburner](./bitburner.md) &gt; [Grafting](./bitburner.grafting.md) &gt; [getGraftableAugmentations](./bitburner.grafting.getgraftableaugmentations.md)
## Grafting.getGraftableAugmentations() method
Retrieves a list of Augmentations that can be grafted.
<b>Signature:</b>
```typescript
getGraftableAugmentations(): string[];
```
<b>Returns:</b>
string\[\]
An array of graftable Augmentations.
## Remarks
RAM cost: 5 GB
Note that this function returns a list of currently graftable Augmentations, based off of the Augmentations that you already own.

@ -22,5 +22,6 @@ This API requires Source-File 10 to use.
| --- | --- |
| [getAugmentationGraftPrice(augName)](./bitburner.grafting.getaugmentationgraftprice.md) | Retrieve the grafting cost of an aug. |
| [getAugmentationGraftTime(augName)](./bitburner.grafting.getaugmentationgrafttime.md) | Retrieves the time required to graft an aug. |
| [getGraftableAugmentations()](./bitburner.grafting.getgraftableaugmentations.md) | Retrieves a list of Augmentations that can be grafted. |
| [graftAugmentation(augName, focus)](./bitburner.grafting.graftaugmentation.md) | Begins grafting the named aug. You must be in New Tokyo to use this. |

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

@ -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. |
@ -113,11 +115,11 @@ export async function main(ns) {
| [getWeakenTime(host)](./bitburner.ns.getweakentime.md) | Get the execution time of a weaken() call. |
| [grow(host, opts)](./bitburner.ns.grow.md) | Spoof money in a servers bank account, increasing the amount available. |
| [growthAnalyze(host, growthAmount, cores)](./bitburner.ns.growthanalyze.md) | Calculate the number of grow thread needed to grow a server by a certain multiplier. |
| [growthAnalyzeSecurity(threads)](./bitburner.ns.growthanalyzesecurity.md) | Calculate the security increase for a number of thread. |
| [growthAnalyzeSecurity(threads, hostname, cores)](./bitburner.ns.growthanalyzesecurity.md) | Calculate the security increase for a number of thread. |
| [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)

4
package-lock.json generated

@ -1,12 +1,12 @@
{
"name": "bitburner",
"version": "1.6.0",
"version": "1.6.4",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "bitburner",
"version": "1.6.0",
"version": "1.6.4",
"hasInstallScript": true,
"license": "SEE LICENSE IN license.txt",
"dependencies": {

@ -1,7 +1,7 @@
{
"name": "bitburner",
"license": "SEE LICENSE IN license.txt",
"version": "1.6.0",
"version": "1.6.4",
"main": "electron-main.js",
"author": {
"name": "Daniel Xie & Olivier Gagnon"
@ -109,6 +109,7 @@
"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",
@ -117,6 +118,7 @@
"build:dev": "webpack --mode development",
"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",
@ -129,6 +131,9 @@
"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"
}
}

@ -380,9 +380,6 @@ export class Augmentation {
// Name of Augmentation
name = "";
// Whether the player owns this Augmentation
owned = false;
// Array of names of all prerequisites
prereqs: string[] = [];

@ -118,8 +118,6 @@ function resetAugmentation(aug: Augmentation): void {
}
function applyAugmentation(aug: IPlayerOwnedAugmentation, reapply = false): void {
Augmentations[aug.name].owned = true;
const augObj = Augmentations[aug.name];
// Apply multipliers

@ -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;

@ -1920,7 +1920,7 @@ export class Bladeburner implements IBladeburner {
}
// If the Player starts doing some other actions, set action to idle and alert
if (Augmentations[AugmentationNames.BladesSimulacrum].owned === false && player.isWorking) {
if (player.hasAugmentation(AugmentationNames.BladesSimulacrum) === false && player.isWorking) {
if (this.action.type !== ActionTypes["Idle"]) {
let msg = "Your Bladeburner action was cancelled because you started doing something else.";
if (this.automateEnabled) {

@ -116,7 +116,7 @@ export const CONSTANTS: {
TotalNumBitNodes: number;
LatestUpdate: string;
} = {
VersionString: "1.6.3",
VersionString: "1.6.4",
VersionNumber: 13,
// Speed (in ms) at which the main loop is updated

@ -161,9 +161,9 @@ export class Material {
break;
case "Robots":
this.dmd = 90;
this.dmdR = [80, 9];
this.dmdR = [80, 99];
this.cmp = 90;
this.cmpR = [80, 9];
this.cmpR = [80, 99];
this.bCost = 75e3;
this.mv = 0.5; //Less mv bc its processed twice
this.mku = 1;
@ -172,7 +172,7 @@ export class Material {
this.dmd = 90;
this.dmdR = [80, 99];
this.cmp = 90;
this.cmpR = [80, 9];
this.cmpR = [80, 99];
this.bCost = 15e3;
this.mv = 0.8; //Less mv bc its processed twice
this.mku = 0.5;

67
src/CotMG/DummyGift.ts Normal file

@ -0,0 +1,67 @@
import { ActiveFragment } from "./ActiveFragment";
import { IStaneksGift } from "./IStaneksGift";
export class DummyGift implements IStaneksGift {
storedCycles = 0;
fragments: ActiveFragment[] = [];
_width: number;
_height: number;
constructor(width: number, height: number, fragments: ActiveFragment[]) {
this.fragments = fragments;
this._width = width;
this._height = height;
}
width(): number {
return this._width;
}
height(): number {
return this._height;
}
charge(): any {
throw new Error("unimplemented for dummy gift");
}
process(): any {
throw new Error("unimplemented for dummy gift");
}
effect(): any {
throw new Error("unimplemented for dummy gift");
}
canPlace(): any {
throw new Error("unimplemented for dummy gift");
}
place(): any {
throw new Error("unimplemented for dummy gift");
}
findFragment(): any {
throw new Error("unimplemented for dummy gift");
}
fragmentAt(worldX: number, worldY: number): ActiveFragment | undefined {
for (const aFrag of this.fragments) {
if (aFrag.fullAt(worldX, worldY)) {
return aFrag;
}
}
return undefined;
}
delete(): any {
throw new Error("unimplemented for dummy gift");
}
clear(): any {
throw new Error("unimplemented for dummy gift");
}
count(): any {
throw new Error("unimplemented for dummy gift");
}
inBonus(): any {
throw new Error("unimplemented for dummy gift");
}
prestigeAugmentation(): any {
throw new Error("unimplemented for dummy gift");
}
prestigeSourceFile(): any {
throw new Error("unimplemented for dummy gift");
}
}

@ -12,3 +12,26 @@ export function loadStaneksGift(saveString: string): void {
staneksGift = new StaneksGift();
}
}
export function zeros(dimensions: number[]): any {
const array = [];
for (let i = 0; i < dimensions[0]; ++i) {
array.push(dimensions.length == 1 ? 0 : zeros(dimensions.slice(1)));
}
return array;
}
export function calculateGrid(gift: IStaneksGift): number[][] {
const newgrid = zeros([gift.width(), gift.height()]) as unknown as number[][];
for (let i = 0; i < gift.width(); i++) {
for (let j = 0; j < gift.height(); j++) {
const fragment = gift.fragmentAt(i, j);
if (!fragment) continue;
newgrid[i][j] = 1;
}
}
return newgrid;
}

@ -0,0 +1,33 @@
import { Box, Table } from "@mui/material";
import * as React from "react";
import { ActiveFragment } from "../ActiveFragment";
import { DummyGift } from "../DummyGift";
import { Grid } from "./Grid";
import { calculateGrid, zeros } from "../Helper";
interface IProps {
width: number;
height: number;
fragments: ActiveFragment[];
}
export function DummyGrid(props: IProps): React.ReactElement {
const gift = new DummyGift(props.width, props.height, props.fragments);
const activeGrid = calculateGrid(gift);
const ghostGrid = zeros([props.width, props.height]);
return (
<Box>
<Table>
<Grid
width={props.width}
height={props.height}
activeGrid={activeGrid}
ghostGrid={ghostGrid}
gift={gift}
enter={() => undefined}
click={() => undefined}
/>
</Table>
</Box>
);
}

60
src/CotMG/ui/Grid.tsx Normal file

@ -0,0 +1,60 @@
import { TableBody, TableRow } from "@mui/material";
import * as React from "react";
import { ActiveFragment } from "../ActiveFragment";
import { IStaneksGift } from "../IStaneksGift";
import { Cell } from "./Cell";
interface IProps {
width: number;
height: number;
activeGrid: number[][];
ghostGrid: number[][];
gift: IStaneksGift;
enter(i: number, j: number): void;
click(i: number, j: number): void;
}
function randomColor(fragment: ActiveFragment): string {
// Can't set Math.random seed so copy casino. TODO refactor both RNG later.
let s1 = Math.pow((fragment.x + 1) * (fragment.y + 1), 10);
let s2 = s1;
let s3 = s1;
const colors = [];
for (let i = 0; i < 3; i++) {
s1 = (171 * s1) % 30269;
s2 = (172 * s2) % 30307;
s3 = (170 * s3) % 30323;
colors.push((s1 / 30269.0 + s2 / 30307.0 + s3 / 30323.0) % 1.0);
}
return `rgb(${colors[0] * 256}, ${colors[1] * 256}, ${colors[2] * 256})`;
}
export function Grid(props: IProps): React.ReactElement {
function color(worldX: number, worldY: number): string {
if (props.ghostGrid[worldX][worldY] && props.activeGrid[worldX][worldY]) return "red";
if (props.ghostGrid[worldX][worldY]) return "white";
if (props.activeGrid[worldX][worldY]) {
const fragment = props.gift.fragmentAt(worldX, worldY);
if (!fragment) throw new Error("ActiveFragment should not be null");
return randomColor(fragment);
}
return "";
}
// switch the width/length to make axis consistent.
const elems = [];
for (let j = 0; j < props.height; j++) {
const cells = [];
for (let i = 0; i < props.width; i++) {
cells.push(
<Cell key={i} onMouseEnter={() => props.enter(i, j)} onClick={() => props.click(i, j)} color={color(i, j)} />,
);
}
elems.push(<TableRow key={j}>{cells}</TableRow>);
}
return <TableBody>{elems}</TableBody>;
}

@ -1,62 +1,20 @@
import * as React from "react";
import { Fragment, NoneFragment } from "../Fragment";
import { ActiveFragment } from "../ActiveFragment";
import { FragmentType } from "../FragmentType";
import { IStaneksGift } from "../IStaneksGift";
import { Cell } from "./Cell";
import { FragmentInspector } from "./FragmentInspector";
import { FragmentSelector } from "./FragmentSelector";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import TableRow from "@mui/material/TableRow";
import TableBody from "@mui/material/TableBody";
import { Table } from "../../ui/React/Table";
function zeros(dimensions: number[]): any {
const array = [];
for (let i = 0; i < dimensions[0]; ++i) {
array.push(dimensions.length == 1 ? 0 : zeros(dimensions.slice(1)));
}
return array;
}
function randomColor(fragment: ActiveFragment): string {
// Can't set Math.random seed so copy casino. TODO refactor both RNG later.
let s1 = Math.pow((fragment.x + 1) * (fragment.y + 1), 10);
let s2 = s1;
let s3 = s1;
const colors = [];
for (let i = 0; i < 3; i++) {
s1 = (171 * s1) % 30269;
s2 = (172 * s2) % 30307;
s3 = (170 * s3) % 30323;
colors.push((s1 / 30269.0 + s2 / 30307.0 + s3 / 30323.0) % 1.0);
}
return `rgb(${colors[0] * 256}, ${colors[1] * 256}, ${colors[2] * 256})`;
}
import { Grid } from "./Grid";
import { zeros, calculateGrid } from "../Helper";
interface IProps {
gift: IStaneksGift;
}
export function MainBoard(props: IProps): React.ReactElement {
function calculateGrid(gift: IStaneksGift): any {
const newgrid = zeros([gift.width(), gift.height()]);
for (let i = 0; i < gift.width(); i++) {
for (let j = 0; j < gift.height(); j++) {
const fragment = gift.fragmentAt(i, j);
if (!fragment) continue;
newgrid[i][j] = 1;
}
}
return newgrid;
}
const [grid, setGrid] = React.useState(calculateGrid(props.gift));
const [ghostGrid, setGhostGrid] = React.useState(zeros([props.gift.width(), props.gift.height()]));
const [pos, setPos] = React.useState([0, 0]);
@ -96,44 +54,11 @@ export function MainBoard(props: IProps): React.ReactElement {
setGrid(calculateGrid(props.gift));
}
function color(worldX: number, worldY: number): string {
if (ghostGrid[worldX][worldY] && grid[worldX][worldY]) return "red";
if (ghostGrid[worldX][worldY]) return "white";
if (grid[worldX][worldY]) {
const fragment = props.gift.fragmentAt(worldX, worldY);
if (!fragment) throw new Error("ActiveFragment should not be null");
return randomColor(fragment);
}
return "";
}
function clear(): void {
props.gift.clear();
setGrid(zeros([props.gift.width(), props.gift.height()]));
}
// switch the width/length to make axis consistent.
const elems = [];
for (let j = 0; j < props.gift.height(); j++) {
const cells = [];
for (let i = 0; i < props.gift.width(); i++) {
cells.push(
<Cell
key={i}
onMouseEnter={() => moveGhost(i, j, rotation)}
onClick={() => clickAt(i, j)}
color={color(i, j)}
/>,
);
}
elems.push(
<TableRow key={j} className="staneksgift_row">
{cells}
</TableRow>,
);
}
function updateSelectedFragment(fragment: Fragment): void {
setSelectedFragment(fragment);
const newgrid = zeros([props.gift.width(), props.gift.height()]);
@ -162,7 +87,15 @@ export function MainBoard(props: IProps): React.ReactElement {
<Button onClick={clear}>Clear</Button>
<Box display="flex">
<Table>
<TableBody>{elems}</TableBody>
<Grid
width={props.gift.width()}
height={props.gift.height()}
activeGrid={grid}
ghostGrid={ghostGrid}
gift={props.gift}
enter={(i, j) => moveGhost(i, j, rotation)}
click={(i, j) => clickAt(i, j)}
/>
</Table>
<FragmentInspector gift={props.gift} x={pos[0]} y={pos[1]} fragment={props.gift.fragmentAt(pos[0], pos[1])} />
</Box>

@ -4,7 +4,12 @@ import { CONSTANTS } from "../../Constants";
import { StaneksGiftEvents } from "../StaneksGiftEvents";
import { MainBoard } from "./MainBoard";
import { IStaneksGift } from "../IStaneksGift";
import { Info } from "@mui/icons-material";
import { dialogBoxCreate } from "../../ui/React/DialogBox";
import Typography from "@mui/material/Typography";
import { ActiveFragment } from "../ActiveFragment";
import { Fragments } from "../Fragment";
import { DummyGrid } from "./DummyGrid";
type IProps = {
staneksGift: IStaneksGift;
@ -18,7 +23,162 @@ export function StaneksGiftRoot({ staneksGift }: IProps): React.ReactElement {
useEffect(() => StaneksGiftEvents.subscribe(rerender), []);
return (
<>
<Typography variant="h4">Stanek's Gift</Typography>
<Typography variant="h4">
Stanek's Gift
<Info
sx={{ ml: 1, mb: 0 }}
color="info"
onClick={() =>
dialogBoxCreate(
<>
<Typography>
Stanek's Gift is a powerful, unique augmentation obtained by joining the Church of the Machine God,
which can be found in Chongqing. It is only possible to join the church if you are in BitNode 13 or
possess at least one level of Source File 13, and you will be turned away if you have purchased or
installed any augmentations beside NeuroFlux Governors. You are, however, permitted to install
augmentations as normal once you have joined the church.
</Typography>
<br />
<Typography>
Initially, those bearing the gift will find that its overwhelming power worsens all of their stats by
10%. This penalty can be overcome in time by receiving free upgrades from the Church of the Machine
God faction, but the reputation requirements for these upgrades are steep, and you can only obtain
reputation with the church by charging the gift.
</Typography>
<br />
<Typography>
In order to charge Stanek's Gift, the user must first arrange stat-modifying fragments within the grid
located on the device. This may be done manually or by scripts that utilize the Stanek's Gift
Netscript API. Not every tile of the grid must house a fragment, but fragments cannot overlap or
otherwise share tiles. Fragments can be rotated, but their design does not allow them to be flipped
around to mirror their original shape. Note that the size of the grid is determined by the BitNode you
are currently in and the level of your Source File 13, if applicable.
</Typography>
<br />
<Typography>
There exist two kinds of fragments. The first are Stat Fragments, which take up 4 tiles of the grid.
Each Stat Fragment is unique, and there is only one of each. There is no way to obtain more of these
fragments. Each Stat Fragment has an associated stat that it will improve, as well as a multiplier on
its effectiveness known as power. When initially placed, a Stat Fragment will have no effect. In order
for the fragment to gain stat boosts, it must be charged. The other kind of fragments are known as
Booster Fragments, which take up 5 tiles of the grid. There is no shortage of Booster Fragments, and
it is virtually impossible to run out of them. While not providing any direct stat increases to their
user, Stat Fragments increase the efficacy of adjacent Stat Fragments by 10%, and do not need to be
charged.
</Typography>
<DummyGrid
width={4}
height={4}
fragments={[
new ActiveFragment({
x: 0,
y: 0,
rotation: 0,
fragment: Fragments.find((f) => f.id === 5) ?? Fragments[0],
}),
new ActiveFragment({
x: 0,
y: 2,
rotation: 0,
fragment: Fragments.find((f) => f.id === 101) ?? Fragments[0],
}),
]}
/>
<Typography sx={{ fontStyle: "italic" }}>
This boost provides a bonus to the touching fragment
</Typography>
<DummyGrid
width={4}
height={4}
fragments={[
new ActiveFragment({
x: 0,
y: 1,
rotation: 3,
fragment: Fragments.find((f) => f.id === 100) ?? Fragments[0],
}),
new ActiveFragment({
x: 0,
y: 0,
rotation: 2,
fragment: Fragments.find((f) => f.id === 1) ?? Fragments[0],
}),
]}
/>
<Typography sx={{ fontStyle: "italic" }}>
Even though the booster touches many tiles, the bonus is only applied once.
</Typography>
<DummyGrid
width={4}
height={4}
fragments={[
new ActiveFragment({
x: 0,
y: 0,
rotation: 0,
fragment: Fragments.find((f) => f.id === 5) ?? Fragments[0],
}),
new ActiveFragment({
x: 2,
y: 0,
rotation: 0,
fragment: Fragments.find((f) => f.id === 105) ?? Fragments[0],
}),
]}
/>
<Typography sx={{ fontStyle: "italic" }}>
Even though the booster touches many tiles, the bonus is only applied once.
</Typography>
<DummyGrid
width={4}
height={4}
fragments={[
new ActiveFragment({
x: 0,
y: 0,
rotation: 1,
fragment: Fragments.find((f) => f.id === 27) ?? Fragments[0],
}),
new ActiveFragment({
x: 0,
y: 1,
rotation: 2,
fragment: Fragments.find((f) => f.id === 100) ?? Fragments[0],
}),
new ActiveFragment({
x: 2,
y: 0,
rotation: 1,
fragment: Fragments.find((f) => f.id === 30) ?? Fragments[0],
}),
]}
/>
<Typography sx={{ fontStyle: "italic" }}>
This booster provides bonus to all fragment it touches.
</Typography>
<br />
<Typography>
Stat Fragments are charged using the stanek.chargeFragment(rootX, rootY) NetScript API function. The
charging process ordinarily takes 1000ms to complete, but only takes 200ms during bonus time. When the
function finishes executing, the fragment's charge levels will be raised by an amount corresponding to
the number of threads that were used. Note that it is no more effective to charge a fragment many
times with few threads than to charge few times with many threads, so there is no need to distribute
charging jobs across multiple scripts. As a Stat Fragment's charge level is increased, its bonuses
will increase, but there will be diminishing returns. As such, it is generally most efficient to
charge all of the placed fragments equally. The charge level of a fragment will not decrease over
time, but it will be reset to 0 upon removing it from the board or installing augmentations.
</Typography>
</>,
)
}
/>
</Typography>
<Typography>
The gift is a grid on which you can place upgrades called fragments. The main type of fragment increases a stat,
like your hacking skill or agility exp. Once a stat fragment is placed it then needs to be charged via scripts

@ -72,17 +72,12 @@ export function buyDarkwebItem(itemName: string): void {
// buy and push
Player.loseMoney(item.price, "other");
const programsRef = Player.getHomeComputer().programs;
// Remove partially created program if there is one
const existingPartialExeIndex = programsRef.findIndex(
(program) => item?.program && program.startsWith(item?.program),
);
// findIndex returns -1 if there is no match, we only want to splice on a match
if (existingPartialExeIndex > -1) {
programsRef.splice(existingPartialExeIndex, 1);
Player.getHomeComputer().pushProgram(item.program);
// Cancel if the program is in progress of writing
if (Player.createProgramName === item.program) {
Player.isWorking = false;
Player.resetWorkStatus();
}
// Add the newly bought, full .exe
Player.getHomeComputer().programs.push(item.program);
Terminal.print(
"You have purchased the " + item.program + " program. The new program can be found on your home computer.",

@ -10,6 +10,7 @@ import Button from "@mui/material/Button";
import { Money } from "../../ui/React/Money";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { IRouter } from "../../ui/Router";
import { checkForMessagesToSend } from "../../Message/MessageHelpers";
interface IProps {
player: IPlayer;
@ -45,6 +46,10 @@ export function General(props: IProps): React.ReactElement {
props.router.toBitVerse(false, false);
}
function checkMessages(): void {
checkForMessagesToSend();
}
useEffect(() => {
if (error) throw new ReferenceError("Manually thrown error");
}, [error]);
@ -88,6 +93,7 @@ export function General(props: IProps): React.ReactElement {
<Button onClick={quickHackW0r1dD43m0n}>Quick w0rld_d34m0n</Button>
<Button onClick={hackW0r1dD43m0n}>Hack w0rld_d34m0n</Button>
<Button onClick={() => setError(true)}>Throw Error</Button>
<Button onClick={checkMessages}>Check Messages</Button>
</AccordionDetails>
</Accordion>
);

@ -2,7 +2,7 @@ import { Player } from "./Player";
import { Router } from "./ui/GameRoot";
import { removeLeadingSlash } from "./Terminal/DirectoryHelpers";
import { Terminal } from "./Terminal";
import { SnackbarEvents } from "./ui/React/Snackbar";
import { SnackbarEvents, ToastVariant } from "./ui/React/Snackbar";
import { IMap, IReturnStatus } from "./types";
import { GetServer } from "./Server/AllServers";
import { ImportPlayerData, SaveData, saveObject } from "./SaveObject";
@ -111,8 +111,7 @@ function initAppNotifier(): void {
if (!fn) fn = Terminal.print;
fn.bind(Terminal)(message);
},
toast: (message: string, type: "info" | "success" | "warning" | "error", duration = 2000) =>
SnackbarEvents.emit(message, type, duration),
toast: (message: string, type: ToastVariant, duration = 2000) => SnackbarEvents.emit(message, type, duration),
};
// Will be consumud by the electron wrapper.
@ -127,7 +126,7 @@ function initSaveFunctions(): void {
saveObject.exportGame();
} catch (error) {
console.log(error);
SnackbarEvents.emit("Could not export game.", "error", 2000);
SnackbarEvents.emit("Could not export game.", ToastVariant.ERROR, 2000);
}
},
triggerScriptsExport: (): void => exportScripts("*", Player.getHomeComputer()),
@ -176,7 +175,7 @@ function initElectronBridge(): void {
})
.catch((error: any) => {
console.log(error);
SnackbarEvents.emit("Could not save game.", "error", 2000);
SnackbarEvents.emit("Could not save game.", ToastVariant.ERROR, 2000);
});
});
bridge.receive("trigger-game-export", () => {
@ -184,7 +183,7 @@ function initElectronBridge(): void {
(window as any).appSaveFns.triggerGameExport();
} catch (error) {
console.log(error);
SnackbarEvents.emit("Could not export game.", "error", 2000);
SnackbarEvents.emit("Could not export game.", ToastVariant.ERROR, 2000);
}
});
bridge.receive("trigger-scripts-export", () => {
@ -192,7 +191,7 @@ function initElectronBridge(): void {
(window as any).appSaveFns.triggerScriptsExport();
} catch (error) {
console.log(error);
SnackbarEvents.emit("Could not export scripts.", "error", 2000);
SnackbarEvents.emit("Could not export scripts.", ToastVariant.ERROR, 2000);
}
});
}

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