mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-19 06:03:50 +01:00
Merge branch 'dev' of github.com:danielyxie/bitburner into dev
This commit is contained in:
commit
07538d6509
@ -26,6 +26,10 @@ export const CorporationConstants: {
|
||||
BaseMaxProducts: number;
|
||||
AllCorporationStates: string[];
|
||||
AllMaterials: string[];
|
||||
AllIndustryTypes: string[];
|
||||
AllUnlocks: string[];
|
||||
AllUpgrades: string[];
|
||||
AllResearch: string[];
|
||||
FundingRoundShares: number[];
|
||||
FundingRoundMultiplier: number[];
|
||||
AvgProfitLength: number;
|
||||
@ -82,6 +86,70 @@ export const CorporationConstants: {
|
||||
"AI Cores",
|
||||
"Real Estate",
|
||||
],
|
||||
AllIndustryTypes: [
|
||||
"Energy",
|
||||
"Utilities",
|
||||
"Agriculture",
|
||||
"Fishing",
|
||||
"Mining",
|
||||
"Food",
|
||||
"Tobacco",
|
||||
"Chemical",
|
||||
"Pharmaceutical",
|
||||
"Hardware",
|
||||
"Robotics",
|
||||
"Software",
|
||||
"Healthcare",
|
||||
"RealEstate",
|
||||
],
|
||||
AllUnlocks: [
|
||||
"Export",
|
||||
"Smart Supply",
|
||||
"Market Research - Demand",
|
||||
"Market Data - Competition",
|
||||
"VeChain",
|
||||
"Shady Accounting",
|
||||
"Government Partnership",
|
||||
"Warehouse API",
|
||||
"Office API",
|
||||
],
|
||||
AllUpgrades: [
|
||||
"Smart Factories",
|
||||
"Smart Storage",
|
||||
"DreamSense",
|
||||
"Wilson Analytics",
|
||||
"Nuoptimal Nootropic Injector Implants",
|
||||
"Speech Processor Implants",
|
||||
"Neural Accelerators",
|
||||
"FocusWires",
|
||||
"ABC SalesBots",
|
||||
"Project Insight",
|
||||
],
|
||||
AllResearch: [
|
||||
"Hi-Tech R&D Laboratory",
|
||||
"AutoBrew",
|
||||
"AutoPartyManager",
|
||||
"Automatic Drug Administration",
|
||||
"Bulk Purchasing",
|
||||
"CPH4 Injections",
|
||||
"Drones",
|
||||
"Drones - Assembly",
|
||||
"Drones - Transport",
|
||||
"Go-Juice",
|
||||
"HRBuddy-Recruitment",
|
||||
"HRBuddy-Training",
|
||||
"JoyWire",
|
||||
"Market-TA.I",
|
||||
"Market-TA.II",
|
||||
"Overclock",
|
||||
"Self-Correcting Assemblers",
|
||||
"Sti.mu",
|
||||
"sudo.Assist",
|
||||
"uPgrade: Capacity.I",
|
||||
"uPgrade: Capacity.II",
|
||||
"uPgrade: Dashboard",
|
||||
"uPgrade: Fulcrum",
|
||||
],
|
||||
FundingRoundShares: [0.1, 0.35, 0.25, 0.2],
|
||||
FundingRoundMultiplier: [4, 3, 3, 2.5],
|
||||
|
||||
|
@ -459,7 +459,7 @@ export function IndustryOffice(props: IProps): React.ReactElement {
|
||||
{!division.hasResearch("AutoBrew") && (
|
||||
<>
|
||||
<Tooltip
|
||||
title={<Typography>Throw an office party to increase your employee's morale and happiness</Typography>}
|
||||
title={<Typography>Provide your employees with coffee, increasing their energy by 5%</Typography>}
|
||||
>
|
||||
<span>
|
||||
<Button
|
||||
|
@ -151,7 +151,7 @@ const positive = [
|
||||
"patient",
|
||||
"dynamic",
|
||||
"loyal",
|
||||
"based",
|
||||
"straightforward",
|
||||
];
|
||||
|
||||
const negative = [
|
||||
|
@ -1,22 +1,15 @@
|
||||
import { getRamCost } from "./RamCostGenerator";
|
||||
import type { IPort } from "../NetscriptPort";
|
||||
import type { BaseServer } from "../Server/BaseServer";
|
||||
import type { WorkerScript } from "./WorkerScript";
|
||||
import { makeRuntimeRejectMsg } from "../NetscriptEvaluator";
|
||||
import { Player } from "../Player";
|
||||
import { CityName } from "../Locations/data/CityNames";
|
||||
import { BasicHGWOptions } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Server } from "../Server/Server";
|
||||
import { FormulaGang } from "../Gang/formulas/formulas";
|
||||
import { INetscriptHelper, ScriptIdentifier } from "../NetscriptFunctions/INetscriptHelper";
|
||||
import { GangMember } from "../Gang/GangMember";
|
||||
import { GangMemberTask } from "../Gang/GangMemberTask";
|
||||
import { helpers } from "./NetscriptHelpers";
|
||||
import { ScriptArg } from "./ScriptArg";
|
||||
import { NSEnums } from "src/ScriptEditor/NetscriptDefinitions";
|
||||
import { NSFull } from "src/NetscriptFunctions";
|
||||
|
||||
type ExternalFunction = (...args: unknown[]) => unknown;
|
||||
export type ExternalAPI = {
|
||||
[string: string]: ExternalAPI | ExternalFunction;
|
||||
|
||||
export type ExternalAPILayer = {
|
||||
[key: string]: ExternalAPILayer | ExternalFunction | ScriptArg[];
|
||||
};
|
||||
|
||||
type InternalFunction<F extends (...args: unknown[]) => unknown> = (ctx: NetscriptContext) => F;
|
||||
@ -24,48 +17,23 @@ type InternalFunction<F extends (...args: unknown[]) => unknown> = (ctx: Netscri
|
||||
export type InternalAPI<API> = {
|
||||
[Property in keyof API]: API[Property] extends ExternalFunction
|
||||
? InternalFunction<API[Property]>
|
||||
: API[Property] extends NSEnums
|
||||
? NSEnums
|
||||
: API[Property] extends ScriptArg[]
|
||||
? ScriptArg[]
|
||||
: API[Property] extends object
|
||||
? InternalAPI<API[Property]>
|
||||
: never;
|
||||
};
|
||||
|
||||
type WrappedNetscriptFunction = (...args: unknown[]) => unknown;
|
||||
type WrappedNetscriptAPI = {
|
||||
readonly [string: string]: WrappedNetscriptAPI | WrappedNetscriptFunction;
|
||||
};
|
||||
|
||||
export type NetscriptContext = {
|
||||
makeRuntimeErrorMsg: (message: string) => string;
|
||||
log: (message: () => string) => void;
|
||||
workerScript: WorkerScript;
|
||||
function: string;
|
||||
helper: WrappedNetscriptHelpers;
|
||||
};
|
||||
|
||||
type WrappedNetscriptHelpers = {
|
||||
makeRuntimeErrorMsg: (msg: string) => string;
|
||||
string: (argName: string, v: unknown) => string;
|
||||
number: (argName: string, v: unknown) => number;
|
||||
ustring: (argName: string, v: unknown) => string | undefined;
|
||||
unumber: (argName: string, v: unknown) => number | undefined;
|
||||
scriptArgs(args: unknown): ScriptArg[];
|
||||
scriptIdentifier: (fn: unknown, hostname: unknown, args: unknown) => ScriptIdentifier;
|
||||
city: (argName: string, v: unknown) => CityName;
|
||||
boolean: (v: unknown) => boolean;
|
||||
getServer: (hostname: string) => BaseServer;
|
||||
checkSingularityAccess: () => void;
|
||||
hack: (hostname: string, manual: boolean, { threads: requestedThreads, stock }?: BasicHGWOptions) => Promise<number>;
|
||||
getValidPort: (port: number) => IPort;
|
||||
player(p: unknown): IPlayer;
|
||||
server(s: unknown): Server;
|
||||
gang(g: unknown): FormulaGang;
|
||||
gangMember: (m: unknown) => GangMember;
|
||||
gangTask: (t: unknown) => GangMemberTask;
|
||||
functionPath: string;
|
||||
};
|
||||
|
||||
function wrapFunction(
|
||||
helpers: INetscriptHelper,
|
||||
wrappedAPI: ExternalAPI,
|
||||
wrappedAPI: ExternalAPILayer,
|
||||
workerScript: WorkerScript,
|
||||
func: (_ctx: NetscriptContext) => (...args: unknown[]) => unknown,
|
||||
...tree: string[]
|
||||
@ -73,44 +41,19 @@ function wrapFunction(
|
||||
const functionPath = tree.join(".");
|
||||
const functionName = tree.pop();
|
||||
if (typeof functionName !== "string") {
|
||||
throw makeRuntimeRejectMsg(workerScript, "Failure occured while wrapping netscript api");
|
||||
throw helpers.makeRuntimeRejectMsg(workerScript, "Failure occured while wrapping netscript api");
|
||||
}
|
||||
const ctx = {
|
||||
makeRuntimeErrorMsg: (message: string) => {
|
||||
return helpers.makeRuntimeErrorMsg(functionPath, message);
|
||||
},
|
||||
log: (message: () => string) => {
|
||||
workerScript.log(functionPath, message);
|
||||
},
|
||||
workerScript,
|
||||
function: functionName,
|
||||
helper: {
|
||||
makeRuntimeErrorMsg: (msg: string) => helpers.makeRuntimeErrorMsg(functionPath, msg),
|
||||
string: (argName: string, v: unknown) => helpers.string(functionPath, argName, v),
|
||||
number: (argName: string, v: unknown) => helpers.number(functionPath, argName, v),
|
||||
ustring: (argName: string, v: unknown) => helpers.ustring(functionPath, argName, v),
|
||||
unumber: (argName: string, v: unknown) => helpers.unumber(functionPath, argName, v),
|
||||
scriptArgs: (v: unknown) => helpers.scriptArgs(functionPath, v),
|
||||
scriptIdentifier: (fn: unknown, hostname: unknown, args: unknown) =>
|
||||
helpers.scriptIdentifier(functionPath, fn, hostname, args),
|
||||
city: (argName: string, v: unknown) => helpers.city(functionPath, argName, v),
|
||||
boolean: helpers.boolean,
|
||||
getServer: (hostname: string) => helpers.getServer(hostname, ctx),
|
||||
checkSingularityAccess: () => helpers.checkSingularityAccess(functionName),
|
||||
hack: (hostname: string, manual: boolean, extra?: BasicHGWOptions) => helpers.hack(ctx, hostname, manual, extra),
|
||||
getValidPort: (port: number) => helpers.getValidPort(functionPath, port),
|
||||
player: (p: unknown) => helpers.player(functionPath, p),
|
||||
server: (s: unknown) => helpers.server(functionPath, s),
|
||||
gang: (g: unknown) => helpers.gang(functionPath, g),
|
||||
gangMember: (m: unknown) => helpers.gangMember(functionPath, m),
|
||||
gangTask: (t: unknown) => helpers.gangTask(functionPath, t),
|
||||
},
|
||||
functionPath,
|
||||
};
|
||||
function wrappedFunction(...args: unknown[]): unknown {
|
||||
helpers.updateDynamicRam(ctx.function, getRamCost(Player, ...tree, ctx.function));
|
||||
helpers.checkEnvFlags(ctx);
|
||||
helpers.updateDynamicRam(ctx, getRamCost(Player, ...tree, ctx.function));
|
||||
return func(ctx)(...args);
|
||||
}
|
||||
const parent = getNestedProperty(wrappedAPI, ...tree);
|
||||
const parent = getNestedProperty(wrappedAPI, tree);
|
||||
Object.defineProperty(parent, functionName, {
|
||||
value: wrappedFunction,
|
||||
writable: true,
|
||||
@ -118,20 +61,25 @@ function wrapFunction(
|
||||
});
|
||||
}
|
||||
|
||||
export function wrapAPI(
|
||||
helpers: INetscriptHelper,
|
||||
wrappedAPI: ExternalAPI,
|
||||
export function wrapAPI(workerScript: WorkerScript, namespace: object, args: ScriptArg[]): NSFull {
|
||||
const wrappedAPI = wrapAPILayer({}, workerScript, namespace);
|
||||
wrappedAPI.args = args;
|
||||
return wrappedAPI as unknown as NSFull;
|
||||
}
|
||||
|
||||
export function wrapAPILayer(
|
||||
wrappedAPI: ExternalAPILayer,
|
||||
workerScript: WorkerScript,
|
||||
namespace: object,
|
||||
...tree: string[]
|
||||
): WrappedNetscriptAPI {
|
||||
) {
|
||||
for (const [key, value] of Object.entries(namespace)) {
|
||||
if (typeof value === "function") {
|
||||
wrapFunction(helpers, wrappedAPI, workerScript, value, ...tree, key);
|
||||
wrapFunction(wrappedAPI, workerScript, value, ...tree, key);
|
||||
} else if (Array.isArray(value)) {
|
||||
setNestedProperty(wrappedAPI, value, key);
|
||||
setNestedProperty(wrappedAPI, value.slice(), key);
|
||||
} else if (typeof value === "object") {
|
||||
wrapAPI(helpers, wrappedAPI, workerScript, value, ...tree, key);
|
||||
wrapAPILayer(wrappedAPI, workerScript, value, ...tree, key);
|
||||
} else {
|
||||
setNestedProperty(wrappedAPI, value, ...tree, key);
|
||||
}
|
||||
@ -139,28 +87,21 @@ export function wrapAPI(
|
||||
return wrappedAPI;
|
||||
}
|
||||
|
||||
// TODO: This doesn't even work properly.
|
||||
function setNestedProperty(root: object, value: unknown, ...tree: string[]): void {
|
||||
function setNestedProperty(root: any, value: unknown, ...tree: string[]): void {
|
||||
let target = root;
|
||||
const key = tree.pop();
|
||||
if (!key) {
|
||||
throw new Error("Failure occured while wrapping netscript api (setNestedProperty)");
|
||||
if (!key) throw new Error("Failure occured while wrapping netscript api (setNestedProperty)");
|
||||
for (const branch of tree) {
|
||||
target[branch] ??= {};
|
||||
target = target[branch];
|
||||
}
|
||||
for (let branch of Object.values(target)) {
|
||||
if (branch === undefined) {
|
||||
branch = {};
|
||||
}
|
||||
target = branch;
|
||||
}
|
||||
Object.assign(target, { [key]: value });
|
||||
target[key] = value;
|
||||
}
|
||||
|
||||
function getNestedProperty(root: any, ...tree: string[]): unknown {
|
||||
function getNestedProperty(root: any, tree: string[]): unknown {
|
||||
let target = root;
|
||||
for (const branch of tree) {
|
||||
if (target[branch] === undefined) {
|
||||
target[branch] = {};
|
||||
}
|
||||
target[branch] ??= {};
|
||||
target = target[branch];
|
||||
}
|
||||
return target;
|
||||
|
@ -10,6 +10,12 @@ export class Environment {
|
||||
*/
|
||||
stopFlag = false;
|
||||
|
||||
/**
|
||||
* The currently running function
|
||||
*/
|
||||
|
||||
runningFn = "";
|
||||
|
||||
/**
|
||||
* Environment variables (currently only Netscript functions)
|
||||
*/
|
||||
|
665
src/Netscript/NetscriptHelpers.ts
Normal file
665
src/Netscript/NetscriptHelpers.ts
Normal file
@ -0,0 +1,665 @@
|
||||
import { NetscriptContext } from "./APIWrapper";
|
||||
import { WorkerScript } from "./WorkerScript";
|
||||
import { GetAllServers, GetServer } from "../Server/AllServers";
|
||||
import { Player } from "../Player";
|
||||
import { ScriptDeath } from "./ScriptDeath";
|
||||
import { isString } from "../utils/helpers/isString";
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
import { ScriptArg } from "./ScriptArg";
|
||||
import { CityName } from "../Locations/data/CityNames";
|
||||
import { BasicHGWOptions } from "src/ScriptEditor/NetscriptDefinitions";
|
||||
import { Server } from "../Server/Server";
|
||||
import {
|
||||
calculateHackingChance,
|
||||
calculateHackingExpGain,
|
||||
calculateHackingTime,
|
||||
calculatePercentMoneyHacked,
|
||||
} from "../Hacking";
|
||||
import { netscriptCanHack } from "../Hacking/netscriptCanHack";
|
||||
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { influenceStockThroughServerHack } from "../StockMarket/PlayerInfluencing";
|
||||
import { IPort } from "../NetscriptPort";
|
||||
import { NetscriptPorts } from "../NetscriptWorker";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { FormulaGang } from "../Gang/formulas/formulas";
|
||||
import { GangMember } from "../Gang/GangMember";
|
||||
import { GangMemberTask } from "../Gang/GangMemberTask";
|
||||
import { RunningScript } from "../Script/RunningScript";
|
||||
import { toNative } from "../NetscriptFunctions/toNative";
|
||||
import { ScriptIdentifier } from "./ScriptIdentifier";
|
||||
import { findRunningScript, findRunningScriptByPid } from "../Script/ScriptHelpers";
|
||||
import { RunningScript as IRunningScript } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { arrayToString } from "../utils/helpers/arrayToString";
|
||||
import { HacknetServer } from "../Hacknet/HacknetServer";
|
||||
import { BaseServer } from "../Server/BaseServer";
|
||||
|
||||
export const helpers = {
|
||||
string,
|
||||
number,
|
||||
scriptArgs,
|
||||
argsToString,
|
||||
isScriptErrorMessage,
|
||||
makeRuntimeRejectMsg,
|
||||
makeRuntimeErrorMsg,
|
||||
resolveNetscriptRequestedThreads,
|
||||
checkEnvFlags,
|
||||
checkSingularityAccess,
|
||||
netscriptDelay,
|
||||
updateDynamicRam,
|
||||
city,
|
||||
getServer,
|
||||
scriptIdentifier,
|
||||
hack,
|
||||
getValidPort,
|
||||
player,
|
||||
server,
|
||||
gang,
|
||||
gangMember,
|
||||
gangTask,
|
||||
log,
|
||||
getFunctionNames,
|
||||
getRunningScript,
|
||||
getRunningScriptByArgs,
|
||||
getCannotFindRunningScriptErrorMessage,
|
||||
createPublicRunningScript,
|
||||
failOnHacknetServer,
|
||||
};
|
||||
|
||||
/** Convert a provided value v for argument argName to string. If it wasn't originally a string or number, throw. */
|
||||
function string(ctx: NetscriptContext, argName: string, v: unknown): string {
|
||||
if (typeof v === "string") return v;
|
||||
if (typeof v === "number") return v + ""; // cast to string;
|
||||
throw makeRuntimeErrorMsg(ctx, `'${argName}' should be a string.`);
|
||||
}
|
||||
|
||||
/** Convert provided value v for argument argName to number. Throw if could not convert to a non-NaN number. */
|
||||
function number(ctx: NetscriptContext, argName: string, v: unknown): number {
|
||||
if (typeof v === "string") {
|
||||
const x = parseFloat(v);
|
||||
if (!isNaN(x)) return x; // otherwise it wasn't even a string representing a number.
|
||||
} else if (typeof v === "number") {
|
||||
if (isNaN(v)) throw makeRuntimeErrorMsg(ctx, `'${argName}' is NaN.`);
|
||||
return v;
|
||||
}
|
||||
throw makeRuntimeErrorMsg(ctx, `'${argName}' should be a number.`);
|
||||
}
|
||||
|
||||
/** Returns args back if it is a ScriptArg[]. Throws an error if it is not. */
|
||||
function scriptArgs(ctx: NetscriptContext, args: unknown) {
|
||||
if (!isScriptArgs(args)) throw makeRuntimeErrorMsg(ctx, "'args' is not an array of script args");
|
||||
return args;
|
||||
}
|
||||
|
||||
/** Determines if the given msg string is an error created by makeRuntimeRejectMsg. */
|
||||
function isScriptErrorMessage(msg: string): boolean {
|
||||
if (!isString(msg)) {
|
||||
return false;
|
||||
}
|
||||
const splitMsg = msg.split("|DELIMITER|");
|
||||
return splitMsg.length == 4;
|
||||
}
|
||||
|
||||
/** Convert multiple arguments for tprint or print into a single string. */
|
||||
function argsToString(args: unknown[]): string {
|
||||
let out = "";
|
||||
for (let arg of args) {
|
||||
if (arg === null) {
|
||||
out += "null";
|
||||
continue;
|
||||
}
|
||||
if (arg === undefined) {
|
||||
out += "undefined";
|
||||
continue;
|
||||
}
|
||||
arg = toNative(arg);
|
||||
out += typeof arg === "object" ? JSON.stringify(arg) : `${arg}`;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/** Creates an error message string containing hostname, scriptname, and the error message msg */
|
||||
function makeRuntimeRejectMsg(workerScript: WorkerScript, msg: string): string {
|
||||
for (const scriptUrl of workerScript.scriptRef.dependencies) {
|
||||
msg = msg.replace(new RegExp(scriptUrl.url, "g"), scriptUrl.filename);
|
||||
}
|
||||
|
||||
return "|DELIMITER|" + workerScript.hostname + "|DELIMITER|" + workerScript.name + "|DELIMITER|" + msg;
|
||||
}
|
||||
|
||||
/** Creates an error message string with a stack trace. */
|
||||
function makeRuntimeErrorMsg(ctx: NetscriptContext, msg: string): string {
|
||||
const errstack = new Error().stack;
|
||||
if (errstack === undefined) throw new Error("how did we not throw an error?");
|
||||
const stack = errstack.split("\n").slice(1);
|
||||
const workerScript = ctx.workerScript;
|
||||
const caller = ctx.function;
|
||||
const scripts = workerScript.getServer().scripts;
|
||||
const userstack = [];
|
||||
for (const stackline of stack) {
|
||||
let filename;
|
||||
for (const script of scripts) {
|
||||
if (script.url && stackline.includes(script.url)) {
|
||||
filename = script.filename;
|
||||
}
|
||||
for (const dependency of script.dependencies) {
|
||||
if (stackline.includes(dependency.url)) {
|
||||
filename = dependency.filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!filename) continue;
|
||||
|
||||
interface ILine {
|
||||
line: string;
|
||||
func: string;
|
||||
}
|
||||
|
||||
function parseChromeStackline(line: string): ILine | null {
|
||||
const lineRe = /.*:(\d+):\d+.*/;
|
||||
const funcRe = /.*at (.+) \(.*/;
|
||||
|
||||
const lineMatch = line.match(lineRe);
|
||||
const funcMatch = line.match(funcRe);
|
||||
if (lineMatch && funcMatch) {
|
||||
return { line: lineMatch[1], func: funcMatch[1] };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
let call = { line: "-1", func: "unknown" };
|
||||
const chromeCall = parseChromeStackline(stackline);
|
||||
if (chromeCall) {
|
||||
call = chromeCall;
|
||||
}
|
||||
|
||||
function parseFirefoxStackline(line: string): ILine | null {
|
||||
const lineRe = /.*:(\d+):\d+$/;
|
||||
const lineMatch = line.match(lineRe);
|
||||
|
||||
const lio = line.lastIndexOf("@");
|
||||
|
||||
if (lineMatch && lio !== -1) {
|
||||
return { line: lineMatch[1], func: line.slice(0, lio) };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const firefoxCall = parseFirefoxStackline(stackline);
|
||||
if (firefoxCall) {
|
||||
call = firefoxCall;
|
||||
}
|
||||
|
||||
userstack.push(`${filename}:L${call.line}@${call.func}`);
|
||||
}
|
||||
|
||||
workerScript.log(caller, () => msg);
|
||||
let rejectMsg = `${caller}: ${msg}`;
|
||||
if (userstack.length !== 0) rejectMsg += `<br><br>Stack:<br>${userstack.join("<br>")}`;
|
||||
return makeRuntimeRejectMsg(workerScript, rejectMsg);
|
||||
}
|
||||
|
||||
/** Validate requested number of threads for h/g/w options */
|
||||
function resolveNetscriptRequestedThreads(ctx: NetscriptContext, requestedThreads?: number): number {
|
||||
const threads = ctx.workerScript.scriptRef.threads;
|
||||
if (!requestedThreads) {
|
||||
return isNaN(threads) || threads < 1 ? 1 : threads;
|
||||
}
|
||||
const requestedThreadsAsInt = requestedThreads | 0;
|
||||
if (isNaN(requestedThreads) || requestedThreadsAsInt < 1) {
|
||||
throw makeRuntimeRejectMsg(
|
||||
ctx.workerScript,
|
||||
`Invalid thread count passed to ${ctx.function}: ${requestedThreads}. Threads must be a positive number.`,
|
||||
);
|
||||
}
|
||||
if (requestedThreadsAsInt > threads) {
|
||||
throw makeRuntimeRejectMsg(
|
||||
ctx.workerScript,
|
||||
`Too many threads requested by ${ctx.function}. Requested: ${requestedThreads}. Has: ${threads}.`,
|
||||
);
|
||||
}
|
||||
return requestedThreadsAsInt;
|
||||
}
|
||||
|
||||
/** Validate singularity access by throwing an error if the player does not have access. */
|
||||
function checkSingularityAccess(ctx: NetscriptContext): void {
|
||||
if (Player.bitNodeN !== 4 && Player.sourceFileLvl(4) === 0) {
|
||||
throw makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
`This singularity function requires Source-File 4 to run. A power up you obtain later in the game.
|
||||
It will be very obvious when and how you can obtain it.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** Create an error if a script is dead or if concurrent ns function calls are made */
|
||||
function checkEnvFlags(ctx: NetscriptContext): void {
|
||||
const ws = ctx.workerScript;
|
||||
if (ws.env.stopFlag) throw new ScriptDeath(ws);
|
||||
if (ws.env.runningFn && ctx.function !== "asleep") {
|
||||
ws.errorMessage = makeRuntimeRejectMsg(
|
||||
ws,
|
||||
`Concurrent calls to Netscript functions are not allowed!
|
||||
Did you forget to await hack(), grow(), or some other
|
||||
promise-returning function?
|
||||
Currently running: ${ws.env.runningFn} tried to run: ${ctx.function}`,
|
||||
);
|
||||
if (ws.delayReject) ws.delayReject(new ScriptDeath(ws));
|
||||
throw new ScriptDeath(ws); //No idea if this is the right thing to throw
|
||||
}
|
||||
}
|
||||
|
||||
/** Set a timeout for performing a task, mark the script as busy in the meantime. */
|
||||
function netscriptDelay(ctx: NetscriptContext, time: number): Promise<void> {
|
||||
const ws = ctx.workerScript;
|
||||
return new Promise(function (resolve, reject) {
|
||||
ws.delay = window.setTimeout(() => {
|
||||
ws.delay = null;
|
||||
ws.delayReject = undefined;
|
||||
ws.env.runningFn = "";
|
||||
if (ws.env.stopFlag) reject(new ScriptDeath(ws));
|
||||
else resolve();
|
||||
}, time);
|
||||
ws.delayReject = reject;
|
||||
ws.env.runningFn = ctx.function;
|
||||
});
|
||||
}
|
||||
|
||||
/** Adds to dynamic ram cost when calling new ns functions from a script */
|
||||
function updateDynamicRam(ctx: NetscriptContext, ramCost: number): void {
|
||||
const ws = ctx.workerScript;
|
||||
const fnName = ctx.function;
|
||||
if (ws.dynamicLoadedFns[fnName]) return;
|
||||
ws.dynamicLoadedFns[fnName] = true;
|
||||
|
||||
let threads = ws.scriptRef.threads;
|
||||
if (typeof threads !== "number") {
|
||||
console.warn(`WorkerScript detected NaN for threadcount for ${ws.name} on ${ws.hostname}`);
|
||||
threads = 1;
|
||||
}
|
||||
ws.dynamicRamUsage += ramCost;
|
||||
if (ws.dynamicRamUsage > 1.01 * ws.ramUsage) {
|
||||
ws.errorMessage = makeRuntimeRejectMsg(
|
||||
ws,
|
||||
`Dynamic RAM usage calculated to be greater than initial RAM usage on fn: ${fnName}.
|
||||
This is probably because you somehow circumvented the static RAM calculation.
|
||||
|
||||
Threads: ${threads}
|
||||
Dynamic RAM Usage: ${numeralWrapper.formatRAM(ws.dynamicRamUsage)}
|
||||
Static RAM Usage: ${numeralWrapper.formatRAM(ws.ramUsage)}
|
||||
|
||||
One of these could be the reason:
|
||||
* Using eval() to get a reference to a ns function
|
||||
const myScan = eval('ns.scan');
|
||||
|
||||
* Using map access to do the same
|
||||
const myScan = ns['scan'];
|
||||
|
||||
Sorry :(`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** Validates the input v as being a CityName. Throws an error if it is not. */
|
||||
function city(ctx: NetscriptContext, argName: string, v: unknown): CityName {
|
||||
if (typeof v !== "string") throw makeRuntimeErrorMsg(ctx, `${argName} should be a city name.`);
|
||||
const s = v as CityName;
|
||||
if (!Object.values(CityName).includes(s)) throw makeRuntimeErrorMsg(ctx, `${argName} should be a city name.`);
|
||||
return s;
|
||||
}
|
||||
|
||||
function scriptIdentifier(
|
||||
ctx: NetscriptContext,
|
||||
scriptID: unknown,
|
||||
_hostname: unknown,
|
||||
_args: unknown,
|
||||
): ScriptIdentifier {
|
||||
const ws = ctx.workerScript;
|
||||
// Provide the pid for the current script if no identifier provided
|
||||
if (scriptID === undefined) return ws.pid;
|
||||
if (typeof scriptID === "number") return scriptID;
|
||||
if (typeof scriptID === "string") {
|
||||
const hostname = _hostname === undefined ? ctx.workerScript.hostname : string(ctx, "hostname", _hostname);
|
||||
const args = _args === undefined ? [] : scriptArgs(ctx, _args);
|
||||
return {
|
||||
scriptname: scriptID,
|
||||
hostname,
|
||||
args,
|
||||
};
|
||||
}
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Server for a specific hostname/ip, throwing an error
|
||||
* if the server doesn't exist.
|
||||
* @param {NetscriptContext} ctx - Context from which getServer is being called. For logging purposes.
|
||||
* @param {string} hostname - Hostname of the server
|
||||
* @returns {BaseServer} The specified server as a BaseServer
|
||||
*/
|
||||
function getServer(ctx: NetscriptContext, hostname: string) {
|
||||
const server = GetServer(hostname);
|
||||
if (server == null) {
|
||||
const str = hostname === "" ? "'' (empty string)" : "'" + hostname + "'";
|
||||
throw makeRuntimeErrorMsg(ctx, `Invalid hostname: ${str}`);
|
||||
}
|
||||
return server;
|
||||
}
|
||||
|
||||
function isScriptArgs(args: unknown): args is ScriptArg[] {
|
||||
const isScriptArg = (arg: unknown) => typeof arg === "string" || typeof arg === "number" || typeof arg === "boolean";
|
||||
return Array.isArray(args) && args.every(isScriptArg);
|
||||
}
|
||||
|
||||
async function hack(
|
||||
ctx: NetscriptContext,
|
||||
hostname: string,
|
||||
manual: boolean,
|
||||
{ threads: requestedThreads, stock }: BasicHGWOptions = {},
|
||||
): Promise<number> {
|
||||
const ws = ctx.workerScript;
|
||||
const threads = helpers.resolveNetscriptRequestedThreads(ctx, requestedThreads);
|
||||
const server = getServer(ctx, hostname);
|
||||
if (!(server instanceof Server)) {
|
||||
throw makeRuntimeErrorMsg(ctx, "Cannot be executed on this server.");
|
||||
}
|
||||
|
||||
// Calculate the hacking time
|
||||
const hackingTime = calculateHackingTime(server, Player); // This is in seconds
|
||||
|
||||
// No root access or skill level too low
|
||||
const canHack = netscriptCanHack(server, Player);
|
||||
if (!canHack.res) {
|
||||
throw makeRuntimeErrorMsg(ctx, canHack.msg || "");
|
||||
}
|
||||
|
||||
log(
|
||||
ctx,
|
||||
() =>
|
||||
`Executing on '${server.hostname}' in ${convertTimeMsToTimeElapsedString(
|
||||
hackingTime * 1000,
|
||||
true,
|
||||
)} (t=${numeralWrapper.formatThreads(threads)})`,
|
||||
);
|
||||
|
||||
return helpers.netscriptDelay(ctx, hackingTime * 1000).then(function () {
|
||||
const hackChance = calculateHackingChance(server, Player);
|
||||
const rand = Math.random();
|
||||
let expGainedOnSuccess = calculateHackingExpGain(server, Player) * threads;
|
||||
const expGainedOnFailure = expGainedOnSuccess / 4;
|
||||
if (rand < hackChance) {
|
||||
// Success!
|
||||
const percentHacked = calculatePercentMoneyHacked(server, Player);
|
||||
let maxThreadNeeded = Math.ceil(1 / percentHacked);
|
||||
if (isNaN(maxThreadNeeded)) {
|
||||
// Server has a 'max money' of 0 (probably). We'll set this to an arbitrarily large value
|
||||
maxThreadNeeded = 1e6;
|
||||
}
|
||||
|
||||
let moneyDrained = Math.floor(server.moneyAvailable * percentHacked) * threads;
|
||||
|
||||
// Over-the-top safety checks
|
||||
if (moneyDrained <= 0) {
|
||||
moneyDrained = 0;
|
||||
expGainedOnSuccess = expGainedOnFailure;
|
||||
}
|
||||
if (moneyDrained > server.moneyAvailable) {
|
||||
moneyDrained = server.moneyAvailable;
|
||||
}
|
||||
server.moneyAvailable -= moneyDrained;
|
||||
if (server.moneyAvailable < 0) {
|
||||
server.moneyAvailable = 0;
|
||||
}
|
||||
|
||||
let moneyGained = moneyDrained * BitNodeMultipliers.ScriptHackMoneyGain;
|
||||
if (manual) {
|
||||
moneyGained = moneyDrained * BitNodeMultipliers.ManualHackMoney;
|
||||
}
|
||||
|
||||
Player.gainMoney(moneyGained, "hacking");
|
||||
ws.scriptRef.onlineMoneyMade += moneyGained;
|
||||
Player.scriptProdSinceLastAug += moneyGained;
|
||||
ws.scriptRef.recordHack(server.hostname, moneyGained, threads);
|
||||
Player.gainHackingExp(expGainedOnSuccess);
|
||||
if (manual) Player.gainIntelligenceExp(0.005);
|
||||
ws.scriptRef.onlineExpGained += expGainedOnSuccess;
|
||||
log(
|
||||
ctx,
|
||||
() =>
|
||||
`Successfully hacked '${server.hostname}' for ${numeralWrapper.formatMoney(
|
||||
moneyGained,
|
||||
)} and ${numeralWrapper.formatExp(expGainedOnSuccess)} exp (t=${numeralWrapper.formatThreads(threads)})`,
|
||||
);
|
||||
server.fortify(CONSTANTS.ServerFortifyAmount * Math.min(threads, maxThreadNeeded));
|
||||
if (stock) {
|
||||
influenceStockThroughServerHack(server, moneyDrained);
|
||||
}
|
||||
if (manual) {
|
||||
server.backdoorInstalled = true;
|
||||
}
|
||||
return Promise.resolve(moneyGained);
|
||||
} else {
|
||||
// Player only gains 25% exp for failure?
|
||||
Player.gainHackingExp(expGainedOnFailure);
|
||||
ws.scriptRef.onlineExpGained += expGainedOnFailure;
|
||||
log(
|
||||
ctx,
|
||||
() =>
|
||||
`Failed to hack '${server.hostname}'. Gained ${numeralWrapper.formatExp(
|
||||
expGainedOnFailure,
|
||||
)} exp (t=${numeralWrapper.formatThreads(threads)})`,
|
||||
);
|
||||
return Promise.resolve(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getValidPort(ctx: NetscriptContext, port: number): IPort {
|
||||
if (isNaN(port)) {
|
||||
throw makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
`Invalid argument. Must be a port number between 1 and ${CONSTANTS.NumNetscriptPorts}, is ${port}`,
|
||||
);
|
||||
}
|
||||
port = Math.round(port);
|
||||
if (port < 1 || port > CONSTANTS.NumNetscriptPorts) {
|
||||
throw makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
`Trying to use an invalid port: ${port}. Only ports 1-${CONSTANTS.NumNetscriptPorts} are valid.`,
|
||||
);
|
||||
}
|
||||
const iport = NetscriptPorts[port - 1];
|
||||
if (iport == null || !(iport instanceof Object)) {
|
||||
throw makeRuntimeErrorMsg(ctx, `Could not find port: ${port}. This is a bug. Report to dev.`);
|
||||
}
|
||||
return iport;
|
||||
}
|
||||
|
||||
function player(ctx: NetscriptContext, p: unknown): IPlayer {
|
||||
const fakePlayer = {
|
||||
hp: undefined,
|
||||
mults: undefined,
|
||||
numPeopleKilled: undefined,
|
||||
money: undefined,
|
||||
city: undefined,
|
||||
location: undefined,
|
||||
bitNodeN: undefined,
|
||||
totalPlaytime: undefined,
|
||||
playtimeSinceLastAug: undefined,
|
||||
playtimeSinceLastBitnode: undefined,
|
||||
jobs: undefined,
|
||||
factions: undefined,
|
||||
tor: undefined,
|
||||
inBladeburner: undefined,
|
||||
hasCorporation: undefined,
|
||||
entropy: undefined,
|
||||
};
|
||||
if (!roughlyIs(fakePlayer, p)) throw makeRuntimeErrorMsg(ctx, `player should be a Player.`);
|
||||
return p as IPlayer;
|
||||
}
|
||||
|
||||
function server(ctx: NetscriptContext, s: unknown): Server {
|
||||
if (!roughlyIs(new Server(), s)) throw makeRuntimeErrorMsg(ctx, `server should be a Server.`);
|
||||
return s as Server;
|
||||
}
|
||||
|
||||
function roughlyIs(expect: object, actual: unknown): boolean {
|
||||
if (typeof actual !== "object" || actual == null) return false;
|
||||
const expects = Object.keys(expect);
|
||||
const actuals = Object.keys(actual);
|
||||
for (const expect of expects)
|
||||
if (!actuals.includes(expect)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function gang(ctx: NetscriptContext, g: unknown): FormulaGang {
|
||||
if (!roughlyIs({ respect: 0, territory: 0, wantedLevel: 0 }, g))
|
||||
throw makeRuntimeErrorMsg(ctx, `gang should be a Gang.`);
|
||||
return g as FormulaGang;
|
||||
}
|
||||
|
||||
function gangMember(ctx: NetscriptContext, m: unknown): GangMember {
|
||||
if (!roughlyIs(new GangMember(), m)) throw makeRuntimeErrorMsg(ctx, `member should be a GangMember.`);
|
||||
return m as GangMember;
|
||||
}
|
||||
|
||||
function gangTask(ctx: NetscriptContext, t: unknown): GangMemberTask {
|
||||
if (!roughlyIs(new GangMemberTask("", "", false, false, {}), t))
|
||||
throw makeRuntimeErrorMsg(ctx, `task should be a GangMemberTask.`);
|
||||
return t as GangMemberTask;
|
||||
}
|
||||
|
||||
function log(ctx: NetscriptContext, message: () => string) {
|
||||
ctx.workerScript.log(ctx.functionPath, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for and returns the RunningScript object for the specified script.
|
||||
* If the 'fn' argument is not specified, this returns the current RunningScript.
|
||||
* @param {string} fn - Filename of script
|
||||
* @param {string} hostname - Hostname/ip of the server on which the script resides
|
||||
* @param {any[]} scriptArgs - Running script's arguments
|
||||
* @returns {RunningScript}
|
||||
* Running script identified by the parameters, or null if no such script
|
||||
* exists, or the current running script if the first argument 'fn'
|
||||
* is not specified.
|
||||
*/
|
||||
function getRunningScriptByArgs(
|
||||
ctx: NetscriptContext,
|
||||
fn: string,
|
||||
hostname: string,
|
||||
scriptArgs: ScriptArg[],
|
||||
): RunningScript | null {
|
||||
if (!Array.isArray(scriptArgs)) {
|
||||
throw helpers.makeRuntimeRejectMsg(
|
||||
ctx.workerScript,
|
||||
`Invalid scriptArgs argument passed into getRunningScript() from ${ctx.function}(). ` +
|
||||
`This is probably a bug. Please report to game developer`,
|
||||
);
|
||||
}
|
||||
|
||||
if (fn != null && typeof fn === "string") {
|
||||
// Get Logs of another script
|
||||
if (hostname == null) {
|
||||
hostname = ctx.workerScript.hostname;
|
||||
}
|
||||
const server = helpers.getServer(ctx, hostname);
|
||||
|
||||
return findRunningScript(fn, scriptArgs, server);
|
||||
}
|
||||
|
||||
// If no arguments are specified, return the current RunningScript
|
||||
return ctx.workerScript.scriptRef;
|
||||
}
|
||||
|
||||
/** Provides an array of all function names on a nested object */
|
||||
function getFunctionNames(obj: object, prefix: string): string[] {
|
||||
const functionNames: string[] = [];
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
if (key === "args") {
|
||||
continue;
|
||||
} else if (typeof value == "function") {
|
||||
functionNames.push(prefix + key);
|
||||
} else if (typeof value == "object") {
|
||||
functionNames.push(...getFunctionNames(value, key + "."));
|
||||
}
|
||||
}
|
||||
return functionNames;
|
||||
}
|
||||
|
||||
function getRunningScriptByPid(pid: number): RunningScript | null {
|
||||
for (const server of GetAllServers()) {
|
||||
const runningScript = findRunningScriptByPid(pid, server);
|
||||
if (runningScript) return runningScript;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getRunningScript(ctx: NetscriptContext, ident: ScriptIdentifier): RunningScript | null {
|
||||
if (typeof ident === "number") {
|
||||
return getRunningScriptByPid(ident);
|
||||
} else {
|
||||
return getRunningScriptByArgs(ctx, ident.scriptname, ident.hostname, ident.args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for getting the error log message when the user specifies
|
||||
* a nonexistent running script
|
||||
* @param {string} fn - Filename of script
|
||||
* @param {string} hostname - Hostname/ip of the server on which the script resides
|
||||
* @param {any[]} scriptArgs - Running script's arguments
|
||||
* @returns {string} Error message to print to logs
|
||||
*/
|
||||
function getCannotFindRunningScriptErrorMessage(ident: ScriptIdentifier): string {
|
||||
if (typeof ident === "number") return `Cannot find running script with pid: ${ident}`;
|
||||
|
||||
return `Cannot find running script ${ident.scriptname} on server ${ident.hostname} with args: ${arrayToString(
|
||||
ident.args,
|
||||
)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes a `RunningScript` to remove sensitive information, making it suitable for
|
||||
* return through an NS function.
|
||||
* @see NS.getRecentScripts
|
||||
* @see NS.getRunningScript
|
||||
* @param runningScript Existing, internal RunningScript
|
||||
* @returns A sanitized, NS-facing copy of the RunningScript
|
||||
*/
|
||||
function createPublicRunningScript(runningScript: RunningScript): IRunningScript {
|
||||
return {
|
||||
args: runningScript.args.slice(),
|
||||
filename: runningScript.filename,
|
||||
logs: runningScript.logs.slice(),
|
||||
offlineExpGained: runningScript.offlineExpGained,
|
||||
offlineMoneyMade: runningScript.offlineMoneyMade,
|
||||
offlineRunningTime: runningScript.offlineRunningTime,
|
||||
onlineExpGained: runningScript.onlineExpGained,
|
||||
onlineMoneyMade: runningScript.onlineMoneyMade,
|
||||
onlineRunningTime: runningScript.onlineRunningTime,
|
||||
pid: runningScript.pid,
|
||||
ramUsage: runningScript.ramUsage,
|
||||
server: runningScript.server,
|
||||
threads: runningScript.threads,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to fail a function if the function's target is a Hacknet Server.
|
||||
* This is used for functions that should run on normal Servers, but not Hacknet Servers
|
||||
* @param {Server} server - Target server
|
||||
* @param {string} callingFn - Name of calling function. For logging purposes
|
||||
* @returns {boolean} True if the server is a Hacknet Server, false otherwise
|
||||
*/
|
||||
function failOnHacknetServer(ctx: NetscriptContext, server: BaseServer, callingFn = ""): boolean {
|
||||
if (server instanceof HacknetServer) {
|
||||
ctx.workerScript.log(callingFn, () => `Does not work on Hacknet Servers`);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -346,6 +346,11 @@ const grafting = {
|
||||
};
|
||||
|
||||
const corporation = {
|
||||
getMaterialNames: 0,
|
||||
getIndustryTypes: 0,
|
||||
getUnlockables: 0,
|
||||
getUpgradeNames: 0,
|
||||
getResearchNames: 0,
|
||||
createCorporation: 0,
|
||||
hasUnlockUpgrade: 0,
|
||||
getUnlockUpgradeCost: 0,
|
||||
|
9
src/Netscript/ScriptIdentifier.ts
Normal file
9
src/Netscript/ScriptIdentifier.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { ScriptArg } from "./ScriptArg";
|
||||
|
||||
export type ScriptIdentifier = //This was previously in INetscriptHelper.ts, may move to its own file or a generic types file.
|
||||
| number
|
||||
| {
|
||||
scriptname: string;
|
||||
hostname: string;
|
||||
args: ScriptArg[];
|
||||
};
|
@ -10,7 +10,6 @@ import { WorkerScriptStartStopEventEmitter } from "./WorkerScriptStartStopEventE
|
||||
import { RunningScript } from "../Script/RunningScript";
|
||||
import { GetServer } from "../Server/AllServers";
|
||||
|
||||
import { compareArrays } from "../utils/helpers/compareArrays";
|
||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
import { AddRecentScript } from "./RecentScripts";
|
||||
import { Player } from "../Player";
|
||||
@ -33,13 +32,8 @@ export function killWorkerScript(params: killScriptParams): boolean {
|
||||
|
||||
// If for some reason that doesn't work, we'll try the old way
|
||||
for (const ws of workerScripts.values()) {
|
||||
if (
|
||||
ws.name == params.runningScript.filename &&
|
||||
ws.hostname == params.hostname &&
|
||||
compareArrays(ws.args, params.runningScript.args)
|
||||
) {
|
||||
if (ws.scriptRef === params.runningScript) {
|
||||
stopAndCleanUpWorkerScript(ws);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -52,7 +46,6 @@ function killWorkerScriptByPid(pid: number): boolean {
|
||||
const ws = workerScripts.get(pid);
|
||||
if (ws instanceof WorkerScript) {
|
||||
stopAndCleanUpWorkerScript(ws);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -86,7 +79,6 @@ function stopAndCleanUpWorkerScript(workerScript: WorkerScript): void {
|
||||
*/
|
||||
function removeWorkerScript(workerScript: WorkerScript): void {
|
||||
const ip = workerScript.hostname;
|
||||
const name = workerScript.name;
|
||||
|
||||
// Get the server on which the script runs
|
||||
const server = GetServer(ip);
|
||||
@ -98,7 +90,7 @@ function removeWorkerScript(workerScript: WorkerScript): void {
|
||||
// Delete the RunningScript object from that server
|
||||
for (let i = 0; i < server.runningScripts.length; ++i) {
|
||||
const runningScript = server.runningScripts[i];
|
||||
if (runningScript.filename === name && compareArrays(runningScript.args, workerScript.args)) {
|
||||
if (runningScript === workerScript.scriptRef) {
|
||||
server.runningScripts.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
|
@ -1,65 +0,0 @@
|
||||
import { isString } from "./utils/helpers/isString";
|
||||
import { GetServer } from "./Server/AllServers";
|
||||
import { ScriptDeath } from "./Netscript/ScriptDeath";
|
||||
import { WorkerScript } from "./Netscript/WorkerScript";
|
||||
import { NetscriptContext } from "./Netscript/APIWrapper";
|
||||
|
||||
export function netscriptDelay(time: number, workerScript: WorkerScript): Promise<void> {
|
||||
// Cancel any pre-existing netscriptDelay'ed function call
|
||||
// TODO: the rejection almost certainly ends up in the uncaught rejection handler.
|
||||
// Maybe reject with a stack-trace'd error message?
|
||||
if (workerScript.delayReject) workerScript.delayReject();
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
workerScript.delay = window.setTimeout(() => {
|
||||
workerScript.delay = null;
|
||||
workerScript.delayReject = undefined;
|
||||
if (workerScript.env.stopFlag) reject(new ScriptDeath(workerScript));
|
||||
else resolve();
|
||||
}, time);
|
||||
workerScript.delayReject = reject;
|
||||
});
|
||||
}
|
||||
|
||||
export function makeRuntimeRejectMsg(workerScript: WorkerScript, msg: string): string {
|
||||
const server = GetServer(workerScript.hostname);
|
||||
if (server == null) {
|
||||
throw new Error(`WorkerScript constructed with invalid server ip: ${workerScript.hostname}`);
|
||||
}
|
||||
|
||||
for (const scriptUrl of workerScript.scriptRef.dependencies) {
|
||||
// Return just the original msg if it's nullish so that we don't get a workerscript error
|
||||
msg = msg?.replace(new RegExp(scriptUrl.url, "g"), scriptUrl.filename) ?? msg;
|
||||
}
|
||||
|
||||
return "|DELIMITER|" + server.hostname + "|DELIMITER|" + workerScript.name + "|DELIMITER|" + msg;
|
||||
}
|
||||
|
||||
export function resolveNetscriptRequestedThreads(ctx: NetscriptContext, requestedThreads?: number): number {
|
||||
const threads = ctx.workerScript.scriptRef.threads;
|
||||
if (!requestedThreads) {
|
||||
return isNaN(threads) || threads < 1 ? 1 : threads;
|
||||
}
|
||||
const requestedThreadsAsInt = requestedThreads | 0;
|
||||
if (isNaN(requestedThreads) || requestedThreadsAsInt < 1) {
|
||||
throw makeRuntimeRejectMsg(
|
||||
ctx.workerScript,
|
||||
`Invalid thread count passed to ${ctx.function}: ${requestedThreads}. Threads must be a positive number.`,
|
||||
);
|
||||
}
|
||||
if (requestedThreadsAsInt > threads) {
|
||||
throw makeRuntimeRejectMsg(
|
||||
ctx.workerScript,
|
||||
`Too many threads requested by ${ctx.function}. Requested: ${requestedThreads}. Has: ${threads}.`,
|
||||
);
|
||||
}
|
||||
return requestedThreadsAsInt;
|
||||
}
|
||||
|
||||
export function isScriptErrorMessage(msg: string): boolean {
|
||||
if (!isString(msg)) {
|
||||
return false;
|
||||
}
|
||||
const splitMsg = msg.split("|DELIMITER|");
|
||||
return splitMsg.length == 4;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,13 @@
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player as player } from "../Player";
|
||||
import { Bladeburner } from "../Bladeburner/Bladeburner";
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import { Bladeburner as INetscriptBladeburner, BladeburnerCurAction } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { IAction } from "src/Bladeburner/IAction";
|
||||
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
||||
import { BlackOperation } from "../Bladeburner/BlackOperation";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
|
||||
export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript): InternalAPI<INetscriptBladeburner> {
|
||||
export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
|
||||
const checkBladeburnerAccess = function (ctx: NetscriptContext, skipjoined = false): void {
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
||||
@ -18,13 +18,13 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
});
|
||||
if (!apiAccess) {
|
||||
const apiDenied = `You do not currently have access to the Bladeburner API. You must either be in BitNode-7 or have Source-File 7.`;
|
||||
throw ctx.makeRuntimeErrorMsg(apiDenied);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, apiDenied);
|
||||
}
|
||||
if (!skipjoined) {
|
||||
const bladeburnerAccess = bladeburner instanceof Bladeburner;
|
||||
if (!bladeburnerAccess) {
|
||||
const bladeburnerDenied = `You must be a member of the Bladeburner division to use this API.`;
|
||||
throw ctx.makeRuntimeErrorMsg(bladeburnerDenied);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, bladeburnerDenied);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -33,7 +33,7 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
||||
if (!bladeburner.cities.hasOwnProperty(city)) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid city: ${city}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid city: ${city}`);
|
||||
}
|
||||
};
|
||||
|
||||
@ -42,11 +42,11 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
||||
const actionId = bladeburner.getActionIdFromTypeAndName(type, name);
|
||||
if (!actionId) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid action type='${type}', name='${name}'`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid action type='${type}', name='${name}'`);
|
||||
}
|
||||
const actionObj = bladeburner.getActionObject(actionId);
|
||||
if (!actionObj) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid action type='${type}', name='${name}'`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid action type='${type}', name='${name}'`);
|
||||
}
|
||||
|
||||
return actionObj;
|
||||
@ -74,7 +74,7 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
getBlackOpRank:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_blackOpName: unknown): number => {
|
||||
const blackOpName = ctx.helper.string("blackOpName", _blackOpName);
|
||||
const blackOpName = helpers.string(ctx, "blackOpName", _blackOpName);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const action = getBladeburnerActionObject(ctx, "blackops", blackOpName);
|
||||
if (!(action instanceof BlackOperation)) throw new Error("action was not a black operation");
|
||||
@ -95,15 +95,15 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
startAction:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown): boolean => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.startActionNetscriptFn(player, type, name, workerScript);
|
||||
return bladeburner.startActionNetscriptFn(player, type, name, ctx.workerScript);
|
||||
} catch (e: unknown) {
|
||||
throw ctx.makeRuntimeErrorMsg(String(e));
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
|
||||
}
|
||||
},
|
||||
stopBladeburnerAction: (ctx: NetscriptContext) => (): void => {
|
||||
@ -121,8 +121,8 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
getActionTime:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown): number => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
@ -130,13 +130,13 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
const time = bladeburner.getActionTimeNetscriptFn(player, type, name);
|
||||
if (typeof time === "string") {
|
||||
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
||||
ctx.log(() => errorLogText);
|
||||
helpers.log(ctx, () => errorLogText);
|
||||
return -1;
|
||||
} else {
|
||||
return time;
|
||||
}
|
||||
} catch (e: unknown) {
|
||||
throw ctx.makeRuntimeErrorMsg(String(e));
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
|
||||
}
|
||||
},
|
||||
getActionCurrentTime: (ctx: NetscriptContext) => (): number => {
|
||||
@ -149,14 +149,14 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
1000;
|
||||
return timecomputed;
|
||||
} catch (e: unknown) {
|
||||
throw ctx.makeRuntimeErrorMsg(String(e));
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
|
||||
}
|
||||
},
|
||||
getActionEstimatedSuccessChance:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown): [number, number] => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
@ -164,21 +164,21 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
const chance = bladeburner.getActionEstimatedSuccessChanceNetscriptFn(player, type, name);
|
||||
if (typeof chance === "string") {
|
||||
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
|
||||
ctx.log(() => errorLogText);
|
||||
helpers.log(ctx, () => errorLogText);
|
||||
return [-1, -1];
|
||||
} else {
|
||||
return chance;
|
||||
}
|
||||
} catch (e: unknown) {
|
||||
throw ctx.makeRuntimeErrorMsg(String(e));
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
|
||||
}
|
||||
},
|
||||
getActionRepGain:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown, _level: unknown): number => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
const level = ctx.helper.number("level", _level);
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
const level = helpers.number(ctx, "level", _level);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const action = getBladeburnerActionObject(ctx, type, name);
|
||||
let rewardMultiplier;
|
||||
@ -193,22 +193,22 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
getActionCountRemaining:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown): number => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getActionCountRemainingNetscriptFn(type, name, workerScript);
|
||||
return bladeburner.getActionCountRemainingNetscriptFn(type, name, ctx.workerScript);
|
||||
} catch (e: unknown) {
|
||||
throw ctx.makeRuntimeErrorMsg(String(e));
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
|
||||
}
|
||||
},
|
||||
getActionMaxLevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown): number => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const action = getBladeburnerActionObject(ctx, type, name);
|
||||
return action.maxLevel;
|
||||
@ -216,8 +216,8 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
getActionCurrentLevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown): number => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const action = getBladeburnerActionObject(ctx, type, name);
|
||||
return action.level;
|
||||
@ -225,8 +225,8 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
getActionAutolevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown): boolean => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const action = getBladeburnerActionObject(ctx, type, name);
|
||||
return action.autoLevel;
|
||||
@ -234,9 +234,9 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
setActionAutolevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown, _autoLevel: unknown = true): void => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
const autoLevel = ctx.helper.boolean(_autoLevel);
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
const autoLevel = !!_autoLevel;
|
||||
checkBladeburnerAccess(ctx);
|
||||
const action = getBladeburnerActionObject(ctx, type, name);
|
||||
action.autoLevel = autoLevel;
|
||||
@ -244,13 +244,13 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
setActionLevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown, _level: unknown = 1): void => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
const level = ctx.helper.number("level", _level);
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
const level = helpers.number(ctx, "level", _level);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const action = getBladeburnerActionObject(ctx, type, name);
|
||||
if (level < 1 || level > action.maxLevel) {
|
||||
ctx.helper.makeRuntimeErrorMsg(`Level must be between 1 and ${action.maxLevel}, is ${level}`);
|
||||
helpers.makeRuntimeErrorMsg(ctx, `Level must be between 1 and ${action.maxLevel}, is ${level}`);
|
||||
}
|
||||
action.level = level;
|
||||
},
|
||||
@ -269,77 +269,77 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
getSkillLevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_skillName: unknown): number => {
|
||||
const skillName = ctx.helper.string("skillName", _skillName);
|
||||
const skillName = helpers.string(ctx, "skillName", _skillName);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getSkillLevelNetscriptFn(skillName, workerScript);
|
||||
return bladeburner.getSkillLevelNetscriptFn(skillName, ctx.workerScript);
|
||||
} catch (e: unknown) {
|
||||
throw ctx.makeRuntimeErrorMsg(String(e));
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
|
||||
}
|
||||
},
|
||||
getSkillUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_skillName: unknown, _count: unknown = 1): number => {
|
||||
const skillName = ctx.helper.string("skillName", _skillName);
|
||||
const count = ctx.helper.number("count", _count);
|
||||
const skillName = helpers.string(ctx, "skillName", _skillName);
|
||||
const count = helpers.number(ctx, "count", _count);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getSkillUpgradeCostNetscriptFn(skillName, count, workerScript);
|
||||
return bladeburner.getSkillUpgradeCostNetscriptFn(skillName, count, ctx.workerScript);
|
||||
} catch (e: unknown) {
|
||||
throw ctx.makeRuntimeErrorMsg(String(e));
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
|
||||
}
|
||||
},
|
||||
upgradeSkill:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_skillName: unknown, _count: unknown = 1): boolean => {
|
||||
const skillName = ctx.helper.string("skillName", _skillName);
|
||||
const count = ctx.helper.number("count", _count);
|
||||
const skillName = helpers.string(ctx, "skillName", _skillName);
|
||||
const count = helpers.number(ctx, "count", _count);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.upgradeSkillNetscriptFn(skillName, count, workerScript);
|
||||
return bladeburner.upgradeSkillNetscriptFn(skillName, count, ctx.workerScript);
|
||||
} catch (e: unknown) {
|
||||
throw ctx.makeRuntimeErrorMsg(String(e));
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
|
||||
}
|
||||
},
|
||||
getTeamSize:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown): number => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getTeamSizeNetscriptFn(type, name, workerScript);
|
||||
return bladeburner.getTeamSizeNetscriptFn(type, name, ctx.workerScript);
|
||||
} catch (e: unknown) {
|
||||
throw ctx.makeRuntimeErrorMsg(String(e));
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
|
||||
}
|
||||
},
|
||||
setTeamSize:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown, _size: unknown): number => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
const size = ctx.helper.number("size", _size);
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const name = helpers.string(ctx, "name", _name);
|
||||
const size = helpers.number(ctx, "size", _size);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.setTeamSizeNetscriptFn(type, name, size, workerScript);
|
||||
return bladeburner.setTeamSizeNetscriptFn(type, name, size, ctx.workerScript);
|
||||
} catch (e: unknown) {
|
||||
throw ctx.makeRuntimeErrorMsg(String(e));
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
|
||||
}
|
||||
},
|
||||
getCityEstimatedPopulation:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_cityName: unknown): number => {
|
||||
const cityName = ctx.helper.string("cityName", _cityName);
|
||||
const cityName = helpers.string(ctx, "cityName", _cityName);
|
||||
checkBladeburnerAccess(ctx);
|
||||
checkBladeburnerCity(ctx, cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
@ -349,7 +349,7 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
getCityCommunities:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_cityName: unknown): number => {
|
||||
const cityName = ctx.helper.string("cityName", _cityName);
|
||||
const cityName = helpers.string(ctx, "cityName", _cityName);
|
||||
checkBladeburnerAccess(ctx);
|
||||
checkBladeburnerCity(ctx, cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
@ -359,7 +359,7 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
getCityChaos:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_cityName: unknown): number => {
|
||||
const cityName = ctx.helper.string("cityName", _cityName);
|
||||
const cityName = helpers.string(ctx, "cityName", _cityName);
|
||||
checkBladeburnerAccess(ctx);
|
||||
checkBladeburnerCity(ctx, cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
@ -375,7 +375,7 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
switchCity:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_cityName: unknown): boolean => {
|
||||
const cityName = ctx.helper.string("cityName", _cityName);
|
||||
const cityName = helpers.string(ctx, "cityName", _cityName);
|
||||
checkBladeburnerAccess(ctx);
|
||||
checkBladeburnerCity(ctx, cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
@ -393,7 +393,7 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
checkBladeburnerAccess(ctx, true);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.joinBladeburnerFactionNetscriptFn(workerScript);
|
||||
return bladeburner.joinBladeburnerFactionNetscriptFn(ctx.workerScript);
|
||||
},
|
||||
joinBladeburnerDivision: (ctx: NetscriptContext) => (): boolean => {
|
||||
if (player.bitNodeN === 7 || player.sourceFileLvl(7) > 0) {
|
||||
@ -409,11 +409,11 @@ export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript
|
||||
player.skills.agility >= 100
|
||||
) {
|
||||
player.bladeburner = new Bladeburner(player);
|
||||
ctx.log(() => "You have been accepted into the Bladeburner division");
|
||||
helpers.log(ctx, () => "You have been accepted into the Bladeburner division");
|
||||
|
||||
return true;
|
||||
} else {
|
||||
ctx.log(() => "You do not meet the requirements for joining the Bladeburner division");
|
||||
helpers.log(ctx, () => "You do not meet the requirements for joining the Bladeburner division");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,21 @@
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player as player } from "../Player";
|
||||
import { is2DArray } from "../utils/helpers/is2DArray";
|
||||
import { CodingContract } from "../CodingContracts";
|
||||
import { CodingAttemptOptions, CodingContract as ICodingContract } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
|
||||
export function NetscriptCodingContract(player: IPlayer, workerScript: WorkerScript): InternalAPI<ICodingContract> {
|
||||
export function NetscriptCodingContract(): InternalAPI<ICodingContract> {
|
||||
const getCodingContract = function (
|
||||
ctx: NetscriptContext,
|
||||
func: string,
|
||||
hostname: string,
|
||||
filename: string,
|
||||
): CodingContract {
|
||||
const server = ctx.helper.getServer(hostname);
|
||||
const server = helpers.getServer(ctx, hostname);
|
||||
const contract = server.getContract(filename);
|
||||
if (contract == null) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Cannot find contract '${filename}' on server '${hostname}'`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Cannot find contract '${filename}' on server '${hostname}'`);
|
||||
}
|
||||
|
||||
return contract;
|
||||
@ -27,11 +27,11 @@ export function NetscriptCodingContract(player: IPlayer, workerScript: WorkerScr
|
||||
(
|
||||
answer: unknown,
|
||||
_filename: unknown,
|
||||
_hostname: unknown = workerScript.hostname,
|
||||
_hostname: unknown = ctx.workerScript.hostname,
|
||||
{ returnReward }: CodingAttemptOptions = { returnReward: false },
|
||||
): boolean | string => {
|
||||
const filename = ctx.helper.string("filename", _filename);
|
||||
const hostname = ctx.helper.string("hostname", _hostname);
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const hostname = helpers.string(ctx, "hostname", _hostname);
|
||||
const contract = getCodingContract(ctx, "attempt", hostname, filename);
|
||||
|
||||
// Convert answer to string. If the answer is a 2D array, then we have to
|
||||
@ -51,19 +51,20 @@ export function NetscriptCodingContract(player: IPlayer, workerScript: WorkerScr
|
||||
const creward = contract.reward;
|
||||
if (creward === null) throw new Error("Somehow solved a contract that didn't have a reward");
|
||||
|
||||
const serv = ctx.helper.getServer(hostname);
|
||||
const serv = helpers.getServer(ctx, hostname);
|
||||
if (contract.isSolution(answerStr)) {
|
||||
const reward = player.gainCodingContractReward(creward, contract.getDifficulty());
|
||||
ctx.log(() => `Successfully completed Coding Contract '${filename}'. Reward: ${reward}`);
|
||||
helpers.log(ctx, () => `Successfully completed Coding Contract '${filename}'. Reward: ${reward}`);
|
||||
serv.removeContract(filename);
|
||||
return returnReward ? reward : true;
|
||||
} else {
|
||||
++contract.tries;
|
||||
if (contract.tries >= contract.getMaxNumTries()) {
|
||||
ctx.log(() => `Coding Contract attempt '${filename}' failed. Contract is now self-destructing`);
|
||||
helpers.log(ctx, () => `Coding Contract attempt '${filename}' failed. Contract is now self-destructing`);
|
||||
serv.removeContract(filename);
|
||||
} else {
|
||||
ctx.log(
|
||||
helpers.log(
|
||||
ctx,
|
||||
() =>
|
||||
`Coding Contract attempt '${filename}' failed. ${
|
||||
contract.getMaxNumTries() - contract.tries
|
||||
@ -76,17 +77,17 @@ export function NetscriptCodingContract(player: IPlayer, workerScript: WorkerScr
|
||||
},
|
||||
getContractType:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_filename: unknown, _hostname: unknown = workerScript.hostname): string => {
|
||||
const filename = ctx.helper.string("filename", _filename);
|
||||
const hostname = ctx.helper.string("hostname", _hostname);
|
||||
(_filename: unknown, _hostname: unknown = ctx.workerScript.hostname): string => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const hostname = helpers.string(ctx, "hostname", _hostname);
|
||||
const contract = getCodingContract(ctx, "getContractType", hostname, filename);
|
||||
return contract.getType();
|
||||
},
|
||||
getData:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_filename: unknown, _hostname: unknown = workerScript.hostname): unknown => {
|
||||
const filename = ctx.helper.string("filename", _filename);
|
||||
const hostname = ctx.helper.string("hostname", _hostname);
|
||||
(_filename: unknown, _hostname: unknown = ctx.workerScript.hostname): unknown => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const hostname = helpers.string(ctx, "hostname", _hostname);
|
||||
const contract = getCodingContract(ctx, "getData", hostname, filename);
|
||||
const data = contract.getData();
|
||||
if (Array.isArray(data)) {
|
||||
@ -107,17 +108,17 @@ export function NetscriptCodingContract(player: IPlayer, workerScript: WorkerScr
|
||||
},
|
||||
getDescription:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_filename: unknown, _hostname: unknown = workerScript.hostname): string => {
|
||||
const filename = ctx.helper.string("filename", _filename);
|
||||
const hostname = ctx.helper.string("hostname", _hostname);
|
||||
(_filename: unknown, _hostname: unknown = ctx.workerScript.hostname): string => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const hostname = helpers.string(ctx, "hostname", _hostname);
|
||||
const contract = getCodingContract(ctx, "getDescription", hostname, filename);
|
||||
return contract.getDescription();
|
||||
},
|
||||
getNumTriesRemaining:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_filename: unknown, _hostname: unknown = workerScript.hostname): number => {
|
||||
const filename = ctx.helper.string("filename", _filename);
|
||||
const hostname = ctx.helper.string("hostname", _hostname);
|
||||
(_filename: unknown, _hostname: unknown = ctx.workerScript.hostname): number => {
|
||||
const filename = helpers.string(ctx, "filename", _filename);
|
||||
const hostname = helpers.string(ctx, "hostname", _hostname);
|
||||
const contract = getCodingContract(ctx, "getNumTriesRemaining", hostname, filename);
|
||||
return contract.getMaxNumTries() - contract.tries;
|
||||
},
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player as player } from "../Player";
|
||||
|
||||
import { OfficeSpace } from "../Corporation/OfficeSpace";
|
||||
import { Employee } from "../Corporation/Employee";
|
||||
@ -65,9 +65,10 @@ import { CorporationConstants } from "../Corporation/data/Constants";
|
||||
import { ResearchMap } from "../Corporation/ResearchMap";
|
||||
import { Factions } from "../Faction/Factions";
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
|
||||
export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation> {
|
||||
export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
function createCorporation(corporationName: string, selfFund = true): boolean {
|
||||
if (!player.canAccessCorporation() || player.hasCorporation()) return false;
|
||||
if (!corporationName) return false;
|
||||
@ -101,7 +102,7 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
}
|
||||
|
||||
function getUpgradeLevel(ctx: NetscriptContext, _upgradeName: string): number {
|
||||
const upgradeName = ctx.helper.string("upgradeName", _upgradeName);
|
||||
const upgradeName = helpers.string(ctx, "upgradeName", _upgradeName);
|
||||
const corporation = getCorporation();
|
||||
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade.name === upgradeName);
|
||||
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
||||
@ -110,7 +111,7 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
}
|
||||
|
||||
function getUpgradeLevelCost(ctx: NetscriptContext, _upgradeName: string): number {
|
||||
const upgradeName = ctx.helper.string("upgradeName", _upgradeName);
|
||||
const upgradeName = helpers.string(ctx, "upgradeName", _upgradeName);
|
||||
const corporation = getCorporation();
|
||||
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade.name === upgradeName);
|
||||
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
||||
@ -274,10 +275,11 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
}
|
||||
|
||||
function checkAccess(ctx: NetscriptContext, api?: number): void {
|
||||
if (player.corporation === null) throw ctx.makeRuntimeErrorMsg("Must own a corporation.");
|
||||
if (player.corporation === null) throw helpers.makeRuntimeErrorMsg(ctx, "Must own a corporation.");
|
||||
if (!api) return;
|
||||
|
||||
if (!player.corporation.unlockUpgrades[api]) throw ctx.makeRuntimeErrorMsg("You do not have access to this API.");
|
||||
if (!player.corporation.unlockUpgrades[api])
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, "You do not have access to this API.");
|
||||
}
|
||||
|
||||
function getSafeDivision(division: Industry): NSDivision {
|
||||
@ -314,11 +316,11 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _amt: unknown = 1): number => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const amt = ctx.helper.number("amount", _amt);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const amt = helpers.number(ctx, "amount", _amt);
|
||||
if (amt < 1) {
|
||||
throw ctx.makeRuntimeErrorMsg("You must provide a positive number");
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, "You must provide a positive number");
|
||||
}
|
||||
const warehouse = getWarehouse(divisionName, cityName);
|
||||
return UpgradeWarehouseCost(warehouse, amt);
|
||||
@ -327,8 +329,8 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown): boolean => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const division = getDivision(divisionName);
|
||||
if (!(cityName in division.warehouses)) throw new Error(`Invalid city name '${cityName}'`);
|
||||
const warehouse = division.warehouses[cityName];
|
||||
@ -338,8 +340,8 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown): NSWarehouse => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const warehouse = getWarehouse(divisionName, cityName);
|
||||
return {
|
||||
level: warehouse.level,
|
||||
@ -353,9 +355,9 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _materialName: unknown): NSMaterial => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const materialName = ctx.helper.string("materialName", _materialName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const materialName = helpers.string(ctx, "materialName", _materialName);
|
||||
const material = getMaterial(divisionName, cityName, materialName);
|
||||
const corporation = getCorporation();
|
||||
return {
|
||||
@ -374,8 +376,8 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _productName: unknown): NSProduct => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const productName = ctx.helper.string("productName", _productName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const productName = helpers.string(ctx, "productName", _productName);
|
||||
const product = getProduct(divisionName, productName);
|
||||
const corporation = getCorporation();
|
||||
return {
|
||||
@ -401,8 +403,8 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const corporation = getCorporation();
|
||||
PurchaseWarehouse(corporation, getDivision(divisionName), cityName);
|
||||
},
|
||||
@ -410,12 +412,12 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _amt: unknown = 1): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const amt = ctx.helper.number("amount", _amt);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const amt = helpers.number(ctx, "amount", _amt);
|
||||
const corporation = getCorporation();
|
||||
if (amt < 1) {
|
||||
throw ctx.makeRuntimeErrorMsg("You must provide a positive number");
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, "You must provide a positive number");
|
||||
}
|
||||
UpgradeWarehouse(corporation, getDivision(divisionName), getWarehouse(divisionName, cityName), amt);
|
||||
},
|
||||
@ -423,11 +425,11 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _materialName: unknown, _amt: unknown, _price: unknown): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const materialName = ctx.helper.string("materialName", _materialName);
|
||||
const amt = ctx.helper.string("amt", _amt);
|
||||
const price = ctx.helper.string("price", _price);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const materialName = helpers.string(ctx, "materialName", _materialName);
|
||||
const amt = helpers.string(ctx, "amt", _amt);
|
||||
const price = helpers.string(ctx, "price", _price);
|
||||
const material = getMaterial(divisionName, cityName, materialName);
|
||||
SellMaterial(material, amt, price);
|
||||
},
|
||||
@ -442,12 +444,12 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
_all: unknown,
|
||||
): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const productName = ctx.helper.string("productName", _productName);
|
||||
const amt = ctx.helper.string("amt", _amt);
|
||||
const price = ctx.helper.string("price", _price);
|
||||
const all = ctx.helper.boolean(_all);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const productName = helpers.string(ctx, "productName", _productName);
|
||||
const amt = helpers.string(ctx, "amt", _amt);
|
||||
const price = helpers.string(ctx, "price", _price);
|
||||
const all = !!_all;
|
||||
const product = getProduct(divisionName, productName);
|
||||
SellProduct(product, cityName, amt, price, all);
|
||||
},
|
||||
@ -455,44 +457,44 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _productName: unknown): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const productName = ctx.helper.string("productName", _productName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const productName = helpers.string(ctx, "productName", _productName);
|
||||
getDivision(divisionName).discontinueProduct(getProduct(divisionName, productName));
|
||||
},
|
||||
setSmartSupply:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _enabled: unknown): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const enabled = ctx.helper.boolean(_enabled);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const enabled = !!_enabled;
|
||||
const warehouse = getWarehouse(divisionName, cityName);
|
||||
if (!hasUnlockUpgrade("Smart Supply"))
|
||||
throw ctx.makeRuntimeErrorMsg(`You have not purchased the Smart Supply upgrade!`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `You have not purchased the Smart Supply upgrade!`);
|
||||
SetSmartSupply(warehouse, enabled);
|
||||
},
|
||||
setSmartSupplyUseLeftovers:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _materialName: unknown, _enabled: unknown): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const materialName = ctx.helper.string("materialName", _materialName);
|
||||
const enabled = ctx.helper.boolean(_enabled);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const materialName = helpers.string(ctx, "materialName", _materialName);
|
||||
const enabled = !!_enabled;
|
||||
const warehouse = getWarehouse(divisionName, cityName);
|
||||
const material = getMaterial(divisionName, cityName, materialName);
|
||||
if (!hasUnlockUpgrade("Smart Supply"))
|
||||
throw ctx.makeRuntimeErrorMsg(`You have not purchased the Smart Supply upgrade!`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `You have not purchased the Smart Supply upgrade!`);
|
||||
SetSmartSupplyUseLeftovers(warehouse, material, enabled);
|
||||
},
|
||||
buyMaterial:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _materialName: unknown, _amt: unknown): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const materialName = ctx.helper.string("materialName", _materialName);
|
||||
const amt = ctx.helper.number("amt", _amt);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const materialName = helpers.string(ctx, "materialName", _materialName);
|
||||
const amt = helpers.number(ctx, "amt", _amt);
|
||||
if (amt < 0) throw new Error("Invalid value for amount field! Must be numeric and greater than 0");
|
||||
const material = getMaterial(divisionName, cityName, materialName);
|
||||
BuyMaterial(material, amt);
|
||||
@ -501,13 +503,13 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _materialName: unknown, _amt: unknown): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
if (!hasResearched(getDivision(divisionName), "Bulk Purchasing"))
|
||||
throw new Error(`You have not researched Bulk Purchasing in ${divisionName}`);
|
||||
const corporation = getCorporation();
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const materialName = ctx.helper.string("materialName", _materialName);
|
||||
const amt = ctx.helper.number("amt", _amt);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const materialName = helpers.string(ctx, "materialName", _materialName);
|
||||
const amt = helpers.number(ctx, "amt", _amt);
|
||||
const warehouse = getWarehouse(divisionName, cityName);
|
||||
const material = getMaterial(divisionName, cityName, materialName);
|
||||
BulkPurchase(corporation, warehouse, material, amt);
|
||||
@ -522,11 +524,11 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
_marketingInvest: unknown,
|
||||
): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const productName = ctx.helper.string("productName", _productName);
|
||||
const designInvest = ctx.helper.number("designInvest", _designInvest);
|
||||
const marketingInvest = ctx.helper.number("marketingInvest", _marketingInvest);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const productName = helpers.string(ctx, "productName", _productName);
|
||||
const designInvest = helpers.number(ctx, "designInvest", _designInvest);
|
||||
const marketingInvest = helpers.number(ctx, "marketingInvest", _marketingInvest);
|
||||
const corporation = getCorporation();
|
||||
MakeProduct(corporation, getDivision(divisionName), cityName, productName, designInvest, marketingInvest);
|
||||
},
|
||||
@ -534,10 +536,10 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _productName: unknown, _cityName: unknown, _qty: unknown): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const productName = ctx.helper.string("productName", _productName);
|
||||
const qty = ctx.helper.number("qty", _qty);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const productName = helpers.string(ctx, "productName", _productName);
|
||||
const qty = helpers.number(ctx, "qty", _qty);
|
||||
LimitProductProduction(getProduct(divisionName, productName), cityName, qty);
|
||||
},
|
||||
exportMaterial:
|
||||
@ -551,12 +553,12 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
_amt: unknown,
|
||||
): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const sourceDivision = ctx.helper.string("sourceDivision", _sourceDivision);
|
||||
const sourceCity = ctx.helper.string("sourceCity", _sourceCity);
|
||||
const targetDivision = ctx.helper.string("targetDivision", _targetDivision);
|
||||
const targetCity = ctx.helper.string("targetCity", _targetCity);
|
||||
const materialName = ctx.helper.string("materialName", _materialName);
|
||||
const amt = ctx.helper.string("amt", _amt);
|
||||
const sourceDivision = helpers.string(ctx, "sourceDivision", _sourceDivision);
|
||||
const sourceCity = helpers.string(ctx, "sourceCity", _sourceCity);
|
||||
const targetDivision = helpers.string(ctx, "targetDivision", _targetDivision);
|
||||
const targetCity = helpers.string(ctx, "targetCity", _targetCity);
|
||||
const materialName = helpers.string(ctx, "materialName", _materialName);
|
||||
const amt = helpers.string(ctx, "amt", _amt);
|
||||
ExportMaterial(
|
||||
targetDivision,
|
||||
targetCity,
|
||||
@ -576,12 +578,12 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
_amt: unknown,
|
||||
): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const sourceDivision = ctx.helper.string("sourceDivision", _sourceDivision);
|
||||
const sourceCity = ctx.helper.string("sourceCity", _sourceCity);
|
||||
const targetDivision = ctx.helper.string("targetDivision", _targetDivision);
|
||||
const targetCity = ctx.helper.string("targetCity", _targetCity);
|
||||
const materialName = ctx.helper.string("materialName", _materialName);
|
||||
const amt = ctx.helper.string("amt", _amt);
|
||||
const sourceDivision = helpers.string(ctx, "sourceDivision", _sourceDivision);
|
||||
const sourceCity = helpers.string(ctx, "sourceCity", _sourceCity);
|
||||
const targetDivision = helpers.string(ctx, "targetDivision", _targetDivision);
|
||||
const targetCity = helpers.string(ctx, "targetCity", _targetCity);
|
||||
const materialName = helpers.string(ctx, "materialName", _materialName);
|
||||
const amt = helpers.string(ctx, "amt", _amt);
|
||||
CancelExportMaterial(
|
||||
targetDivision,
|
||||
targetCity,
|
||||
@ -593,56 +595,56 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _materialName: unknown, _qty: unknown): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const materialName = ctx.helper.string("materialName", _materialName);
|
||||
const qty = ctx.helper.number("qty", _qty);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const materialName = helpers.string(ctx, "materialName", _materialName);
|
||||
const qty = helpers.number(ctx, "qty", _qty);
|
||||
LimitMaterialProduction(getMaterial(divisionName, cityName, materialName), qty);
|
||||
},
|
||||
setMaterialMarketTA1:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _materialName: unknown, _on: unknown): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const materialName = ctx.helper.string("materialName", _materialName);
|
||||
const on = ctx.helper.boolean(_on);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const materialName = helpers.string(ctx, "materialName", _materialName);
|
||||
const on = !!_on;
|
||||
if (!getDivision(divisionName).hasResearch("Market-TA.I"))
|
||||
throw ctx.makeRuntimeErrorMsg(`You have not researched MarketTA.I for division: ${divisionName}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `You have not researched MarketTA.I for division: ${divisionName}`);
|
||||
SetMaterialMarketTA1(getMaterial(divisionName, cityName, materialName), on);
|
||||
},
|
||||
setMaterialMarketTA2:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _materialName: unknown, _on: unknown): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const materialName = ctx.helper.string("materialName", _materialName);
|
||||
const on = ctx.helper.boolean(_on);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const materialName = helpers.string(ctx, "materialName", _materialName);
|
||||
const on = !!_on;
|
||||
if (!getDivision(divisionName).hasResearch("Market-TA.II"))
|
||||
throw ctx.makeRuntimeErrorMsg(`You have not researched MarketTA.II for division: ${divisionName}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `You have not researched MarketTA.II for division: ${divisionName}`);
|
||||
SetMaterialMarketTA2(getMaterial(divisionName, cityName, materialName), on);
|
||||
},
|
||||
setProductMarketTA1:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _productName: unknown, _on: unknown): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const productName = ctx.helper.string("productName", _productName);
|
||||
const on = ctx.helper.boolean(_on);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const productName = helpers.string(ctx, "productName", _productName);
|
||||
const on = !!_on;
|
||||
if (!getDivision(divisionName).hasResearch("Market-TA.I"))
|
||||
throw ctx.makeRuntimeErrorMsg(`You have not researched MarketTA.I for division: ${divisionName}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `You have not researched MarketTA.I for division: ${divisionName}`);
|
||||
SetProductMarketTA1(getProduct(divisionName, productName), on);
|
||||
},
|
||||
setProductMarketTA2:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _productName: unknown, _on: unknown): void => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const productName = ctx.helper.string("productName", _productName);
|
||||
const on = ctx.helper.boolean(_on);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const productName = helpers.string(ctx, "productName", _productName);
|
||||
const on = !!_on;
|
||||
if (!getDivision(divisionName).hasResearch("Market-TA.II"))
|
||||
throw ctx.makeRuntimeErrorMsg(`You have not researched MarketTA.II for division: ${divisionName}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `You have not researched MarketTA.II for division: ${divisionName}`);
|
||||
SetProductMarketTA2(getProduct(divisionName, productName), on);
|
||||
},
|
||||
};
|
||||
@ -652,7 +654,7 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown): number => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const division = getDivision(divisionName);
|
||||
return division.getAdVertCost();
|
||||
},
|
||||
@ -660,7 +662,7 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown): number => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const division = getDivision(divisionName);
|
||||
return division.numAdVerts;
|
||||
},
|
||||
@ -668,25 +670,25 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _researchName: unknown): number => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const researchName = ctx.helper.string("researchName", _researchName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const researchName = helpers.string(ctx, "researchName", _researchName);
|
||||
return getResearchCost(getDivision(divisionName), researchName);
|
||||
},
|
||||
hasResearched:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _researchName: unknown): boolean => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const researchName = ctx.helper.string("researchName", _researchName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const researchName = helpers.string(ctx, "researchName", _researchName);
|
||||
return hasResearched(getDivision(divisionName), researchName);
|
||||
},
|
||||
getOfficeSizeUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _size: unknown): number => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const size = ctx.helper.number("size", _size);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const size = helpers.number(ctx, "size", _size);
|
||||
if (size < 0) throw new Error("Invalid value for size field! Must be numeric and greater than 0");
|
||||
const office = getOffice(divisionName, cityName);
|
||||
const initialPriceMult = Math.round(office.size / CorporationConstants.OfficeInitialSize);
|
||||
@ -701,10 +703,10 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _employeeName: unknown, _job: unknown): void => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const employeeName = ctx.helper.string("employeeName", _employeeName);
|
||||
const job = ctx.helper.string("job", _job);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const employeeName = helpers.string(ctx, "employeeName", _employeeName);
|
||||
const job = helpers.string(ctx, "job", _job);
|
||||
|
||||
if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`);
|
||||
const office = getOffice(divisionName, cityName);
|
||||
@ -715,10 +717,10 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _job: unknown, _amount: unknown): boolean => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const amount = ctx.helper.number("amount", _amount);
|
||||
const job = ctx.helper.string("job", _job);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const amount = helpers.number(ctx, "amount", _amount);
|
||||
const job = helpers.string(ctx, "job", _job);
|
||||
|
||||
if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`);
|
||||
const office = getOffice(divisionName, cityName);
|
||||
@ -729,8 +731,8 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown): NSEmployee | undefined => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const office = getOffice(divisionName, cityName);
|
||||
const employee = office.hireRandomEmployee();
|
||||
if (employee === undefined) return undefined;
|
||||
@ -753,9 +755,9 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _size: unknown): void => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const size = ctx.helper.number("size", _size);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const size = helpers.number(ctx, "size", _size);
|
||||
if (size < 0) throw new Error("Invalid value for size field! Must be numeric and greater than 0");
|
||||
const office = getOffice(divisionName, cityName);
|
||||
const corporation = getCorporation();
|
||||
@ -765,9 +767,9 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _costPerEmployee: unknown): number => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const costPerEmployee = ctx.helper.number("costPerEmployee", _costPerEmployee);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const costPerEmployee = helpers.number(ctx, "costPerEmployee", _costPerEmployee);
|
||||
|
||||
if (costPerEmployee < 0) {
|
||||
throw new Error("Invalid value for Cost Per Employee field! Must be numeric and greater than 0");
|
||||
@ -782,8 +784,8 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown): boolean => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
|
||||
const corporation = getCorporation();
|
||||
const office = getOffice(divisionName, cityName);
|
||||
@ -794,7 +796,7 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown): void => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const corporation = getCorporation();
|
||||
HireAdVert(corporation, getDivision(divisionName));
|
||||
},
|
||||
@ -802,16 +804,16 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _researchName: unknown): void => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const researchName = ctx.helper.string("researchName", _researchName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const researchName = helpers.string(ctx, "researchName", _researchName);
|
||||
Research(getDivision(divisionName), researchName);
|
||||
},
|
||||
getOffice:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown): NSOffice => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const office = getOffice(divisionName, cityName);
|
||||
return {
|
||||
loc: office.loc,
|
||||
@ -847,9 +849,9 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown, _employeeName: unknown): NSEmployee => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const employeeName = ctx.helper.string("employeeName", _employeeName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const employeeName = helpers.string(ctx, "employeeName", _employeeName);
|
||||
const employee = getEmployee(divisionName, cityName, employeeName);
|
||||
return {
|
||||
name: employee.name,
|
||||
@ -871,12 +873,27 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
return {
|
||||
...warehouseAPI,
|
||||
...officeAPI,
|
||||
getMaterialNames: () => (): string[] => {
|
||||
return CorporationConstants.AllMaterials;
|
||||
},
|
||||
getIndustryTypes: () => (): string[] => {
|
||||
return CorporationConstants.AllIndustryTypes;
|
||||
},
|
||||
getUnlockables: () => (): string[] => {
|
||||
return CorporationConstants.AllUnlocks;
|
||||
},
|
||||
getUpgradeNames: () => (): string[] => {
|
||||
return CorporationConstants.AllUpgrades;
|
||||
},
|
||||
getResearchNames: () => (): string[] => {
|
||||
return CorporationConstants.AllResearch;
|
||||
},
|
||||
expandIndustry:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_industryName: unknown, _divisionName: unknown): void => {
|
||||
checkAccess(ctx);
|
||||
const industryName = ctx.helper.string("industryName", _industryName);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const industryName = helpers.string(ctx, "industryName", _industryName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const corporation = getCorporation();
|
||||
NewIndustry(corporation, industryName, divisionName);
|
||||
},
|
||||
@ -884,8 +901,8 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown, _cityName: unknown): void => {
|
||||
checkAccess(ctx);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const cityName = ctx.helper.city("cityName", _cityName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
if (!CorporationConstants.Cities.includes(cityName)) throw new Error("Invalid city name");
|
||||
const corporation = getCorporation();
|
||||
const division = getDivision(divisionName);
|
||||
@ -895,7 +912,7 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_upgradeName: unknown): void => {
|
||||
checkAccess(ctx);
|
||||
const upgradeName = ctx.helper.string("upgradeName", _upgradeName);
|
||||
const upgradeName = helpers.string(ctx, "upgradeName", _upgradeName);
|
||||
const corporation = getCorporation();
|
||||
const upgrade = Object.values(CorporationUnlockUpgrades).find((upgrade) => upgrade.name === upgradeName);
|
||||
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
||||
@ -905,7 +922,7 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_upgradeName: unknown): void => {
|
||||
checkAccess(ctx);
|
||||
const upgradeName = ctx.helper.string("upgradeName", _upgradeName);
|
||||
const upgradeName = helpers.string(ctx, "upgradeName", _upgradeName);
|
||||
const corporation = getCorporation();
|
||||
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade.name === upgradeName);
|
||||
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
||||
@ -915,12 +932,12 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_rate: unknown): void => {
|
||||
checkAccess(ctx);
|
||||
const rate = ctx.helper.number("rate", _rate);
|
||||
const rate = helpers.number(ctx, "rate", _rate);
|
||||
const max = CorporationConstants.DividendMaxRate;
|
||||
if (rate < 0 || rate > max)
|
||||
throw new Error(`Invalid value for rate field! Must be numeric, greater than 0, and less than ${max}`);
|
||||
const corporation = getCorporation();
|
||||
if (!corporation.public) throw ctx.makeRuntimeErrorMsg(`Your company has not gone public!`);
|
||||
if (!corporation.public) throw helpers.makeRuntimeErrorMsg(ctx, `Your company has not gone public!`);
|
||||
IssueDividends(corporation, rate);
|
||||
},
|
||||
|
||||
@ -930,7 +947,7 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_divisionName: unknown): NSDivision => {
|
||||
checkAccess(ctx);
|
||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const division = getDivision(divisionName);
|
||||
return getSafeDivision(division);
|
||||
},
|
||||
@ -958,43 +975,43 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
createCorporation:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_corporationName: unknown, _selfFund: unknown = true): boolean => {
|
||||
const corporationName = ctx.helper.string("corporationName", _corporationName);
|
||||
const selfFund = ctx.helper.boolean(_selfFund);
|
||||
const corporationName = helpers.string(ctx, "corporationName", _corporationName);
|
||||
const selfFund = !_selfFund;
|
||||
return createCorporation(corporationName, selfFund);
|
||||
},
|
||||
hasUnlockUpgrade:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_upgradeName: unknown): boolean => {
|
||||
checkAccess(ctx);
|
||||
const upgradeName = ctx.helper.string("upgradeName", _upgradeName);
|
||||
const upgradeName = helpers.string(ctx, "upgradeName", _upgradeName);
|
||||
return hasUnlockUpgrade(upgradeName);
|
||||
},
|
||||
getUnlockUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_upgradeName: unknown): number => {
|
||||
checkAccess(ctx);
|
||||
const upgradeName = ctx.helper.string("upgradeName", _upgradeName);
|
||||
const upgradeName = helpers.string(ctx, "upgradeName", _upgradeName);
|
||||
return getUnlockUpgradeCost(upgradeName);
|
||||
},
|
||||
getUpgradeLevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_upgradeName: unknown): number => {
|
||||
checkAccess(ctx);
|
||||
const upgradeName = ctx.helper.string("upgradeName", _upgradeName);
|
||||
const upgradeName = helpers.string(ctx, "upgradeName", _upgradeName);
|
||||
return getUpgradeLevel(ctx, upgradeName);
|
||||
},
|
||||
getUpgradeLevelCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_upgradeName: unknown): number => {
|
||||
checkAccess(ctx);
|
||||
const upgradeName = ctx.helper.string("upgradeName", _upgradeName);
|
||||
const upgradeName = helpers.string(ctx, "upgradeName", _upgradeName);
|
||||
return getUpgradeLevelCost(ctx, upgradeName);
|
||||
},
|
||||
getExpandIndustryCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_industryName: unknown): number => {
|
||||
checkAccess(ctx);
|
||||
const industryName = ctx.helper.string("industryName", _industryName);
|
||||
const industryName = helpers.string(ctx, "industryName", _industryName);
|
||||
return getExpandIndustryCost(industryName);
|
||||
},
|
||||
getExpandCityCost: (ctx: NetscriptContext) => (): number => {
|
||||
@ -1013,29 +1030,29 @@ export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation
|
||||
(ctx: NetscriptContext) =>
|
||||
(_numShares: unknown): boolean => {
|
||||
checkAccess(ctx);
|
||||
const numShares = ctx.helper.number("numShares", _numShares);
|
||||
const numShares = helpers.number(ctx, "numShares", _numShares);
|
||||
return goPublic(numShares);
|
||||
},
|
||||
sellShares:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_numShares: unknown): number => {
|
||||
checkAccess(ctx);
|
||||
const numShares = ctx.helper.number("numShares", _numShares);
|
||||
const numShares = helpers.number(ctx, "numShares", _numShares);
|
||||
return SellShares(getCorporation(), player, numShares);
|
||||
},
|
||||
buyBackShares:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_numShares: unknown): boolean => {
|
||||
checkAccess(ctx);
|
||||
const numShares = ctx.helper.number("numShares", _numShares);
|
||||
const numShares = helpers.number(ctx, "numShares", _numShares);
|
||||
return BuyBackShares(getCorporation(), player, numShares);
|
||||
},
|
||||
bribe:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_factionName: unknown, _amountCash: unknown): boolean => {
|
||||
checkAccess(ctx);
|
||||
const factionName = ctx.helper.string("factionName", _factionName);
|
||||
const amountCash = ctx.helper.number("amountCash", _amountCash);
|
||||
const factionName = helpers.string(ctx, "factionName", _factionName);
|
||||
const amountCash = helpers.number(ctx, "amountCash", _amountCash);
|
||||
return bribe(factionName, amountCash);
|
||||
},
|
||||
getBonusTime: (ctx: NetscriptContext) => (): number => {
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player as player } from "../Player";
|
||||
import { Exploit } from "../Exploits/Exploit";
|
||||
import * as bcrypt from "bcryptjs";
|
||||
import { Apr1Events as devMenu } from "../ui/Apr1";
|
||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
|
||||
export interface INetscriptExtra {
|
||||
heart: {
|
||||
@ -15,7 +16,7 @@ export interface INetscriptExtra {
|
||||
rainbow(guess: string): void;
|
||||
}
|
||||
|
||||
export function NetscriptExtra(player: IPlayer): InternalAPI<INetscriptExtra> {
|
||||
export function NetscriptExtra(): InternalAPI<INetscriptExtra> {
|
||||
return {
|
||||
heart: {
|
||||
// Easter egg function
|
||||
@ -67,7 +68,7 @@ export function NetscriptExtra(player: IPlayer): InternalAPI<INetscriptExtra> {
|
||||
function tryGuess(): boolean {
|
||||
// eslint-disable-next-line no-sync
|
||||
const verified = bcrypt.compareSync(
|
||||
ctx.helper.string("guess", guess),
|
||||
helpers.string(ctx, "guess", guess),
|
||||
"$2a$10$aertxDEkgor8baVtQDZsLuMwwGYmkRM/ohcA6FjmmzIHQeTCsrCcO",
|
||||
);
|
||||
if (verified) {
|
||||
|
@ -1,12 +1,13 @@
|
||||
import { toNative } from "./toNative";
|
||||
import libarg from "arg";
|
||||
import { ScriptArg } from "../Netscript/ScriptArg";
|
||||
import { NetscriptContext } from "../Netscript/APIWrapper";
|
||||
|
||||
type FlagType = StringConstructor | NumberConstructor | BooleanConstructor | StringConstructor[];
|
||||
type FlagsRet = { [key: string]: ScriptArg };
|
||||
export function Flags(vargs: string[]): () => (data: unknown) => FlagsRet {
|
||||
return (/* ctx: NetscriptContext */) =>
|
||||
(schema: unknown): FlagsRet => {
|
||||
export function Flags(ctx: NetscriptContext | string[]): (data: unknown) => FlagsRet {
|
||||
const vargs = Array.isArray(ctx) ? ctx : ctx.workerScript.args;
|
||||
return (schema: unknown): FlagsRet => {
|
||||
schema = toNative(schema);
|
||||
if (!Array.isArray(schema)) throw new Error("flags schema passed in is invalid.");
|
||||
const args: {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player as player } from "../Player";
|
||||
import { calculateServerGrowth } from "../Server/formulas/grow";
|
||||
import {
|
||||
calculateMoneyGainRate,
|
||||
@ -43,11 +42,12 @@ import {
|
||||
import { favorToRep as calculateFavorToRep, repToFavor as calculateRepToFavor } from "../Faction/formulas/favor";
|
||||
import { repFromDonation } from "../Faction/formulas/donation";
|
||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
|
||||
export function NetscriptFormulas(player: IPlayer, helper: INetscriptHelper): InternalAPI<IFormulas> {
|
||||
export function NetscriptFormulas(): InternalAPI<IFormulas> {
|
||||
const checkFormulasAccess = function (ctx: NetscriptContext): void {
|
||||
if (!player.hasProgram(Programs.Formulas.name)) {
|
||||
throw helper.makeRuntimeErrorMsg(`formulas.${ctx.function}`, `Requires Formulas.exe to run.`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Requires Formulas.exe to run.`);
|
||||
}
|
||||
};
|
||||
return {
|
||||
@ -55,22 +55,22 @@ export function NetscriptFormulas(player: IPlayer, helper: INetscriptHelper): In
|
||||
calculateFavorToRep:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_favor: unknown): number => {
|
||||
const favor = ctx.helper.number("favor", _favor);
|
||||
const favor = helpers.number(ctx, "favor", _favor);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateFavorToRep(favor);
|
||||
},
|
||||
calculateRepToFavor:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_rep: unknown): number => {
|
||||
const rep = ctx.helper.number("rep", _rep);
|
||||
const rep = helpers.number(ctx, "rep", _rep);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateRepToFavor(rep);
|
||||
},
|
||||
repFromDonation:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_amount: unknown, _player: unknown): number => {
|
||||
const amount = ctx.helper.number("amount", _amount);
|
||||
const player = ctx.helper.player(_player);
|
||||
const amount = helpers.number(ctx, "amount", _amount);
|
||||
const player = helpers.player(ctx, _player);
|
||||
checkFormulasAccess(ctx);
|
||||
return repFromDonation(amount, player);
|
||||
},
|
||||
@ -79,16 +79,16 @@ export function NetscriptFormulas(player: IPlayer, helper: INetscriptHelper): In
|
||||
calculateSkill:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_exp: unknown, _mult: unknown = 1): number => {
|
||||
const exp = ctx.helper.number("exp", _exp);
|
||||
const mult = ctx.helper.number("mult", _mult);
|
||||
const exp = helpers.number(ctx, "exp", _exp);
|
||||
const mult = helpers.number(ctx, "mult", _mult);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateSkill(exp, mult);
|
||||
},
|
||||
calculateExp:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_skill: unknown, _mult: unknown = 1): number => {
|
||||
const skill = ctx.helper.number("skill", _skill);
|
||||
const mult = ctx.helper.number("mult", _mult);
|
||||
const skill = helpers.number(ctx, "skill", _skill);
|
||||
const mult = helpers.number(ctx, "mult", _mult);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateExp(skill, mult);
|
||||
},
|
||||
@ -97,58 +97,58 @@ export function NetscriptFormulas(player: IPlayer, helper: INetscriptHelper): In
|
||||
hackChance:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_server: unknown, _player: unknown): number => {
|
||||
const server = ctx.helper.server(_server);
|
||||
const player = ctx.helper.player(_player);
|
||||
const server = helpers.server(ctx, _server);
|
||||
const player = helpers.player(ctx, _player);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateHackingChance(server, player);
|
||||
},
|
||||
hackExp:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_server: unknown, _player: unknown): number => {
|
||||
const server = ctx.helper.server(_server);
|
||||
const player = ctx.helper.player(_player);
|
||||
const server = helpers.server(ctx, _server);
|
||||
const player = helpers.player(ctx, _player);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateHackingExpGain(server, player);
|
||||
},
|
||||
hackPercent:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_server: unknown, _player: unknown): number => {
|
||||
const server = ctx.helper.server(_server);
|
||||
const player = ctx.helper.player(_player);
|
||||
const server = helpers.server(ctx, _server);
|
||||
const player = helpers.player(ctx, _player);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculatePercentMoneyHacked(server, player);
|
||||
},
|
||||
growPercent:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_server: unknown, _threads: unknown, _player: unknown, _cores: unknown = 1): number => {
|
||||
const server = ctx.helper.server(_server);
|
||||
const player = ctx.helper.player(_player);
|
||||
const threads = ctx.helper.number("threads", _threads);
|
||||
const cores = ctx.helper.number("cores", _cores);
|
||||
const server = helpers.server(ctx, _server);
|
||||
const player = helpers.player(ctx, _player);
|
||||
const threads = helpers.number(ctx, "threads", _threads);
|
||||
const cores = helpers.number(ctx, "cores", _cores);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateServerGrowth(server, threads, player, cores);
|
||||
},
|
||||
hackTime:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_server: unknown, _player: unknown): number => {
|
||||
const server = ctx.helper.server(_server);
|
||||
const player = ctx.helper.player(_player);
|
||||
const server = helpers.server(ctx, _server);
|
||||
const player = helpers.player(ctx, _player);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateHackingTime(server, player) * 1000;
|
||||
},
|
||||
growTime:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_server: unknown, _player: unknown): number => {
|
||||
const server = ctx.helper.server(_server);
|
||||
const player = ctx.helper.player(_player);
|
||||
const server = helpers.server(ctx, _server);
|
||||
const player = helpers.player(ctx, _player);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateGrowTime(server, player) * 1000;
|
||||
},
|
||||
weakenTime:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_server: unknown, _player: unknown): number => {
|
||||
const server = ctx.helper.server(_server);
|
||||
const player = ctx.helper.player(_player);
|
||||
const server = helpers.server(ctx, _server);
|
||||
const player = helpers.player(ctx, _player);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateWeakenTime(server, player) * 1000;
|
||||
},
|
||||
@ -157,45 +157,45 @@ export function NetscriptFormulas(player: IPlayer, helper: INetscriptHelper): In
|
||||
moneyGainRate:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_level: unknown, _ram: unknown, _cores: unknown, _mult: unknown = 1): number => {
|
||||
const level = ctx.helper.number("level", _level);
|
||||
const ram = ctx.helper.number("ram", _ram);
|
||||
const cores = ctx.helper.number("cores", _cores);
|
||||
const mult = ctx.helper.number("mult", _mult);
|
||||
const level = helpers.number(ctx, "level", _level);
|
||||
const ram = helpers.number(ctx, "ram", _ram);
|
||||
const cores = helpers.number(ctx, "cores", _cores);
|
||||
const mult = helpers.number(ctx, "mult", _mult);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateMoneyGainRate(level, ram, cores, mult);
|
||||
},
|
||||
levelUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_startingLevel: unknown, _extraLevels: unknown = 1, _costMult: unknown = 1): number => {
|
||||
const startingLevel = ctx.helper.number("startingLevel", _startingLevel);
|
||||
const extraLevels = ctx.helper.number("extraLevels", _extraLevels);
|
||||
const costMult = ctx.helper.number("costMult", _costMult);
|
||||
const startingLevel = helpers.number(ctx, "startingLevel", _startingLevel);
|
||||
const extraLevels = helpers.number(ctx, "extraLevels", _extraLevels);
|
||||
const costMult = helpers.number(ctx, "costMult", _costMult);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateLevelUpgradeCost(startingLevel, extraLevels, costMult);
|
||||
},
|
||||
ramUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_startingRam: unknown, _extraLevels: unknown = 1, _costMult: unknown = 1): number => {
|
||||
const startingRam = ctx.helper.number("startingRam", _startingRam);
|
||||
const extraLevels = ctx.helper.number("extraLevels", _extraLevels);
|
||||
const costMult = ctx.helper.number("costMult", _costMult);
|
||||
const startingRam = helpers.number(ctx, "startingRam", _startingRam);
|
||||
const extraLevels = helpers.number(ctx, "extraLevels", _extraLevels);
|
||||
const costMult = helpers.number(ctx, "costMult", _costMult);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateRamUpgradeCost(startingRam, extraLevels, costMult);
|
||||
},
|
||||
coreUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_startingCore: unknown, _extraCores: unknown = 1, _costMult: unknown = 1): number => {
|
||||
const startingCore = ctx.helper.number("startingCore", _startingCore);
|
||||
const extraCores = ctx.helper.number("extraCores", _extraCores);
|
||||
const costMult = ctx.helper.number("costMult", _costMult);
|
||||
const startingCore = helpers.number(ctx, "startingCore", _startingCore);
|
||||
const extraCores = helpers.number(ctx, "extraCores", _extraCores);
|
||||
const costMult = helpers.number(ctx, "costMult", _costMult);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateCoreUpgradeCost(startingCore, extraCores, costMult);
|
||||
},
|
||||
hacknetNodeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_n: unknown, _mult: unknown): number => {
|
||||
const n = ctx.helper.number("n", _n);
|
||||
const mult = ctx.helper.number("mult", _mult);
|
||||
const n = helpers.number(ctx, "n", _n);
|
||||
const mult = helpers.number(ctx, "mult", _mult);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateNodeCost(n, mult);
|
||||
},
|
||||
@ -208,69 +208,66 @@ export function NetscriptFormulas(player: IPlayer, helper: INetscriptHelper): In
|
||||
hashGainRate:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_level: unknown, _ramUsed: unknown, _maxRam: unknown, _cores: unknown, _mult: unknown = 1): number => {
|
||||
const level = ctx.helper.number("level", _level);
|
||||
const ramUsed = ctx.helper.number("ramUsed", _ramUsed);
|
||||
const maxRam = ctx.helper.number("maxRam", _maxRam);
|
||||
const cores = ctx.helper.number("cores", _cores);
|
||||
const mult = ctx.helper.number("mult", _mult);
|
||||
const level = helpers.number(ctx, "level", _level);
|
||||
const ramUsed = helpers.number(ctx, "ramUsed", _ramUsed);
|
||||
const maxRam = helpers.number(ctx, "maxRam", _maxRam);
|
||||
const cores = helpers.number(ctx, "cores", _cores);
|
||||
const mult = helpers.number(ctx, "mult", _mult);
|
||||
checkFormulasAccess(ctx);
|
||||
return HScalculateHashGainRate(level, ramUsed, maxRam, cores, mult);
|
||||
},
|
||||
levelUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_startingLevel: unknown, _extraLevels: unknown = 1, _costMult: unknown = 1): number => {
|
||||
const startingLevel = ctx.helper.number("startingLevel", _startingLevel);
|
||||
const extraLevels = ctx.helper.number("extraLevels", _extraLevels);
|
||||
const costMult = ctx.helper.number("costMult", _costMult);
|
||||
const startingLevel = helpers.number(ctx, "startingLevel", _startingLevel);
|
||||
const extraLevels = helpers.number(ctx, "extraLevels", _extraLevels);
|
||||
const costMult = helpers.number(ctx, "costMult", _costMult);
|
||||
checkFormulasAccess(ctx);
|
||||
return HScalculateLevelUpgradeCost(startingLevel, extraLevels, costMult);
|
||||
},
|
||||
ramUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_startingRam: unknown, _extraLevels: unknown = 1, _costMult: unknown = 1): number => {
|
||||
const startingRam = ctx.helper.number("startingRam", _startingRam);
|
||||
const extraLevels = ctx.helper.number("extraLevels", _extraLevels);
|
||||
const costMult = ctx.helper.number("costMult", _costMult);
|
||||
const startingRam = helpers.number(ctx, "startingRam", _startingRam);
|
||||
const extraLevels = helpers.number(ctx, "extraLevels", _extraLevels);
|
||||
const costMult = helpers.number(ctx, "costMult", _costMult);
|
||||
checkFormulasAccess(ctx);
|
||||
return HScalculateRamUpgradeCost(startingRam, extraLevels, costMult);
|
||||
},
|
||||
coreUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_startingCore: unknown, _extraCores: unknown = 1, _costMult: unknown = 1): number => {
|
||||
const startingCore = ctx.helper.number("startingCore", _startingCore);
|
||||
const extraCores = ctx.helper.number("extraCores", _extraCores);
|
||||
const costMult = ctx.helper.number("costMult", _costMult);
|
||||
const startingCore = helpers.number(ctx, "startingCore", _startingCore);
|
||||
const extraCores = helpers.number(ctx, "extraCores", _extraCores);
|
||||
const costMult = helpers.number(ctx, "costMult", _costMult);
|
||||
checkFormulasAccess(ctx);
|
||||
return HScalculateCoreUpgradeCost(startingCore, extraCores, costMult);
|
||||
},
|
||||
cacheUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_startingCache: unknown, _extraCache: unknown = 1): number => {
|
||||
const startingCache = ctx.helper.number("startingCache", _startingCache);
|
||||
const extraCache = ctx.helper.number("extraCache", _extraCache);
|
||||
const startingCache = helpers.number(ctx, "startingCache", _startingCache);
|
||||
const extraCache = helpers.number(ctx, "extraCache", _extraCache);
|
||||
checkFormulasAccess(ctx);
|
||||
return HScalculateCacheUpgradeCost(startingCache, extraCache);
|
||||
},
|
||||
hashUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_upgName: unknown, _level: unknown): number => {
|
||||
const upgName = helper.string("hashUpgradeCost", "upgName", _upgName);
|
||||
const level = ctx.helper.number("level", _level);
|
||||
const upgName = helpers.string(ctx, "upgName", _upgName);
|
||||
const level = helpers.number(ctx, "level", _level);
|
||||
checkFormulasAccess(ctx);
|
||||
const upg = player.hashManager.getUpgrade(upgName);
|
||||
if (!upg) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"formulas.hacknetServers.calculateHashUpgradeCost",
|
||||
`Invalid Hash Upgrade: ${upgName}`,
|
||||
);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid Hash Upgrade: ${upgName}`);
|
||||
}
|
||||
return upg.getCost(level);
|
||||
},
|
||||
hacknetServerCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_n: unknown, _mult: unknown = 1): number => {
|
||||
const n = ctx.helper.number("n", _n);
|
||||
const mult = ctx.helper.number("mult", _mult);
|
||||
const n = helpers.number(ctx, "n", _n);
|
||||
const mult = helpers.number(ctx, "mult", _mult);
|
||||
checkFormulasAccess(ctx);
|
||||
return HScalculateServerCost(n, mult);
|
||||
},
|
||||
@ -283,48 +280,48 @@ export function NetscriptFormulas(player: IPlayer, helper: INetscriptHelper): In
|
||||
wantedPenalty:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_gang: unknown): number => {
|
||||
const gang = ctx.helper.gang(_gang);
|
||||
const gang = helpers.gang(ctx, _gang);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateWantedPenalty(gang);
|
||||
},
|
||||
respectGain:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_gang: unknown, _member: unknown, _task: unknown): number => {
|
||||
const gang = ctx.helper.gang(_gang);
|
||||
const member = ctx.helper.gangMember(_member);
|
||||
const task = ctx.helper.gangTask(_task);
|
||||
const gang = helpers.gang(ctx, _gang);
|
||||
const member = helpers.gangMember(ctx, _member);
|
||||
const task = helpers.gangTask(ctx, _task);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateRespectGain(gang, member, task);
|
||||
},
|
||||
wantedLevelGain:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_gang: unknown, _member: unknown, _task: unknown): number => {
|
||||
const gang = ctx.helper.gang(_gang);
|
||||
const member = ctx.helper.gangMember(_member);
|
||||
const task = ctx.helper.gangTask(_task);
|
||||
const gang = helpers.gang(ctx, _gang);
|
||||
const member = helpers.gangMember(ctx, _member);
|
||||
const task = helpers.gangTask(ctx, _task);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateWantedLevelGain(gang, member, task);
|
||||
},
|
||||
moneyGain:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_gang: unknown, _member: unknown, _task: unknown): number => {
|
||||
const gang = ctx.helper.gang(_gang);
|
||||
const member = ctx.helper.gangMember(_member);
|
||||
const task = ctx.helper.gangTask(_task);
|
||||
const gang = helpers.gang(ctx, _gang);
|
||||
const member = helpers.gangMember(ctx, _member);
|
||||
const task = helpers.gangTask(ctx, _task);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateMoneyGain(gang, member, task);
|
||||
},
|
||||
ascensionPointsGain:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_exp: unknown): number => {
|
||||
const exp = ctx.helper.number("exp", _exp);
|
||||
const exp = helpers.number(ctx, "exp", _exp);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateAscensionPointsGain(exp);
|
||||
},
|
||||
ascensionMultiplier:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_points: unknown): number => {
|
||||
const points = ctx.helper.number("points", _points);
|
||||
const points = helpers.number(ctx, "points", _points);
|
||||
checkFormulasAccess(ctx);
|
||||
return calculateAscensionMult(points);
|
||||
},
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { FactionNames } from "../Faction/data/FactionNames";
|
||||
import { GangConstants } from "../Gang/data/Constants";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player as player } from "../Player";
|
||||
import { Gang } from "../Gang/Gang";
|
||||
import { AllGangs } from "../Gang/AllGangs";
|
||||
import { GangMemberTasks } from "../Gang/GangMemberTasks";
|
||||
import { GangMemberUpgrades } from "../Gang/GangMemberUpgrades";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { GangMember } from "../Gang/GangMember";
|
||||
import { GangMemberTask } from "../Gang/GangMemberTask";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
|
||||
import {
|
||||
Gang as IGang,
|
||||
@ -21,13 +21,13 @@ import {
|
||||
} from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
|
||||
export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): InternalAPI<IGang> {
|
||||
export function NetscriptGang(): InternalAPI<IGang> {
|
||||
const checkGangApiAccess = function (ctx: NetscriptContext): void {
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Must have joined gang");
|
||||
const hasAccess = gang instanceof Gang;
|
||||
if (!hasAccess) {
|
||||
throw ctx.makeRuntimeErrorMsg(`You do not currently have a Gang`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `You do not currently have a Gang`);
|
||||
}
|
||||
};
|
||||
|
||||
@ -35,13 +35,13 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): Inte
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Must have joined gang");
|
||||
for (const member of gang.members) if (member.name === name) return member;
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid gang member: '${name}'`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid gang member: '${name}'`);
|
||||
};
|
||||
|
||||
const getGangTask = function (ctx: NetscriptContext, name: string): GangMemberTask {
|
||||
const task = GangMemberTasks[name];
|
||||
if (!task) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid task: '${name}'`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid task: '${name}'`);
|
||||
}
|
||||
|
||||
return task;
|
||||
@ -51,7 +51,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): Inte
|
||||
createGang:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_faction: unknown): boolean => {
|
||||
const faction = ctx.helper.string("faction", _faction);
|
||||
const faction = helpers.string(ctx, "faction", _faction);
|
||||
// this list is copied from Faction/ui/Root.tsx
|
||||
|
||||
if (!player.canAccessGang() || !GangConstants.Names.includes(faction)) return false;
|
||||
@ -102,7 +102,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): Inte
|
||||
getMemberInformation:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_memberName: unknown): GangMemberInfo => {
|
||||
const memberName = ctx.helper.string("memberName", _memberName);
|
||||
const memberName = helpers.string(ctx, "memberName", _memberName);
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
@ -163,15 +163,15 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): Inte
|
||||
recruitMember:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_memberName: unknown): boolean => {
|
||||
const memberName = ctx.helper.string("memberName", _memberName);
|
||||
const memberName = helpers.string(ctx, "memberName", _memberName);
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
const recruited = gang.recruitMember(memberName);
|
||||
if (recruited) {
|
||||
workerScript.log("gang.recruitMember", () => `Successfully recruited Gang Member '${memberName}'`);
|
||||
ctx.workerScript.log("gang.recruitMember", () => `Successfully recruited Gang Member '${memberName}'`);
|
||||
} else {
|
||||
workerScript.log("gang.recruitMember", () => `Failed to recruit Gang Member '${memberName}'`);
|
||||
ctx.workerScript.log("gang.recruitMember", () => `Failed to recruit Gang Member '${memberName}'`);
|
||||
}
|
||||
|
||||
return recruited;
|
||||
@ -187,14 +187,14 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): Inte
|
||||
setMemberTask:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_memberName: unknown, _taskName: unknown): boolean => {
|
||||
const memberName = ctx.helper.string("memberName", _memberName);
|
||||
const taskName = ctx.helper.string("taskName", _taskName);
|
||||
const memberName = helpers.string(ctx, "memberName", _memberName);
|
||||
const taskName = helpers.string(ctx, "taskName", _taskName);
|
||||
checkGangApiAccess(ctx);
|
||||
const member = getGangMember(ctx, memberName);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
if (!gang.getAllTaskNames().includes(taskName)) {
|
||||
workerScript.log(
|
||||
ctx.workerScript.log(
|
||||
"gang.setMemberTask",
|
||||
() =>
|
||||
`Failed to assign Gang Member '${memberName}' to Invalid task '${taskName}'. '${memberName}' is now Unassigned`,
|
||||
@ -203,12 +203,12 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): Inte
|
||||
}
|
||||
const success = member.assignToTask(taskName);
|
||||
if (success) {
|
||||
workerScript.log(
|
||||
ctx.workerScript.log(
|
||||
"gang.setMemberTask",
|
||||
() => `Successfully assigned Gang Member '${memberName}' to '${taskName}' task`,
|
||||
);
|
||||
} else {
|
||||
workerScript.log(
|
||||
ctx.workerScript.log(
|
||||
"gang.setMemberTask",
|
||||
() =>
|
||||
`Failed to assign Gang Member '${memberName}' to '${taskName}' task. '${memberName}' is now Unassigned`,
|
||||
@ -220,7 +220,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): Inte
|
||||
getTaskStats:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_taskName: unknown): GangTaskStats => {
|
||||
const taskName = ctx.helper.string("taskName", _taskName);
|
||||
const taskName = helpers.string(ctx, "taskName", _taskName);
|
||||
checkGangApiAccess(ctx);
|
||||
const task = getGangTask(ctx, taskName);
|
||||
const copy = Object.assign({}, task);
|
||||
@ -234,7 +234,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): Inte
|
||||
getEquipmentCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_equipName: unknown): number => {
|
||||
const equipName = ctx.helper.string("equipName", _equipName);
|
||||
const equipName = helpers.string(ctx, "equipName", _equipName);
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
@ -245,7 +245,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): Inte
|
||||
getEquipmentType:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_equipName: unknown): string => {
|
||||
const equipName = ctx.helper.string("equipName", _equipName);
|
||||
const equipName = helpers.string(ctx, "equipName", _equipName);
|
||||
checkGangApiAccess(ctx);
|
||||
const upg = GangMemberUpgrades[equipName];
|
||||
if (upg == null) return "";
|
||||
@ -254,11 +254,11 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): Inte
|
||||
getEquipmentStats:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_equipName: unknown): EquipmentStats => {
|
||||
const equipName = ctx.helper.string("equipName", _equipName);
|
||||
const equipName = helpers.string(ctx, "equipName", _equipName);
|
||||
checkGangApiAccess(ctx);
|
||||
const equipment = GangMemberUpgrades[equipName];
|
||||
if (!equipment) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid equipment: ${equipName}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid equipment: ${equipName}`);
|
||||
}
|
||||
const typecheck: EquipmentStats = equipment.mults;
|
||||
return Object.assign({}, typecheck) as any;
|
||||
@ -266,8 +266,8 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): Inte
|
||||
purchaseEquipment:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_memberName: unknown, _equipName: unknown): boolean => {
|
||||
const memberName = ctx.helper.string("memberName", _memberName);
|
||||
const equipName = ctx.helper.string("equipName", _equipName);
|
||||
const memberName = helpers.string(ctx, "memberName", _memberName);
|
||||
const equipName = helpers.string(ctx, "equipName", _equipName);
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
@ -276,9 +276,12 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): Inte
|
||||
if (!equipment) return false;
|
||||
const res = member.buyUpgrade(equipment, player, gang);
|
||||
if (res) {
|
||||
workerScript.log("gang.purchaseEquipment", () => `Purchased '${equipName}' for Gang member '${memberName}'`);
|
||||
ctx.workerScript.log(
|
||||
"gang.purchaseEquipment",
|
||||
() => `Purchased '${equipName}' for Gang member '${memberName}'`,
|
||||
);
|
||||
} else {
|
||||
workerScript.log(
|
||||
ctx.workerScript.log(
|
||||
"gang.purchaseEquipment",
|
||||
() => `Failed to purchase '${equipName}' for Gang member '${memberName}'`,
|
||||
);
|
||||
@ -289,18 +292,18 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): Inte
|
||||
ascendMember:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_memberName: unknown): GangMemberAscension | undefined => {
|
||||
const memberName = ctx.helper.string("memberName", _memberName);
|
||||
const memberName = helpers.string(ctx, "memberName", _memberName);
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
const member = getGangMember(ctx, memberName);
|
||||
if (!member.canAscend()) return;
|
||||
return gang.ascendMember(member, workerScript);
|
||||
return gang.ascendMember(member, ctx.workerScript);
|
||||
},
|
||||
getAscensionResult:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_memberName: unknown): GangMemberAscension | undefined => {
|
||||
const memberName = ctx.helper.string("memberName", _memberName);
|
||||
const memberName = helpers.string(ctx, "memberName", _memberName);
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
@ -314,27 +317,27 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): Inte
|
||||
setTerritoryWarfare:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_engage: unknown): void => {
|
||||
const engage = ctx.helper.boolean(_engage);
|
||||
const engage = !!_engage;
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
if (engage) {
|
||||
gang.territoryWarfareEngaged = true;
|
||||
workerScript.log("gang.setTerritoryWarfare", () => "Engaging in Gang Territory Warfare");
|
||||
ctx.workerScript.log("gang.setTerritoryWarfare", () => "Engaging in Gang Territory Warfare");
|
||||
} else {
|
||||
gang.territoryWarfareEngaged = false;
|
||||
workerScript.log("gang.setTerritoryWarfare", () => "Disengaging in Gang Territory Warfare");
|
||||
ctx.workerScript.log("gang.setTerritoryWarfare", () => "Disengaging in Gang Territory Warfare");
|
||||
}
|
||||
},
|
||||
getChanceToWinClash:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_otherGang: unknown): number => {
|
||||
const otherGang = ctx.helper.string("otherGang", _otherGang);
|
||||
const otherGang = helpers.string(ctx, "otherGang", _otherGang);
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
if (AllGangs[otherGang] == null) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid gang: ${otherGang}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid gang: ${otherGang}`);
|
||||
}
|
||||
|
||||
const playerPower = AllGangs[gang.facName].power;
|
||||
|
@ -4,15 +4,17 @@ import { hasAugmentationPrereqs } from "../Faction/FactionHelpers";
|
||||
import { CityName } from "../Locations/data/CityNames";
|
||||
import { GraftableAugmentation } from "../PersonObjects/Grafting/GraftableAugmentation";
|
||||
import { getGraftingAvailableAugs, calculateGraftingTimeWithBonus } from "../PersonObjects/Grafting/GraftingHelpers";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player as player } from "../Player";
|
||||
import { Grafting as IGrafting } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { Router } from "../ui/GameRoot";
|
||||
import { GraftingWork } from "../Work/GraftingWork";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
|
||||
export function NetscriptGrafting(player: IPlayer): InternalAPI<IGrafting> {
|
||||
export function NetscriptGrafting(): InternalAPI<IGrafting> {
|
||||
const checkGraftingAPIAccess = (ctx: NetscriptContext): void => {
|
||||
if (!player.canAccessGrafting()) {
|
||||
throw ctx.makeRuntimeErrorMsg(
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
"You do not currently have access to the Grafting API. This is either because you are not in BitNode 10 or because you do not have Source-File 10",
|
||||
);
|
||||
}
|
||||
@ -22,10 +24,10 @@ export function NetscriptGrafting(player: IPlayer): InternalAPI<IGrafting> {
|
||||
getAugmentationGraftPrice:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_augName: unknown): number => {
|
||||
const augName = ctx.helper.string("augName", _augName);
|
||||
const augName = helpers.string(ctx, "augName", _augName);
|
||||
checkGraftingAPIAccess(ctx);
|
||||
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid aug: ${augName}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid aug: ${augName}`);
|
||||
}
|
||||
const graftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
||||
return graftableAug.cost;
|
||||
@ -34,10 +36,10 @@ export function NetscriptGrafting(player: IPlayer): InternalAPI<IGrafting> {
|
||||
getAugmentationGraftTime:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_augName: string): number => {
|
||||
const augName = ctx.helper.string("augName", _augName);
|
||||
const augName = helpers.string(ctx, "augName", _augName);
|
||||
checkGraftingAPIAccess(ctx);
|
||||
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid aug: ${augName}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid aug: ${augName}`);
|
||||
}
|
||||
const graftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
||||
return calculateGraftingTimeWithBonus(player, graftableAug);
|
||||
@ -52,14 +54,14 @@ export function NetscriptGrafting(player: IPlayer): InternalAPI<IGrafting> {
|
||||
graftAugmentation:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_augName: string, _focus: unknown = true): boolean => {
|
||||
const augName = ctx.helper.string("augName", _augName);
|
||||
const focus = ctx.helper.boolean(_focus);
|
||||
const augName = helpers.string(ctx, "augName", _augName);
|
||||
const focus = !!_focus;
|
||||
checkGraftingAPIAccess(ctx);
|
||||
if (player.city !== CityName.NewTokyo) {
|
||||
throw ctx.makeRuntimeErrorMsg("You must be in New Tokyo to begin grafting an Augmentation.");
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, "You must be in New Tokyo to begin grafting an Augmentation.");
|
||||
}
|
||||
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||
ctx.log(() => `Invalid aug: ${augName}`);
|
||||
helpers.log(ctx, () => `Invalid aug: ${augName}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -67,12 +69,12 @@ export function NetscriptGrafting(player: IPlayer): InternalAPI<IGrafting> {
|
||||
|
||||
const craftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
||||
if (player.money < craftableAug.cost) {
|
||||
ctx.log(() => `You don't have enough money to craft ${augName}`);
|
||||
helpers.log(ctx, () => `You don't have enough money to craft ${augName}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasAugmentationPrereqs(craftableAug.augmentation)) {
|
||||
ctx.log(() => `You don't have the pre-requisites for ${augName}`);
|
||||
helpers.log(ctx, () => `You don't have the pre-requisites for ${augName}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -92,7 +94,7 @@ export function NetscriptGrafting(player: IPlayer): InternalAPI<IGrafting> {
|
||||
Router.toTerminal();
|
||||
}
|
||||
|
||||
ctx.log(() => `Began grafting Augmentation ${augName}.`);
|
||||
helpers.log(ctx, () => `Began grafting Augmentation ${augName}.`);
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { Player as player } from "../Player";
|
||||
import { HacknetServerConstants } from "../Hacknet/data/Constants";
|
||||
import {
|
||||
getCostOfNextHacknetNode,
|
||||
@ -21,12 +20,13 @@ import { GetServer } from "../Server/AllServers";
|
||||
|
||||
import { Hacknet as IHacknet, NodeStats } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
|
||||
export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript): InternalAPI<IHacknet> {
|
||||
export function NetscriptHacknet(): InternalAPI<IHacknet> {
|
||||
// Utility function to get Hacknet Node object
|
||||
const getHacknetNode = function (ctx: NetscriptContext, i: number): HacknetNode | HacknetServer {
|
||||
if (i < 0 || i >= player.hacknetNodes.length) {
|
||||
throw ctx.makeRuntimeErrorMsg("Index specified for Hacknet Node is out-of-bounds: " + i);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, "Index specified for Hacknet Node is out-of-bounds: " + i);
|
||||
}
|
||||
|
||||
if (hasHacknetServers(player)) {
|
||||
@ -35,7 +35,8 @@ export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript): I
|
||||
const hserver = GetServer(hi);
|
||||
if (!(hserver instanceof HacknetServer)) throw new Error("hacknet server was not actually hacknet server");
|
||||
if (hserver == null) {
|
||||
throw ctx.makeRuntimeErrorMsg(
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
`Could not get Hacknet Server for index ${i}. This is probably a bug, please report to game dev`,
|
||||
);
|
||||
}
|
||||
@ -71,7 +72,7 @@ export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript): I
|
||||
getNodeStats:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown): NodeStats => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const i = helpers.number(ctx, "i", _i);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
const hasUpgraded = hasHacknetServers(player);
|
||||
const res: NodeStats = {
|
||||
@ -95,38 +96,38 @@ export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript): I
|
||||
upgradeLevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): boolean => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const n = ctx.helper.number("n", _n);
|
||||
const i = helpers.number(ctx, "i", _i);
|
||||
const n = helpers.number(ctx, "n", _n);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
return purchaseLevelUpgrade(player, node, n);
|
||||
},
|
||||
upgradeRam:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): boolean => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const n = ctx.helper.number("n", _n);
|
||||
const i = helpers.number(ctx, "i", _i);
|
||||
const n = helpers.number(ctx, "n", _n);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
return purchaseRamUpgrade(player, node, n);
|
||||
},
|
||||
upgradeCore:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): boolean => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const n = ctx.helper.number("n", _n);
|
||||
const i = helpers.number(ctx, "i", _i);
|
||||
const n = helpers.number(ctx, "n", _n);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
return purchaseCoreUpgrade(player, node, n);
|
||||
},
|
||||
upgradeCache:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): boolean => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const n = ctx.helper.number("n", _n);
|
||||
const i = helpers.number(ctx, "i", _i);
|
||||
const n = helpers.number(ctx, "n", _n);
|
||||
if (!hasHacknetServers(player)) {
|
||||
return false;
|
||||
}
|
||||
const node = getHacknetNode(ctx, i);
|
||||
if (!(node instanceof HacknetServer)) {
|
||||
workerScript.log("hacknet.upgradeCache", () => "Can only be called on hacknet servers");
|
||||
helpers.log(ctx, () => "Can only be called on hacknet servers");
|
||||
return false;
|
||||
}
|
||||
const res = purchaseCacheUpgrade(player, node, n);
|
||||
@ -138,38 +139,38 @@ export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript): I
|
||||
getLevelUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): number => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const n = ctx.helper.number("n", _n);
|
||||
const i = helpers.number(ctx, "i", _i);
|
||||
const n = helpers.number(ctx, "n", _n);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
return node.calculateLevelUpgradeCost(n, player.mults.hacknet_node_level_cost);
|
||||
},
|
||||
getRamUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): number => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const n = ctx.helper.number("n", _n);
|
||||
const i = helpers.number(ctx, "i", _i);
|
||||
const n = helpers.number(ctx, "n", _n);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
return node.calculateRamUpgradeCost(n, player.mults.hacknet_node_ram_cost);
|
||||
},
|
||||
getCoreUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): number => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const n = ctx.helper.number("n", _n);
|
||||
const i = helpers.number(ctx, "i", _i);
|
||||
const n = helpers.number(ctx, "n", _n);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
return node.calculateCoreUpgradeCost(n, player.mults.hacknet_node_core_cost);
|
||||
},
|
||||
getCacheUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): number => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const n = ctx.helper.number("n", _n);
|
||||
const i = helpers.number(ctx, "i", _i);
|
||||
const n = helpers.number(ctx, "n", _n);
|
||||
if (!hasHacknetServers(player)) {
|
||||
return Infinity;
|
||||
}
|
||||
const node = getHacknetNode(ctx, i);
|
||||
if (!(node instanceof HacknetServer)) {
|
||||
workerScript.log("hacknet.getCacheUpgradeCost", () => "Can only be called on hacknet servers");
|
||||
helpers.log(ctx, () => "Can only be called on hacknet servers");
|
||||
return -1;
|
||||
}
|
||||
return node.calculateCacheUpgradeCost(n);
|
||||
@ -189,8 +190,8 @@ export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript): I
|
||||
hashCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_upgName: unknown, _count: unknown = 1): number => {
|
||||
const upgName = ctx.helper.string("upgName", _upgName);
|
||||
const count = ctx.helper.number("count", _count);
|
||||
const upgName = helpers.string(ctx, "upgName", _upgName);
|
||||
const count = helpers.number(ctx, "count", _count);
|
||||
if (!hasHacknetServers(player)) {
|
||||
return Infinity;
|
||||
}
|
||||
@ -200,9 +201,9 @@ export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript): I
|
||||
spendHashes:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_upgName: unknown, _upgTarget: unknown = "", _count: unknown = 1): boolean => {
|
||||
const upgName = ctx.helper.string("upgName", _upgName);
|
||||
const upgTarget = ctx.helper.string("upgTarget", _upgTarget);
|
||||
const count = ctx.helper.number("count", _count);
|
||||
const upgName = helpers.string(ctx, "upgName", _upgName);
|
||||
const upgTarget = helpers.string(ctx, "upgTarget", _upgTarget);
|
||||
const count = helpers.number(ctx, "count", _count);
|
||||
if (!hasHacknetServers(player)) {
|
||||
return false;
|
||||
}
|
||||
@ -217,10 +218,10 @@ export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript): I
|
||||
getHashUpgradeLevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_upgName: unknown): number => {
|
||||
const upgName = ctx.helper.string("upgName", _upgName);
|
||||
const upgName = helpers.string(ctx, "upgName", _upgName);
|
||||
const level = player.hashManager.upgrades[upgName];
|
||||
if (level === undefined) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid Hash Upgrade: ${upgName}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid Hash Upgrade: ${upgName}`);
|
||||
}
|
||||
return level;
|
||||
},
|
||||
|
@ -1,41 +0,0 @@
|
||||
import { CityName } from "../Locations/data/CityNames";
|
||||
import { NetscriptContext } from "../Netscript/APIWrapper";
|
||||
import { IPort } from "../NetscriptPort";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Server } from "../Server/Server";
|
||||
import { BaseServer } from "../Server/BaseServer";
|
||||
import { FormulaGang } from "../Gang/formulas/formulas";
|
||||
import { GangMember } from "../Gang/GangMember";
|
||||
import { GangMemberTask } from "../Gang/GangMemberTask";
|
||||
import { BasicHGWOptions } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { ScriptArg } from "../Netscript/ScriptArg";
|
||||
|
||||
export type ScriptIdentifier =
|
||||
| number
|
||||
| {
|
||||
fn: string;
|
||||
hostname: string;
|
||||
args: ScriptArg[];
|
||||
};
|
||||
|
||||
export interface INetscriptHelper {
|
||||
updateDynamicRam(functionName: string, ram: number): void;
|
||||
makeRuntimeErrorMsg(functionName: string, message: string): string;
|
||||
string(funcName: string, argName: string, v: unknown): string;
|
||||
number(funcName: string, argName: string, v: unknown): number;
|
||||
ustring(funcName: string, argName: string, v: unknown): string | undefined;
|
||||
unumber(funcName: string, argName: string, v: unknown): number | undefined;
|
||||
scriptArgs(funcName: string, args: unknown): ScriptArg[];
|
||||
scriptIdentifier(funcName: string, fn: unknown, hostname: unknown, args: unknown): ScriptIdentifier;
|
||||
city(funcName: string, argName: string, v: unknown): CityName;
|
||||
boolean(v: unknown): boolean;
|
||||
getServer(ip: string, ctx: NetscriptContext): BaseServer;
|
||||
checkSingularityAccess(func: string): void;
|
||||
hack(ctx: NetscriptContext, hostname: string, manual: boolean, extra?: BasicHGWOptions): Promise<number>;
|
||||
getValidPort(funcName: string, port: number): IPort;
|
||||
player(funcName: string, p: unknown): IPlayer;
|
||||
server(funcName: string, s: unknown): Server;
|
||||
gang(funcName: string, g: unknown): FormulaGang;
|
||||
gangMember(funcName: string, m: unknown): GangMember;
|
||||
gangTask(funcName: string, m: unknown): GangMemberTask;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player as player } from "../Player";
|
||||
|
||||
import {
|
||||
Infiltration as IInfiltration,
|
||||
@ -18,8 +18,9 @@ import { Factions } from "../Faction/Factions";
|
||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
import { checkEnum } from "../utils/helpers/checkEnum";
|
||||
import { LocationName } from "../Locations/data/LocationNames";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
|
||||
export function NetscriptInfiltration(player: IPlayer): InternalAPI<IInfiltration> {
|
||||
export function NetscriptInfiltration(): InternalAPI<IInfiltration> {
|
||||
const getLocationsWithInfiltrations = Object.values(Locations).filter(
|
||||
(location: Location) => location.infiltrationData,
|
||||
);
|
||||
@ -27,9 +28,9 @@ export function NetscriptInfiltration(player: IPlayer): InternalAPI<IInfiltratio
|
||||
const calculateInfiltrationData = (ctx: NetscriptContext, locationName: string): InfiltrationLocation => {
|
||||
if (!checkEnum(LocationName, locationName)) throw new Error(`Location '${locationName}' does not exists.`);
|
||||
const location = Locations[locationName];
|
||||
if (location === undefined) throw ctx.makeRuntimeErrorMsg(`Location '${location}' does not exists.`);
|
||||
if (location === undefined) throw helpers.makeRuntimeErrorMsg(ctx, `Location '${location}' does not exists.`);
|
||||
if (location.infiltrationData === undefined)
|
||||
throw ctx.makeRuntimeErrorMsg(`Location '${location}' does not provide infiltrations.`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Location '${location}' does not provide infiltrations.`);
|
||||
const startingSecurityLevel = location.infiltrationData.startingSecurityLevel;
|
||||
const difficulty = calculateDifficulty(player, startingSecurityLevel);
|
||||
const reward = calculateReward(player, startingSecurityLevel);
|
||||
@ -54,7 +55,7 @@ export function NetscriptInfiltration(player: IPlayer): InternalAPI<IInfiltratio
|
||||
getInfiltration:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_location: unknown): InfiltrationLocation => {
|
||||
const location = ctx.helper.string("location", _location);
|
||||
const location = helpers.string(ctx, "location", _location);
|
||||
return calculateInfiltrationData(ctx, location);
|
||||
},
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player as player } from "../Player";
|
||||
import { findSleevePurchasableAugs } from "../PersonObjects/Sleeve/SleeveHelpers";
|
||||
import { StaticAugmentations } from "../Augmentation/StaticAugmentations";
|
||||
import { CityName } from "../Locations/data/CityNames";
|
||||
@ -17,11 +17,13 @@ import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
import { isSleeveBladeburnerWork } from "../PersonObjects/Sleeve/Work/SleeveBladeburnerWork";
|
||||
import { isSleeveFactionWork } from "../PersonObjects/Sleeve/Work/SleeveFactionWork";
|
||||
import { isSleeveCompanyWork } from "../PersonObjects/Sleeve/Work/SleeveCompanyWork";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
|
||||
export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
export function NetscriptSleeve(): InternalAPI<ISleeve> {
|
||||
const checkSleeveAPIAccess = function (ctx: NetscriptContext): void {
|
||||
if (player.bitNodeN !== 10 && !player.sourceFileLvl(10)) {
|
||||
throw ctx.makeRuntimeErrorMsg(
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
"You do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10",
|
||||
);
|
||||
}
|
||||
@ -30,8 +32,8 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
const checkSleeveNumber = function (ctx: NetscriptContext, sleeveNumber: number): void {
|
||||
if (sleeveNumber >= player.sleeves.length || sleeveNumber < 0) {
|
||||
const msg = `Invalid sleeve number: ${sleeveNumber}`;
|
||||
ctx.log(() => msg);
|
||||
throw ctx.makeRuntimeErrorMsg(msg);
|
||||
helpers.log(ctx, () => msg);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, msg);
|
||||
}
|
||||
};
|
||||
|
||||
@ -58,7 +60,7 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
setToShockRecovery:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].shockRecovery(player);
|
||||
@ -66,7 +68,7 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
setToSynchronize:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].synchronize(player);
|
||||
@ -74,8 +76,8 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
setToCommitCrime:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown, _crimeRoughName: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const crimeRoughName = ctx.helper.string("crimeName", _crimeRoughName);
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
const crimeRoughName = helpers.string(ctx, "crimeName", _crimeRoughName);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
const crime = findCrime(crimeRoughName);
|
||||
@ -87,9 +89,9 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
setToUniversityCourse:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown, _universityName: unknown, _className: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const universityName = ctx.helper.string("universityName", _universityName);
|
||||
const className = ctx.helper.string("className", _className);
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
const universityName = helpers.string(ctx, "universityName", _universityName);
|
||||
const className = helpers.string(ctx, "className", _className);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].takeUniversityCourse(player, universityName, className);
|
||||
@ -97,21 +99,21 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
travel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown, _cityName: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const cityName = ctx.helper.string("cityName", _cityName);
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
const cityName = helpers.string(ctx, "cityName", _cityName);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
if (checkEnum(CityName, cityName)) {
|
||||
return player.sleeves[sleeveNumber].travel(player, cityName);
|
||||
} else {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid city name: '${cityName}'.`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid city name: '${cityName}'.`);
|
||||
}
|
||||
},
|
||||
setToCompanyWork:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown, acompanyName: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const companyName = ctx.helper.string("companyName", acompanyName);
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
const companyName = helpers.string(ctx, "companyName", acompanyName);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
@ -122,7 +124,8 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
}
|
||||
const other = player.sleeves[i];
|
||||
if (isSleeveCompanyWork(other.currentWork) && other.currentWork.companyName === companyName) {
|
||||
throw ctx.makeRuntimeErrorMsg(
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
`Sleeve ${sleeveNumber} cannot work for company ${companyName} because Sleeve ${i} is already working for them.`,
|
||||
);
|
||||
}
|
||||
@ -133,9 +136,9 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
setToFactionWork:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown, _factionName: unknown, _workType: unknown): boolean | undefined => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const factionName = ctx.helper.string("factionName", _factionName);
|
||||
const workType = ctx.helper.string("workType", _workType);
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
const factionName = helpers.string(ctx, "factionName", _factionName);
|
||||
const workType = helpers.string(ctx, "workType", _workType);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
@ -146,14 +149,16 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
}
|
||||
const other = player.sleeves[i];
|
||||
if (isSleeveFactionWork(other.currentWork) && other.currentWork.factionName === factionName) {
|
||||
throw ctx.makeRuntimeErrorMsg(
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because Sleeve ${i} is already working for them.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (player.gang && player.gang.facName == factionName) {
|
||||
throw ctx.makeRuntimeErrorMsg(
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because you have started a gang with them.`,
|
||||
);
|
||||
}
|
||||
@ -163,9 +168,9 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
setToGymWorkout:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown, _gymName: unknown, _stat: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const gymName = ctx.helper.string("gymName", _gymName);
|
||||
const stat = ctx.helper.string("stat", _stat);
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
const gymName = helpers.string(ctx, "gymName", _gymName);
|
||||
const stat = helpers.string(ctx, "stat", _stat);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
@ -174,7 +179,7 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
getSleeveStats:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown): SleeveSkills => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
return getSleeveStats(sleeveNumber);
|
||||
@ -182,7 +187,7 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
getTask:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown): SleeveTask | null => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
@ -193,7 +198,7 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
getInformation:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown): SleeveInformation => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
@ -229,7 +234,7 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
getSleeveAugmentations:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown): string[] => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
@ -242,7 +247,7 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
getSleevePurchasableAugs:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown): AugmentPair[] => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
@ -261,18 +266,18 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
purchaseSleeveAug:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown, _augName: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const augName = ctx.helper.string("augName", _augName);
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
const augName = helpers.string(ctx, "augName", _augName);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
if (getSleeveStats(sleeveNumber).shock > 0) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Sleeve shock too high: Sleeve ${sleeveNumber}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Sleeve shock too high: Sleeve ${sleeveNumber}`);
|
||||
}
|
||||
|
||||
const aug = StaticAugmentations[augName];
|
||||
if (!aug) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid aug: ${augName}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid aug: ${augName}`);
|
||||
}
|
||||
|
||||
return player.sleeves[sleeveNumber].tryBuyAugmentation(player, aug);
|
||||
@ -281,7 +286,7 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
(ctx: NetscriptContext) =>
|
||||
(_augName: unknown): number => {
|
||||
checkSleeveAPIAccess(ctx);
|
||||
const augName = ctx.helper.string("augName", _augName);
|
||||
const augName = helpers.string(ctx, "augName", _augName);
|
||||
const aug: Augmentation = StaticAugmentations[augName];
|
||||
return aug.baseCost;
|
||||
},
|
||||
@ -289,20 +294,20 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
(ctx: NetscriptContext) =>
|
||||
(_augName: unknown): number => {
|
||||
checkSleeveAPIAccess(ctx);
|
||||
const augName = ctx.helper.string("augName", _augName);
|
||||
const augName = helpers.string(ctx, "augName", _augName);
|
||||
const aug: Augmentation = StaticAugmentations[augName];
|
||||
return aug.getCost(player).repCost;
|
||||
},
|
||||
setToBladeburnerAction:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown, _action: unknown, _contract?: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const action = ctx.helper.string("action", _action);
|
||||
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
||||
const action = helpers.string(ctx, "action", _action);
|
||||
let contract: string;
|
||||
if (typeof _contract === "undefined") {
|
||||
contract = "------";
|
||||
} else {
|
||||
contract = ctx.helper.string("contract", _contract);
|
||||
contract = helpers.string(ctx, "contract", _contract);
|
||||
}
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
@ -315,7 +320,8 @@ export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
}
|
||||
const other = player.sleeves[i];
|
||||
if (isSleeveBladeburnerWork(other.currentWork) && other.currentWork.actionName === contract) {
|
||||
throw ctx.helper.makeRuntimeErrorMsg(
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
`Sleeve ${sleeveNumber} cannot take on contracts because Sleeve ${i} is already performing that action.`,
|
||||
);
|
||||
}
|
||||
|
@ -1,7 +1,4 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { netscriptDelay } from "../NetscriptEvaluator";
|
||||
import { Player as player } from "../Player";
|
||||
|
||||
import { staneksGift } from "../CotMG/Helper";
|
||||
import { Fragments, FragmentById } from "../CotMG/Fragment";
|
||||
@ -18,111 +15,109 @@ import { applyAugmentation } from "../Augmentation/AugmentationHelpers";
|
||||
import { FactionNames } from "../Faction/data/FactionNames";
|
||||
import { joinFaction } from "../Faction/FactionHelpers";
|
||||
import { Factions } from "../Faction/Factions";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
|
||||
export function NetscriptStanek(
|
||||
player: IPlayer,
|
||||
workerScript: WorkerScript,
|
||||
helper: INetscriptHelper,
|
||||
): InternalAPI<IStanek> {
|
||||
function checkStanekAPIAccess(func: string): void {
|
||||
export function NetscriptStanek(): InternalAPI<IStanek> {
|
||||
function checkStanekAPIAccess(ctx: NetscriptContext): void {
|
||||
if (!player.hasAugmentation(AugmentationNames.StaneksGift1, true)) {
|
||||
throw helper.makeRuntimeErrorMsg(func, "Stanek's Gift is not installed");
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, "Stanek's Gift is not installed");
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
giftWidth: () =>
|
||||
giftWidth: (ctx: NetscriptContext) =>
|
||||
function (): number {
|
||||
checkStanekAPIAccess("giftWidth");
|
||||
checkStanekAPIAccess(ctx);
|
||||
return staneksGift.width();
|
||||
},
|
||||
giftHeight: () =>
|
||||
giftHeight: (ctx: NetscriptContext) =>
|
||||
function (): number {
|
||||
checkStanekAPIAccess("giftHeight");
|
||||
checkStanekAPIAccess(ctx);
|
||||
return staneksGift.height();
|
||||
},
|
||||
chargeFragment: (_ctx: NetscriptContext) =>
|
||||
chargeFragment: (ctx: NetscriptContext) =>
|
||||
function (_rootX: unknown, _rootY: unknown): Promise<void> {
|
||||
//Get the fragment object using the given coordinates
|
||||
const rootX = _ctx.helper.number("rootX", _rootX);
|
||||
const rootY = _ctx.helper.number("rootY", _rootY);
|
||||
checkStanekAPIAccess("chargeFragment");
|
||||
const rootX = helpers.number(ctx, "rootX", _rootX);
|
||||
const rootY = helpers.number(ctx, "rootY", _rootY);
|
||||
checkStanekAPIAccess(ctx);
|
||||
const fragment = staneksGift.findFragment(rootX, rootY);
|
||||
//Check whether the selected fragment can ge charged
|
||||
if (!fragment) throw _ctx.makeRuntimeErrorMsg(`No fragment with root (${rootX}, ${rootY}).`);
|
||||
if (!fragment) throw helpers.makeRuntimeErrorMsg(ctx, `No fragment with root (${rootX}, ${rootY}).`);
|
||||
if (fragment.fragment().type == FragmentType.Booster) {
|
||||
throw _ctx.makeRuntimeErrorMsg(
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
`The fragment with root (${rootX}, ${rootY}) is a Booster Fragment and thus cannot be charged.`,
|
||||
);
|
||||
}
|
||||
//Charge the fragment
|
||||
const time = staneksGift.inBonus() ? 200 : 1000;
|
||||
return netscriptDelay(time, workerScript).then(function () {
|
||||
staneksGift.charge(player, fragment, workerScript.scriptRef.threads);
|
||||
_ctx.log(() => `Charged fragment with ${_ctx.workerScript.scriptRef.threads} threads.`);
|
||||
return helpers.netscriptDelay(ctx, time).then(function () {
|
||||
staneksGift.charge(player, fragment, ctx.workerScript.scriptRef.threads);
|
||||
helpers.log(ctx, () => `Charged fragment with ${ctx.workerScript.scriptRef.threads} threads.`);
|
||||
return Promise.resolve();
|
||||
});
|
||||
},
|
||||
fragmentDefinitions: (_ctx: NetscriptContext) =>
|
||||
fragmentDefinitions: (ctx: NetscriptContext) =>
|
||||
function (): IFragment[] {
|
||||
checkStanekAPIAccess("fragmentDefinitions");
|
||||
_ctx.log(() => `Returned ${Fragments.length} fragments`);
|
||||
checkStanekAPIAccess(ctx);
|
||||
helpers.log(ctx, () => `Returned ${Fragments.length} fragments`);
|
||||
return Fragments.map((f) => f.copy());
|
||||
},
|
||||
activeFragments: (_ctx: NetscriptContext) =>
|
||||
activeFragments: (ctx: NetscriptContext) =>
|
||||
function (): IActiveFragment[] {
|
||||
checkStanekAPIAccess("activeFragments");
|
||||
_ctx.log(() => `Returned ${staneksGift.fragments.length} fragments`);
|
||||
checkStanekAPIAccess(ctx);
|
||||
helpers.log(ctx, () => `Returned ${staneksGift.fragments.length} fragments`);
|
||||
return staneksGift.fragments.map((af) => {
|
||||
return { ...af.copy(), ...af.fragment().copy() };
|
||||
});
|
||||
},
|
||||
clearGift: (_ctx: NetscriptContext) =>
|
||||
clearGift: (ctx: NetscriptContext) =>
|
||||
function (): void {
|
||||
checkStanekAPIAccess("clearGift");
|
||||
_ctx.log(() => `Cleared Stanek's Gift.`);
|
||||
checkStanekAPIAccess(ctx);
|
||||
helpers.log(ctx, () => `Cleared Stanek's Gift.`);
|
||||
staneksGift.clear();
|
||||
},
|
||||
canPlaceFragment: (_ctx: NetscriptContext) =>
|
||||
canPlaceFragment: (ctx: NetscriptContext) =>
|
||||
function (_rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown): boolean {
|
||||
const rootX = _ctx.helper.number("rootX", _rootX);
|
||||
const rootY = _ctx.helper.number("rootY", _rootY);
|
||||
const rotation = _ctx.helper.number("rotation", _rotation);
|
||||
const fragmentId = _ctx.helper.number("fragmentId", _fragmentId);
|
||||
checkStanekAPIAccess("canPlaceFragment");
|
||||
const rootX = helpers.number(ctx, "rootX", _rootX);
|
||||
const rootY = helpers.number(ctx, "rootY", _rootY);
|
||||
const rotation = helpers.number(ctx, "rotation", _rotation);
|
||||
const fragmentId = helpers.number(ctx, "fragmentId", _fragmentId);
|
||||
checkStanekAPIAccess(ctx);
|
||||
const fragment = FragmentById(fragmentId);
|
||||
if (!fragment) throw _ctx.makeRuntimeErrorMsg(`Invalid fragment id: ${fragmentId}`);
|
||||
if (!fragment) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid fragment id: ${fragmentId}`);
|
||||
const can = staneksGift.canPlace(rootX, rootY, rotation, fragment);
|
||||
return can;
|
||||
},
|
||||
placeFragment: (_ctx: NetscriptContext) =>
|
||||
placeFragment: (ctx: NetscriptContext) =>
|
||||
function (_rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown): boolean {
|
||||
const rootX = _ctx.helper.number("rootX", _rootX);
|
||||
const rootY = _ctx.helper.number("rootY", _rootY);
|
||||
const rotation = _ctx.helper.number("rotation", _rotation);
|
||||
const fragmentId = _ctx.helper.number("fragmentId", _fragmentId);
|
||||
checkStanekAPIAccess("placeFragment");
|
||||
const rootX = helpers.number(ctx, "rootX", _rootX);
|
||||
const rootY = helpers.number(ctx, "rootY", _rootY);
|
||||
const rotation = helpers.number(ctx, "rotation", _rotation);
|
||||
const fragmentId = helpers.number(ctx, "fragmentId", _fragmentId);
|
||||
checkStanekAPIAccess(ctx);
|
||||
const fragment = FragmentById(fragmentId);
|
||||
if (!fragment) throw _ctx.makeRuntimeErrorMsg(`Invalid fragment id: ${fragmentId}`);
|
||||
if (!fragment) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid fragment id: ${fragmentId}`);
|
||||
return staneksGift.place(rootX, rootY, rotation, fragment);
|
||||
},
|
||||
getFragment: (_ctx: NetscriptContext) =>
|
||||
getFragment: (ctx: NetscriptContext) =>
|
||||
function (_rootX: unknown, _rootY: unknown): IActiveFragment | undefined {
|
||||
const rootX = _ctx.helper.number("rootX", _rootX);
|
||||
const rootY = _ctx.helper.number("rootY", _rootY);
|
||||
checkStanekAPIAccess("getFragment");
|
||||
const rootX = helpers.number(ctx, "rootX", _rootX);
|
||||
const rootY = helpers.number(ctx, "rootY", _rootY);
|
||||
checkStanekAPIAccess(ctx);
|
||||
const fragment = staneksGift.findFragment(rootX, rootY);
|
||||
if (fragment !== undefined) return fragment.copy();
|
||||
return undefined;
|
||||
},
|
||||
removeFragment: (_ctx: NetscriptContext) =>
|
||||
removeFragment: (ctx: NetscriptContext) =>
|
||||
function (_rootX: unknown, _rootY: unknown): boolean {
|
||||
const rootX = _ctx.helper.number("rootX", _rootX);
|
||||
const rootY = _ctx.helper.number("rootY", _rootY);
|
||||
checkStanekAPIAccess("removeFragment");
|
||||
const rootX = helpers.number(ctx, "rootX", _rootX);
|
||||
const rootY = helpers.number(ctx, "rootY", _rootY);
|
||||
checkStanekAPIAccess(ctx);
|
||||
return staneksGift.delete(rootX, rootY);
|
||||
},
|
||||
acceptGift: (_ctx: NetscriptContext) =>
|
||||
acceptGift: (ctx: NetscriptContext) =>
|
||||
function (): boolean {
|
||||
//Check if the player is eligible to join the church
|
||||
if (
|
||||
@ -138,7 +133,8 @@ export function NetscriptStanek(
|
||||
!player.queuedAugmentations.some((a) => a.name === AugmentationNames.StaneksGift1)
|
||||
) {
|
||||
applyAugmentation({ name: AugmentationNames.StaneksGift1, level: 1 });
|
||||
_ctx.log(
|
||||
helpers.log(
|
||||
ctx,
|
||||
() => `'${FactionNames.ChurchOfTheMachineGod}' joined and '${AugmentationNames.StaneksGift1}' installed.`,
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Player as player } from "../Player";
|
||||
import { buyStock, sellStock, shortStock, sellShort } from "../StockMarket/BuyingAndSelling";
|
||||
import { StockMarket, SymbolToStockMap, placeOrder, cancelOrder, initStockMarketFn } from "../StockMarket/StockMarket";
|
||||
import { getBuyTransactionCost, getSellTransactionGain } from "../StockMarket/StockMarketHelpers";
|
||||
@ -14,25 +13,26 @@ import {
|
||||
} from "../StockMarket/StockMarketCosts";
|
||||
import { Stock } from "../StockMarket/Stock";
|
||||
import { StockOrder, TIX } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
|
||||
export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript): InternalAPI<TIX> {
|
||||
export function NetscriptStockMarket(): InternalAPI<TIX> {
|
||||
/**
|
||||
* Checks if the player has TIX API access. Throws an error if the player does not
|
||||
*/
|
||||
const checkTixApiAccess = function (ctx: NetscriptContext): void {
|
||||
if (!player.hasWseAccount) {
|
||||
throw ctx.makeRuntimeErrorMsg(`You don't have WSE Access! Cannot use ${ctx.function}()`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `You don't have WSE Access! Cannot use ${ctx.function}()`);
|
||||
}
|
||||
if (!player.hasTixApiAccess) {
|
||||
throw ctx.makeRuntimeErrorMsg(`You don't have TIX API Access! Cannot use ${ctx.function}()`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `You don't have TIX API Access! Cannot use ${ctx.function}()`);
|
||||
}
|
||||
};
|
||||
|
||||
const getStockFromSymbol = function (ctx: NetscriptContext, symbol: string): Stock {
|
||||
const stock = SymbolToStockMap[symbol];
|
||||
if (stock == null) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid stock symbol: '${symbol}'`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid stock symbol: '${symbol}'`);
|
||||
}
|
||||
|
||||
return stock;
|
||||
@ -58,7 +58,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
getPrice:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const symbol = helpers.string(ctx, "symbol", _symbol);
|
||||
checkTixApiAccess(ctx);
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
|
||||
@ -67,7 +67,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
getAskPrice:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const symbol = helpers.string(ctx, "symbol", _symbol);
|
||||
checkTixApiAccess(ctx);
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
|
||||
@ -76,7 +76,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
getBidPrice:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const symbol = helpers.string(ctx, "symbol", _symbol);
|
||||
checkTixApiAccess(ctx);
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
|
||||
@ -85,18 +85,18 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
getPosition:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown): [number, number, number, number] => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const symbol = helpers.string(ctx, "symbol", _symbol);
|
||||
checkTixApiAccess(ctx);
|
||||
const stock = SymbolToStockMap[symbol];
|
||||
if (stock == null) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid stock symbol: ${symbol}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid stock symbol: ${symbol}`);
|
||||
}
|
||||
return [stock.playerShares, stock.playerAvgPx, stock.playerShortShares, stock.playerAvgShortPx];
|
||||
},
|
||||
getMaxShares:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const symbol = helpers.string(ctx, "symbol", _symbol);
|
||||
checkTixApiAccess(ctx);
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
|
||||
@ -105,9 +105,9 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
getPurchaseCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown, _shares: unknown, _posType: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
let shares = ctx.helper.number("shares", _shares);
|
||||
const posType = ctx.helper.string("posType", _posType);
|
||||
const symbol = helpers.string(ctx, "symbol", _symbol);
|
||||
let shares = helpers.number(ctx, "shares", _shares);
|
||||
const posType = helpers.string(ctx, "posType", _posType);
|
||||
checkTixApiAccess(ctx);
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
shares = Math.round(shares);
|
||||
@ -132,9 +132,9 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
getSaleGain:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown, _shares: unknown, _posType: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
let shares = ctx.helper.number("shares", _shares);
|
||||
const posType = ctx.helper.string("posType", _posType);
|
||||
const symbol = helpers.string(ctx, "symbol", _symbol);
|
||||
let shares = helpers.number(ctx, "shares", _shares);
|
||||
const posType = helpers.string(ctx, "posType", _posType);
|
||||
checkTixApiAccess(ctx);
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
shares = Math.round(shares);
|
||||
@ -159,68 +159,77 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
buyStock:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown, _shares: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const shares = ctx.helper.number("shares", _shares);
|
||||
const symbol = helpers.string(ctx, "symbol", _symbol);
|
||||
const shares = helpers.number(ctx, "shares", _shares);
|
||||
checkTixApiAccess(ctx);
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
const res = buyStock(stock, shares, workerScript, {});
|
||||
const res = buyStock(stock, shares, ctx.workerScript, {});
|
||||
return res ? stock.getAskPrice() : 0;
|
||||
},
|
||||
sellStock:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown, _shares: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const shares = ctx.helper.number("shares", _shares);
|
||||
const symbol = helpers.string(ctx, "symbol", _symbol);
|
||||
const shares = helpers.number(ctx, "shares", _shares);
|
||||
checkTixApiAccess(ctx);
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
const res = sellStock(stock, shares, workerScript, {});
|
||||
const res = sellStock(stock, shares, ctx.workerScript, {});
|
||||
|
||||
return res ? stock.getBidPrice() : 0;
|
||||
},
|
||||
buyShort:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown, _shares: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const shares = ctx.helper.number("shares", _shares);
|
||||
const symbol = helpers.string(ctx, "symbol", _symbol);
|
||||
const shares = helpers.number(ctx, "shares", _shares);
|
||||
checkTixApiAccess(ctx);
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 1) {
|
||||
throw ctx.makeRuntimeErrorMsg("You must either be in BitNode-8 or you must have Source-File 8 Level 2.");
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 2.",
|
||||
);
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
const res = shortStock(stock, shares, workerScript, {});
|
||||
const res = shortStock(stock, shares, ctx.workerScript, {});
|
||||
|
||||
return res ? stock.getBidPrice() : 0;
|
||||
},
|
||||
sellShort:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown, _shares: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const shares = ctx.helper.number("shares", _shares);
|
||||
const symbol = helpers.string(ctx, "symbol", _symbol);
|
||||
const shares = helpers.number(ctx, "shares", _shares);
|
||||
checkTixApiAccess(ctx);
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 1) {
|
||||
throw ctx.makeRuntimeErrorMsg("You must either be in BitNode-8 or you must have Source-File 8 Level 2.");
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 2.",
|
||||
);
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
const res = sellShort(stock, shares, workerScript, {});
|
||||
const res = sellShort(stock, shares, ctx.workerScript, {});
|
||||
|
||||
return res ? stock.getAskPrice() : 0;
|
||||
},
|
||||
placeOrder:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown, _shares: unknown, _price: unknown, _type: unknown, _pos: unknown): boolean => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const shares = ctx.helper.number("shares", _shares);
|
||||
const price = ctx.helper.number("price", _price);
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const pos = ctx.helper.string("pos", _pos);
|
||||
const symbol = helpers.string(ctx, "symbol", _symbol);
|
||||
const shares = helpers.number(ctx, "shares", _shares);
|
||||
const price = helpers.number(ctx, "price", _price);
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const pos = helpers.string(ctx, "pos", _pos);
|
||||
checkTixApiAccess(ctx);
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 2) {
|
||||
throw ctx.makeRuntimeErrorMsg("You must either be in BitNode-8 or you must have Source-File 8 Level 3.");
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 3.",
|
||||
);
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
@ -237,7 +246,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
} else if (ltype.includes("stop") && ltype.includes("sell")) {
|
||||
orderType = OrderTypes.StopSell;
|
||||
} else {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid order type: ${type}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid order type: ${type}`);
|
||||
}
|
||||
|
||||
const lpos = pos.toLowerCase();
|
||||
@ -246,28 +255,34 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
} else if (lpos.includes("s")) {
|
||||
orderPos = PositionTypes.Short;
|
||||
} else {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid position type: ${pos}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid position type: ${pos}`);
|
||||
}
|
||||
|
||||
return placeOrder(stock, shares, price, orderType, orderPos, workerScript);
|
||||
return placeOrder(stock, shares, price, orderType, orderPos, ctx.workerScript);
|
||||
},
|
||||
cancelOrder:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown, _shares: unknown, _price: unknown, _type: unknown, _pos: unknown): boolean => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const shares = ctx.helper.number("shares", _shares);
|
||||
const price = ctx.helper.number("price", _price);
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const pos = ctx.helper.string("pos", _pos);
|
||||
const symbol = helpers.string(ctx, "symbol", _symbol);
|
||||
const shares = helpers.number(ctx, "shares", _shares);
|
||||
const price = helpers.number(ctx, "price", _price);
|
||||
const type = helpers.string(ctx, "type", _type);
|
||||
const pos = helpers.string(ctx, "pos", _pos);
|
||||
checkTixApiAccess(ctx);
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 2) {
|
||||
throw ctx.makeRuntimeErrorMsg("You must either be in BitNode-8 or you must have Source-File 8 Level 3.");
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 3.",
|
||||
);
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
if (isNaN(shares) || isNaN(price)) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid shares or price. Must be numeric. shares=${shares}, price=${price}`);
|
||||
throw helpers.makeRuntimeErrorMsg(
|
||||
ctx,
|
||||
`Invalid shares or price. Must be numeric. shares=${shares}, price=${price}`,
|
||||
);
|
||||
}
|
||||
let orderType;
|
||||
let orderPos;
|
||||
@ -281,7 +296,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
} else if (ltype.includes("stop") && ltype.includes("sell")) {
|
||||
orderType = OrderTypes.StopSell;
|
||||
} else {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid order type: ${type}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid order type: ${type}`);
|
||||
}
|
||||
|
||||
const lpos = pos.toLowerCase();
|
||||
@ -290,7 +305,7 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
} else if (lpos.includes("s")) {
|
||||
orderPos = PositionTypes.Short;
|
||||
} else {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid position type: ${pos}`);
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid position type: ${pos}`);
|
||||
}
|
||||
const params = {
|
||||
stock: stock,
|
||||
@ -299,13 +314,13 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
type: orderType,
|
||||
pos: orderPos,
|
||||
};
|
||||
return cancelOrder(params, workerScript);
|
||||
return cancelOrder(params, ctx.workerScript);
|
||||
},
|
||||
getOrders: (ctx: NetscriptContext) => (): StockOrder => {
|
||||
checkTixApiAccess(ctx);
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 2) {
|
||||
throw ctx.makeRuntimeErrorMsg("You must either be in BitNode-8 or have Source-File 8 Level 3.");
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, "You must either be in BitNode-8 or have Source-File 8 Level 3.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -332,9 +347,9 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
getVolatility:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const symbol = helpers.string(ctx, "symbol", _symbol);
|
||||
if (!player.has4SDataTixApi) {
|
||||
throw ctx.makeRuntimeErrorMsg("You don't have 4S Market Data TIX API Access!");
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, "You don't have 4S Market Data TIX API Access!");
|
||||
}
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
|
||||
@ -343,9 +358,9 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
getForecast:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const symbol = helpers.string(ctx, "symbol", _symbol);
|
||||
if (!player.has4SDataTixApi) {
|
||||
throw ctx.makeRuntimeErrorMsg("You don't have 4S Market Data TIX API Access!");
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, "You don't have 4S Market Data TIX API Access!");
|
||||
}
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
|
||||
@ -355,69 +370,69 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
},
|
||||
purchase4SMarketData: (ctx: NetscriptContext) => (): boolean => {
|
||||
if (player.has4SData) {
|
||||
ctx.log(() => "Already purchased 4S Market Data.");
|
||||
helpers.log(ctx, () => "Already purchased 4S Market Data.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.money < getStockMarket4SDataCost()) {
|
||||
ctx.log(() => "Not enough money to purchase 4S Market Data.");
|
||||
helpers.log(ctx, () => "Not enough money to purchase 4S Market Data.");
|
||||
return false;
|
||||
}
|
||||
|
||||
player.has4SData = true;
|
||||
player.loseMoney(getStockMarket4SDataCost(), "stock");
|
||||
ctx.log(() => "Purchased 4S Market Data");
|
||||
helpers.log(ctx, () => "Purchased 4S Market Data");
|
||||
return true;
|
||||
},
|
||||
purchase4SMarketDataTixApi: (ctx: NetscriptContext) => (): boolean => {
|
||||
checkTixApiAccess(ctx);
|
||||
|
||||
if (player.has4SDataTixApi) {
|
||||
ctx.log(() => "Already purchased 4S Market Data TIX API");
|
||||
helpers.log(ctx, () => "Already purchased 4S Market Data TIX API");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.money < getStockMarket4STixApiCost()) {
|
||||
ctx.log(() => "Not enough money to purchase 4S Market Data TIX API");
|
||||
helpers.log(ctx, () => "Not enough money to purchase 4S Market Data TIX API");
|
||||
return false;
|
||||
}
|
||||
|
||||
player.has4SDataTixApi = true;
|
||||
player.loseMoney(getStockMarket4STixApiCost(), "stock");
|
||||
ctx.log(() => "Purchased 4S Market Data TIX API");
|
||||
helpers.log(ctx, () => "Purchased 4S Market Data TIX API");
|
||||
return true;
|
||||
},
|
||||
purchaseWseAccount: (ctx: NetscriptContext) => (): boolean => {
|
||||
if (player.hasWseAccount) {
|
||||
ctx.log(() => "Already purchased WSE Account");
|
||||
helpers.log(ctx, () => "Already purchased WSE Account");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.money < getStockMarketWseCost()) {
|
||||
ctx.log(() => "Not enough money to purchase WSE Account Access");
|
||||
helpers.log(ctx, () => "Not enough money to purchase WSE Account Access");
|
||||
return false;
|
||||
}
|
||||
|
||||
player.hasWseAccount = true;
|
||||
initStockMarketFn();
|
||||
player.loseMoney(getStockMarketWseCost(), "stock");
|
||||
ctx.log(() => "Purchased WSE Account Access");
|
||||
helpers.log(ctx, () => "Purchased WSE Account Access");
|
||||
return true;
|
||||
},
|
||||
purchaseTixApi: (ctx: NetscriptContext) => (): boolean => {
|
||||
if (player.hasTixApiAccess) {
|
||||
ctx.log(() => "Already purchased TIX API");
|
||||
helpers.log(ctx, () => "Already purchased TIX API");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.money < getStockMarketTixApiCost()) {
|
||||
ctx.log(() => "Not enough money to purchase TIX API Access");
|
||||
helpers.log(ctx, () => "Not enough money to purchase TIX API Access");
|
||||
return false;
|
||||
}
|
||||
|
||||
player.hasTixApiAccess = true;
|
||||
player.loseMoney(getStockMarketTixApiCost(), "stock");
|
||||
ctx.log(() => "Purchased TIX API");
|
||||
helpers.log(ctx, () => "Purchased TIX API");
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
@ -10,8 +10,9 @@ import { defaultTheme } from "../Themes/Themes";
|
||||
import { defaultStyles } from "../Themes/Styles";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { hash } from "../hash/hash";
|
||||
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
import { Terminal } from "../../src/Terminal";
|
||||
import { helpers } from "../Netscript/NetscriptHelpers";
|
||||
|
||||
export function NetscriptUserInterface(): InternalAPI<IUserInterface> {
|
||||
return {
|
||||
@ -43,9 +44,9 @@ export function NetscriptUserInterface(): InternalAPI<IUserInterface> {
|
||||
if (errors.length === 0) {
|
||||
Object.assign(Settings.theme, currentTheme);
|
||||
ThemeEvents.emit();
|
||||
ctx.log(() => `Successfully set theme`);
|
||||
helpers.log(ctx, () => `Successfully set theme`);
|
||||
} else {
|
||||
ctx.log(() => `Failed to set theme. Errors: ${errors.join(", ")}`);
|
||||
helpers.log(ctx, () => `Failed to set theme. Errors: ${errors.join(", ")}`);
|
||||
}
|
||||
},
|
||||
|
||||
@ -66,22 +67,22 @@ export function NetscriptUserInterface(): InternalAPI<IUserInterface> {
|
||||
if (errors.length === 0) {
|
||||
Object.assign(Settings.styles, currentStyles);
|
||||
ThemeEvents.emit();
|
||||
ctx.log(() => `Successfully set styles`);
|
||||
helpers.log(ctx, () => `Successfully set styles`);
|
||||
} else {
|
||||
ctx.log(() => `Failed to set styles. Errors: ${errors.join(", ")}`);
|
||||
helpers.log(ctx, () => `Failed to set styles. Errors: ${errors.join(", ")}`);
|
||||
}
|
||||
},
|
||||
|
||||
resetTheme: (ctx: NetscriptContext) => (): void => {
|
||||
Settings.theme = { ...defaultTheme };
|
||||
ThemeEvents.emit();
|
||||
ctx.log(() => `Reinitialized theme to default`);
|
||||
helpers.log(ctx, () => `Reinitialized theme to default`);
|
||||
},
|
||||
|
||||
resetStyles: (ctx: NetscriptContext) => (): void => {
|
||||
Settings.styles = { ...defaultStyles };
|
||||
ThemeEvents.emit();
|
||||
ctx.log(() => `Reinitialized styles to default`);
|
||||
helpers.log(ctx, () => `Reinitialized styles to default`);
|
||||
},
|
||||
|
||||
getGameInfo: () => (): GameInfo => {
|
||||
@ -99,7 +100,7 @@ export function NetscriptUserInterface(): InternalAPI<IUserInterface> {
|
||||
},
|
||||
|
||||
clearTerminal: (ctx: NetscriptContext) => (): void => {
|
||||
ctx.log(() => `Clearing terminal`);
|
||||
helpers.log(ctx, () => `Clearing terminal`);
|
||||
Terminal.clear();
|
||||
},
|
||||
};
|
||||
|
@ -5,7 +5,7 @@
|
||||
import * as walk from "acorn-walk";
|
||||
import { parse } from "acorn";
|
||||
|
||||
import { makeRuntimeRejectMsg } from "./NetscriptEvaluator";
|
||||
import { helpers } from "./Netscript/NetscriptHelpers";
|
||||
import { ScriptUrl } from "./Script/ScriptUrl";
|
||||
import { WorkerScript } from "./Netscript/WorkerScript";
|
||||
import { Script } from "./Script/Script";
|
||||
@ -74,18 +74,21 @@ export async function executeJSScript(
|
||||
const ns = workerScript.env.vars;
|
||||
|
||||
if (!loadedModule) {
|
||||
throw makeRuntimeRejectMsg(workerScript, `${script.filename} cannot be run because the script module won't load`);
|
||||
throw helpers.makeRuntimeRejectMsg(
|
||||
workerScript,
|
||||
`${script.filename} cannot be run because the script module won't load`,
|
||||
);
|
||||
}
|
||||
// TODO: putting await in a non-async function yields unhelpful
|
||||
// "SyntaxError: unexpected reserved word" with no line number information.
|
||||
if (!loadedModule.main) {
|
||||
throw makeRuntimeRejectMsg(
|
||||
throw helpers.makeRuntimeRejectMsg(
|
||||
workerScript,
|
||||
`${script.filename} cannot be run because it does not have a main function.`,
|
||||
);
|
||||
}
|
||||
if (!ns) {
|
||||
throw makeRuntimeRejectMsg(
|
||||
throw helpers.makeRuntimeRejectMsg(
|
||||
workerScript,
|
||||
`${script.filename} cannot be run because the NS object hasn't been constructed properly.`,
|
||||
);
|
||||
|
@ -11,7 +11,6 @@ import { generateNextPid } from "./Netscript/Pid";
|
||||
|
||||
import { CONSTANTS } from "./Constants";
|
||||
import { Interpreter } from "./ThirdParty/JSInterpreter";
|
||||
import { isScriptErrorMessage, makeRuntimeRejectMsg } from "./NetscriptEvaluator";
|
||||
import { NetscriptFunctions } from "./NetscriptFunctions";
|
||||
import { executeJSScript, Node } from "./NetscriptJSEvaluator";
|
||||
import { NetscriptPort, IPort } from "./NetscriptPort";
|
||||
@ -29,7 +28,6 @@ import { dialogBoxCreate } from "./ui/React/DialogBox";
|
||||
import { arrayToString } from "./utils/helpers/arrayToString";
|
||||
import { roundToTwo } from "./utils/helpers/roundToTwo";
|
||||
import { isString } from "./utils/helpers/isString";
|
||||
import { sprintf } from "sprintf-js";
|
||||
|
||||
import { parse } from "acorn";
|
||||
import { simple as walksimple } from "acorn-walk";
|
||||
@ -38,6 +36,8 @@ import { Player } from "./Player";
|
||||
import { Terminal } from "./Terminal";
|
||||
import { IPlayer } from "./PersonObjects/IPlayer";
|
||||
import { ScriptArg } from "./Netscript/ScriptArg";
|
||||
import { helpers } from "./Netscript/NetscriptHelpers";
|
||||
import { NS } from "./ScriptEditor/NetscriptDefinitions";
|
||||
|
||||
// Netscript Ports are instantiated here
|
||||
export const NetscriptPorts: IPort[] = [];
|
||||
@ -63,83 +63,6 @@ export function prestigeWorkerScripts(): void {
|
||||
// that resolves or rejects when the corresponding worker script is done.
|
||||
function startNetscript2Script(player: IPlayer, workerScript: WorkerScript): Promise<void> {
|
||||
workerScript.running = true;
|
||||
|
||||
// The name of the currently running netscript function, to prevent concurrent
|
||||
// calls to hack, grow, etc.
|
||||
let runningFn: string | null = null;
|
||||
|
||||
// We need to go through the environment and wrap each function in such a way that it
|
||||
// can be called at most once at a time. This will prevent situations where multiple
|
||||
// hack promises are outstanding, for example.
|
||||
function wrap(propName: string, f: (...args: unknown[]) => Promise<void>): (...args: unknown[]) => Promise<void> {
|
||||
// This function unfortunately cannot be an async function, because we don't
|
||||
// know if the original one was, and there's no way to tell.
|
||||
return function (...args: unknown[]) {
|
||||
// Wrap every netscript function with a check for the stop flag.
|
||||
// This prevents cases where we never stop because we are only calling
|
||||
// netscript functions that don't check this.
|
||||
// This is not a problem for legacy Netscript because it also checks the
|
||||
// stop flag in the evaluator.
|
||||
if (workerScript.env.stopFlag) {
|
||||
throw new ScriptDeath(workerScript);
|
||||
}
|
||||
|
||||
if (propName === "asleep") return f(...args); // OK for multiple simultaneous calls to sleep.
|
||||
|
||||
const msg =
|
||||
"Concurrent calls to Netscript functions are not allowed! " +
|
||||
"Did you forget to await hack(), grow(), or some other " +
|
||||
"promise-returning function? (Currently running: %s tried to run: %s)";
|
||||
if (runningFn) {
|
||||
workerScript.errorMessage = makeRuntimeRejectMsg(workerScript, sprintf(msg, runningFn, propName));
|
||||
throw new ScriptDeath(workerScript);
|
||||
}
|
||||
runningFn = propName;
|
||||
|
||||
// If the function throws an error, clear the runningFn flag first, and then re-throw it
|
||||
// This allows people to properly catch errors thrown by NS functions without getting
|
||||
// the concurrent call error above
|
||||
let result;
|
||||
try {
|
||||
result = f(...args);
|
||||
} catch (e: unknown) {
|
||||
runningFn = null;
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (result && result.finally !== undefined) {
|
||||
return result.finally(function () {
|
||||
runningFn = null;
|
||||
});
|
||||
} else {
|
||||
runningFn = null;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function wrapObject(vars: unknown, ...tree: string[]): void {
|
||||
const isObject = (x: unknown): x is { [key: string]: unknown } => typeof x === "object";
|
||||
if (!isObject(vars)) throw new Error("wrong argument sent to wrapObject");
|
||||
for (const prop of Object.keys(vars)) {
|
||||
let e = vars[prop];
|
||||
switch (typeof e) {
|
||||
case "function": {
|
||||
e = wrap([...tree, prop].join("."), e as any);
|
||||
break;
|
||||
}
|
||||
case "object": {
|
||||
if (Array.isArray(e)) continue;
|
||||
wrapObject(e, ...tree, prop);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
wrapObject(workerScript.env.vars);
|
||||
|
||||
// Note: the environment that we pass to the JS script only needs to contain the functions visible
|
||||
// to that script, which env.vars does at this point.
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
executeJSScript(player, workerScript.getServer().scripts, workerScript)
|
||||
.then(() => {
|
||||
@ -149,15 +72,18 @@ function startNetscript2Script(player: IPlayer, workerScript: WorkerScript): Pro
|
||||
}).catch((e) => {
|
||||
if (e instanceof Error) {
|
||||
if (e instanceof SyntaxError) {
|
||||
workerScript.errorMessage = makeRuntimeRejectMsg(workerScript, e.message + " (sorry we can't be more helpful)");
|
||||
workerScript.errorMessage = helpers.makeRuntimeRejectMsg(
|
||||
workerScript,
|
||||
e.message + " (sorry we can't be more helpful)",
|
||||
);
|
||||
} else {
|
||||
workerScript.errorMessage = makeRuntimeRejectMsg(
|
||||
workerScript.errorMessage = helpers.makeRuntimeRejectMsg(
|
||||
workerScript,
|
||||
e.message + ((e.stack && "\nstack:\n" + e.stack.toString()) || ""),
|
||||
);
|
||||
}
|
||||
throw new ScriptDeath(workerScript);
|
||||
} else if (isScriptErrorMessage(e)) {
|
||||
} else if (helpers.isScriptErrorMessage(e)) {
|
||||
workerScript.errorMessage = e;
|
||||
throw new ScriptDeath(workerScript);
|
||||
} else if (e instanceof ScriptDeath) {
|
||||
@ -165,7 +91,7 @@ function startNetscript2Script(player: IPlayer, workerScript: WorkerScript): Pro
|
||||
}
|
||||
|
||||
// Don't know what to do with it, let's try making an error message out of it
|
||||
workerScript.errorMessage = makeRuntimeRejectMsg(workerScript, "" + e);
|
||||
workerScript.errorMessage = helpers.makeRuntimeRejectMsg(workerScript, "" + e);
|
||||
throw new ScriptDeath(workerScript);
|
||||
});
|
||||
}
|
||||
@ -189,8 +115,11 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<void> {
|
||||
}
|
||||
|
||||
const interpreterInitialization = function (int: Interpreter, scope: unknown): void {
|
||||
interface NS1 extends NS {
|
||||
[key: string]: any;
|
||||
}
|
||||
//Add the Netscript environment
|
||||
const ns = NetscriptFunctions(workerScript);
|
||||
const ns = NetscriptFunctions(workerScript) as NS1;
|
||||
for (const name of Object.keys(ns)) {
|
||||
const entry = ns[name];
|
||||
if (typeof entry === "function") {
|
||||
@ -242,7 +171,7 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<void> {
|
||||
name === "vsprintf" ||
|
||||
name === "scp" ||
|
||||
name == "write" ||
|
||||
name === "tryWrite" ||
|
||||
name === "tryWritePort" ||
|
||||
name === "run" ||
|
||||
name === "exec"
|
||||
) {
|
||||
@ -319,8 +248,8 @@ function startNetscript1Script(workerScript: WorkerScript): Promise<void> {
|
||||
}
|
||||
} catch (_e: unknown) {
|
||||
let e = String(_e);
|
||||
if (!isScriptErrorMessage(e)) {
|
||||
e = makeRuntimeRejectMsg(workerScript, e);
|
||||
if (!helpers.isScriptErrorMessage(e)) {
|
||||
e = helpers.makeRuntimeRejectMsg(workerScript, e);
|
||||
}
|
||||
workerScript.errorMessage = e;
|
||||
return reject(new ScriptDeath(workerScript));
|
||||
@ -598,7 +527,7 @@ function createAndAddWorkerScript(
|
||||
console.error("Evaluating workerscript returns an Error. THIS SHOULDN'T HAPPEN: " + e.toString());
|
||||
return;
|
||||
} else if (e instanceof ScriptDeath) {
|
||||
if (isScriptErrorMessage(workerScript.errorMessage)) {
|
||||
if (helpers.isScriptErrorMessage(workerScript.errorMessage)) {
|
||||
const errorTextArray = workerScript.errorMessage.split("|DELIMITER|");
|
||||
if (errorTextArray.length != 4) {
|
||||
console.error("ERROR: Something wrong with Error text in evaluator...");
|
||||
@ -622,7 +551,7 @@ function createAndAddWorkerScript(
|
||||
workerScript.log("", () => "Script killed");
|
||||
return; // Already killed, so stop here
|
||||
}
|
||||
} else if (isScriptErrorMessage(e)) {
|
||||
} else if (helpers.isScriptErrorMessage(e)) {
|
||||
dialogBoxCreate("Script runtime unknown error. This is a bug please contact game developer");
|
||||
console.error(
|
||||
"ERROR: Evaluating workerscript returns only error message rather than WorkerScript object. THIS SHOULDN'T HAPPEN: " +
|
||||
|
27
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
27
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -4281,7 +4281,7 @@ export interface InfiltrationReward {
|
||||
* @public
|
||||
*/
|
||||
export interface ILocation {
|
||||
city: CityName | null;
|
||||
city: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
@ -6920,6 +6920,31 @@ export interface Corporation extends WarehouseAPI, OfficeAPI {
|
||||
* @returns An offer of investment
|
||||
*/
|
||||
getInvestmentOffer(): InvestmentOffer;
|
||||
/**
|
||||
* Get list of materials
|
||||
* @returns material names
|
||||
*/
|
||||
getMaterialNames(): string[];
|
||||
/**
|
||||
* Get list of industry types
|
||||
* @returns industry names
|
||||
*/
|
||||
getIndustryTypes(): string[];
|
||||
/**
|
||||
* Get list of one-time unlockable upgrades
|
||||
* @returns unlockable upgrades names
|
||||
*/
|
||||
getUnlockables(): string[];
|
||||
/**
|
||||
* Get list of upgrade names
|
||||
* @returns upgrade names
|
||||
*/
|
||||
getUpgradeNames(): string[];
|
||||
/**
|
||||
* Get list of research names
|
||||
* @returns research names
|
||||
*/
|
||||
getResearchNames(): string[];
|
||||
/**
|
||||
* Accept investment based on you companies current valuation
|
||||
* @remarks
|
||||
|
@ -309,7 +309,7 @@ export async function determineAllPossibilitiesForTabCompletion(
|
||||
return "--" + f[0];
|
||||
});
|
||||
try {
|
||||
return flagFunc()(schema);
|
||||
return flagFunc(schema);
|
||||
} catch (err) {
|
||||
return {};
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { ScriptDeath } from "./Netscript/ScriptDeath";
|
||||
import { isScriptErrorMessage } from "./NetscriptEvaluator";
|
||||
import { helpers } from "./Netscript/NetscriptHelpers";
|
||||
import { dialogBoxCreate } from "./ui/React/DialogBox";
|
||||
|
||||
export function setupUncaughtPromiseHandler(): void {
|
||||
window.addEventListener("unhandledrejection", function (e) {
|
||||
if (isScriptErrorMessage(e.reason)) {
|
||||
if (helpers.isScriptErrorMessage(e.reason)) {
|
||||
const errorTextArray = e.reason.split("|DELIMITER|");
|
||||
const hostname = errorTextArray[1];
|
||||
const scriptName = errorTextArray[2];
|
||||
|
@ -381,7 +381,7 @@ export function InteractiveTutorialRoot(): React.ReactElement {
|
||||
<Typography>
|
||||
Scripts must end with the {tutorialScriptExtension} extension. Let's make a script now by entering{" "}
|
||||
</Typography>
|
||||
<Typography classes={{ root: classes.textfield }}>{`[home ~/]> nano ${tutorialScriptName}`}</Typography>
|
||||
<Typography classes={{ root: classes.textfield }}>{`[n00dles ~/]> nano ${tutorialScriptName}`}</Typography>
|
||||
|
||||
<Typography>
|
||||
after the hack command finishes running (Sidenote: Pressing ctrl + c will end a command like hack early)
|
||||
@ -439,7 +439,7 @@ export function InteractiveTutorialRoot(): React.ReactElement {
|
||||
<br />
|
||||
To check how much RAM is available on this machine, enter
|
||||
</Typography>
|
||||
<Typography classes={{ root: classes.textfield }}>{"[home ~/]> free"}</Typography>
|
||||
<Typography classes={{ root: classes.textfield }}>{"[n00dles ~/]> free"}</Typography>
|
||||
</>
|
||||
),
|
||||
canNext: false,
|
||||
@ -448,9 +448,9 @@ export function InteractiveTutorialRoot(): React.ReactElement {
|
||||
content: (
|
||||
<>
|
||||
<Typography>
|
||||
We have 8GB of free RAM on this machine, which is enough to run our script. Let's run our script using
|
||||
We have 4GB of free RAM on this machine, which is enough to run our script. Let's run our script using
|
||||
</Typography>
|
||||
<Typography classes={{ root: classes.textfield }}>{`[home ~/]> run ${tutorialScriptName}`}</Typography>
|
||||
<Typography classes={{ root: classes.textfield }}>{`[n00dles ~/]> run ${tutorialScriptName}`}</Typography>
|
||||
</>
|
||||
),
|
||||
canNext: false,
|
||||
@ -497,7 +497,7 @@ export function InteractiveTutorialRoot(): React.ReactElement {
|
||||
One last thing about scripts, each active script contains logs that detail what it's doing. We can check
|
||||
these logs using the tail command. Do that now for the script we just ran by typing{" "}
|
||||
</Typography>
|
||||
<Typography classes={{ root: classes.textfield }}>{`[home ~/]> tail ${tutorialScriptName}`}</Typography>
|
||||
<Typography classes={{ root: classes.textfield }}>{`[n00dles ~/]> tail ${tutorialScriptName}`}</Typography>
|
||||
</>
|
||||
),
|
||||
canNext: false,
|
||||
|
@ -139,6 +139,10 @@ function PromptMenuSelect({ prompt, resolve }: IContentProps): React.ReactElemen
|
||||
return content;
|
||||
};
|
||||
|
||||
if (!Array.isArray(prompt?.options?.choices)) {
|
||||
return <Typography>Error: Please provide an array of string choices</Typography>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div style={{ display: "flex", alignItems: "center", paddingTop: "10px" }}>
|
||||
|
@ -60,7 +60,7 @@ describe("tutorial", () => {
|
||||
cy.findByText(/now we'll run the script/i);
|
||||
cy.findByRole("textbox").type("free{enter}");
|
||||
|
||||
cy.findByText(/We have 8GB of free RAM on this machine/i);
|
||||
cy.findByText(/We have 4GB of free RAM on this machine/i);
|
||||
cy.findByRole("textbox").type("run n00dles.script{enter}");
|
||||
|
||||
cy.findByText(/Your script is now running/i);
|
||||
|
Loading…
Reference in New Issue
Block a user