Merge pull request #1949 from danielyxie/dev

build
This commit is contained in:
hydroflame
2021-12-16 12:58:30 -05:00
committed by GitHub
32 changed files with 442 additions and 244 deletions

32
dist/bitburner.d.ts vendored
View File

@ -2124,6 +2124,27 @@ export declare interface NodeStats {
/** /**
* Collection of all functions passed to scripts * Collection of all functions passed to scripts
* @public * @public
* @remarks
* <b>Basic ns1 usage example:</b>
* ```ts
* // Basic ns functions can be used directly
* methodName();
* // Some related functions are gathered within a common namespace
* property.methodName();
* ```
* {@link https://bitburner.readthedocs.io/en/latest/netscript/netscript1.html| ns1 in-game docs}
* <hr>
* <b>Basic ns2 usage example:</b>
* ```ts
* export async function main(ns) {
* // Basic ns functions can be accessed on the ns object
* await ns.methodName;
* // Some related functions are gathered under a sub-property of the ns object
* await ns.property.methodName;
* }
* ```
* {@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 extends Singularity {
/** /**
@ -2321,9 +2342,9 @@ export declare interface NS extends Singularity {
* *
* @example * @example
* ```ts * ```ts
* //For example, assume the following returns 1: * //For example, assume the following returns 0.01:
* hackAnalyze("foodnstuff"); * hackAnalyze("foodnstuff");
* //This means that if hack the foodnstuff server, then you will steal 1% of its total money. If you hack using N threads, then you will steal N% of its total money. * //This means that if hack the foodnstuff server, then you will steal 1% of its total money. If you hack using N threads, then you will steal N*0.01% of its total money.
* ``` * ```
* @param host - Hostname of the target server. * @param host - Hostname of the target server.
* @returns The percentage of money you will steal from the target server with a single hack. * @returns The percentage of money you will steal from the target server with a single hack.
@ -3259,13 +3280,12 @@ export declare interface NS extends Singularity {
deleteServer(host: string): boolean; deleteServer(host: string): boolean;
/** /**
* Returns an array with either the hostnames or IPs of all of the servers you have purchased. * Returns an array with the hostnames of all of the servers you have purchased.
* *
* @remarks 2.25 GB * @remarks 2.25 GB
* @param hostnameMode - Optional. Defaults to true. Returns hostnames if true, and IPs if false. * @returns Returns an array with the hostnames of all of the servers you have purchased.
* @returns Returns an array with either the hostnames or IPs of all of the servers you have purchased.
*/ */
getPurchasedServers(hostnameMode?: boolean): string[]; getPurchasedServers(): string[];
/** /**
* Returns the maximum number of servers you can purchase. * Returns the maximum number of servers you can purchase.

26
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

View File

@ -9,14 +9,15 @@ if (greenworks.init()) {
const debug = false; const debug = false;
function createWindow() { function createWindow(killall) {
const win = new BrowserWindow({ const win = new BrowserWindow({
show: false, show: false,
}); });
win.removeMenu(); win.removeMenu();
win.maximize(); win.maximize();
win.loadFile("index.html"); noScripts = killall ? { query: { noScripts: killall } } : {};
win.loadFile("index.html", noScripts);
win.show(); win.show();
if (debug) win.webContents.openDevTools(); if (debug) win.webContents.openDevTools();
@ -75,7 +76,7 @@ function createWindow() {
if (intervalID) clearInterval(intervalID); if (intervalID) clearInterval(intervalID);
win.webContents.forcefullyCrashRenderer(); win.webContents.forcefullyCrashRenderer();
win.close(); win.close();
createWindow(); createWindow(true);
}, },
}, },
], ],
@ -110,5 +111,5 @@ function createWindow() {
} }
app.whenReady().then(() => { app.whenReady().then(() => {
createWindow(); createWindow(false);
}); });

View File

@ -14221,7 +14221,7 @@
{ {
"kind": "Interface", "kind": "Interface",
"canonicalReference": "bitburner!NS:interface", "canonicalReference": "bitburner!NS:interface",
"docComment": "/**\n * Collection of all functions passed to scripts\n *\n * @public\n */\n", "docComment": "/**\n * Collection of all functions passed to scripts\n *\n * @remarks\n *\n * <b>Basic ns1 usage example:</b>\n * ```ts\n * // Basic ns functions can be used directly\n * methodName();\n * // Some related functions are gathered within a common namespace\n * property.methodName();\n * ```\n *\n * {@link https://bitburner.readthedocs.io/en/latest/netscript/netscript1.html | ns1 in-game docs} <hr> <b>Basic ns2 usage example:</b>\n * ```ts\n * export async function main(ns) {\n * // Basic ns functions can be accessed on the ns object\n * await ns.methodName;\n * // Some related functions are gathered under a sub-property of the ns object\n * await ns.property.methodName;\n * }\n * ```\n *\n * {@link https://bitburner.readthedocs.io/en/latest/netscript/netscriptjs.html | ns2 in-game docs} <hr>\n *\n * @public\n */\n",
"excerptTokens": [ "excerptTokens": [
{ {
"kind": "Content", "kind": "Content",
@ -15562,19 +15562,11 @@
{ {
"kind": "MethodSignature", "kind": "MethodSignature",
"canonicalReference": "bitburner!NS#getPurchasedServers:member(1)", "canonicalReference": "bitburner!NS#getPurchasedServers:member(1)",
"docComment": "/**\n * Returns an array with either the hostnames or IPs of all of the servers you have purchased.\n *\n * @remarks\n *\n * 2.25 GB\n *\n * @param hostnameMode - Optional. Defaults to true. Returns hostnames if true, and IPs if false.\n *\n * @returns Returns an array with either the hostnames or IPs of all of the servers you have purchased.\n */\n", "docComment": "/**\n * Returns an array with the hostnames of all of the servers you have purchased.\n *\n * @remarks\n *\n * 2.25 GB\n *\n * @returns Returns an array with the hostnames of all of the servers you have purchased.\n */\n",
"excerptTokens": [ "excerptTokens": [
{ {
"kind": "Content", "kind": "Content",
"text": "getPurchasedServers(hostnameMode?: " "text": "getPurchasedServers(): "
},
{
"kind": "Content",
"text": "boolean"
},
{
"kind": "Content",
"text": "): "
}, },
{ {
"kind": "Content", "kind": "Content",
@ -15587,20 +15579,12 @@
], ],
"isOptional": false, "isOptional": false,
"returnTypeTokenRange": { "returnTypeTokenRange": {
"startIndex": 3, "startIndex": 1,
"endIndex": 4 "endIndex": 2
}, },
"releaseTag": "Public", "releaseTag": "Public",
"overloadIndex": 1, "overloadIndex": 1,
"parameters": [ "parameters": [],
{
"parameterName": "hostnameMode",
"parameterTypeTokenRange": {
"startIndex": 1,
"endIndex": 2
}
}
],
"name": "getPurchasedServers" "name": "getPurchasedServers"
}, },
{ {
@ -16839,7 +16823,7 @@
{ {
"kind": "MethodSignature", "kind": "MethodSignature",
"canonicalReference": "bitburner!NS#hackAnalyze:member(1)", "canonicalReference": "bitburner!NS#hackAnalyze:member(1)",
"docComment": "/**\n * Get the percent of money stolen with a single thread.\n *\n * @remarks\n *\n * RAM cost: 1 GB\n *\n * Returns the percentage of the specified servers money you will steal with a single hack. This value is returned in percentage form, not decimal (Netscript functions typically return in decimal form, but not this one).\n *\n * @param host - Hostname of the target server.\n *\n * @returns The percentage of money you will steal from the target server with a single hack.\n *\n * @example\n * ```ts\n * //For example, assume the following returns 1:\n * hackAnalyze(\"foodnstuff\");\n * //This means that if hack the foodnstuff server, then you will steal 1% of its total money. If you hack using N threads, then you will steal N% of its total money.\n * ```\n *\n */\n", "docComment": "/**\n * Get the percent of money stolen with a single thread.\n *\n * @remarks\n *\n * RAM cost: 1 GB\n *\n * Returns the percentage of the specified servers money you will steal with a single hack. This value is returned in percentage form, not decimal (Netscript functions typically return in decimal form, but not this one).\n *\n * @param host - Hostname of the target server.\n *\n * @returns The percentage of money you will steal from the target server with a single hack.\n *\n * @example\n * ```ts\n * //For example, assume the following returns 0.01:\n * hackAnalyze(\"foodnstuff\");\n * //This means that if hack the foodnstuff server, then you will steal 1% of its total money. If you hack using N threads, then you will steal N*0.01% of its total money.\n * ```\n *\n */\n",
"excerptTokens": [ "excerptTokens": [
{ {
"kind": "Content", "kind": "Content",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -4,25 +4,18 @@
## NS.getPurchasedServers() method ## NS.getPurchasedServers() method
Returns an array with either the hostnames or IPs of all of the servers you have purchased. Returns an array with the hostnames of all of the servers you have purchased.
<b>Signature:</b> <b>Signature:</b>
```typescript ```typescript
getPurchasedServers(hostnameMode?: boolean): string[]; getPurchasedServers(): string[];
``` ```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| hostnameMode | boolean | Optional. Defaults to true. Returns hostnames if true, and IPs if false. |
<b>Returns:</b> <b>Returns:</b>
string\[\] string\[\]
Returns an array with either the hostnames or IPs of all of the servers you have purchased. Returns an array with the hostnames of all of the servers you have purchased.
## Remarks ## Remarks

View File

@ -22,7 +22,7 @@ getWeakenTime(host: string): number;
number number
Returns the amount of time in milliseconds it takes to execute the weaken Netscript function. Returns Infinity if called on a Hacknet Server. Returns the amount of time in milliseconds it takes to execute the grow Netscript function. Returns Infinity if called on a Hacknet Server.
## Remarks ## Remarks

View File

@ -34,8 +34,8 @@ Returns the percentage of the specified servers money you will steal with a s
```ts ```ts
//For example, assume the following returns 1: //For example, assume the following returns 0.01:
hackAnalyze("foodnstuff"); hackAnalyze("foodnstuff");
//This means that if hack the foodnstuff server, then you will steal 1% of its total money. If you hack using N threads, then you will steal N% of its total money. //This means that if hack the foodnstuff server, then you will steal 1% of its total money. If you hack using N threads, then you will steal N*0.01% of its total money.
``` ```

View File

@ -11,12 +11,37 @@ Collection of all functions passed to scripts
```typescript ```typescript
export interface NS extends Singularity export interface NS extends Singularity
``` ```
<b>Extends:</b> [Singularity](./bitburner.singularity.md) <b>Extends:</b> [Singularity](./bitburner.singularity.md)
## Remarks
<b>Basic ns1 usage example:</b>
```ts
// Basic ns functions can be used directly
methodName();
// Some related functions are gathered within a common namespace
property.methodName();
```
[ns1 in-game docs](https://bitburner.readthedocs.io/en/latest/netscript/netscript1.html) <hr> <b>Basic ns2 usage example:</b>
```ts
export async function main(ns) {
// Basic ns functions can be accessed on the ns object
await ns.methodName;
// Some related functions are gathered under a sub-property of the ns object
await ns.property.methodName;
}
```
[ns2 in-game docs](https://bitburner.readthedocs.io/en/latest/netscript/netscriptjs.html) <hr>
## Properties ## Properties
| Property | Type | Description | | Property | Type | Description |
| --- | --- | --- | | -------------------------------------------------- | ----------------------------------------------- | --------------------------------------------------- |
| [args](./bitburner.ns.args.md) | (string \| number \| boolean)\[\] | Arguments passed into the script. | | [args](./bitburner.ns.args.md) | (string \| number \| boolean)\[\] | Arguments passed into the script. |
| [bladeburner](./bitburner.ns.bladeburner.md) | [Bladeburner](./bitburner.bladeburner.md) | Namespace for bladeburner functions. | | [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. | | [codingcontract](./bitburner.ns.codingcontract.md) | [CodingContract](./bitburner.codingcontract.md) | Namespace for codingcontract functions. |
@ -31,7 +56,7 @@ export interface NS extends Singularity
## Methods ## Methods
| Method | Description | | Method | Description |
| --- | --- | | -------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| [alert(msg)](./bitburner.ns.alert.md) | Open up a message box. | | [alert(msg)](./bitburner.ns.alert.md) | Open up a message box. |
| [asleep(millis)](./bitburner.ns.asleep.md) | Suspends the script for n milliseconds. Doesn't block with concurrent calls. | | [asleep(millis)](./bitburner.ns.asleep.md) | Suspends the script for n milliseconds. Doesn't block with concurrent calls. |
| [atExit(f)](./bitburner.ns.atexit.md) | Add callback function when the script dies | | [atExit(f)](./bitburner.ns.atexit.md) | Add callback function when the script dies |
@ -61,7 +86,7 @@ export interface NS extends Singularity
| [getPurchasedServerCost(ram)](./bitburner.ns.getpurchasedservercost.md) | Get cost of purchasing a server. | | [getPurchasedServerCost(ram)](./bitburner.ns.getpurchasedservercost.md) | Get cost of purchasing a server. |
| [getPurchasedServerLimit()](./bitburner.ns.getpurchasedserverlimit.md) | Returns the maximum number of servers you can purchase. | | [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. | | [getPurchasedServerMaxRam()](./bitburner.ns.getpurchasedservermaxram.md) | Returns the maximum RAM that a purchased server can have. |
| [getPurchasedServers(hostnameMode)](./bitburner.ns.getpurchasedservers.md) | Returns an array with either the hostnames or IPs of all of the servers you have purchased. | | [getPurchasedServers()](./bitburner.ns.getpurchasedservers.md) | Returns an array with the hostnames of all of the servers you have purchased. |
| [getRunningScript(filename, hostname, args)](./bitburner.ns.getrunningscript.md) | Get general info about a running script. | | [getRunningScript(filename, hostname, args)](./bitburner.ns.getrunningscript.md) | Get general info about a running script. |
| [getScriptExpGain(script, host, args)](./bitburner.ns.getscriptexpgain.md) | Get the exp gain of a script. | | [getScriptExpGain(script, host, args)](./bitburner.ns.getscriptexpgain.md) | Get the exp gain of a script. |
| [getScriptIncome(script, host, args)](./bitburner.ns.getscriptincome.md) | Get the income of a script. | | [getScriptIncome(script, host, args)](./bitburner.ns.getscriptincome.md) | Get the income of a script. |
@ -130,4 +155,3 @@ export interface NS extends Singularity
| [wget(url, target, host)](./bitburner.ns.wget.md) | Download a file from the internet. | | [wget(url, target, host)](./bitburner.ns.wget.md) | Download a file from the internet. |
| [write(handle, data, mode)](./bitburner.ns.write.md) | Write data to a file. | | [write(handle, data, mode)](./bitburner.ns.write.md) | Write data to a file. |
| [writePort(port, data)](./bitburner.ns.writeport.md) | Write data to a port. | | [writePort(port, data)](./bitburner.ns.writeport.md) | Write data to a port. |

1
package-lock.json generated
View File

@ -5,6 +5,7 @@
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "bitburner",
"version": "1.1.0", "version": "1.1.0",
"hasInstallScript": true, "hasInstallScript": true,
"license": "SEE LICENSE IN license.txt", "license": "SEE LICENSE IN license.txt",

View File

@ -109,6 +109,6 @@
"test:watch": "jest --watch", "test:watch": "jest --watch",
"watch": "webpack --watch --mode production", "watch": "webpack --watch --mode production",
"watch:dev": "webpack --watch --mode development", "watch:dev": "webpack --watch --mode development",
"electron": "cp -r electron/* .package && cp index.html .package && cp main.bundle.js .package && cp dist/vendor.bundle.js .package/dist && cp -r dist/ext .package/dist/ext && electron-packager .package bitburner --all --out .build --overwrite --icon .package/icon.png" "electron": "cp -r electron/* .package && cp index.html .package && cp main.bundle.js .package && cp dist/vendor.bundle.js .package/dist/ && cp -r dist/ext .package/dist/ && electron-packager .package bitburner --all --out .build --overwrite --icon .package/icon.png"
} }
} }

View File

@ -82,16 +82,24 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea
setGangOpen(true); setGangOpen(true);
} }
function startWork(): void {
player.startFocusing();
router.toWork();
}
function startFieldWork(faction: Faction): void { function startFieldWork(faction: Faction): void {
player.startFactionFieldWork(router, faction); player.startFactionFieldWork(faction);
startWork();
} }
function startHackingContracts(faction: Faction): void { function startHackingContracts(faction: Faction): void {
player.startFactionHackWork(router, faction); player.startFactionHackWork(faction);
startWork();
} }
function startSecurityWork(faction: Faction): void { function startSecurityWork(faction: Faction): void {
player.startFactionSecurityWork(router, faction); player.startFactionSecurityWork(faction);
startWork();
} }
// We have a special flag for whether the player this faction is the player's // We have a special flag for whether the player this faction is the player's

View File

@ -171,10 +171,11 @@ export function CompanyLocation(props: IProps): React.ReactElement {
const pos = companyPosition; const pos = companyPosition;
if (pos instanceof CompanyPosition) { if (pos instanceof CompanyPosition) {
if (pos.isPartTimeJob() || pos.isSoftwareConsultantJob() || pos.isBusinessConsultantJob()) { if (pos.isPartTimeJob() || pos.isSoftwareConsultantJob() || pos.isBusinessConsultantJob()) {
p.startWorkPartTime(router, props.locName); p.startWorkPartTime(props.locName);
} else { } else {
p.startWork(router, props.locName); p.startWork(props.locName);
} }
p.startFocusing();
router.toWork(); router.toWork();
} }
} }

View File

@ -941,6 +941,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return runScriptFromScript("run", scriptServer, scriptname, args, workerScript, threads); return runScriptFromScript("run", scriptServer, scriptname, args, workerScript, threads);
}, },
exec: function (scriptname: any, hostname: any, threads: any = 1, ...args: any[]): any { exec: function (scriptname: any, hostname: any, threads: any = 1, ...args: any[]): any {
console.log(`${scriptname} ${hostname} ${threads} ${JSON.stringify(args)}`);
updateDynamicRam("exec", getRamCost("exec")); updateDynamicRam("exec", getRamCost("exec"));
if (scriptname === undefined || hostname === undefined) { if (scriptname === undefined || hostname === undefined) {
throw makeRuntimeErrorMsg("exec", "Usage: exec(scriptname, server, [numThreads], [arg1], [arg2]...)"); throw makeRuntimeErrorMsg("exec", "Usage: exec(scriptname, server, [numThreads], [arg1], [arg2]...)");
@ -1061,11 +1062,13 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
throw makeRuntimeErrorMsg("scp", "No scripts to copy"); throw makeRuntimeErrorMsg("scp", "No scripts to copy");
} }
let res = true; let res = true;
await Promise.all(scripts.map(async function(script) { await Promise.all(
if (!await NetscriptFunctions(workerScript).scp(script, hostname1, hostname2)) { scripts.map(async function (script) {
if (!(await NetscriptFunctions(workerScript).scp(script, hostname1, hostname2))) {
res = false; res = false;
} }
})); }),
);
return Promise.resolve(res); return Promise.resolve(res);
} }
@ -2120,12 +2123,15 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
return Player.playtimeSinceLastAug; return Player.playtimeSinceLastAug;
}, },
alert: function (message: any): void { alert: function (message: any): void {
dialogBoxCreate(message); message = toNative(message);
dialogBoxCreate(JSON.stringify(message));
}, },
toast: function (message: any, variant: any = "success"): void { toast: function (message: any, variant: any = "success"): void {
if (!["success", "info", "warning", "error"].includes(variant)) if (!["success", "info", "warning", "error"].includes(variant))
throw new Error(`variant must be one of "success", "info", "warning", or "error"`); throw new Error(`variant must be one of "success", "info", "warning", or "error"`);
SnackbarEvents.emit(message, variant);
message = toNative(message);
SnackbarEvents.emit(JSON.stringify(message), variant);
}, },
prompt: function (txt: any): any { prompt: function (txt: any): any {
if (!isString(txt)) { if (!isString(txt)) {

View File

@ -622,6 +622,38 @@ export function NetscriptSingularity(
return Promise.resolve(); return Promise.resolve();
}); });
}, },
isFocused: function (): boolean {
helper.updateDynamicRam("isFocused", getRamCost("isFocused"));
helper.checkSingularityAccess("isFocused", 2);
return player.focus;
},
setFocus: function (afocus: any): boolean {
const focus = helper.boolean(afocus);
helper.updateDynamicRam("setFocus", getRamCost("setFocus"));
helper.checkSingularityAccess("setFocus", 2);
if (!player.isWorking) {
throw helper.makeRuntimeErrorMsg("setFocus", "Not currently working");
}
if (
!(
player.workType == CONSTANTS.WorkTypeFaction ||
player.workType == CONSTANTS.WorkTypeCompany ||
player.workType == CONSTANTS.WorkTypeCompanyPartTime
)
) {
throw helper.makeRuntimeErrorMsg("setFocus", "Cannot change focus for current job");
}
if (!player.focus && focus) {
player.startFocusing();
Router.toWork();
return true;
} else if (player.focus && !focus) {
player.stopFocusing();
Router.toTerminal();
return true;
}
return false;
},
getStats: function (): any { getStats: function (): any {
helper.updateDynamicRam("getStats", getRamCost("getStats")); helper.updateDynamicRam("getStats", getRamCost("getStats"));
helper.checkSingularityAccess("getStats", 1); helper.checkSingularityAccess("getStats", 1);
@ -703,7 +735,9 @@ export function NetscriptSingularity(
helper.updateDynamicRam("stopAction", getRamCost("stopAction")); helper.updateDynamicRam("stopAction", getRamCost("stopAction"));
helper.checkSingularityAccess("stopAction", 1); helper.checkSingularityAccess("stopAction", 1);
if (player.isWorking) { if (player.isWorking) {
if (player.focus) {
Router.toTerminal(); Router.toTerminal();
}
const txt = player.singularityStopWork(); const txt = player.singularityStopWork();
workerScript.log("stopAction", () => txt); workerScript.log("stopAction", () => txt);
return true; return true;
@ -814,16 +848,21 @@ export function NetscriptSingularity(
return false; return false;
} }
const wasWorking = player.isWorking;
const wasFocused = player.focus;
if (player.isWorking) { if (player.isWorking) {
const txt = player.singularityStopWork(); const txt = player.singularityStopWork();
workerScript.log("workForCompany", () => txt); workerScript.log("workForCompany", () => txt);
} }
if (companyPosition.isPartTimeJob()) { if (companyPosition.isPartTimeJob()) {
player.startWorkPartTime(Router, companyName); player.startWorkPartTime(companyName);
} else { } else {
player.startWork(Router, companyName); player.startWork(companyName);
} }
if (!wasWorking || (wasWorking && !wasFocused)) player.stopFocusing();
else if (wasWorking && wasFocused) player.startFocusing();
workerScript.log( workerScript.log(
"workForCompany", "workForCompany",
() => `Began working at '${player.companyName}' as a '${companyPositionName}'`, () => `Began working at '${player.companyName}' as a '${companyPositionName}'`,
@ -963,6 +1002,8 @@ export function NetscriptSingularity(
return false; return false;
} }
const wasWorking = player.isWorking;
const wasFocused = player.focus;
if (player.isWorking) { if (player.isWorking) {
const txt = player.singularityStopWork(); const txt = player.singularityStopWork();
workerScript.log("workForFaction", () => txt); workerScript.log("workForFaction", () => txt);
@ -1060,7 +1101,9 @@ export function NetscriptSingularity(
workerScript.log("workForFaction", () => `Faction '${fac.name}' do not need help with hacking contracts.`); workerScript.log("workForFaction", () => `Faction '${fac.name}' do not need help with hacking contracts.`);
return false; return false;
} }
player.startFactionHackWork(Router, fac); player.startFactionHackWork(fac);
if (!wasWorking || (wasWorking && !wasFocused)) player.stopFocusing();
else if (wasWorking && wasFocused) player.startFocusing();
workerScript.log("workForFaction", () => `Started carrying out hacking contracts for '${fac.name}'`); workerScript.log("workForFaction", () => `Started carrying out hacking contracts for '${fac.name}'`);
return true; return true;
case "field": case "field":
@ -1070,7 +1113,9 @@ export function NetscriptSingularity(
workerScript.log("workForFaction", () => `Faction '${fac.name}' do not need help with field missions.`); workerScript.log("workForFaction", () => `Faction '${fac.name}' do not need help with field missions.`);
return false; return false;
} }
player.startFactionFieldWork(Router, fac); player.startFactionFieldWork(fac);
if (!wasWorking || (wasWorking && !wasFocused)) player.stopFocusing();
else if (wasWorking && wasFocused) player.startFocusing();
workerScript.log("workForFaction", () => `Started carrying out field missions for '${fac.name}'`); workerScript.log("workForFaction", () => `Started carrying out field missions for '${fac.name}'`);
return true; return true;
case "security": case "security":
@ -1080,7 +1125,9 @@ export function NetscriptSingularity(
workerScript.log("workForFaction", () => `Faction '${fac.name}' do not need help with security work.`); workerScript.log("workForFaction", () => `Faction '${fac.name}' do not need help with security work.`);
return false; return false;
} }
player.startFactionSecurityWork(Router, fac); player.startFactionSecurityWork(fac);
if (!wasWorking || (wasWorking && !wasFocused)) player.stopFocusing();
else if (wasWorking && wasFocused) player.startFocusing();
workerScript.log("workForFaction", () => `Started carrying out security work for '${fac.name}'`); workerScript.log("workForFaction", () => `Started carrying out security work for '${fac.name}'`);
return true; return true;
default: default:

View File

@ -709,6 +709,7 @@ export function runScriptFromScript(
); );
const runningScriptObj = new RunningScript(script, args); const runningScriptObj = new RunningScript(script, args);
runningScriptObj.threads = threads; runningScriptObj.threads = threads;
runningScriptObj.server = server.hostname;
return startWorkerScript(runningScriptObj, server, workerScript); return startWorkerScript(runningScriptObj, server, workerScript);
} }

View File

@ -211,7 +211,7 @@ export interface IPlayer {
setMoney(amt: number): void; setMoney(amt: number): void;
singularityStopWork(): string; singularityStopWork(): string;
startBladeburner(p: any): void; startBladeburner(p: any): void;
startFactionWork(router: IRouter, faction: Faction): void; startFactionWork(faction: Faction): void;
startClass(router: IRouter, costMult: number, expMult: number, className: string): void; startClass(router: IRouter, costMult: number, expMult: number, className: string): void;
startCorporation(corpName: string, additionalShares?: number): void; startCorporation(corpName: string, additionalShares?: number): void;
startCrime( startCrime(
@ -227,13 +227,13 @@ export interface IPlayer {
time: number, time: number,
singParams: any, singParams: any,
): void; ): void;
startFactionFieldWork(router: IRouter, faction: Faction): void; startFactionFieldWork(faction: Faction): void;
startFactionHackWork(router: IRouter, faction: Faction): void; startFactionHackWork(faction: Faction): void;
startFactionSecurityWork(router: IRouter, faction: Faction): void; startFactionSecurityWork(faction: Faction): void;
startFocusing(): void; startFocusing(): void;
startGang(facName: string, isHacking: boolean): void; startGang(facName: string, isHacking: boolean): void;
startWork(router: IRouter, companyName: string): void; startWork(companyName: string): void;
startWorkPartTime(router: IRouter, companyName: string): void; startWorkPartTime(companyName: string): void;
takeDamage(amt: number): boolean; takeDamage(amt: number): boolean;
travel(to: CityName): boolean; travel(to: CityName): boolean;
giveExploit(exploit: Exploit): void; giveExploit(exploit: Exploit): void;

View File

@ -216,7 +216,7 @@ export class PlayerObject implements IPlayer {
setMoney: (amt: number) => void; setMoney: (amt: number) => void;
singularityStopWork: () => string; singularityStopWork: () => string;
startBladeburner: (p: any) => void; startBladeburner: (p: any) => void;
startFactionWork: (router: IRouter, faction: Faction) => void; startFactionWork: (faction: Faction) => void;
startClass: (router: IRouter, costMult: number, expMult: number, className: string) => void; startClass: (router: IRouter, costMult: number, expMult: number, className: string) => void;
startCorporation: (corpName: string, additionalShares?: number) => void; startCorporation: (corpName: string, additionalShares?: number) => void;
startCrime: ( startCrime: (
@ -232,13 +232,13 @@ export class PlayerObject implements IPlayer {
time: number, time: number,
singParams: any, singParams: any,
) => void; ) => void;
startFactionFieldWork: (router: IRouter, faction: Faction) => void; startFactionFieldWork: (faction: Faction) => void;
startFactionHackWork: (router: IRouter, faction: Faction) => void; startFactionHackWork: (faction: Faction) => void;
startFactionSecurityWork: (router: IRouter, faction: Faction) => void; startFactionSecurityWork: (faction: Faction) => void;
startFocusing: () => void; startFocusing: () => void;
startGang: (facName: string, isHacking: boolean) => void; startGang: (facName: string, isHacking: boolean) => void;
startWork: (router: IRouter, companyName: string) => void; startWork: (companyName: string) => void;
startWorkPartTime: (router: IRouter, companyName: string) => void; startWorkPartTime: (companyName: string) => void;
takeDamage: (amt: number) => boolean; takeDamage: (amt: number) => boolean;
travel: (to: CityName) => boolean; travel: (to: CityName) => boolean;
giveExploit: (exploit: Exploit) => void; giveExploit: (exploit: Exploit) => void;

View File

@ -554,10 +554,9 @@ export function processWorkEarnings(this: IPlayer, numCycles = 1): void {
} }
/* Working for Company */ /* Working for Company */
export function startWork(this: IPlayer, router: IRouter, companyName: string): void { export function startWork(this: IPlayer, companyName: string): void {
this.resetWorkStatus(CONSTANTS.WorkTypeCompany, companyName); this.resetWorkStatus(CONSTANTS.WorkTypeCompany, companyName);
this.isWorking = true; this.isWorking = true;
this.focus = true;
this.companyName = companyName; this.companyName = companyName;
this.workType = CONSTANTS.WorkTypeCompany; this.workType = CONSTANTS.WorkTypeCompany;
@ -571,7 +570,6 @@ export function startWork(this: IPlayer, router: IRouter, companyName: string):
this.workMoneyGainRate = this.getWorkMoneyGain(); this.workMoneyGainRate = this.getWorkMoneyGain();
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer8Hours; this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer8Hours;
router.toWork();
} }
export function process(this: IPlayer, router: IRouter, numCycles = 1): void { export function process(this: IPlayer, router: IRouter, numCycles = 1): void {
@ -723,10 +721,9 @@ export function finishWork(this: IPlayer, cancelled: boolean, sing = false): str
return ""; return "";
} }
export function startWorkPartTime(this: IPlayer, router: IRouter, companyName: string): void { export function startWorkPartTime(this: IPlayer, companyName: string): void {
this.resetWorkStatus(CONSTANTS.WorkTypeCompanyPartTime, companyName); this.resetWorkStatus(CONSTANTS.WorkTypeCompanyPartTime, companyName);
this.isWorking = true; this.isWorking = true;
this.focus = true;
this.companyName = companyName; this.companyName = companyName;
this.workType = CONSTANTS.WorkTypeCompanyPartTime; this.workType = CONSTANTS.WorkTypeCompanyPartTime;
@ -740,7 +737,6 @@ export function startWorkPartTime(this: IPlayer, router: IRouter, companyName: s
this.workMoneyGainRate = this.getWorkMoneyGain(); this.workMoneyGainRate = this.getWorkMoneyGain();
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer8Hours; this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer8Hours;
router.toWork();
} }
export function workPartTime(this: IPlayer, numCycles: number): boolean { export function workPartTime(this: IPlayer, numCycles: number): boolean {
@ -832,7 +828,7 @@ export function stopFocusing(this: IPlayer): void {
} }
/* Working for Faction */ /* Working for Faction */
export function startFactionWork(this: IPlayer, router: IRouter, faction: Faction): void { export function startFactionWork(this: IPlayer, faction: Faction): void {
//Update reputation gain rate to account for faction favor //Update reputation gain rate to account for faction favor
let favorMult = 1 + faction.favor / 100; let favorMult = 1 + faction.favor / 100;
if (isNaN(favorMult)) { if (isNaN(favorMult)) {
@ -842,15 +838,13 @@ export function startFactionWork(this: IPlayer, router: IRouter, faction: Factio
this.workRepGainRate *= BitNodeMultipliers.FactionWorkRepGain; this.workRepGainRate *= BitNodeMultipliers.FactionWorkRepGain;
this.isWorking = true; this.isWorking = true;
this.focus = true;
this.workType = CONSTANTS.WorkTypeFaction; this.workType = CONSTANTS.WorkTypeFaction;
this.currentWorkFactionName = faction.name; this.currentWorkFactionName = faction.name;
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer20Hours; this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer20Hours;
router.toWork();
} }
export function startFactionHackWork(this: IPlayer, router: IRouter, faction: Faction): void { export function startFactionHackWork(this: IPlayer, faction: Faction): void {
this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkHacking); this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkHacking);
this.workHackExpGainRate = 0.15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain; this.workHackExpGainRate = 0.15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
@ -859,10 +853,10 @@ export function startFactionHackWork(this: IPlayer, router: IRouter, faction: Fa
this.factionWorkType = CONSTANTS.FactionWorkHacking; this.factionWorkType = CONSTANTS.FactionWorkHacking;
this.currentWorkFactionDescription = "carrying out hacking contracts"; this.currentWorkFactionDescription = "carrying out hacking contracts";
this.startFactionWork(router, faction); this.startFactionWork(faction);
} }
export function startFactionFieldWork(this: IPlayer, router: IRouter, faction: Faction): void { export function startFactionFieldWork(this: IPlayer, faction: Faction): void {
this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkField); this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkField);
this.workHackExpGainRate = 0.1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain; this.workHackExpGainRate = 0.1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
@ -876,10 +870,10 @@ export function startFactionFieldWork(this: IPlayer, router: IRouter, faction: F
this.factionWorkType = CONSTANTS.FactionWorkField; this.factionWorkType = CONSTANTS.FactionWorkField;
this.currentWorkFactionDescription = "carrying out field missions"; this.currentWorkFactionDescription = "carrying out field missions";
this.startFactionWork(router, faction); this.startFactionWork(faction);
} }
export function startFactionSecurityWork(this: IPlayer, router: IRouter, faction: Faction): void { export function startFactionSecurityWork(this: IPlayer, faction: Faction): void {
this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkSecurity); this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkSecurity);
this.workHackExpGainRate = 0.05 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain; this.workHackExpGainRate = 0.05 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
@ -893,7 +887,7 @@ export function startFactionSecurityWork(this: IPlayer, router: IRouter, faction
this.factionWorkType = CONSTANTS.FactionWorkSecurity; this.factionWorkType = CONSTANTS.FactionWorkSecurity;
this.currentWorkFactionDescription = "performing security detail"; this.currentWorkFactionDescription = "performing security detail";
this.startFactionWork(router, faction); this.startFactionWork(faction);
} }
export function workForFaction(this: IPlayer, numCycles: number): boolean { export function workForFaction(this: IPlayer, numCycles: number): boolean {

View File

@ -168,6 +168,13 @@ export function prestigeSourceFile(flume: boolean): void {
const homeComp = Player.getHomeComputer(); const homeComp = Player.getHomeComputer();
// Stop a Terminal action if there is one.
if (Terminal.action !== null) {
Terminal.finishAction(Router, Player, true);
}
Terminal.clear();
LogBoxClearEvents.emit();
// Delete all servers except home computer // Delete all servers except home computer
prestigeAllServers(); // Must be done before initForeignServers() prestigeAllServers(); // Must be done before initForeignServers()

View File

@ -1985,6 +1985,25 @@ export interface Singularity {
* @returns True if the installation was successful. * @returns True if the installation was successful.
*/ */
installBackdoor(): Promise<void>; installBackdoor(): Promise<void>;
/**
* SF4.2 - Check if the player is focused.
* @remarks
* RAM cost: 0.1 GB
*
*
* @returns True if the player is focused.
*/
isFocused(): boolean;
/**
* SF4.2 - Set the players focus.
* @remarks
* RAM cost: 0.1 GB
*
* @returns True if the focus was changed.
*/
setFocus(focus: boolean): boolean;
} }
/** /**
@ -2831,9 +2850,9 @@ export interface CodingContract {
* *
* @param filename - Filename of the contract. * @param filename - Filename of the contract.
* @param host - Host of the server containing the contract. Optional. Defaults to current server if not provided. * @param host - Host of the server containing the contract. Optional. Defaults to current server if not provided.
* @returns The specified contracts data; * @returns The specified contracts data, data type depends on contract type.;
*/ */
getData(filename: string, host?: string): string; getData(filename: string, host?: string): any;
/** /**
* Get the number of attempt remaining. * Get the number of attempt remaining.
@ -3707,6 +3726,27 @@ interface Stanek {
/** /**
* Collection of all functions passed to scripts * Collection of all functions passed to scripts
* @public * @public
* @remarks
* <b>Basic ns1 usage example:</b>
* ```ts
* // Basic ns functions can be used directly
* getHostname();
* // Some related functions are gathered within a common namespace
* stock.getPrice();
* ```
* {@link https://bitburner.readthedocs.io/en/latest/netscript/netscript1.html| ns1 in-game docs}
* <hr>
* <b>Basic ns2 usage example:</b>
* ```ts
* export async function main(ns) {
* // Basic ns functions can be accessed on the ns object
* await ns.getHostname();
* // Some related functions are gathered under a sub-property of the ns object
* await ns.stock.getPrice();
* }
* ```
* {@link https://bitburner.readthedocs.io/en/latest/netscript/netscriptjs.html| ns2 in-game docs}
* <hr>
*/ */
export interface NS extends Singularity { export interface NS extends Singularity {
/** /**
@ -3906,7 +3946,7 @@ export interface NS extends Singularity {
* ```ts * ```ts
* //For example, assume the following returns 0.01: * //For example, assume the following returns 0.01:
* hackAnalyze("foodnstuff"); * hackAnalyze("foodnstuff");
* //This means that if hack the foodnstuff server, then you will steal 1% of its total money. If you hack using N threads, then you will steal N*0.01% of its total money. * //This means that if hack the foodnstuff server, then you will steal 1% of its total money. If you hack using N threads, then you will steal N*0.01 times its total money.
* ``` * ```
* @param host - Hostname of the target server. * @param host - Hostname of the target server.
* @returns The percentage of money you will steal from the target server with a single hack. * @returns The percentage of money you will steal from the target server with a single hack.
@ -4584,7 +4624,7 @@ export interface NS extends Singularity {
* RAM cost: 0.1 GB * RAM cost: 0.1 GB
* *
* Returns the servers instrinsic growth parameter. This growth * Returns the servers instrinsic growth parameter. This growth
* parameter is a number between 1 and 100 that represents how * parameter is a number between 0 and 100 that represents how
* quickly the servers money grows. This parameter affects the * quickly the servers money grows. This parameter affects the
* percentage by which the servers money is increased when using the * percentage by which the servers money is increased when using the
* grow function. A higher growth parameter will result in a * grow function. A higher growth parameter will result in a

View File

@ -178,7 +178,7 @@ export const defaultSettings: IDefaultSettings = {
Locale: "en", Locale: "en",
MaxLogCapacity: 50, MaxLogCapacity: 50,
MaxPortCapacity: 50, MaxPortCapacity: 50,
MaxTerminalCapacity: 200, MaxTerminalCapacity: 500,
SaveGameOnFileSave: true, SaveGameOnFileSave: true,
SuppressBuyAugmentationConfirmation: false, SuppressBuyAugmentationConfirmation: false,
SuppressFactionInvites: false, SuppressFactionInvites: false,

View File

@ -169,6 +169,45 @@ export function getAllParentDirectories(path: string): string {
return t_path.slice(0, lastSlash + 1); return t_path.slice(0, lastSlash + 1);
} }
/**
* Given a destination that only contains a directory part, returns the
* path to the source filename inside the new destination directory.
* Otherwise, returns the path to the destination file.
* @param destination The destination path or file name
* @param source The source path
* @param cwd The current working directory
* @returns A file path which may be absolute or relative
*/
export function getDestinationFilepath(destination: string, source: string, cwd: string) {
const dstDir = evaluateDirectoryPath(destination, cwd);
// If evaluating the directory for this destination fails, we have a filename or full path.
if (dstDir === null) {
return destination;
} else {
// Append the filename to the directory provided.
let t_path = removeTrailingSlash(dstDir);
const fileName = getFileName(source);
return t_path + "/" + fileName;
}
}
/**
* Given a filepath, returns the file name (e.g. without directory parts)
* For example:
* /home/var/test.js -> test.js
* ./var/test.js -> test.js
* test.js -> test.js
*/
export function getFileName(path: string): string {
const t_path = path;
const lastSlash = t_path.lastIndexOf("/");
if (lastSlash === -1) {
return t_path;
}
return t_path.slice(lastSlash + 1);
}
/** /**
* Checks if a file path refers to a file in the root directory. * Checks if a file path refers to a file in the root directory.
*/ */

View File

@ -254,9 +254,8 @@ export class Terminal implements ITerminal {
const expGain = calculateHackingExpGain(server, player); const expGain = calculateHackingExpGain(server, player);
server.weaken(CONSTANTS.ServerWeakenAmount); server.weaken(CONSTANTS.ServerWeakenAmount);
this.print( this.print(
`'${server.hostname}' security level weakened to ${server.hackDifficulty}. Gained ${numeralWrapper.formatExp( `'${server.hostname}' security level weakened to ${server.hackDifficulty.toFixed(3)} ` +
expGain, `and Gained ${numeralWrapper.formatExp(expGain)} hacking exp.`,
)} hacking exp.`,
); );
} }

View File

@ -3,6 +3,7 @@ import { IRouter } from "../../ui/Router";
import { IPlayer } from "../../PersonObjects/IPlayer"; import { IPlayer } from "../../PersonObjects/IPlayer";
import { BaseServer } from "../../Server/BaseServer"; import { BaseServer } from "../../Server/BaseServer";
import { isScriptFilename } from "../../Script/isScriptFilename"; import { isScriptFilename } from "../../Script/isScriptFilename";
import { getDestinationFilepath, areFilesEqual } from "../DirectoryHelpers";
export function cp( export function cp(
terminal: ITerminal, terminal: ITerminal,
@ -16,9 +17,23 @@ export function cp(
terminal.error("Incorrect usage of cp command. Usage: cp [src] [dst]"); terminal.error("Incorrect usage of cp command. Usage: cp [src] [dst]");
return; return;
} }
const src = args[0] + ""; // Convert a relative path source file to the absolute path.
const dst = args[1] + ""; const src = terminal.getFilepath(args[0] + "");
if (src === dst) { if (src === null) {
terminal.error("src cannot be a directory");
return;
}
// Get the destination based on the source file and the current directory
const t_dst = getDestinationFilepath(args[1] + "", src, terminal.cwd());
if (t_dst === null) {
terminal.error("error parsing dst file");
return;
}
// Convert a relative path destination file to the absolute path.
const dst = terminal.getFilepath(t_dst);
if (areFilesEqual(src, dst)) {
terminal.error("src and dst cannot be the same"); terminal.error("src and dst cannot be the same");
return; return;
} }
@ -50,7 +65,7 @@ export function cp(
const tRes = server.writeToTextFile(dst, txtFile.text); const tRes = server.writeToTextFile(dst, txtFile.text);
if (!tRes.success) { if (!tRes.success) {
terminal.error("scp failed"); terminal.error("cp failed");
return; return;
} }
if (tRes.overwritten) { if (tRes.overwritten) {
@ -71,13 +86,13 @@ export function cp(
} }
} }
if (sourceScript == null) { if (sourceScript == null) {
terminal.error("cp() failed. No such script exists"); terminal.error("cp failed. No such script exists");
return; return;
} }
const sRes = server.writeToScriptFile(dst, sourceScript.code); const sRes = server.writeToScriptFile(dst, sourceScript.code);
if (!sRes.success) { if (!sRes.success) {
terminal.error(`scp failed`); terminal.error(`cp failed`);
return; return;
} }
if (sRes.overwritten) { if (sRes.overwritten) {

View File

@ -5,6 +5,7 @@ import { BaseServer } from "../../Server/BaseServer";
import { isScriptFilename } from "../../Script/isScriptFilename"; import { isScriptFilename } from "../../Script/isScriptFilename";
import { TextFile } from "../../TextFile"; import { TextFile } from "../../TextFile";
import { Script } from "../../Script/Script"; import { Script } from "../../Script/Script";
import { getDestinationFilepath, areFilesEqual } from "../DirectoryHelpers";
export function mv( export function mv(
terminal: ITerminal, terminal: ITerminal,
@ -20,7 +21,7 @@ export function mv(
try { try {
const source = args[0] + ""; const source = args[0] + "";
const dest = args[1] + ""; const t_dest = args[1] + "";
if (!isScriptFilename(source) && !source.endsWith(".txt")) { if (!isScriptFilename(source) && !source.endsWith(".txt")) {
terminal.error(`'mv' can only be used on scripts and text files (.txt)`); terminal.error(`'mv' can only be used on scripts and text files (.txt)`);
@ -34,9 +35,19 @@ export function mv(
} }
const sourcePath = terminal.getFilepath(source); const sourcePath = terminal.getFilepath(source);
const destPath = terminal.getFilepath(dest); // Get the destination based on the source file and the current directory
const dest = getDestinationFilepath(t_dest, source, terminal.cwd());
if (dest === null) {
terminal.error("error parsing dst file");
return;
}
const destFile = terminal.getFile(player, dest); const destFile = terminal.getFile(player, dest);
const destPath = terminal.getFilepath(dest);
if (areFilesEqual(sourcePath, destPath)) {
terminal.error(`Source and destination files are the same file`);
return;
}
// 'mv' command only works on scripts and txt files. // 'mv' command only works on scripts and txt files.
// Also, you can't convert between different file types // Also, you can't convert between different file types
@ -55,7 +66,7 @@ export function mv(
if (destFile != null) { if (destFile != null) {
// Already exists, will be overwritten, so we'll delete it // Already exists, will be overwritten, so we'll delete it
const status = server.removeFile(destPath); const status = server.removeFile(dest);
if (!status.res) { if (!status.res) {
terminal.error(`Something went wrong...please contact game dev (probably a bug)`); terminal.error(`Something went wrong...please contact game dev (probably a bug)`);
return; return;

View File

@ -20,7 +20,11 @@ export function runProgram(
const programName = args[0] + ""; const programName = args[0] + "";
if (!player.hasProgram(programName)) { if (!player.hasProgram(programName)) {
terminal.error("No such executable on home computer (Only programs that exist on your home computer can be run)"); terminal.error(
`No such (exe, script, js, ns, or cct) file! (Only programs that exist on your home computer or scripts on ${
player.getCurrentServer().hostname
} can be run)`,
);
return; return;
} }

View File

@ -14,7 +14,7 @@ export function scp(
): void { ): void {
try { try {
if (args.length !== 2) { if (args.length !== 2) {
terminal.error("Incorrect usage of scp command. Usage: scp [file] [destination hostname/ip]"); terminal.error("Incorrect usage of scp command. Usage: scp [file] [destination hostname]");
return; return;
} }
const scriptname = terminal.getFilepath(args[0] + ""); const scriptname = terminal.getFilepath(args[0] + "");

View File

@ -41,7 +41,7 @@ export function ScriptProduction(): React.ReactElement {
<TableBody> <TableBody>
<TableRow> <TableRow>
<TableCell component="th" scope="row" classes={{ root: classes.cell }}> <TableCell component="th" scope="row" classes={{ root: classes.cell }}>
<Typography variant="body2">Total production:</Typography> <Typography variant="body2">Total production since last Augment Installation:</Typography>
</TableCell> </TableCell>
<TableCell align="left" classes={{ root: classes.cell }}> <TableCell align="left" classes={{ root: classes.cell }}>
<Typography variant="body2"> <Typography variant="body2">

View File

@ -443,8 +443,11 @@ export function InteractiveTutorialRoot(): React.ReactElement {
<Typography color={"primary"}>Tutorial</Typography> <Typography color={"primary"}>Tutorial</Typography>
</ListItem> </ListItem>
<Typography> <Typography>
in the main navigation menu to look at the documentation. If you are an experienced JavaScript developer, I in the main navigation menu to look at the documentation.
would highly suggest you check out the section on NetscriptJS/Netscript 2.0, it's faster and more powerful. <br />
<br />
If you know even a little bit of programming it is highly recommended you use NS2 instead. You will enjoy
the game much more.
<br /> <br />
<br /> <br />
For now, let's move on to something else! For now, let's move on to something else!