diff --git a/src/Netscript/APIWrapper.ts b/src/Netscript/APIWrapper.ts index 81496285a..f163c0d58 100644 --- a/src/Netscript/APIWrapper.ts +++ b/src/Netscript/APIWrapper.ts @@ -5,13 +5,15 @@ import { ScriptArg } from "./ScriptArg"; import { NSEnums } from "src/ScriptEditor/NetscriptDefinitions"; import { NSFull } from "src/NetscriptFunctions"; -type ExternalFunction = (...args: unknown[]) => unknown; +type ExternalFunction = (...args: any[]) => void; export type ExternalAPILayer = { [key: string]: ExternalAPILayer | ExternalFunction | ScriptArg[]; }; -type InternalFunction unknown> = (ctx: NetscriptContext) => F; +type InternalFunction = ( + ctx: NetscriptContext, +) => ((...args: unknown[]) => ReturnType) & F; export type InternalAPI = { [Property in keyof API]: API[Property] extends ExternalFunction diff --git a/src/Netscript/NetscriptHelpers.ts b/src/Netscript/NetscriptHelpers.ts index 163bacf50..5ce438fd7 100644 --- a/src/Netscript/NetscriptHelpers.ts +++ b/src/Netscript/NetscriptHelpers.ts @@ -65,6 +65,39 @@ export const helpers = { failOnHacknetServer, }; +export function assertObjectType( + ctx: NetscriptContext, + name: string, + obj: unknown, + desiredObject: T, +): asserts obj is T { + if (typeof obj !== "object" || obj === null) { + throw makeRuntimeErrorMsg( + ctx, + `Type ${obj === null ? "null" : typeof obj} provided for ${name}. Must be an object.`, + "TYPE", + ); + } + const objHas = Object.prototype.hasOwnProperty.bind(obj); + for (const [key, val] of Object.entries(desiredObject)) { + if (!objHas(key)) { + throw makeRuntimeErrorMsg( + ctx, + `Object provided for argument ${name} is missing required property ${key}.`, + "TYPE", + ); + } + const objVal = (obj as Record)[key]; + if (typeof val !== typeof objVal) { + throw makeRuntimeErrorMsg( + ctx, + `Incorrect type ${typeof objVal} provided for property ${key} on ${name} argument. Should be type ${typeof val}.`, + "TYPE", + ); + } + } +} + const userFriendlyString = (v: unknown): string => { const clip = (s: string): string => { if (s.length > 15) return s.slice(0, 12) + "..."; @@ -220,10 +253,7 @@ function resolveNetscriptRequestedThreads(ctx: NetscriptContext, requestedThread } const requestedThreadsAsInt = requestedThreads | 0; if (isNaN(requestedThreads) || requestedThreadsAsInt < 1) { - throw makeRuntimeErrorMsg( - ctx, - `Invalid thread count passed to ${ctx.function}: ${requestedThreads}. Threads must be a positive number.`, - ); + throw makeRuntimeErrorMsg(ctx, `Invalid thread count: ${requestedThreads}. Threads must be a positive number.`); } if (requestedThreadsAsInt > threads) { throw makeRuntimeErrorMsg( diff --git a/src/Netscript/RamCostGenerator.ts b/src/Netscript/RamCostGenerator.ts index 165c256a2..9c72aecea 100644 --- a/src/Netscript/RamCostGenerator.ts +++ b/src/Netscript/RamCostGenerator.ts @@ -546,6 +546,7 @@ export const RamCosts: RamCostTree> = { // Easter egg function break: 0, }, + iKnowWhatImDoing: 0, formulas: { mockServer: 0, diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index 6bdb559ad..56b210599 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -42,7 +42,7 @@ import { runScriptFromScript } from "./NetscriptWorker"; import { killWorkerScript } from "./Netscript/killWorkerScript"; import { workerScripts } from "./Netscript/WorkerScripts"; import { WorkerScript } from "./Netscript/WorkerScript"; -import { helpers } from "./Netscript/NetscriptHelpers"; +import { helpers, assertObjectType } from "./Netscript/NetscriptHelpers"; import { numeralWrapper } from "./ui/numeralFormat"; import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions"; import { LogBoxEvents, LogBoxCloserEvents, LogBoxPositionEvents, LogBoxSizeEvents } from "./ui/React/LogBoxManager"; @@ -61,19 +61,7 @@ import { NetscriptCorporation } from "./NetscriptFunctions/Corporation"; import { NetscriptFormulas } from "./NetscriptFunctions/Formulas"; import { NetscriptStockMarket } from "./NetscriptFunctions/StockMarket"; import { NetscriptGrafting } from "./NetscriptFunctions/Grafting"; -import { IPort } from "./NetscriptPort"; -import { - NS, - Player as INetscriptPlayer, - RecentScript as IRecentScript, - BasicHGWOptions, - ProcessInfo, - HackingMultipliers, - HacknetMultipliers, - BitNodeMultipliers as IBNMults, - Server as IServerDef, - RunningScript as IRunningScriptDef, -} from "./ScriptEditor/NetscriptDefinitions"; +import { NS, RecentScript as IRecentScript, BasicHGWOptions, ProcessInfo } from "./ScriptEditor/NetscriptDefinitions"; import { NetscriptSingularity } from "./NetscriptFunctions/Singularity"; import { dialogBoxCreate } from "./ui/React/DialogBox"; @@ -84,7 +72,7 @@ import { Flags } from "./NetscriptFunctions/Flags"; import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence"; import { CalculateShareMult, StartSharing } from "./NetworkShare/Share"; import { recentScripts } from "./Netscript/RecentScripts"; -import { InternalAPI, NetscriptContext, wrapAPI } from "./Netscript/APIWrapper"; +import { InternalAPI, wrapAPI } from "./Netscript/APIWrapper"; import { INetscriptExtra } from "./NetscriptFunctions/Extra"; import { ScriptDeath } from "./Netscript/ScriptDeath"; @@ -117,112 +105,104 @@ const base: InternalAPI = { hacknet: NetscriptHacknet(), sprintf: () => sprintf, vsprintf: () => vsprintf, - scan: - (ctx: NetscriptContext) => - (_hostname: unknown = ctx.workerScript.hostname): string[] => { - const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - const out = []; - for (let i = 0; i < server.serversOnNetwork.length; i++) { - const s = getServerOnNetwork(server, i); - if (s === null) continue; - const entry = s.hostname; - if (entry === null) continue; - out.push(entry); - } - helpers.log(ctx, () => `returned ${server.serversOnNetwork.length} connections for ${server.hostname}`); - return out; - }, + scan: (ctx) => (_hostname) => { + const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname; + const server = helpers.getServer(ctx, hostname); + const out: string[] = []; + for (let i = 0; i < server.serversOnNetwork.length; i++) { + const s = getServerOnNetwork(server, i); + if (s === null) continue; + const entry = s.hostname; + if (entry === null) continue; + out.push(entry); + } + helpers.log(ctx, () => `returned ${server.serversOnNetwork.length} connections for ${server.hostname}`); + return out; + }, hack: - (ctx: NetscriptContext) => - (_hostname: unknown, { threads: requestedThreads, stock }: BasicHGWOptions = {}): Promise => { + (ctx) => + (_hostname, opts = {}) => { const hostname = helpers.string(ctx, "hostname", _hostname); - return helpers.hack(ctx, hostname, false, { threads: requestedThreads, stock: stock }); + const optsValidator: BasicHGWOptions = {}; + assertObjectType(ctx, "opts", opts, optsValidator); + return helpers.hack(ctx, hostname, false, { threads: opts.threads, stock: opts.stock }); }, - hackAnalyzeThreads: - (ctx: NetscriptContext) => - (_hostname: unknown, _hackAmount: unknown): number => { - const hostname = helpers.string(ctx, "hostname", _hostname); - const hackAmount = helpers.number(ctx, "hackAmount", _hackAmount); + hackAnalyzeThreads: (ctx) => (_hostname, _hackAmount) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + const hackAmount = helpers.number(ctx, "hackAmount", _hackAmount); - // Check argument validity + // Check argument validity + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return -1; + } + if (isNaN(hackAmount)) { + throw helpers.makeRuntimeErrorMsg( + ctx, + `Invalid hackAmount argument passed into hackAnalyzeThreads: ${hackAmount}. Must be numeric.`, + ); + } + + if (hackAmount < 0 || hackAmount > server.moneyAvailable) { + return -1; + } else if (hackAmount === 0) { + return 0; + } + + const percentHacked = calculatePercentMoneyHacked(server, Player); + + if (percentHacked === 0 || server.moneyAvailable === 0) { + return 0; // To prevent returning infinity below + } + + return hackAmount / Math.floor(server.moneyAvailable * percentHacked); + }, + hackAnalyze: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return 0; + } + + return calculatePercentMoneyHacked(server, Player); + }, + hackAnalyzeSecurity: (ctx) => (_threads, _hostname?) => { + let threads = helpers.number(ctx, "threads", _threads); + if (_hostname) { + const hostname = helpers.string(ctx, "hostname", _hostname); const server = helpers.getServer(ctx, hostname); if (!(server instanceof Server)) { helpers.log(ctx, () => "Cannot be executed on this server."); - return -1; - } - if (isNaN(hackAmount)) { - throw helpers.makeRuntimeErrorMsg( - ctx, - `Invalid hackAmount argument passed into hackAnalyzeThreads: ${hackAmount}. Must be numeric.`, - ); - } - - if (hackAmount < 0 || hackAmount > server.moneyAvailable) { - return -1; - } else if (hackAmount === 0) { return 0; } const percentHacked = calculatePercentMoneyHacked(server, Player); - if (percentHacked === 0 || server.moneyAvailable === 0) { - return 0; // To prevent returning infinity below + if (percentHacked > 0) { + // thread count is limited to the maximum number of threads needed + threads = Math.min(threads, Math.ceil(1 / percentHacked)); } + } - return hackAmount / Math.floor(server.moneyAvailable * percentHacked); - }, - hackAnalyze: - (ctx: NetscriptContext) => - (_hostname: unknown): number => { - const hostname = helpers.string(ctx, "hostname", _hostname); + return CONSTANTS.ServerFortifyAmount * threads; + }, + hackAnalyzeChance: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return 0; - } + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return 0; + } - return calculatePercentMoneyHacked(server, Player); - }, - hackAnalyzeSecurity: - (ctx: NetscriptContext) => - (_threads: unknown, _hostname?: unknown): number => { - let threads = helpers.number(ctx, "threads", _threads); - if (_hostname) { - const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return 0; - } - - const percentHacked = calculatePercentMoneyHacked(server, Player); - - if (percentHacked > 0) { - // thread count is limited to the maximum number of threads needed - threads = Math.min(threads, Math.ceil(1 / percentHacked)); - } - } - - return CONSTANTS.ServerFortifyAmount * threads; - }, - hackAnalyzeChance: - (ctx: NetscriptContext) => - (_hostname: unknown): number => { - const hostname = helpers.string(ctx, "hostname", _hostname); - - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return 0; - } - - return calculateHackingChance(server, Player); - }, + return calculateHackingChance(server, Player); + }, sleep: - (ctx: NetscriptContext) => - async (_time: unknown = 0): Promise => { + (ctx) => + (_time = 0) => { const time = helpers.number(ctx, "time", _time); if (time === undefined) { throw helpers.makeRuntimeErrorMsg(ctx, "Takes 1 argument."); @@ -232,20 +212,24 @@ const base: InternalAPI = { return Promise.resolve(true); }); }, - asleep: (ctx: NetscriptContext) => - function (_time: unknown = 0): Promise { + asleep: + (ctx) => + (_time = 0) => { const time = helpers.number(ctx, "time", _time); helpers.log(ctx, () => `Sleeping for ${time} milliseconds`); return new Promise((resolve) => setTimeout(() => resolve(true), time)); }, grow: - (ctx: NetscriptContext) => - async (_hostname: unknown, { threads: requestedThreads, stock }: BasicHGWOptions = {}): Promise => { + (ctx) => + (_hostname, opts = {}) => { const hostname = helpers.string(ctx, "hostname", _hostname); - const threads = helpers.resolveNetscriptRequestedThreads( - ctx, - requestedThreads ?? ctx.workerScript.scriptRef.threads, - ); + const optsValidator: BasicHGWOptions = {}; + assertObjectType(ctx, "opts", opts, optsValidator); + const requestedThreads = + opts.threads === undefined + ? ctx.workerScript.scriptRef.threads + : helpers.number(ctx, "opts.threads", opts.threads); + const threads = helpers.resolveNetscriptRequestedThreads(ctx, requestedThreads); const server = helpers.getServer(ctx, hostname); if (!(server instanceof Server)) { @@ -290,15 +274,15 @@ const base: InternalAPI = { ); ctx.workerScript.scriptRef.onlineExpGained += expGain; Player.gainHackingExp(expGain); - if (stock) { + if (opts.stock) { influenceStockThroughServerGrow(server, moneyAfter - moneyBefore); } return Promise.resolve(moneyAfter / moneyBefore); }); }, growthAnalyze: - (ctx: NetscriptContext) => - (_hostname: unknown, _growth: unknown, _cores: unknown = 1): number => { + (ctx) => + (_hostname, _growth, _cores = 1) => { const hostname = helpers.string(ctx, "hostname", _hostname); const growth = helpers.number(ctx, "growth", _growth); const cores = helpers.number(ctx, "cores", _cores); @@ -316,8 +300,8 @@ const base: InternalAPI = { return numCycleForGrowth(server, Number(growth), cores); }, growthAnalyzeSecurity: - (ctx: NetscriptContext) => - (_threads: unknown, _hostname?: unknown, _cores: unknown = 1): number => { + (ctx) => + (_threads, _hostname?, _cores = 1) => { let threads = helpers.number(ctx, "threads", _threads); if (_hostname) { const cores = helpers.number(ctx, "cores", _cores); @@ -339,16 +323,17 @@ const base: InternalAPI = { return 2 * CONSTANTS.ServerFortifyAmount * threads; }, weaken: - (ctx: NetscriptContext) => - async (_hostname: unknown, { threads: requestedThreads }: BasicHGWOptions = {}): Promise => { + (ctx) => + async (_hostname, opts = {}) => { const hostname = helpers.string(ctx, "hostname", _hostname); - const threads = helpers.resolveNetscriptRequestedThreads( - ctx, - requestedThreads ?? ctx.workerScript.scriptRef.threads, - ); - if (hostname === undefined) { - throw helpers.makeRuntimeErrorMsg(ctx, "Takes 1 argument."); - } + const optsValidator: BasicHGWOptions = {}; + assertObjectType(ctx, "opts", opts, optsValidator); + const requestedThreads = + opts.threads === undefined + ? ctx.workerScript.scriptRef.threads + : helpers.number(ctx, "opts.threads", opts.threads); + const threads = helpers.resolveNetscriptRequestedThreads(ctx, requestedThreads); + const server = helpers.getServer(ctx, hostname); if (!(server instanceof Server)) { helpers.log(ctx, () => "Cannot be executed on this server."); @@ -393,14 +378,14 @@ const base: InternalAPI = { }); }, weakenAnalyze: - (ctx: NetscriptContext) => - (_threads: unknown, _cores: unknown = 1): number => { + (ctx) => + (_threads, _cores = 1) => { const threads = helpers.number(ctx, "threads", _threads); const cores = helpers.number(ctx, "cores", _cores); const coreBonus = 1 + (cores - 1) / 16; return CONSTANTS.ServerWeakenAmount * threads * coreBonus * BitNodeMultipliers.ServerWeakenRate; }, - share: (ctx: NetscriptContext) => async (): Promise => { + share: (ctx) => () => { helpers.log(ctx, () => "Sharing this computer."); const end = StartSharing( ctx.workerScript.scriptRef.threads * calculateIntelligenceBonus(Player.skills.intelligence, 2), @@ -410,20 +395,20 @@ const base: InternalAPI = { end(); }); }, - getSharePower: () => (): number => { + getSharePower: () => () => { return CalculateShareMult(); }, print: - (ctx: NetscriptContext) => - (...args: unknown[]): void => { + (ctx) => + (...args) => { if (args.length === 0) { throw helpers.makeRuntimeErrorMsg(ctx, "Takes at least 1 argument."); } ctx.workerScript.print(helpers.argsToString(args)); }, printf: - (ctx: NetscriptContext) => - (_format: unknown, ...args: unknown[]): void => { + (ctx) => + (_format, ...args) => { const format = helpers.string(ctx, "format", _format); if (typeof format !== "string") { throw helpers.makeRuntimeErrorMsg(ctx, "First argument must be string for the format."); @@ -431,8 +416,8 @@ const base: InternalAPI = { ctx.workerScript.print(vsprintf(format, args)); }, tprint: - (ctx: NetscriptContext) => - (...args: unknown[]): void => { + (ctx) => + (...args) => { if (args.length === 0) { throw helpers.makeRuntimeErrorMsg(ctx, "Takes at least 1 argument."); } @@ -456,8 +441,8 @@ const base: InternalAPI = { Terminal.print(`${ctx.workerScript.scriptRef.filename}: ${str}`); }, tprintf: - (ctx: NetscriptContext) => - (_format: unknown, ...args: unknown[]): void => { + (ctx) => + (_format, ...args) => { const format = helpers.string(ctx, "format", _format); const str = vsprintf(format, args); @@ -479,64 +464,58 @@ const base: InternalAPI = { } Terminal.print(`${str}`); }, - clearLog: (ctx: NetscriptContext) => (): void => { + clearLog: (ctx) => () => { ctx.workerScript.scriptRef.clearLog(); }, - disableLog: - (ctx: NetscriptContext) => - (_fn: unknown): void => { - const fn = helpers.string(ctx, "fn", _fn); - if (fn === "ALL") { - for (const fn of Object.keys(possibleLogs)) { - ctx.workerScript.disableLogs[fn] = true; - } - helpers.log(ctx, () => `Disabled logging for all functions`); - } else if (possibleLogs[fn] === undefined) { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid argument: ${fn}.`); - } else { + disableLog: (ctx) => (_fn) => { + const fn = helpers.string(ctx, "fn", _fn); + if (fn === "ALL") { + for (const fn of Object.keys(possibleLogs)) { ctx.workerScript.disableLogs[fn] = true; - helpers.log(ctx, () => `Disabled logging for ${fn}`); } - }, - enableLog: - (ctx: NetscriptContext) => - (_fn: unknown): void => { - const fn = helpers.string(ctx, "fn", _fn); - if (fn === "ALL") { - for (const fn of Object.keys(possibleLogs)) { - delete ctx.workerScript.disableLogs[fn]; - } - helpers.log(ctx, () => `Enabled logging for all functions`); - } else if (possibleLogs[fn] === undefined) { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid argument: ${fn}.`); + helpers.log(ctx, () => `Disabled logging for all functions`); + } else if (possibleLogs[fn] === undefined) { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid argument: ${fn}.`); + } else { + ctx.workerScript.disableLogs[fn] = true; + helpers.log(ctx, () => `Disabled logging for ${fn}`); + } + }, + enableLog: (ctx) => (_fn) => { + const fn = helpers.string(ctx, "fn", _fn); + if (fn === "ALL") { + for (const fn of Object.keys(possibleLogs)) { + delete ctx.workerScript.disableLogs[fn]; } - delete ctx.workerScript.disableLogs[fn]; - helpers.log(ctx, () => `Enabled logging for ${fn}`); - }, - isLogEnabled: - (ctx: NetscriptContext) => - (_fn: unknown): boolean => { - const fn = helpers.string(ctx, "fn", _fn); - if (possibleLogs[fn] === undefined) { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid argument: ${fn}.`); - } - return !ctx.workerScript.disableLogs[fn]; - }, + helpers.log(ctx, () => `Enabled logging for all functions`); + } else if (possibleLogs[fn] === undefined) { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid argument: ${fn}.`); + } + delete ctx.workerScript.disableLogs[fn]; + helpers.log(ctx, () => `Enabled logging for ${fn}`); + }, + isLogEnabled: (ctx) => (_fn) => { + const fn = helpers.string(ctx, "fn", _fn); + if (possibleLogs[fn] === undefined) { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid argument: ${fn}.`); + } + return !ctx.workerScript.disableLogs[fn]; + }, getScriptLogs: - (ctx: NetscriptContext) => - (scriptID: unknown, hostname: unknown, ...scriptArgs: unknown[]): string[] => { + (ctx) => + (scriptID, hostname, ...scriptArgs) => { const ident = helpers.scriptIdentifier(ctx, scriptID, hostname, scriptArgs); const runningScriptObj = helpers.getRunningScript(ctx, ident); if (runningScriptObj == null) { helpers.log(ctx, () => helpers.getCannotFindRunningScriptErrorMessage(ident)); - return []; + return [] as string[]; } return runningScriptObj.logs.slice(); }, tail: - (ctx: NetscriptContext) => - (scriptID: unknown, hostname: unknown, ...scriptArgs: unknown[]): void => { + (ctx) => + (scriptID, hostname, ...scriptArgs) => { const ident = helpers.scriptIdentifier(ctx, scriptID, hostname, scriptArgs); const runningScriptObj = helpers.getRunningScript(ctx, ident); if (runningScriptObj == null) { @@ -547,172 +526,160 @@ const base: InternalAPI = { LogBoxEvents.emit(runningScriptObj); }, moveTail: - (ctx: NetscriptContext) => - (_x: unknown, _y: unknown, _pid: unknown = ctx.workerScript.scriptRef.pid) => { + (ctx) => + (_x, _y, _pid = ctx.workerScript.scriptRef.pid) => { const x = helpers.number(ctx, "x", _x); const y = helpers.number(ctx, "y", _y); const pid = helpers.number(ctx, "pid", _pid); LogBoxPositionEvents.emit({ pid, data: { x, y } }); }, resizeTail: - (ctx: NetscriptContext) => - (_w: unknown, _h: unknown, _pid: unknown = ctx.workerScript.scriptRef.pid) => { + (ctx) => + (_w, _h, _pid = ctx.workerScript.scriptRef.pid) => { const w = helpers.number(ctx, "w", _w); const h = helpers.number(ctx, "h", _h); const pid = helpers.number(ctx, "pid", _pid); LogBoxSizeEvents.emit({ pid, data: { w, h } }); }, closeTail: - (ctx: NetscriptContext) => - (_pid: unknown = ctx.workerScript.scriptRef.pid): void => { + (ctx) => + (_pid = ctx.workerScript.scriptRef.pid) => { const pid = helpers.number(ctx, "pid", _pid); //Emit an event to tell the game to close the tail window if it exists LogBoxCloserEvents.emit(pid); }, - nuke: - (ctx: NetscriptContext) => - (_hostname: unknown): boolean => { - const hostname = helpers.string(ctx, "hostname", _hostname); + nuke: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return false; - } - if (server.hasAdminRights) { - helpers.log(ctx, () => `Already have root access to '${server.hostname}'.`); - return true; - } - if (!Player.hasProgram(Programs.NukeProgram.name)) { - throw helpers.makeRuntimeErrorMsg(ctx, "You do not have the NUKE.exe virus!"); - } - if (server.openPortCount < server.numOpenPortsRequired) { - throw helpers.makeRuntimeErrorMsg(ctx, "Not enough ports opened to use NUKE.exe virus."); - } - server.hasAdminRights = true; - helpers.log(ctx, () => `Executed NUKE.exe virus on '${server.hostname}' to gain root access.`); + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return false; + } + if (server.hasAdminRights) { + helpers.log(ctx, () => `Already have root access to '${server.hostname}'.`); return true; - }, - brutessh: - (ctx: NetscriptContext) => - (_hostname: unknown): boolean => { - const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return false; - } - if (!Player.hasProgram(Programs.BruteSSHProgram.name)) { - throw helpers.makeRuntimeErrorMsg(ctx, "You do not have the BruteSSH.exe program!"); - } - if (!server.sshPortOpen) { - helpers.log(ctx, () => `Executed BruteSSH.exe on '${server.hostname}' to open SSH port (22).`); - server.sshPortOpen = true; - ++server.openPortCount; - } else { - helpers.log(ctx, () => `SSH Port (22) already opened on '${server.hostname}'.`); - } - return true; - }, - ftpcrack: - (ctx: NetscriptContext) => - (_hostname: unknown): boolean => { - const hostname = helpers.string(ctx, "hostname", _hostname); - if (hostname === undefined) { - throw helpers.makeRuntimeErrorMsg(ctx, "Takes 1 argument."); - } - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return false; - } - if (!Player.hasProgram(Programs.FTPCrackProgram.name)) { - throw helpers.makeRuntimeErrorMsg(ctx, "You do not have the FTPCrack.exe program!"); - } - if (!server.ftpPortOpen) { - helpers.log(ctx, () => `Executed FTPCrack.exe on '${server.hostname}' to open FTP port (21).`); - server.ftpPortOpen = true; - ++server.openPortCount; - } else { - helpers.log(ctx, () => `FTP Port (21) already opened on '${server.hostname}'.`); - } - return true; - }, - relaysmtp: - (ctx: NetscriptContext) => - (_hostname: unknown): boolean => { - const hostname = helpers.string(ctx, "hostname", _hostname); - if (hostname === undefined) { - throw helpers.makeRuntimeErrorMsg(ctx, "Takes 1 argument."); - } - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return false; - } - if (!Player.hasProgram(Programs.RelaySMTPProgram.name)) { - throw helpers.makeRuntimeErrorMsg(ctx, "You do not have the relaySMTP.exe program!"); - } - if (!server.smtpPortOpen) { - helpers.log(ctx, () => `Executed relaySMTP.exe on '${server.hostname}' to open SMTP port (25).`); - server.smtpPortOpen = true; - ++server.openPortCount; - } else { - helpers.log(ctx, () => `SMTP Port (25) already opened on '${server.hostname}'.`); - } - return true; - }, - httpworm: - (ctx: NetscriptContext) => - (_hostname: unknown): boolean => { - const hostname = helpers.string(ctx, "hostname", _hostname); - if (hostname === undefined) { - throw helpers.makeRuntimeErrorMsg(ctx, "Takes 1 argument"); - } - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return false; - } - if (!Player.hasProgram(Programs.HTTPWormProgram.name)) { - throw helpers.makeRuntimeErrorMsg(ctx, "You do not have the HTTPWorm.exe program!"); - } - if (!server.httpPortOpen) { - helpers.log(ctx, () => `Executed HTTPWorm.exe on '${server.hostname}' to open HTTP port (80).`); - server.httpPortOpen = true; - ++server.openPortCount; - } else { - helpers.log(ctx, () => `HTTP Port (80) already opened on '${server.hostname}'.`); - } - return true; - }, - sqlinject: - (ctx: NetscriptContext) => - (_hostname: unknown): boolean => { - const hostname = helpers.string(ctx, "hostname", _hostname); - if (hostname === undefined) { - throw helpers.makeRuntimeErrorMsg(ctx, "Takes 1 argument."); - } - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return false; - } - if (!Player.hasProgram(Programs.SQLInjectProgram.name)) { - throw helpers.makeRuntimeErrorMsg(ctx, "You do not have the SQLInject.exe program!"); - } - if (!server.sqlPortOpen) { - helpers.log(ctx, () => `Executed SQLInject.exe on '${server.hostname}' to open SQL port (1433).`); - server.sqlPortOpen = true; - ++server.openPortCount; - } else { - helpers.log(ctx, () => `SQL Port (1433) already opened on '${server.hostname}'.`); - } - return true; - }, + } + if (!Player.hasProgram(Programs.NukeProgram.name)) { + throw helpers.makeRuntimeErrorMsg(ctx, "You do not have the NUKE.exe virus!"); + } + if (server.openPortCount < server.numOpenPortsRequired) { + throw helpers.makeRuntimeErrorMsg(ctx, "Not enough ports opened to use NUKE.exe virus."); + } + server.hasAdminRights = true; + helpers.log(ctx, () => `Executed NUKE.exe virus on '${server.hostname}' to gain root access.`); + return true; + }, + brutessh: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return false; + } + if (!Player.hasProgram(Programs.BruteSSHProgram.name)) { + throw helpers.makeRuntimeErrorMsg(ctx, "You do not have the BruteSSH.exe program!"); + } + if (!server.sshPortOpen) { + helpers.log(ctx, () => `Executed BruteSSH.exe on '${server.hostname}' to open SSH port (22).`); + server.sshPortOpen = true; + ++server.openPortCount; + } else { + helpers.log(ctx, () => `SSH Port (22) already opened on '${server.hostname}'.`); + } + return true; + }, + ftpcrack: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + if (hostname === undefined) { + throw helpers.makeRuntimeErrorMsg(ctx, "Takes 1 argument."); + } + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return false; + } + if (!Player.hasProgram(Programs.FTPCrackProgram.name)) { + throw helpers.makeRuntimeErrorMsg(ctx, "You do not have the FTPCrack.exe program!"); + } + if (!server.ftpPortOpen) { + helpers.log(ctx, () => `Executed FTPCrack.exe on '${server.hostname}' to open FTP port (21).`); + server.ftpPortOpen = true; + ++server.openPortCount; + } else { + helpers.log(ctx, () => `FTP Port (21) already opened on '${server.hostname}'.`); + } + return true; + }, + relaysmtp: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + if (hostname === undefined) { + throw helpers.makeRuntimeErrorMsg(ctx, "Takes 1 argument."); + } + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return false; + } + if (!Player.hasProgram(Programs.RelaySMTPProgram.name)) { + throw helpers.makeRuntimeErrorMsg(ctx, "You do not have the relaySMTP.exe program!"); + } + if (!server.smtpPortOpen) { + helpers.log(ctx, () => `Executed relaySMTP.exe on '${server.hostname}' to open SMTP port (25).`); + server.smtpPortOpen = true; + ++server.openPortCount; + } else { + helpers.log(ctx, () => `SMTP Port (25) already opened on '${server.hostname}'.`); + } + return true; + }, + httpworm: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + if (hostname === undefined) { + throw helpers.makeRuntimeErrorMsg(ctx, "Takes 1 argument"); + } + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return false; + } + if (!Player.hasProgram(Programs.HTTPWormProgram.name)) { + throw helpers.makeRuntimeErrorMsg(ctx, "You do not have the HTTPWorm.exe program!"); + } + if (!server.httpPortOpen) { + helpers.log(ctx, () => `Executed HTTPWorm.exe on '${server.hostname}' to open HTTP port (80).`); + server.httpPortOpen = true; + ++server.openPortCount; + } else { + helpers.log(ctx, () => `HTTP Port (80) already opened on '${server.hostname}'.`); + } + return true; + }, + sqlinject: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + if (hostname === undefined) { + throw helpers.makeRuntimeErrorMsg(ctx, "Takes 1 argument."); + } + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return false; + } + if (!Player.hasProgram(Programs.SQLInjectProgram.name)) { + throw helpers.makeRuntimeErrorMsg(ctx, "You do not have the SQLInject.exe program!"); + } + if (!server.sqlPortOpen) { + helpers.log(ctx, () => `Executed SQLInject.exe on '${server.hostname}' to open SQL port (1433).`); + server.sqlPortOpen = true; + ++server.openPortCount; + } else { + helpers.log(ctx, () => `SQL Port (1433) already opened on '${server.hostname}'.`); + } + return true; + }, run: - (ctx: NetscriptContext) => - (_scriptname: unknown, _threads: unknown = 1, ..._args: unknown[]): number => { + (ctx) => + (_scriptname, _threads = 1, ..._args) => { const scriptname = helpers.string(ctx, "scriptname", _scriptname); const threads = helpers.number(ctx, "threads", _threads); const args = helpers.scriptArgs(ctx, _args); @@ -730,8 +697,8 @@ const base: InternalAPI = { return runScriptFromScript("run", scriptServer, scriptname, args, ctx.workerScript, threads); }, exec: - (ctx: NetscriptContext) => - (_scriptname: unknown, _hostname: unknown, _threads: unknown = 1, ..._args: unknown[]): number => { + (ctx) => + (_scriptname, _hostname, _threads = 1, ..._args) => { const scriptname = helpers.string(ctx, "scriptname", _scriptname); const hostname = helpers.string(ctx, "hostname", _hostname); const threads = helpers.number(ctx, "threads", _threads); @@ -746,8 +713,8 @@ const base: InternalAPI = { return runScriptFromScript("exec", server, scriptname, args, ctx.workerScript, threads); }, spawn: - (ctx: NetscriptContext) => - (_scriptname: unknown, _threads: unknown = 1, ..._args: unknown[]): void => { + (ctx) => + (_scriptname, _threads = 1, ..._args) => { const scriptname = helpers.string(ctx, "scriptname", _scriptname); const threads = helpers.number(ctx, "threads", _threads); const args = helpers.scriptArgs(ctx, _args); @@ -775,8 +742,8 @@ const base: InternalAPI = { } }, kill: - (ctx: NetscriptContext) => - (scriptID: unknown, hostname: unknown, ...scriptArgs: unknown[]): boolean => { + (ctx) => + (scriptID, hostname?, ...scriptArgs) => { const ident = helpers.scriptIdentifier(ctx, scriptID, hostname, scriptArgs); let res; const killByPid = typeof ident === "number"; @@ -819,8 +786,8 @@ const base: InternalAPI = { } }, killall: - (ctx: NetscriptContext) => - (_hostname: unknown = ctx.workerScript.hostname, _safetyguard: unknown = true): boolean => { + (ctx) => + (_hostname = ctx.workerScript.hostname, _safetyguard = true) => { const hostname = helpers.string(ctx, "hostname", _hostname); const safetyguard = !!_safetyguard; if (hostname === undefined) { @@ -843,14 +810,14 @@ const base: InternalAPI = { return scriptsKilled > 0; }, - exit: (ctx: NetscriptContext) => (): never => { + exit: (ctx) => () => { helpers.log(ctx, () => "Exiting..."); killWorkerScript(ctx.workerScript); throw new ScriptDeath(ctx.workerScript); }, scp: - (ctx: NetscriptContext) => - (_files: unknown, _destination: unknown, _source: unknown = ctx.workerScript.hostname): boolean => { + (ctx) => + (_files, _destination, _source = ctx.workerScript.hostname) => { const destination = helpers.string(ctx, "destination", _destination); const source = helpers.string(ctx, "source", _source); const destServer = helpers.getServer(ctx, destination); @@ -952,8 +919,8 @@ const base: InternalAPI = { return noFailures; }, ls: - (ctx: NetscriptContext) => - (_hostname: unknown, _grep: unknown = ""): string[] => { + (ctx) => + (_hostname, _grep = ""): string[] => { const hostname = helpers.string(ctx, "hostname", _hostname); const grep = helpers.string(ctx, "grep", _grep); @@ -1026,11 +993,11 @@ const base: InternalAPI = { })); }, ps: - (ctx: NetscriptContext) => - (_hostname: unknown = ctx.workerScript.hostname): ProcessInfo[] => { + (ctx) => + (_hostname = ctx.workerScript.hostname) => { const hostname = helpers.string(ctx, "hostname", _hostname); const server = helpers.getServer(ctx, hostname); - const processes = []; + const processes: ProcessInfo[] = []; for (const script of server.runningScripts) { processes.push({ filename: script.filename, @@ -1041,21 +1008,19 @@ const base: InternalAPI = { } return processes; }, - hasRootAccess: - (ctx: NetscriptContext) => - (_hostname: unknown): boolean => { - const hostname = helpers.string(ctx, "hostname", _hostname); + hasRootAccess: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - return server.hasAdminRights; - }, - getHostname: (ctx: NetscriptContext) => (): string => ctx.workerScript.hostname, - getHackingLevel: (ctx: NetscriptContext) => (): number => { + const server = helpers.getServer(ctx, hostname); + return server.hasAdminRights; + }, + getHostname: (ctx) => () => ctx.workerScript.hostname, + getHackingLevel: (ctx) => () => { Player.updateSkillLevels(); helpers.log(ctx, () => `returned ${Player.skills.hacking}`); return Player.skills.hacking; }, - getHackingMultipliers: () => (): HackingMultipliers => { + getHackingMultipliers: () => () => { return { chance: Player.mults.hacking_chance, speed: Player.mults.hacking_speed, @@ -1063,7 +1028,7 @@ const base: InternalAPI = { growth: Player.mults.hacking_grow, }; }, - getHacknetMultipliers: () => (): HacknetMultipliers => { + getHacknetMultipliers: () => () => { return { production: Player.mults.hacknet_node_money, purchaseCost: Player.mults.hacknet_node_purchase_cost, @@ -1072,7 +1037,7 @@ const base: InternalAPI = { levelCost: Player.mults.hacknet_node_level_cost, }; }, - getBitNodeMultipliers: (ctx: NetscriptContext) => (): IBNMults => { + getBitNodeMultipliers: (ctx) => () => { if (Player.sourceFileLvl(5) <= 0 && Player.bitNodeN !== 5) { throw helpers.makeRuntimeErrorMsg(ctx, "Requires Source-File 5 to run."); } @@ -1080,8 +1045,8 @@ const base: InternalAPI = { return copy; }, getServer: - (ctx: NetscriptContext) => - (_hostname: unknown = ctx.workerScript.hostname): IServerDef => { + (ctx) => + (_hostname = ctx.workerScript.hostname) => { const hostname = helpers.string(ctx, "hostname", _hostname); const server = helpers.getServer(ctx, hostname); const copy = Object.assign({}, server) as Server; @@ -1104,147 +1069,131 @@ const base: InternalAPI = { if (!copy.serverGrowth) copy.serverGrowth = 0; return copy; }, - getServerMoneyAvailable: - (ctx: NetscriptContext) => - (_hostname: unknown): number => { - const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return 0; - } - if (helpers.failOnHacknetServer(ctx, server)) { - return 0; - } - if (server.hostname == "home") { - // Return player's money - helpers.log(ctx, () => `returned player's money: ${numeralWrapper.formatMoney(Player.money)}`); - return Player.money; - } - helpers.log(ctx, () => `returned ${numeralWrapper.formatMoney(server.moneyAvailable)} for '${server.hostname}'`); - return server.moneyAvailable; - }, - getServerSecurityLevel: - (ctx: NetscriptContext) => - (_hostname: unknown): number => { - const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return 1; - } - if (helpers.failOnHacknetServer(ctx, server)) { - return 1; - } - helpers.log( - ctx, - () => `returned ${numeralWrapper.formatServerSecurity(server.hackDifficulty)} for '${server.hostname}'`, - ); - return server.hackDifficulty; - }, - getServerBaseSecurityLevel: - (ctx: NetscriptContext) => - (_hostname: unknown): number => { - const hostname = helpers.string(ctx, "hostname", _hostname); - helpers.log(ctx, () => `getServerBaseSecurityLevel is deprecated because it's not useful.`); - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return 1; - } - if (helpers.failOnHacknetServer(ctx, server)) { - return 1; - } - helpers.log( - ctx, - () => `returned ${numeralWrapper.formatServerSecurity(server.baseDifficulty)} for '${server.hostname}'`, - ); - return server.baseDifficulty; - }, - getServerMinSecurityLevel: - (ctx: NetscriptContext) => - (_hostname: unknown): number => { - const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return 1; - } - if (helpers.failOnHacknetServer(ctx, server)) { - return 1; - } - helpers.log( - ctx, - () => `returned ${numeralWrapper.formatServerSecurity(server.minDifficulty)} for ${server.hostname}`, - ); - return server.minDifficulty; - }, - getServerRequiredHackingLevel: - (ctx: NetscriptContext) => - (_hostname: unknown): number => { - const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return 1; - } - if (helpers.failOnHacknetServer(ctx, server)) { - return 1; - } - helpers.log( - ctx, - () => `returned ${numeralWrapper.formatSkill(server.requiredHackingSkill)} for '${server.hostname}'`, - ); - return server.requiredHackingSkill; - }, - getServerMaxMoney: - (ctx: NetscriptContext) => - (_hostname: unknown): number => { - const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return 0; - } - if (helpers.failOnHacknetServer(ctx, server)) { - return 0; - } - helpers.log(ctx, () => `returned ${numeralWrapper.formatMoney(server.moneyMax)} for '${server.hostname}'`); - return server.moneyMax; - }, - getServerGrowth: - (ctx: NetscriptContext) => - (_hostname: unknown): number => { - const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return 1; - } - if (helpers.failOnHacknetServer(ctx, server)) { - return 1; - } - helpers.log(ctx, () => `returned ${server.serverGrowth} for '${server.hostname}'`); - return server.serverGrowth; - }, - getServerNumPortsRequired: - (ctx: NetscriptContext) => - (_hostname: unknown): number => { - const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - if (!(server instanceof Server)) { - helpers.log(ctx, () => "Cannot be executed on this server."); - return 5; - } - if (helpers.failOnHacknetServer(ctx, server)) { - return 5; - } - helpers.log(ctx, () => `returned ${server.numOpenPortsRequired} for '${server.hostname}'`); - return server.numOpenPortsRequired; - }, + getServerMoneyAvailable: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return 0; + } + if (helpers.failOnHacknetServer(ctx, server)) { + return 0; + } + if (server.hostname == "home") { + // Return player's money + helpers.log(ctx, () => `returned player's money: ${numeralWrapper.formatMoney(Player.money)}`); + return Player.money; + } + helpers.log(ctx, () => `returned ${numeralWrapper.formatMoney(server.moneyAvailable)} for '${server.hostname}'`); + return server.moneyAvailable; + }, + getServerSecurityLevel: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return 1; + } + if (helpers.failOnHacknetServer(ctx, server)) { + return 1; + } + helpers.log( + ctx, + () => `returned ${numeralWrapper.formatServerSecurity(server.hackDifficulty)} for '${server.hostname}'`, + ); + return server.hackDifficulty; + }, + getServerBaseSecurityLevel: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + helpers.log(ctx, () => `getServerBaseSecurityLevel is deprecated because it's not useful.`); + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return 1; + } + if (helpers.failOnHacknetServer(ctx, server)) { + return 1; + } + helpers.log( + ctx, + () => `returned ${numeralWrapper.formatServerSecurity(server.baseDifficulty)} for '${server.hostname}'`, + ); + return server.baseDifficulty; + }, + getServerMinSecurityLevel: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return 1; + } + if (helpers.failOnHacknetServer(ctx, server)) { + return 1; + } + helpers.log( + ctx, + () => `returned ${numeralWrapper.formatServerSecurity(server.minDifficulty)} for ${server.hostname}`, + ); + return server.minDifficulty; + }, + getServerRequiredHackingLevel: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return 1; + } + if (helpers.failOnHacknetServer(ctx, server)) { + return 1; + } + helpers.log( + ctx, + () => `returned ${numeralWrapper.formatSkill(server.requiredHackingSkill)} for '${server.hostname}'`, + ); + return server.requiredHackingSkill; + }, + getServerMaxMoney: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return 0; + } + if (helpers.failOnHacknetServer(ctx, server)) { + return 0; + } + helpers.log(ctx, () => `returned ${numeralWrapper.formatMoney(server.moneyMax)} for '${server.hostname}'`); + return server.moneyMax; + }, + getServerGrowth: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return 1; + } + if (helpers.failOnHacknetServer(ctx, server)) { + return 1; + } + helpers.log(ctx, () => `returned ${server.serverGrowth} for '${server.hostname}'`); + return server.serverGrowth; + }, + getServerNumPortsRequired: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + const server = helpers.getServer(ctx, hostname); + if (!(server instanceof Server)) { + helpers.log(ctx, () => "Cannot be executed on this server."); + return 5; + } + if (helpers.failOnHacknetServer(ctx, server)) { + return 5; + } + helpers.log(ctx, () => `returned ${server.numOpenPortsRequired} for '${server.hostname}'`); + return server.numOpenPortsRequired; + }, getServerRam: - (ctx: NetscriptContext) => - (_hostname: unknown): [number, number] => { + (ctx) => + (_hostname): [number, number] => { const hostname = helpers.string(ctx, "hostname", _hostname); helpers.log(ctx, () => `getServerRam is deprecated in favor of getServerMaxRam / getServerUsedRam`); const server = helpers.getServer(ctx, hostname); @@ -1254,31 +1203,25 @@ const base: InternalAPI = { ); return [server.maxRam, server.ramUsed]; }, - getServerMaxRam: - (ctx: NetscriptContext) => - (_hostname: unknown): number => { - const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - helpers.log(ctx, () => `returned ${numeralWrapper.formatRAM(server.maxRam)}`); - return server.maxRam; - }, - getServerUsedRam: - (ctx: NetscriptContext) => - (_hostname: unknown): number => { - const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - helpers.log(ctx, () => `returned ${numeralWrapper.formatRAM(server.ramUsed)}`); - return server.ramUsed; - }, - serverExists: - (ctx: NetscriptContext) => - (_hostname: unknown): boolean => { - const hostname = helpers.string(ctx, "hostname", _hostname); - return GetServer(hostname) !== null; - }, + getServerMaxRam: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + const server = helpers.getServer(ctx, hostname); + helpers.log(ctx, () => `returned ${numeralWrapper.formatRAM(server.maxRam)}`); + return server.maxRam; + }, + getServerUsedRam: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + const server = helpers.getServer(ctx, hostname); + helpers.log(ctx, () => `returned ${numeralWrapper.formatRAM(server.ramUsed)}`); + return server.ramUsed; + }, + serverExists: (ctx) => (_hostname) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + return GetServer(hostname) !== null; + }, fileExists: - (ctx: NetscriptContext) => - (_filename: unknown, _hostname: unknown = ctx.workerScript.hostname): boolean => { + (ctx) => + (_filename, _hostname = ctx.workerScript.hostname) => { const filename = helpers.string(ctx, "filename", _filename); const hostname = helpers.string(ctx, "hostname", _hostname); if (filename === undefined) { @@ -1306,201 +1249,189 @@ const base: InternalAPI = { return txtFile != null; }, isRunning: - (ctx: NetscriptContext) => - (fn: unknown, hostname: unknown, ...scriptArgs: unknown[]): boolean => { + (ctx) => + (fn, hostname, ...scriptArgs) => { const ident = helpers.scriptIdentifier(ctx, fn, hostname, scriptArgs); return helpers.getRunningScript(ctx, ident) !== null; }, - getPurchasedServerLimit: () => (): number => { + getPurchasedServerLimit: () => () => { return getPurchaseServerLimit(); }, - getPurchasedServerMaxRam: () => (): number => { + getPurchasedServerMaxRam: () => () => { return getPurchaseServerMaxRam(); }, - getPurchasedServerCost: - (ctx: NetscriptContext) => - (_ram: unknown): number => { - const ram = helpers.number(ctx, "ram", _ram); + getPurchasedServerCost: (ctx) => (_ram) => { + const ram = helpers.number(ctx, "ram", _ram); - const cost = getPurchaseServerCost(ram); - if (cost === Infinity) { - helpers.log(ctx, () => `Invalid argument: ram='${ram}'`); - return Infinity; - } + const cost = getPurchaseServerCost(ram); + if (cost === Infinity) { + helpers.log(ctx, () => `Invalid argument: ram='${ram}'`); + return Infinity; + } - return cost; - }, - purchaseServer: - (ctx: NetscriptContext) => - (_name: unknown, _ram: unknown): string => { - const name = helpers.string(ctx, "name", _name); - const ram = helpers.number(ctx, "ram", _ram); - let hostnameStr = String(name); - hostnameStr = hostnameStr.replace(/\s+/g, ""); - if (hostnameStr == "") { - helpers.log(ctx, () => `Invalid argument: hostname='${hostnameStr}'`); - return ""; - } + return cost; + }, + purchaseServer: (ctx) => (_name, _ram) => { + const name = helpers.string(ctx, "name", _name); + const ram = helpers.number(ctx, "ram", _ram); + let hostnameStr = String(name); + hostnameStr = hostnameStr.replace(/\s+/g, ""); + if (hostnameStr == "") { + helpers.log(ctx, () => `Invalid argument: hostname='${hostnameStr}'`); + return ""; + } - if (Player.purchasedServers.length >= getPurchaseServerLimit()) { - helpers.log( - ctx, - () => - `You have reached the maximum limit of ${getPurchaseServerLimit()} servers. You cannot purchase any more.`, - ); - return ""; - } - - const cost = getPurchaseServerCost(ram); - if (cost === Infinity) { - if (ram > getPurchaseServerMaxRam()) { - helpers.log(ctx, () => `Invalid argument: ram='${ram}' must not be greater than getPurchaseServerMaxRam`); - } else { - helpers.log(ctx, () => `Invalid argument: ram='${ram}' must be a positive power of 2`); - } - - return ""; - } - - if (Player.money < cost) { - helpers.log(ctx, () => `Not enough money to purchase server. Need ${numeralWrapper.formatMoney(cost)}`); - return ""; - } - const newServ = safelyCreateUniqueServer({ - ip: createUniqueRandomIp(), - hostname: hostnameStr, - organizationName: "", - isConnectedTo: false, - adminRights: true, - purchasedByPlayer: true, - maxRam: ram, - }); - AddToAllServers(newServ); - - Player.purchasedServers.push(newServ.hostname); - const homeComputer = Player.getHomeComputer(); - homeComputer.serversOnNetwork.push(newServ.hostname); - newServ.serversOnNetwork.push(homeComputer.hostname); - Player.loseMoney(cost, "servers"); + if (Player.purchasedServers.length >= getPurchaseServerLimit()) { helpers.log( ctx, - () => `Purchased new server with hostname '${newServ.hostname}' for ${numeralWrapper.formatMoney(cost)}`, + () => + `You have reached the maximum limit of ${getPurchaseServerLimit()} servers. You cannot purchase any more.`, ); - return newServ.hostname; - }, + return ""; + } - getPurchasedServerUpgradeCost: - (ctx: NetscriptContext) => - (_hostname: unknown, _ram: unknown): number => { - const hostname = helpers.string(ctx, "hostname", _hostname); - const ram = helpers.number(ctx, "ram", _ram); - try { - return getPurchasedServerUpgradeCost(hostname, ram); - } catch (err) { - helpers.log(ctx, () => String(err)); - return -1; - } - }, - upgradePurchasedServer: - (ctx: NetscriptContext) => - (_hostname: unknown, _ram: unknown): boolean => { - const hostname = helpers.string(ctx, "hostname", _hostname); - const ram = helpers.number(ctx, "ram", _ram); - try { - upgradePurchasedServer(hostname, ram); - return true; - } catch (err) { - helpers.log(ctx, () => String(err)); - return false; - } - }, - renamePurchasedServer: - (ctx: NetscriptContext) => - (_hostname: unknown, _newName: unknown): boolean => { - const hostname = helpers.string(ctx, "hostname", _hostname); - const newName = helpers.string(ctx, "newName", _newName); - try { - renamePurchasedServer(hostname, newName); - return true; - } catch (err) { - helpers.log(ctx, () => String(err)); - return false; + const cost = getPurchaseServerCost(ram); + if (cost === Infinity) { + if (ram > getPurchaseServerMaxRam()) { + helpers.log(ctx, () => `Invalid argument: ram='${ram}' must not be greater than getPurchaseServerMaxRam`); + } else { + helpers.log(ctx, () => `Invalid argument: ram='${ram}' must be a positive power of 2`); } + + return ""; + } + + if (Player.money < cost) { + helpers.log(ctx, () => `Not enough money to purchase server. Need ${numeralWrapper.formatMoney(cost)}`); + return ""; + } + const newServ = safelyCreateUniqueServer({ + ip: createUniqueRandomIp(), + hostname: hostnameStr, + organizationName: "", + isConnectedTo: false, + adminRights: true, + purchasedByPlayer: true, + maxRam: ram, + }); + AddToAllServers(newServ); + + Player.purchasedServers.push(newServ.hostname); + const homeComputer = Player.getHomeComputer(); + homeComputer.serversOnNetwork.push(newServ.hostname); + newServ.serversOnNetwork.push(homeComputer.hostname); + Player.loseMoney(cost, "servers"); + helpers.log( + ctx, + () => `Purchased new server with hostname '${newServ.hostname}' for ${numeralWrapper.formatMoney(cost)}`, + ); + return newServ.hostname; + }, + + getPurchasedServerUpgradeCost: (ctx) => (_hostname, _ram) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + const ram = helpers.number(ctx, "ram", _ram); + try { + return getPurchasedServerUpgradeCost(hostname, ram); + } catch (err) { + helpers.log(ctx, () => String(err)); + return -1; + } + }, + upgradePurchasedServer: (ctx) => (_hostname, _ram) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + const ram = helpers.number(ctx, "ram", _ram); + try { + upgradePurchasedServer(hostname, ram); + return true; + } catch (err) { + helpers.log(ctx, () => String(err)); return false; - }, - - deleteServer: - (ctx: NetscriptContext) => - (_name: unknown): boolean => { - const name = helpers.string(ctx, "name", _name); - let hostnameStr = String(name); - hostnameStr = hostnameStr.replace(/\s\s+/g, ""); - const server = GetServer(hostnameStr); - if (!(server instanceof Server)) { - helpers.log(ctx, () => `Invalid argument: hostname='${hostnameStr}'`); - return false; - } - - if (!server.purchasedByPlayer || server.hostname === "home") { - helpers.log(ctx, () => "Cannot delete non-purchased server."); - return false; - } - - const hostname = server.hostname; - - // Can't delete server you're currently connected to - if (server.isConnectedTo) { - helpers.log(ctx, () => "You are currently connected to the server you are trying to delete."); - return false; - } - - // A server cannot delete itself - if (hostname === ctx.workerScript.hostname) { - helpers.log(ctx, () => "Cannot delete the server this script is running on."); - return false; - } - - // Delete all scripts running on server - if (server.runningScripts.length > 0) { - helpers.log(ctx, () => `Cannot delete server '${hostname}' because it still has scripts running.`); - return false; - } - - // Delete from player's purchasedServers array - let found = false; - for (let i = 0; i < Player.purchasedServers.length; ++i) { - if (hostname == Player.purchasedServers[i]) { - found = true; - Player.purchasedServers.splice(i, 1); - break; - } - } - - if (!found) { - helpers.log( - ctx, - () => `Could not identify server ${hostname} as a purchased server. This is a bug. Report to dev.`, - ); - return false; - } - - // Delete from all servers - DeleteServer(hostname); - - // Delete from home computer - found = false; - const homeComputer = Player.getHomeComputer(); - for (let i = 0; i < homeComputer.serversOnNetwork.length; ++i) { - if (hostname == homeComputer.serversOnNetwork[i]) { - homeComputer.serversOnNetwork.splice(i, 1); - helpers.log(ctx, () => `Deleted server '${hostnameStr}`); - return true; - } - } - // Wasn't found on home computer - helpers.log(ctx, () => `Could not find server ${hostname} as a purchased server. This is a bug. Report to dev.`); + } + }, + renamePurchasedServer: (ctx) => (_hostname, _newName) => { + const hostname = helpers.string(ctx, "hostname", _hostname); + const newName = helpers.string(ctx, "newName", _newName); + try { + renamePurchasedServer(hostname, newName); + return true; + } catch (err) { + helpers.log(ctx, () => String(err)); return false; - }, + } + return false; + }, + + deleteServer: (ctx) => (_name) => { + const name = helpers.string(ctx, "name", _name); + let hostnameStr = String(name); + hostnameStr = hostnameStr.replace(/\s\s+/g, ""); + const server = GetServer(hostnameStr); + if (!(server instanceof Server)) { + helpers.log(ctx, () => `Invalid argument: hostname='${hostnameStr}'`); + return false; + } + + if (!server.purchasedByPlayer || server.hostname === "home") { + helpers.log(ctx, () => "Cannot delete non-purchased server."); + return false; + } + + const hostname = server.hostname; + + // Can't delete server you're currently connected to + if (server.isConnectedTo) { + helpers.log(ctx, () => "You are currently connected to the server you are trying to delete."); + return false; + } + + // A server cannot delete itself + if (hostname === ctx.workerScript.hostname) { + helpers.log(ctx, () => "Cannot delete the server this script is running on."); + return false; + } + + // Delete all scripts running on server + if (server.runningScripts.length > 0) { + helpers.log(ctx, () => `Cannot delete server '${hostname}' because it still has scripts running.`); + return false; + } + + // Delete from player's purchasedServers array + let found = false; + for (let i = 0; i < Player.purchasedServers.length; ++i) { + if (hostname == Player.purchasedServers[i]) { + found = true; + Player.purchasedServers.splice(i, 1); + break; + } + } + + if (!found) { + helpers.log( + ctx, + () => `Could not identify server ${hostname} as a purchased server. This is a bug. Report to dev.`, + ); + return false; + } + + // Delete from all servers + DeleteServer(hostname); + + // Delete from home computer + found = false; + const homeComputer = Player.getHomeComputer(); + for (let i = 0; i < homeComputer.serversOnNetwork.length; ++i) { + if (hostname == homeComputer.serversOnNetwork[i]) { + homeComputer.serversOnNetwork.splice(i, 1); + helpers.log(ctx, () => `Deleted server '${hostnameStr}`); + return true; + } + } + // Wasn't found on home computer + helpers.log(ctx, () => `Could not find server ${hostname} as a purchased server. This is a bug. Report to dev.`); + return false; + }, getPurchasedServers: () => (): string[] => { const res: string[] = []; Player.purchasedServers.forEach(function (hostname) { @@ -1509,8 +1440,8 @@ const base: InternalAPI = { return res; }, writePort: - (ctx: NetscriptContext) => - (_port: unknown, data: unknown = ""): Promise => { + (ctx) => + (_port, data = ""): Promise => { const port = helpers.number(ctx, "port", _port); if (typeof data !== "string" && typeof data !== "number") { throw helpers.makeRuntimeErrorMsg( @@ -1522,8 +1453,8 @@ const base: InternalAPI = { return Promise.resolve(iport.write(data)); }, write: - (ctx: NetscriptContext) => - (_filename: unknown, _data: unknown = "", _mode: unknown = "a"): void => { + (ctx) => + (_filename, _data = "", _mode = "a") => { let fn = helpers.string(ctx, "handle", _filename); const data = helpers.string(ctx, "data", _data); const mode = helpers.string(ctx, "mode", _mode); @@ -1561,8 +1492,8 @@ const base: InternalAPI = { return; }, tryWritePort: - (ctx: NetscriptContext) => - (_port: unknown, data: unknown = ""): boolean => { + (ctx) => + (_port, data = "") => { const port = helpers.number(ctx, "port", _port); if (typeof data !== "string" && typeof data !== "number") { throw helpers.makeRuntimeErrorMsg( @@ -1573,85 +1504,73 @@ const base: InternalAPI = { const iport = helpers.getValidPort(ctx, port); return iport.tryWrite(data); }, - readPort: - (ctx: NetscriptContext) => - (_port: unknown): unknown => { - const port = helpers.number(ctx, "port", _port); - // Read from port - const iport = helpers.getValidPort(ctx, port); - const x = iport.read(); - return x; - }, - read: - (ctx: NetscriptContext) => - (_filename: unknown): string => { - const fn = helpers.string(ctx, "filename", _filename); + readPort: (ctx) => (_port) => { + const port = helpers.number(ctx, "port", _port); + // Read from port + const iport = helpers.getValidPort(ctx, port); + const x = iport.read(); + return x; + }, + read: (ctx) => (_filename) => { + const fn = helpers.string(ctx, "filename", _filename); + const server = GetServer(ctx.workerScript.hostname); + if (server == null) { + throw helpers.makeRuntimeErrorMsg(ctx, "Error getting Server. This is a bug. Report to dev."); + } + if (isScriptFilename(fn)) { + // Read from script + const script = ctx.workerScript.getScriptOnServer(fn, server); + if (script == null) { + return ""; + } + return script.code; + } else { + // Read from text file + const txtFile = getTextFile(fn, server); + if (txtFile !== null) { + return txtFile.text; + } else { + return ""; + } + } + }, + peek: (ctx) => (_port) => { + const port = helpers.number(ctx, "port", _port); + const iport = helpers.getValidPort(ctx, port); + const x = iport.peek(); + return x; + }, + clear: (ctx) => (_file) => { + const file = helpers.string(ctx, "file", _file); + if (isString(file)) { + // Clear text file + const fn = file; const server = GetServer(ctx.workerScript.hostname); if (server == null) { throw helpers.makeRuntimeErrorMsg(ctx, "Error getting Server. This is a bug. Report to dev."); } - if (isScriptFilename(fn)) { - // Read from script - const script = ctx.workerScript.getScriptOnServer(fn, server); - if (script == null) { - return ""; - } - return script.code; - } else { - // Read from text file - const txtFile = getTextFile(fn, server); - if (txtFile !== null) { - return txtFile.text; - } else { - return ""; - } + const txtFile = getTextFile(fn, server); + if (txtFile != null) { + txtFile.write(""); } - }, - peek: - (ctx: NetscriptContext) => - (_port: unknown): unknown => { - const port = helpers.number(ctx, "port", _port); - const iport = helpers.getValidPort(ctx, port); - const x = iport.peek(); - return x; - }, - clear: - (ctx: NetscriptContext) => - (_file: unknown): void => { - const file = helpers.string(ctx, "file", _file); - if (isString(file)) { - // Clear text file - const fn = file; - const server = GetServer(ctx.workerScript.hostname); - if (server == null) { - throw helpers.makeRuntimeErrorMsg(ctx, "Error getting Server. This is a bug. Report to dev."); - } - const txtFile = getTextFile(fn, server); - if (txtFile != null) { - txtFile.write(""); - } - } else { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid argument: ${file}`); - } - }, - clearPort: - (ctx: NetscriptContext) => - (_port: unknown): void => { - const port = helpers.number(ctx, "port", _port); - // Clear port - const iport = helpers.getValidPort(ctx, port); - iport.clear(); - }, - getPortHandle: - (ctx: NetscriptContext) => - (_port: unknown): IPort => { - const port = helpers.number(ctx, "port", _port); - const iport = helpers.getValidPort(ctx, port); - return iport; - }, + } else { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid argument: ${file}`); + } + }, + clearPort: (ctx) => (_port) => { + const port = helpers.number(ctx, "port", _port); + // Clear port + const iport = helpers.getValidPort(ctx, port); + iport.clear(); + }, + getPortHandle: (ctx) => (_port) => { + const port = helpers.number(ctx, "port", _port); + const iport = helpers.getValidPort(ctx, port); + return iport; + }, rm: - (ctx: NetscriptContext) => - (_fn: unknown, _hostname: unknown = ctx.workerScript.hostname): boolean => { + (ctx) => + (_fn, _hostname = ctx.workerScript.hostname) => { const fn = helpers.string(ctx, "fn", _fn); const hostname = helpers.string(ctx, "hostname", _hostname); const s = helpers.getServer(ctx, hostname); @@ -1663,41 +1582,37 @@ const base: InternalAPI = { return status.res; }, - scriptRunning: - (ctx: NetscriptContext) => - (_scriptname: unknown, _hostname: unknown): boolean => { - const scriptname = helpers.string(ctx, "scriptname", _scriptname); - const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - for (let i = 0; i < server.runningScripts.length; ++i) { - if (server.runningScripts[i].filename == scriptname) { - return true; - } + scriptRunning: (ctx) => (_scriptname, _hostname) => { + const scriptname = helpers.string(ctx, "scriptname", _scriptname); + const hostname = helpers.string(ctx, "hostname", _hostname); + const server = helpers.getServer(ctx, hostname); + for (let i = 0; i < server.runningScripts.length; ++i) { + if (server.runningScripts[i].filename == scriptname) { + return true; } - return false; - }, - scriptKill: - (ctx: NetscriptContext) => - (_scriptname: unknown, _hostname: unknown): boolean => { - const scriptname = helpers.string(ctx, "scriptname", _scriptname); - const hostname = helpers.string(ctx, "hostname", _hostname); - const server = helpers.getServer(ctx, hostname); - let suc = false; - for (let i = 0; i < server.runningScripts.length; i++) { - if (server.runningScripts[i].filename == scriptname) { - killWorkerScript({ runningScript: server.runningScripts[i], hostname: server.hostname }); - suc = true; - i--; - } + } + return false; + }, + scriptKill: (ctx) => (_scriptname, _hostname) => { + const scriptname = helpers.string(ctx, "scriptname", _scriptname); + const hostname = helpers.string(ctx, "hostname", _hostname); + const server = helpers.getServer(ctx, hostname); + let suc = false; + for (let i = 0; i < server.runningScripts.length; i++) { + if (server.runningScripts[i].filename == scriptname) { + killWorkerScript({ runningScript: server.runningScripts[i], hostname: server.hostname }); + suc = true; + i--; } - return suc; - }, - getScriptName: (ctx: NetscriptContext) => (): string => { + } + return suc; + }, + getScriptName: (ctx) => () => { return ctx.workerScript.name; }, getScriptRam: - (ctx: NetscriptContext) => - (_scriptname: unknown, _hostname: unknown = ctx.workerScript.hostname): number => { + (ctx) => + (_scriptname, _hostname = ctx.workerScript.hostname) => { const scriptname = helpers.string(ctx, "scriptname", _scriptname); const hostname = helpers.string(ctx, "hostname", _hostname); const server = helpers.getServer(ctx, hostname); @@ -1709,16 +1624,16 @@ const base: InternalAPI = { return 0; }, getRunningScript: - (ctx: NetscriptContext) => - (fn: unknown, hostname: unknown, ...args: unknown[]): IRunningScriptDef | null => { + (ctx) => + (fn, hostname, ...args) => { const ident = helpers.scriptIdentifier(ctx, fn, hostname, args); const runningScript = helpers.getRunningScript(ctx, ident); if (runningScript === null) return null; return helpers.createPublicRunningScript(runningScript); }, getHackTime: - (ctx: NetscriptContext) => - (_hostname: unknown = ctx.workerScript.hostname): number => { + (ctx) => + (_hostname = ctx.workerScript.hostname) => { const hostname = helpers.string(ctx, "hostname", _hostname); const server = helpers.getServer(ctx, hostname); if (!(server instanceof Server)) { @@ -1732,8 +1647,8 @@ const base: InternalAPI = { return calculateHackingTime(server, Player) * 1000; }, getGrowTime: - (ctx: NetscriptContext) => - (_hostname: unknown = ctx.workerScript.hostname): number => { + (ctx) => + (_hostname = ctx.workerScript.hostname) => { const hostname = helpers.string(ctx, "hostname", _hostname); const server = helpers.getServer(ctx, hostname); if (!(server instanceof Server)) { @@ -1747,8 +1662,8 @@ const base: InternalAPI = { return calculateGrowTime(server, Player) * 1000; }, getWeakenTime: - (ctx: NetscriptContext) => - (_hostname: unknown = ctx.workerScript.hostname): number => { + (ctx) => + (_hostname = ctx.workerScript.hostname) => { const hostname = helpers.string(ctx, "hostname", _hostname); const server = helpers.getServer(ctx, hostname); if (!(server instanceof Server)) { @@ -1761,7 +1676,7 @@ const base: InternalAPI = { return calculateWeakenTime(server, Player) * 1000; }, - getTotalScriptIncome: () => (): [number, number] => { + getTotalScriptIncome: () => () => { // First element is total income of all currently running scripts let total = 0; for (const script of workerScripts.values()) { @@ -1771,8 +1686,8 @@ const base: InternalAPI = { return [total, Player.scriptProdSinceLastAug / (Player.playtimeSinceLastAug / 1000)]; }, getScriptIncome: - (ctx: NetscriptContext) => - (fn: unknown, hostname: unknown, ...args: unknown[]): number => { + (ctx) => + (fn, hostname, ...args) => { const ident = helpers.scriptIdentifier(ctx, fn, hostname, args); const runningScript = helpers.getRunningScript(ctx, ident); if (runningScript == null) { @@ -1781,7 +1696,7 @@ const base: InternalAPI = { } return runningScript.onlineMoneyMade / runningScript.onlineRunningTime; }, - getTotalScriptExpGain: () => (): number => { + getTotalScriptExpGain: () => () => { let total = 0; for (const ws of workerScripts.values()) { total += ws.scriptRef.onlineExpGained / ws.scriptRef.onlineRunningTime; @@ -1789,8 +1704,8 @@ const base: InternalAPI = { return total; }, getScriptExpGain: - (ctx: NetscriptContext) => - (fn: unknown, hostname: unknown, ...args: unknown[]): number => { + (ctx) => + (fn, hostname, ...args) => { const ident = helpers.scriptIdentifier(ctx, fn, hostname, args); const runningScript = helpers.getRunningScript(ctx, ident); if (runningScript == null) { @@ -1799,36 +1714,32 @@ const base: InternalAPI = { } return runningScript.onlineExpGained / runningScript.onlineRunningTime; }, - nFormat: - (ctx: NetscriptContext) => - (_n: unknown, _format: unknown): string => { - const n = helpers.number(ctx, "n", _n); - const format = helpers.string(ctx, "format", _format); - if (isNaN(n)) { - return ""; - } + nFormat: (ctx) => (_n, _format) => { + const n = helpers.number(ctx, "n", _n); + const format = helpers.string(ctx, "format", _format); + if (isNaN(n)) { + return ""; + } - return numeralWrapper.format(n, format); - }, + return numeralWrapper.format(n, format); + }, tFormat: - (ctx: NetscriptContext) => - (_milliseconds: unknown, _milliPrecision: unknown = false): string => { + (ctx) => + (_milliseconds, _milliPrecision = false) => { const milliseconds = helpers.number(ctx, "milliseconds", _milliseconds); const milliPrecision = !!_milliPrecision; return convertTimeMsToTimeElapsedString(milliseconds, milliPrecision); }, - getTimeSinceLastAug: () => (): number => { + getTimeSinceLastAug: () => () => { return Player.playtimeSinceLastAug; }, - alert: - (ctx: NetscriptContext) => - (_message: unknown): void => { - const message = helpers.string(ctx, "message", _message); - dialogBoxCreate(message, true); - }, + alert: (ctx) => (_message) => { + const message = helpers.string(ctx, "message", _message); + dialogBoxCreate(message, true); + }, toast: - (ctx: NetscriptContext) => - (_message: unknown, _variant: unknown = ToastVariant.SUCCESS, _duration: unknown = 2000): void => { + (ctx) => + (_message, _variant = ToastVariant.SUCCESS, _duration = 2000) => { const message = helpers.string(ctx, "message", _message); const variant = helpers.string(ctx, "variant", _variant); const duration = _duration === null ? null : helpers.number(ctx, "duration", _duration); @@ -1837,9 +1748,11 @@ const base: InternalAPI = { SnackbarEvents.emit(message, variant as ToastVariant, duration); }, prompt: - (ctx: NetscriptContext) => - (_txt: unknown, options?: { type?: string; options?: string[] }): Promise => { + (ctx) => + (_txt, options = {}) => { const txt = helpers.string(ctx, "txt", _txt); + const optionsValidator: { type?: string; options?: string[] } = {}; + assertObjectType(ctx, "options", options, optionsValidator); return new Promise(function (resolve) { PromptEvent.emit({ @@ -1850,8 +1763,8 @@ const base: InternalAPI = { }); }, wget: - (ctx: NetscriptContext) => - async (_url: unknown, _target: unknown, _hostname: unknown = ctx.workerScript.hostname): Promise => { + (ctx) => + async (_url, _target, _hostname = ctx.workerScript.hostname) => { const url = helpers.string(ctx, "url", _url); const target = helpers.string(ctx, "target", _target); const hostname = helpers.string(ctx, "hostname", _hostname); @@ -1888,10 +1801,10 @@ const base: InternalAPI = { }); }); }, - getFavorToDonate: () => (): number => { + getFavorToDonate: () => () => { return Math.floor(CONSTANTS.BaseFavorToDonate * BitNodeMultipliers.RepToDonateToFaction); }, - getPlayer: () => (): INetscriptPlayer => { + getPlayer: () => () => { const data = { hp: JSON.parse(JSON.stringify(Player.hp)), skills: JSON.parse(JSON.stringify(Player.skills)), @@ -1915,78 +1828,74 @@ const base: InternalAPI = { Object.assign(data.jobs, Player.jobs); return data; }, - atExit: - (ctx: NetscriptContext) => - (f: unknown): void => { - if (typeof f !== "function") { - throw helpers.makeRuntimeErrorMsg(ctx, "argument should be function"); + atExit: (ctx) => (f) => { + if (typeof f !== "function") { + throw helpers.makeRuntimeErrorMsg(ctx, "argument should be function"); + } + ctx.workerScript.atExit = () => { + f(); + }; // Wrap the user function to prevent WorkerScript leaking as 'this' + }, + mv: (ctx) => (_host, _source, _destination) => { + const host = helpers.string(ctx, "host", _host); + const source = helpers.string(ctx, "source", _source); + const destination = helpers.string(ctx, "destination", _destination); + + if (!isValidFilePath(source)) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid filename: '${source}'`); + if (!isValidFilePath(destination)) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid filename: '${destination}'`); + + const source_is_txt = source.endsWith(".txt"); + const dest_is_txt = destination.endsWith(".txt"); + + if (!isScriptFilename(source) && !source_is_txt) + throw helpers.makeRuntimeErrorMsg(ctx, `'mv' can only be used on scripts and text files (.txt)`); + if (source_is_txt != dest_is_txt) + throw helpers.makeRuntimeErrorMsg(ctx, `Source and destination files must have the same type`); + + if (source === destination) { + return; + } + + const destServer = helpers.getServer(ctx, host); + + if (!source_is_txt && destServer.isRunning(source)) + throw helpers.makeRuntimeErrorMsg(ctx, `Cannot use 'mv' on a script that is running`); + + interface File { + filename: string; + } + + const files = source_is_txt ? destServer.textFiles : destServer.scripts; + let source_file: File | null = null; + let dest_file: File | null = null; + + for (let i = 0; i < files.length; ++i) { + const file = files[i]; + if (file.filename === source) { + source_file = file; + } else if (file.filename === destination) { + dest_file = file; } - ctx.workerScript.atExit = () => { - f(); - }; // Wrap the user function to prevent WorkerScript leaking as 'this' - }, - mv: - (ctx: NetscriptContext) => - (_host: unknown, _source: unknown, _destination: unknown): void => { - const host = helpers.string(ctx, "host", _host); - const source = helpers.string(ctx, "source", _source); - const destination = helpers.string(ctx, "destination", _destination); + } - if (!isValidFilePath(source)) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid filename: '${source}'`); - if (!isValidFilePath(destination)) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid filename: '${destination}'`); + if (source_file == null) throw helpers.makeRuntimeErrorMsg(ctx, `Source file ${source} does not exist`); - const source_is_txt = source.endsWith(".txt"); - const dest_is_txt = destination.endsWith(".txt"); - - if (!isScriptFilename(source) && !source_is_txt) - throw helpers.makeRuntimeErrorMsg(ctx, `'mv' can only be used on scripts and text files (.txt)`); - if (source_is_txt != dest_is_txt) - throw helpers.makeRuntimeErrorMsg(ctx, `Source and destination files must have the same type`); - - if (source === destination) { - return; + if (dest_file != null) { + if (dest_file instanceof TextFile && source_file instanceof TextFile) { + dest_file.text = source_file.text; + } else if (dest_file instanceof Script && source_file instanceof Script) { + dest_file.code = source_file.code; + dest_file.markUpdated(); } - const destServer = helpers.getServer(ctx, host); - - if (!source_is_txt && destServer.isRunning(source)) - throw helpers.makeRuntimeErrorMsg(ctx, `Cannot use 'mv' on a script that is running`); - - interface File { - filename: string; + destServer.removeFile(source); + } else { + source_file.filename = destination; + if (source_file instanceof Script) { + source_file.markUpdated(); } - - const files = source_is_txt ? destServer.textFiles : destServer.scripts; - let source_file: File | null = null; - let dest_file: File | null = null; - - for (let i = 0; i < files.length; ++i) { - const file = files[i]; - if (file.filename === source) { - source_file = file; - } else if (file.filename === destination) { - dest_file = file; - } - } - - if (source_file == null) throw helpers.makeRuntimeErrorMsg(ctx, `Source file ${source} does not exist`); - - if (dest_file != null) { - if (dest_file instanceof TextFile && source_file instanceof TextFile) { - dest_file.text = source_file.text; - } else if (dest_file instanceof Script && source_file instanceof Script) { - dest_file.code = source_file.code; - dest_file.markUpdated(); - } - - destServer.removeFile(source); - } else { - source_file.filename = destination; - if (source_file instanceof Script) { - source_file.markUpdated(); - } - } - }, + } + }, flags: Flags, }; diff --git a/src/NetscriptFunctions/Bladeburner.ts b/src/NetscriptFunctions/Bladeburner.ts index 005f0969a..d57f9a1af 100644 --- a/src/NetscriptFunctions/Bladeburner.ts +++ b/src/NetscriptFunctions/Bladeburner.ts @@ -1,7 +1,7 @@ import { Player } from "@player"; import { Bladeburner } from "../Bladeburner/Bladeburner"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; -import { Bladeburner as INetscriptBladeburner, BladeburnerCurAction } from "../ScriptEditor/NetscriptDefinitions"; +import { Bladeburner as INetscriptBladeburner } from "../ScriptEditor/NetscriptDefinitions"; import { Action } from "src/Bladeburner/Action"; import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper"; import { BlackOperation } from "../Bladeburner/BlackOperation"; @@ -47,75 +47,69 @@ export function NetscriptBladeburner(): InternalAPI { }; return { - getContractNames: (ctx: NetscriptContext) => (): string[] => { + getContractNames: (ctx) => () => { const bladeburner = getBladeburner(ctx); return bladeburner.getContractNamesNetscriptFn(); }, - getOperationNames: (ctx: NetscriptContext) => (): string[] => { + getOperationNames: (ctx) => () => { const bladeburner = getBladeburner(ctx); return bladeburner.getOperationNamesNetscriptFn(); }, - getBlackOpNames: (ctx: NetscriptContext) => (): string[] => { + getBlackOpNames: (ctx) => () => { const bladeburner = getBladeburner(ctx); return bladeburner.getBlackOpNamesNetscriptFn(); }, - getBlackOpRank: - (ctx: NetscriptContext) => - (_blackOpName: unknown): number => { - 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"); - return action.reqdRank; - }, - getGeneralActionNames: (ctx: NetscriptContext) => (): string[] => { + getBlackOpRank: (ctx) => (_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"); + return action.reqdRank; + }, + getGeneralActionNames: (ctx) => () => { const bladeburner = getBladeburner(ctx); return bladeburner.getGeneralActionNamesNetscriptFn(); }, - getSkillNames: (ctx: NetscriptContext) => (): string[] => { + getSkillNames: (ctx) => () => { const bladeburner = getBladeburner(ctx); return bladeburner.getSkillNamesNetscriptFn(); }, - startAction: - (ctx: NetscriptContext) => - (_type: unknown, _name: unknown): boolean => { - const type = helpers.string(ctx, "type", _type); - const name = helpers.string(ctx, "name", _name); - const bladeburner = getBladeburner(ctx); - try { - return bladeburner.startActionNetscriptFn(type, name, ctx.workerScript); - } catch (e: unknown) { - throw helpers.makeRuntimeErrorMsg(ctx, String(e)); - } - }, - stopBladeburnerAction: (ctx: NetscriptContext) => (): void => { + startAction: (ctx) => (_type, _name) => { + const type = helpers.string(ctx, "type", _type); + const name = helpers.string(ctx, "name", _name); + const bladeburner = getBladeburner(ctx); + try { + return bladeburner.startActionNetscriptFn(type, name, ctx.workerScript); + } catch (e: unknown) { + throw helpers.makeRuntimeErrorMsg(ctx, String(e)); + } + }, + stopBladeburnerAction: (ctx) => () => { const bladeburner = getBladeburner(ctx); return bladeburner.resetAction(); }, - getCurrentAction: (ctx: NetscriptContext) => (): BladeburnerCurAction => { + getCurrentAction: (ctx) => () => { const bladeburner = getBladeburner(ctx); return bladeburner.getTypeAndNameFromActionId(bladeburner.action); }, - getActionTime: - (ctx: NetscriptContext) => - (_type: unknown, _name: unknown): number => { - const type = helpers.string(ctx, "type", _type); - const name = helpers.string(ctx, "name", _name); - const bladeburner = getBladeburner(ctx); - try { - const time = bladeburner.getActionTimeNetscriptFn(Player, type, name); - if (typeof time === "string") { - const errorLogText = `Invalid action: type='${type}' name='${name}'`; - helpers.log(ctx, () => errorLogText); - return -1; - } else { - return time; - } - } catch (e: unknown) { - throw helpers.makeRuntimeErrorMsg(ctx, String(e)); + getActionTime: (ctx) => (_type, _name) => { + const type = helpers.string(ctx, "type", _type); + const name = helpers.string(ctx, "name", _name); + const bladeburner = getBladeburner(ctx); + try { + const time = bladeburner.getActionTimeNetscriptFn(Player, type, name); + if (typeof time === "string") { + const errorLogText = `Invalid action: type='${type}' name='${name}'`; + helpers.log(ctx, () => errorLogText); + return -1; + } else { + return time; } - }, - getActionCurrentTime: (ctx: NetscriptContext) => (): number => { + } catch (e: unknown) { + throw helpers.makeRuntimeErrorMsg(ctx, String(e)); + } + }, + getActionCurrentTime: (ctx) => () => { const bladeburner = getBladeburner(ctx); try { const timecomputed = @@ -126,84 +120,72 @@ export function NetscriptBladeburner(): InternalAPI { throw helpers.makeRuntimeErrorMsg(ctx, String(e)); } }, - getActionEstimatedSuccessChance: - (ctx: NetscriptContext) => - (_type: unknown, _name: unknown): [number, number] => { - const type = helpers.string(ctx, "type", _type); - const name = helpers.string(ctx, "name", _name); - const bladeburner = getBladeburner(ctx); - try { - const chance = bladeburner.getActionEstimatedSuccessChanceNetscriptFn(Player, type, name); - if (typeof chance === "string") { - const errorLogText = `Invalid action: type='${type}' name='${name}'`; - helpers.log(ctx, () => errorLogText); - return [-1, -1]; - } else { - return chance; - } - } catch (e: unknown) { - throw helpers.makeRuntimeErrorMsg(ctx, String(e)); - } - }, - getActionRepGain: - (ctx: NetscriptContext) => - (_type: unknown, _name: unknown, _level: unknown): number => { - 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; - if (level == null || isNaN(level)) { - rewardMultiplier = Math.pow(action.rewardFac, action.level - 1); + getActionEstimatedSuccessChance: (ctx) => (_type, _name) => { + const type = helpers.string(ctx, "type", _type); + const name = helpers.string(ctx, "name", _name); + const bladeburner = getBladeburner(ctx); + try { + const chance = bladeburner.getActionEstimatedSuccessChanceNetscriptFn(Player, type, name); + if (typeof chance === "string") { + const errorLogText = `Invalid action: type='${type}' name='${name}'`; + helpers.log(ctx, () => errorLogText); + return [-1, -1]; } else { - rewardMultiplier = Math.pow(action.rewardFac, level - 1); + return chance; } + } catch (e: unknown) { + throw helpers.makeRuntimeErrorMsg(ctx, String(e)); + } + }, + getActionRepGain: (ctx) => (_type, _name, _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; + if (level == null || isNaN(level)) { + rewardMultiplier = Math.pow(action.rewardFac, action.level - 1); + } else { + rewardMultiplier = Math.pow(action.rewardFac, level - 1); + } - return action.rankGain * rewardMultiplier * BitNodeMultipliers.BladeburnerRank; - }, - getActionCountRemaining: - (ctx: NetscriptContext) => - (_type: unknown, _name: unknown): number => { - const type = helpers.string(ctx, "type", _type); - const name = helpers.string(ctx, "name", _name); - const bladeburner = getBladeburner(ctx); - try { - return bladeburner.getActionCountRemainingNetscriptFn(type, name, ctx.workerScript); - } catch (e: unknown) { - throw helpers.makeRuntimeErrorMsg(ctx, String(e)); - } - }, - getActionMaxLevel: - (ctx: NetscriptContext) => - (_type: unknown, _name: unknown): number => { - 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; - }, - getActionCurrentLevel: - (ctx: NetscriptContext) => - (_type: unknown, _name: unknown): number => { - 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; - }, - getActionAutolevel: - (ctx: NetscriptContext) => - (_type: unknown, _name: unknown): boolean => { - 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; - }, + return action.rankGain * rewardMultiplier * BitNodeMultipliers.BladeburnerRank; + }, + getActionCountRemaining: (ctx) => (_type, _name) => { + const type = helpers.string(ctx, "type", _type); + const name = helpers.string(ctx, "name", _name); + const bladeburner = getBladeburner(ctx); + try { + return bladeburner.getActionCountRemainingNetscriptFn(type, name, ctx.workerScript); + } catch (e: unknown) { + throw helpers.makeRuntimeErrorMsg(ctx, String(e)); + } + }, + getActionMaxLevel: (ctx) => (_type, _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; + }, + getActionCurrentLevel: (ctx) => (_type, _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; + }, + getActionAutolevel: (ctx) => (_type, _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; + }, setActionAutolevel: - (ctx: NetscriptContext) => - (_type: unknown, _name: unknown, _autoLevel: unknown = true): void => { + (ctx) => + (_type, _name, _autoLevel = true) => { const type = helpers.string(ctx, "type", _type); const name = helpers.string(ctx, "name", _name); const autoLevel = !!_autoLevel; @@ -212,8 +194,8 @@ export function NetscriptBladeburner(): InternalAPI { action.autoLevel = autoLevel; }, setActionLevel: - (ctx: NetscriptContext) => - (_type: unknown, _name: unknown, _level: unknown = 1): void => { + (ctx) => + (_type, _name, _level = 1) => { const type = helpers.string(ctx, "type", _type); const name = helpers.string(ctx, "name", _name); const level = helpers.number(ctx, "level", _level); @@ -224,28 +206,26 @@ export function NetscriptBladeburner(): InternalAPI { } action.level = level; }, - getRank: (ctx: NetscriptContext) => (): number => { + getRank: (ctx) => () => { const bladeburner = getBladeburner(ctx); return bladeburner.rank; }, - getSkillPoints: (ctx: NetscriptContext) => (): number => { + getSkillPoints: (ctx) => () => { const bladeburner = getBladeburner(ctx); return bladeburner.skillPoints; }, - getSkillLevel: - (ctx: NetscriptContext) => - (_skillName: unknown): number => { - const skillName = helpers.string(ctx, "skillName", _skillName); - const bladeburner = getBladeburner(ctx); - try { - return bladeburner.getSkillLevelNetscriptFn(skillName, ctx.workerScript); - } catch (e: unknown) { - throw helpers.makeRuntimeErrorMsg(ctx, String(e)); - } - }, + getSkillLevel: (ctx) => (_skillName) => { + const skillName = helpers.string(ctx, "skillName", _skillName); + const bladeburner = getBladeburner(ctx); + try { + return bladeburner.getSkillLevelNetscriptFn(skillName, ctx.workerScript); + } catch (e: unknown) { + throw helpers.makeRuntimeErrorMsg(ctx, String(e)); + } + }, getSkillUpgradeCost: - (ctx: NetscriptContext) => - (_skillName: unknown, _count: unknown = 1): number => { + (ctx) => + (_skillName, _count = 1) => { const skillName = helpers.string(ctx, "skillName", _skillName); const count = helpers.number(ctx, "count", _count); const bladeburner = getBladeburner(ctx); @@ -256,8 +236,8 @@ export function NetscriptBladeburner(): InternalAPI { } }, upgradeSkill: - (ctx: NetscriptContext) => - (_skillName: unknown, _count: unknown = 1): boolean => { + (ctx) => + (_skillName, _count = 1) => { const skillName = helpers.string(ctx, "skillName", _skillName); const count = helpers.number(ctx, "count", _count); const bladeburner = getBladeburner(ctx); @@ -267,85 +247,73 @@ export function NetscriptBladeburner(): InternalAPI { throw helpers.makeRuntimeErrorMsg(ctx, String(e)); } }, - getTeamSize: - (ctx: NetscriptContext) => - (_type: unknown, _name: unknown): number => { - const type = helpers.string(ctx, "type", _type); - const name = helpers.string(ctx, "name", _name); - const bladeburner = getBladeburner(ctx); - try { - return bladeburner.getTeamSizeNetscriptFn(type, name, ctx.workerScript); - } catch (e: unknown) { - throw helpers.makeRuntimeErrorMsg(ctx, String(e)); - } - }, - setTeamSize: - (ctx: NetscriptContext) => - (_type: unknown, _name: unknown, _size: unknown): number => { - const type = helpers.string(ctx, "type", _type); - const name = helpers.string(ctx, "name", _name); - const size = helpers.number(ctx, "size", _size); - const bladeburner = getBladeburner(ctx); - try { - return bladeburner.setTeamSizeNetscriptFn(type, name, size, ctx.workerScript); - } catch (e: unknown) { - throw helpers.makeRuntimeErrorMsg(ctx, String(e)); - } - }, - getCityEstimatedPopulation: - (ctx: NetscriptContext) => - (_cityName: unknown): number => { - const cityName = helpers.string(ctx, "cityName", _cityName); - checkBladeburnerAccess(ctx); - checkBladeburnerCity(ctx, cityName); - const bladeburner = Player.bladeburner; - if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); - return bladeburner.cities[cityName].popEst; - }, - getCityCommunities: - (ctx: NetscriptContext) => - (_cityName: unknown): number => { - const cityName = helpers.string(ctx, "cityName", _cityName); - checkBladeburnerAccess(ctx); - checkBladeburnerCity(ctx, cityName); - const bladeburner = Player.bladeburner; - if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); - return bladeburner.cities[cityName].comms; - }, - getCityChaos: - (ctx: NetscriptContext) => - (_cityName: unknown): number => { - const cityName = helpers.string(ctx, "cityName", _cityName); - checkBladeburnerAccess(ctx); - checkBladeburnerCity(ctx, cityName); - const bladeburner = Player.bladeburner; - if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); - return bladeburner.cities[cityName].chaos; - }, - getCity: (ctx: NetscriptContext) => (): string => { + getTeamSize: (ctx) => (_type, _name) => { + const type = helpers.string(ctx, "type", _type); + const name = helpers.string(ctx, "name", _name); + const bladeburner = getBladeburner(ctx); + try { + return bladeburner.getTeamSizeNetscriptFn(type, name, ctx.workerScript); + } catch (e: unknown) { + throw helpers.makeRuntimeErrorMsg(ctx, String(e)); + } + }, + setTeamSize: (ctx) => (_type, _name, _size) => { + const type = helpers.string(ctx, "type", _type); + const name = helpers.string(ctx, "name", _name); + const size = helpers.number(ctx, "size", _size); + const bladeburner = getBladeburner(ctx); + try { + return bladeburner.setTeamSizeNetscriptFn(type, name, size, ctx.workerScript); + } catch (e: unknown) { + throw helpers.makeRuntimeErrorMsg(ctx, String(e)); + } + }, + getCityEstimatedPopulation: (ctx) => (_cityName) => { + const cityName = helpers.string(ctx, "cityName", _cityName); + checkBladeburnerAccess(ctx); + checkBladeburnerCity(ctx, cityName); + const bladeburner = Player.bladeburner; + if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); + return bladeburner.cities[cityName].popEst; + }, + getCityCommunities: (ctx) => (_cityName) => { + const cityName = helpers.string(ctx, "cityName", _cityName); + checkBladeburnerAccess(ctx); + checkBladeburnerCity(ctx, cityName); + const bladeburner = Player.bladeburner; + if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); + return bladeburner.cities[cityName].comms; + }, + getCityChaos: (ctx) => (_cityName) => { + const cityName = helpers.string(ctx, "cityName", _cityName); + checkBladeburnerAccess(ctx); + checkBladeburnerCity(ctx, cityName); + const bladeburner = Player.bladeburner; + if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); + return bladeburner.cities[cityName].chaos; + }, + getCity: (ctx) => () => { const bladeburner = getBladeburner(ctx); return bladeburner.city; }, - switchCity: - (ctx: NetscriptContext) => - (_cityName: unknown): boolean => { - const cityName = helpers.string(ctx, "cityName", _cityName); - checkBladeburnerAccess(ctx); - checkBladeburnerCity(ctx, cityName); - const bladeburner = Player.bladeburner; - if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); - bladeburner.city = cityName; - return true; - }, - getStamina: (ctx: NetscriptContext) => (): [number, number] => { + switchCity: (ctx) => (_cityName) => { + const cityName = helpers.string(ctx, "cityName", _cityName); + checkBladeburnerAccess(ctx); + checkBladeburnerCity(ctx, cityName); + const bladeburner = Player.bladeburner; + if (bladeburner === null) throw new Error("Should not be called without Bladeburner"); + bladeburner.city = cityName; + return true; + }, + getStamina: (ctx) => () => { const bladeburner = getBladeburner(ctx); return [bladeburner.stamina, bladeburner.maxStamina]; }, - joinBladeburnerFaction: (ctx: NetscriptContext) => (): boolean => { + joinBladeburnerFaction: (ctx) => () => { const bladeburner = getBladeburner(ctx); return bladeburner.joinBladeburnerFactionNetscriptFn(ctx.workerScript); }, - joinBladeburnerDivision: (ctx: NetscriptContext) => (): boolean => { + joinBladeburnerDivision: (ctx) => () => { if (Player.bitNodeN === 7 || Player.sourceFileLvl(7) > 0) { if (BitNodeMultipliers.BladeburnerRank === 0) { return false; // Disabled in this bitnode @@ -369,7 +337,7 @@ export function NetscriptBladeburner(): InternalAPI { } return false; }, - getBonusTime: (ctx: NetscriptContext) => (): number => { + getBonusTime: (ctx) => () => { const bladeburner = getBladeburner(ctx); return Math.round(bladeburner.storedCycles / 5) * 1000; }, diff --git a/src/NetscriptFunctions/CodingContract.ts b/src/NetscriptFunctions/CodingContract.ts index a2f0d150a..3336fa7bc 100644 --- a/src/NetscriptFunctions/CodingContract.ts +++ b/src/NetscriptFunctions/CodingContract.ts @@ -2,17 +2,12 @@ import { Player as player } from "../Player"; import { CodingContract } from "../CodingContracts"; import { CodingAttemptOptions, CodingContract as ICodingContract } from "../ScriptEditor/NetscriptDefinitions"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; -import { helpers } from "../Netscript/NetscriptHelpers"; +import { helpers, assertObjectType } from "../Netscript/NetscriptHelpers"; import { codingContractTypesMetadata } from "../data/codingcontracttypes"; import { generateDummyContract } from "../CodingContractGenerator"; export function NetscriptCodingContract(): InternalAPI { - const getCodingContract = function ( - ctx: NetscriptContext, - func: string, - hostname: string, - filename: string, - ): CodingContract { + const getCodingContract = function (ctx: NetscriptContext, hostname: string, filename: string): CodingContract { const server = helpers.getServer(ctx, hostname); const contract = server.getContract(filename); if (contract == null) { @@ -23,102 +18,86 @@ export function NetscriptCodingContract(): InternalAPI { }; return { - attempt: - (ctx: NetscriptContext) => - ( - answer: unknown, - _filename: unknown, - _hostname: unknown = ctx.workerScript.hostname, - { returnReward }: CodingAttemptOptions = { returnReward: false }, - ): boolean | string => { - const filename = helpers.string(ctx, "filename", _filename); - const hostname = helpers.string(ctx, "hostname", _hostname); - const contract = getCodingContract(ctx, "attempt", hostname, filename); + attempt: (ctx) => (answer, _filename, _hostname?, opts?) => { + const filename = helpers.string(ctx, "filename", _filename); + const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname; + const contract = getCodingContract(ctx, hostname, filename); - if (typeof answer !== "number" && typeof answer !== "string" && !Array.isArray(answer)) - throw new Error("The answer provided was not a number, string, or array"); + const optsValidator: CodingAttemptOptions = { returnReward: true }; + opts ??= optsValidator; + assertObjectType(ctx, "opts", opts, optsValidator); + if (typeof answer !== "number" && typeof answer !== "string" && !Array.isArray(answer)) + throw new Error("The answer provided was not a number, string, or array"); - // Convert answer to string. - const answerStr = typeof answer === "string" ? answer : JSON.stringify(answer); - const creward = contract.reward; + // Convert answer to string. + const answerStr = typeof answer === "string" ? answer : JSON.stringify(answer); + const creward = contract.reward; - const serv = helpers.getServer(ctx, hostname); - if (contract.isSolution(answerStr)) { - const reward = player.gainCodingContractReward(creward, contract.getDifficulty()); - helpers.log(ctx, () => `Successfully completed Coding Contract '${filename}'. Reward: ${reward}`); + const serv = helpers.getServer(ctx, hostname); + if (contract.isSolution(answerStr)) { + const reward = player.gainCodingContractReward(creward, contract.getDifficulty()); + helpers.log(ctx, () => `Successfully completed Coding Contract '${filename}'. Reward: ${reward}`); + serv.removeContract(filename); + return opts.returnReward ? reward : true; + } else { + ++contract.tries; + if (contract.tries >= contract.getMaxNumTries()) { + helpers.log(ctx, () => `Coding Contract attempt '${filename}' failed. Contract is now self-destructing`); serv.removeContract(filename); - return returnReward ? reward : true; } else { - ++contract.tries; - if (contract.tries >= contract.getMaxNumTries()) { - helpers.log(ctx, () => `Coding Contract attempt '${filename}' failed. Contract is now self-destructing`); - serv.removeContract(filename); - } else { - helpers.log( - ctx, - () => - `Coding Contract attempt '${filename}' failed. ${ - contract.getMaxNumTries() - contract.tries - } attempts remaining.`, - ); - } - - return returnReward ? "" : false; + helpers.log( + ctx, + () => + `Coding Contract attempt '${filename}' failed. ${ + contract.getMaxNumTries() - contract.tries + } attempts remaining.`, + ); } - }, - getContractType: - (ctx: NetscriptContext) => - (_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 = 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)) { - // For two dimensional arrays, we have to copy the internal arrays using - // slice() as well. As of right now, no contract has arrays that have - // more than two dimensions - const copy = data.slice(); - for (let i = 0; i < copy.length; ++i) { - if (data[i].constructor === Array) { - copy[i] = data[i].slice(); - } - } - return copy; - } else { - return data; + return opts.returnReward ? "" : false; + } + }, + getContractType: (ctx) => (_filename, _hostname?) => { + const filename = helpers.string(ctx, "filename", _filename); + const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname; + const contract = getCodingContract(ctx, hostname, filename); + return contract.getType(); + }, + getData: (ctx) => (_filename, _hostname?) => { + const filename = helpers.string(ctx, "filename", _filename); + const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname; + const contract = getCodingContract(ctx, hostname, filename); + const data = contract.getData(); + if (Array.isArray(data)) { + // For two dimensional arrays, we have to copy the internal arrays using + // slice() as well. As of right now, no contract has arrays that have + // more than two dimensions + const copy = data.slice(); + for (let i = 0; i < copy.length; ++i) { + if (data[i].constructor === Array) { + copy[i] = data[i].slice(); + } } - }, - getDescription: - (ctx: NetscriptContext) => - (_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 = 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; - }, - createDummyContract: - (ctx: NetscriptContext) => - (_type: unknown): void => { - const type = helpers.string(ctx, "type", _type); - generateDummyContract(type); - }, - getContractTypes: () => (): string[] => codingContractTypesMetadata.map((c) => c.name), + + return copy; + } else return data; + }, + getDescription: (ctx) => (_filename, _hostname?) => { + const filename = helpers.string(ctx, "filename", _filename); + const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname; + const contract = getCodingContract(ctx, hostname, filename); + return contract.getDescription(); + }, + getNumTriesRemaining: (ctx) => (_filename, _hostname?) => { + const filename = helpers.string(ctx, "filename", _filename); + const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname; + const contract = getCodingContract(ctx, hostname, filename); + return contract.getMaxNumTries() - contract.tries; + }, + createDummyContract: (ctx) => (_type) => { + const type = helpers.string(ctx, "type", _type); + generateDummyContract(type); + }, + getContractTypes: () => () => codingContractTypesMetadata.map((c) => c.name), }; } diff --git a/src/NetscriptFunctions/Corporation.ts b/src/NetscriptFunctions/Corporation.ts index 8655a6c1b..fed6a59ff 100644 --- a/src/NetscriptFunctions/Corporation.ts +++ b/src/NetscriptFunctions/Corporation.ts @@ -10,16 +10,10 @@ import { Corporation } from "../Corporation/Corporation"; import { Corporation as NSCorporation, - CorporationInfo, - Employee as NSEmployee, - Product as NSProduct, - Material as NSMaterial, - Warehouse as NSWarehouse, Division as NSDivision, WarehouseAPI, OfficeAPI, InvestmentOffer, - Office as NSOffice, } from "../ScriptEditor/NetscriptDefinitions"; import { @@ -308,13 +302,13 @@ export function NetscriptCorporation(): InternalAPI { } const warehouseAPI: InternalAPI = { - getPurchaseWarehouseCost: (ctx: NetscriptContext) => (): number => { + getPurchaseWarehouseCost: (ctx) => () => { checkAccess(ctx, 7); return CorporationConstants.WarehouseInitialCost; }, getUpgradeWarehouseCost: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown, _amt: unknown = 1): number => { + (ctx) => + (_divisionName, _cityName, _amt = 1) => { checkAccess(ctx, 7); const divisionName = helpers.string(ctx, "divisionName", _divisionName); const cityName = helpers.city(ctx, "cityName", _cityName); @@ -325,96 +319,86 @@ export function NetscriptCorporation(): InternalAPI { const warehouse = getWarehouse(divisionName, cityName); return UpgradeWarehouseCost(warehouse, amt); }, - hasWarehouse: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown): boolean => { - checkAccess(ctx, 7); - 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]; - return warehouse !== 0; - }, - getWarehouse: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown): NSWarehouse => { - checkAccess(ctx, 7); - const divisionName = helpers.string(ctx, "divisionName", _divisionName); - const cityName = helpers.city(ctx, "cityName", _cityName); - const warehouse = getWarehouse(divisionName, cityName); - return { - level: warehouse.level, - loc: warehouse.loc, - size: warehouse.size, - sizeUsed: warehouse.sizeUsed, - smartSupplyEnabled: warehouse.smartSupplyEnabled, - }; - }, - getMaterial: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown, _materialName: unknown): NSMaterial => { - checkAccess(ctx, 7); - 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(); - const exports = material.exp.map((e) => { - return { div: e.ind, loc: e.city, amt: e.amt }; - }); - return { - cost: material.bCost, - sCost: material.sCost, - name: material.name, - qty: material.qty, - qlt: material.qlt, - dmd: corporation.unlockUpgrades[2] ? material.dmd : undefined, - cmp: corporation.unlockUpgrades[3] ? material.cmp : undefined, - prod: material.prd, - sell: material.sll, - exp: exports, - }; - }, - getProduct: - (ctx: NetscriptContext) => - (_divisionName: unknown, _productName: unknown): NSProduct => { - checkAccess(ctx, 7); - const divisionName = helpers.string(ctx, "divisionName", _divisionName); - const productName = helpers.string(ctx, "productName", _productName); - const product = getProduct(divisionName, productName); - const corporation = getCorporation(); - return { - name: product.name, - dmd: corporation.unlockUpgrades[2] ? product.dmd : undefined, - cmp: corporation.unlockUpgrades[3] ? product.cmp : undefined, - rat: product.rat, - properties: { - qlt: product.qlt, - per: product.per, - dur: product.dur, - rel: product.rel, - aes: product.aes, - fea: product.fea, - }, - pCost: product.pCost, - sCost: product.sCost, - cityData: product.data, - developmentProgress: product.prog, - }; - }, - purchaseWarehouse: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown): void => { - checkAccess(ctx, 7); - const divisionName = helpers.string(ctx, "divisionName", _divisionName); - const cityName = helpers.city(ctx, "cityName", _cityName); - const corporation = getCorporation(); - PurchaseWarehouse(corporation, getDivision(divisionName), cityName); - }, + hasWarehouse: (ctx) => (_divisionName, _cityName) => { + checkAccess(ctx, 7); + 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]; + return warehouse !== 0; + }, + getWarehouse: (ctx) => (_divisionName, _cityName) => { + checkAccess(ctx, 7); + const divisionName = helpers.string(ctx, "divisionName", _divisionName); + const cityName = helpers.city(ctx, "cityName", _cityName); + const warehouse = getWarehouse(divisionName, cityName); + return { + level: warehouse.level, + loc: warehouse.loc, + size: warehouse.size, + sizeUsed: warehouse.sizeUsed, + smartSupplyEnabled: warehouse.smartSupplyEnabled, + }; + }, + getMaterial: (ctx) => (_divisionName, _cityName, _materialName) => { + checkAccess(ctx, 7); + 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(); + const exports = material.exp.map((e) => { + return { div: e.ind, loc: e.city, amt: e.amt }; + }); + return { + cost: material.bCost, + sCost: material.sCost, + name: material.name, + qty: material.qty, + qlt: material.qlt, + dmd: corporation.unlockUpgrades[2] ? material.dmd : undefined, + cmp: corporation.unlockUpgrades[3] ? material.cmp : undefined, + prod: material.prd, + sell: material.sll, + exp: exports, + }; + }, + getProduct: (ctx) => (_divisionName, _productName) => { + checkAccess(ctx, 7); + const divisionName = helpers.string(ctx, "divisionName", _divisionName); + const productName = helpers.string(ctx, "productName", _productName); + const product = getProduct(divisionName, productName); + const corporation = getCorporation(); + return { + name: product.name, + dmd: corporation.unlockUpgrades[2] ? product.dmd : undefined, + cmp: corporation.unlockUpgrades[3] ? product.cmp : undefined, + rat: product.rat, + properties: { + qlt: product.qlt, + per: product.per, + dur: product.dur, + rel: product.rel, + aes: product.aes, + fea: product.fea, + }, + pCost: product.pCost, + sCost: product.sCost, + cityData: product.data, + developmentProgress: product.prog, + }; + }, + purchaseWarehouse: (ctx) => (_divisionName, _cityName) => { + checkAccess(ctx, 7); + const divisionName = helpers.string(ctx, "divisionName", _divisionName); + const cityName = helpers.city(ctx, "cityName", _cityName); + const corporation = getCorporation(); + PurchaseWarehouse(corporation, getDivision(divisionName), cityName); + }, upgradeWarehouse: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown, _amt: unknown = 1): void => { + (ctx) => + (_divisionName, _cityName, _amt = 1): void => { checkAccess(ctx, 7); const divisionName = helpers.string(ctx, "divisionName", _divisionName); const cityName = helpers.city(ctx, "cityName", _cityName); @@ -425,28 +409,19 @@ export function NetscriptCorporation(): InternalAPI { } UpgradeWarehouse(corporation, getDivision(divisionName), getWarehouse(divisionName, cityName), amt); }, - sellMaterial: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown, _materialName: unknown, _amt: unknown, _price: unknown): void => { - checkAccess(ctx, 7); - 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); - }, + sellMaterial: (ctx) => (_divisionName, _cityName, _materialName, _amt, _price) => { + checkAccess(ctx, 7); + 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); + }, sellProduct: - (ctx: NetscriptContext) => - ( - _divisionName: unknown, - _cityName: unknown, - _productName: unknown, - _amt: unknown, - _price: unknown, - _all: unknown, - ): void => { + (ctx) => + (_divisionName, _cityName, _productName, _amt, _price, _all): void => { checkAccess(ctx, 7); const divisionName = helpers.string(ctx, "divisionName", _divisionName); const cityName = helpers.city(ctx, "cityName", _cityName); @@ -457,76 +432,60 @@ export function NetscriptCorporation(): InternalAPI { const product = getProduct(divisionName, productName); SellProduct(product, cityName, amt, price, all); }, - discontinueProduct: - (ctx: NetscriptContext) => - (_divisionName: unknown, _productName: unknown): void => { - checkAccess(ctx, 7); - 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 = 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 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 = 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 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 = 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); - }, - bulkPurchase: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown, _materialName: unknown, _amt: unknown): void => { - checkAccess(ctx, 7); - 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 = 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); - }, + discontinueProduct: (ctx) => (_divisionName, _productName) => { + checkAccess(ctx, 7); + const divisionName = helpers.string(ctx, "divisionName", _divisionName); + const productName = helpers.string(ctx, "productName", _productName); + getDivision(divisionName).discontinueProduct(getProduct(divisionName, productName)); + }, + setSmartSupply: (ctx) => (_divisionName, _cityName, _enabled) => { + checkAccess(ctx, 7); + 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 helpers.makeRuntimeErrorMsg(ctx, `You have not purchased the Smart Supply upgrade!`); + SetSmartSupply(warehouse, enabled); + }, + setSmartSupplyUseLeftovers: (ctx) => (_divisionName, _cityName, _materialName, _enabled) => { + checkAccess(ctx, 7); + 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 helpers.makeRuntimeErrorMsg(ctx, `You have not purchased the Smart Supply upgrade!`); + SetSmartSupplyUseLeftovers(warehouse, material, enabled); + }, + buyMaterial: (ctx) => (_divisionName, _cityName, _materialName, _amt) => { + checkAccess(ctx, 7); + 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); + }, + bulkPurchase: (ctx) => (_divisionName, _cityName, _materialName, _amt) => { + checkAccess(ctx, 7); + 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 = 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); + }, makeProduct: - (ctx: NetscriptContext) => - ( - _divisionName: unknown, - _cityName: unknown, - _productName: unknown, - _designInvest: unknown, - _marketingInvest: unknown, - ): void => { + (ctx) => + (_divisionName, _cityName, _productName, _designInvest, _marketingInvest): void => { checkAccess(ctx, 7); const divisionName = helpers.string(ctx, "divisionName", _divisionName); const cityName = helpers.city(ctx, "cityName", _cityName); @@ -536,26 +495,17 @@ export function NetscriptCorporation(): InternalAPI { const corporation = getCorporation(); MakeProduct(corporation, getDivision(divisionName), cityName, productName, designInvest, marketingInvest); }, - limitProductProduction: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown, _productName: unknown, _qty: unknown): void => { - checkAccess(ctx, 7); - 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); - }, + limitProductProduction: (ctx) => (_divisionName, _cityName, _productName, _qty) => { + checkAccess(ctx, 7); + 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: - (ctx: NetscriptContext) => - ( - _sourceDivision: unknown, - _sourceCity: unknown, - _targetDivision: unknown, - _targetCity: unknown, - _materialName: unknown, - _amt: unknown, - ): void => { + (ctx) => + (_sourceDivision, _sourceCity, _targetDivision, _targetCity, _materialName, _amt): void => { checkAccess(ctx, 7); const sourceDivision = helpers.string(ctx, "sourceDivision", _sourceDivision); const sourceCity = helpers.string(ctx, "sourceCity", _sourceCity); @@ -572,15 +522,8 @@ export function NetscriptCorporation(): InternalAPI { ); }, cancelExportMaterial: - (ctx: NetscriptContext) => - ( - _sourceDivision: unknown, - _sourceCity: unknown, - _targetDivision: unknown, - _targetCity: unknown, - _materialName: unknown, - _amt: unknown, - ): void => { + (ctx) => + (_sourceDivision, _sourceCity, _targetDivision, _targetCity, _materialName, _amt): void => { checkAccess(ctx, 7); const sourceDivision = helpers.string(ctx, "sourceDivision", _sourceDivision); const sourceCity = helpers.string(ctx, "sourceCity", _sourceCity); @@ -595,372 +538,320 @@ export function NetscriptCorporation(): InternalAPI { amt + "", ); }, - limitMaterialProduction: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown, _materialName: unknown, _qty: unknown): void => { - checkAccess(ctx, 7); - 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 = 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 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 = 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 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 = helpers.string(ctx, "divisionName", _divisionName); - const productName = helpers.string(ctx, "productName", _productName); - const on = !!_on; - if (!getDivision(divisionName).hasResearch("Market-TA.I")) - 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 = helpers.string(ctx, "divisionName", _divisionName); - const productName = helpers.string(ctx, "productName", _productName); - const on = !!_on; - if (!getDivision(divisionName).hasResearch("Market-TA.II")) - throw helpers.makeRuntimeErrorMsg(ctx, `You have not researched MarketTA.II for division: ${divisionName}`); - SetProductMarketTA2(getProduct(divisionName, productName), on); - }, + limitMaterialProduction: (ctx) => (_divisionName, _cityName, _materialName, _qty) => { + checkAccess(ctx, 7); + 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) => (_divisionName, _cityName, _materialName, _on) => { + checkAccess(ctx, 7); + 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 helpers.makeRuntimeErrorMsg(ctx, `You have not researched MarketTA.I for division: ${divisionName}`); + SetMaterialMarketTA1(getMaterial(divisionName, cityName, materialName), on); + }, + setMaterialMarketTA2: (ctx) => (_divisionName, _cityName, _materialName, _on) => { + checkAccess(ctx, 7); + 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 helpers.makeRuntimeErrorMsg(ctx, `You have not researched MarketTA.II for division: ${divisionName}`); + SetMaterialMarketTA2(getMaterial(divisionName, cityName, materialName), on); + }, + setProductMarketTA1: (ctx) => (_divisionName, _productName, _on) => { + checkAccess(ctx, 7); + 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 helpers.makeRuntimeErrorMsg(ctx, `You have not researched MarketTA.I for division: ${divisionName}`); + SetProductMarketTA1(getProduct(divisionName, productName), on); + }, + setProductMarketTA2: (ctx) => (_divisionName, _productName, _on) => { + checkAccess(ctx, 7); + 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 helpers.makeRuntimeErrorMsg(ctx, `You have not researched MarketTA.II for division: ${divisionName}`); + SetProductMarketTA2(getProduct(divisionName, productName), on); + }, }; const officeAPI: InternalAPI = { - getHireAdVertCost: - (ctx: NetscriptContext) => - (_divisionName: unknown): number => { - checkAccess(ctx, 8); - const divisionName = helpers.string(ctx, "divisionName", _divisionName); - const division = getDivision(divisionName); - return division.getAdVertCost(); - }, - getHireAdVertCount: - (ctx: NetscriptContext) => - (_divisionName: unknown): number => { - checkAccess(ctx, 8); - const divisionName = helpers.string(ctx, "divisionName", _divisionName); - const division = getDivision(divisionName); - return division.numAdVerts; - }, - getResearchCost: - (ctx: NetscriptContext) => - (_divisionName: unknown, _researchName: unknown): number => { - checkAccess(ctx, 8); - 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 = 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 = 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); - const costMultiplier = 1.09; - let mult = 0; - for (let i = 0; i < size / CorporationConstants.OfficeInitialSize; ++i) { - mult += Math.pow(costMultiplier, initialPriceMult + i); - } - return CorporationConstants.OfficeInitialCost * mult; - }, - assignJob: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown, _employeeName: unknown, _job: unknown): void => { - checkAccess(ctx, 8); - 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); + getHireAdVertCost: (ctx) => (_divisionName) => { + checkAccess(ctx, 8); + const divisionName = helpers.string(ctx, "divisionName", _divisionName); + const division = getDivision(divisionName); + return division.getAdVertCost(); + }, + getHireAdVertCount: (ctx) => (_divisionName) => { + checkAccess(ctx, 8); + const divisionName = helpers.string(ctx, "divisionName", _divisionName); + const division = getDivision(divisionName); + return division.numAdVerts; + }, + getResearchCost: (ctx) => (_divisionName, _researchName) => { + checkAccess(ctx, 8); + const divisionName = helpers.string(ctx, "divisionName", _divisionName); + const researchName = helpers.string(ctx, "researchName", _researchName); + return getResearchCost(getDivision(divisionName), researchName); + }, + hasResearched: (ctx) => (_divisionName, _researchName) => { + checkAccess(ctx, 8); + const divisionName = helpers.string(ctx, "divisionName", _divisionName); + const researchName = helpers.string(ctx, "researchName", _researchName); + return hasResearched(getDivision(divisionName), researchName); + }, + getOfficeSizeUpgradeCost: (ctx) => (_divisionName, _cityName, _size) => { + checkAccess(ctx, 8); + 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); + const costMultiplier = 1.09; + let mult = 0; + for (let i = 0; i < size / CorporationConstants.OfficeInitialSize; ++i) { + mult += Math.pow(costMultiplier, initialPriceMult + i); + } + return CorporationConstants.OfficeInitialCost * mult; + }, + assignJob: (ctx) => (_divisionName, _cityName, _employeeName, _job) => { + checkAccess(ctx, 8); + 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 (!checkEnum(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`); - const office = getOffice(divisionName, cityName); + if (!checkEnum(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`); + const office = getOffice(divisionName, cityName); - AssignJob(office, employeeName, job); - }, - setAutoJobAssignment: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown, _job: unknown, _amount: unknown): boolean => { - checkAccess(ctx, 8); - 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); + AssignJob(office, employeeName, job); + }, + setAutoJobAssignment: (ctx) => (_divisionName, _cityName, _job, _amount) => { + checkAccess(ctx, 8); + 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 (!checkEnum(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`); - const office = getOffice(divisionName, cityName); + if (!checkEnum(EmployeePositions, job)) throw new Error(`'${job}' is not a valid job.`); + const office = getOffice(divisionName, cityName); - return AutoAssignJob(office, job, amount); - }, - hireEmployee: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown): NSEmployee | undefined => { - checkAccess(ctx, 8); - 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; - return { - name: employee.name, - mor: employee.mor, - hap: employee.hap, - ene: employee.ene, - int: employee.int, - cha: employee.cha, - exp: employee.exp, - cre: employee.cre, - eff: employee.eff, - sal: employee.sal, - loc: employee.loc, - pos: employee.pos, - }; - }, - upgradeOfficeSize: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown, _size: unknown): void => { - checkAccess(ctx, 8); - 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(); - UpgradeOfficeSize(corporation, office, size); - }, - throwParty: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown, _costPerEmployee: unknown): number => { - checkAccess(ctx, 8); - const divisionName = helpers.string(ctx, "divisionName", _divisionName); - const cityName = helpers.city(ctx, "cityName", _cityName); - const costPerEmployee = helpers.number(ctx, "costPerEmployee", _costPerEmployee); + return AutoAssignJob(office, job, amount); + }, + hireEmployee: (ctx) => (_divisionName, _cityName) => { + checkAccess(ctx, 8); + 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; + return { + name: employee.name, + mor: employee.mor, + hap: employee.hap, + ene: employee.ene, + int: employee.int, + cha: employee.cha, + exp: employee.exp, + cre: employee.cre, + eff: employee.eff, + sal: employee.sal, + loc: employee.loc, + pos: employee.pos, + }; + }, + upgradeOfficeSize: (ctx) => (_divisionName, _cityName, _size) => { + checkAccess(ctx, 8); + 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(); + UpgradeOfficeSize(corporation, office, size); + }, + throwParty: (ctx) => (_divisionName, _cityName, _costPerEmployee) => { + checkAccess(ctx, 8); + 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"); - } + if (costPerEmployee < 0) { + throw new Error("Invalid value for Cost Per Employee field! Must be numeric and greater than 0"); + } - const corporation = getCorporation(); - const office = getOffice(divisionName, cityName); + const corporation = getCorporation(); + const office = getOffice(divisionName, cityName); - return ThrowParty(corporation, office, costPerEmployee); - }, - buyCoffee: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown): boolean => { - checkAccess(ctx, 8); - const divisionName = helpers.string(ctx, "divisionName", _divisionName); - const cityName = helpers.city(ctx, "cityName", _cityName); + return ThrowParty(corporation, office, costPerEmployee); + }, + buyCoffee: (ctx) => (_divisionName, _cityName) => { + checkAccess(ctx, 8); + const divisionName = helpers.string(ctx, "divisionName", _divisionName); + const cityName = helpers.city(ctx, "cityName", _cityName); - const corporation = getCorporation(); - const office = getOffice(divisionName, cityName); + const corporation = getCorporation(); + const office = getOffice(divisionName, cityName); - return BuyCoffee(corporation, office); - }, - hireAdVert: - (ctx: NetscriptContext) => - (_divisionName: unknown): void => { - checkAccess(ctx, 8); - const divisionName = helpers.string(ctx, "divisionName", _divisionName); - const corporation = getCorporation(); - HireAdVert(corporation, getDivision(divisionName)); - }, - research: - (ctx: NetscriptContext) => - (_divisionName: unknown, _researchName: unknown): void => { - checkAccess(ctx, 8); - 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 = helpers.string(ctx, "divisionName", _divisionName); - const cityName = helpers.city(ctx, "cityName", _cityName); - const office = getOffice(divisionName, cityName); - return { - loc: office.loc, - size: office.size, - minEne: office.minEne, - maxEne: office.maxEne, - minHap: office.minHap, - maxHap: office.maxHap, - minMor: office.minMor, - maxMor: office.maxMor, - employees: office.employees.map((e) => e.name), - employeeProd: { - Operations: office.employeeProd[EmployeePositions.Operations], - Engineer: office.employeeProd[EmployeePositions.Engineer], - Business: office.employeeProd[EmployeePositions.Business], - Management: office.employeeProd[EmployeePositions.Management], - "Research & Development": office.employeeProd[EmployeePositions.RandD], - Training: office.employeeProd[EmployeePositions.Training], - Unassigned: 0, - }, - employeeJobs: { - Operations: office.employeeJobs[EmployeePositions.Operations], - Engineer: office.employeeJobs[EmployeePositions.Engineer], - Business: office.employeeJobs[EmployeePositions.Business], - Management: office.employeeJobs[EmployeePositions.Management], - "Research & Development": office.employeeJobs[EmployeePositions.RandD], - Training: office.employeeJobs[EmployeePositions.Training], - Unassigned: office.employeeJobs[EmployeePositions.Unassigned], - }, - }; - }, - getEmployee: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown, _employeeName: unknown): NSEmployee => { - checkAccess(ctx, 8); - 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, - mor: employee.mor, - hap: employee.hap, - ene: employee.ene, - int: employee.int, - cha: employee.cha, - exp: employee.exp, - cre: employee.cre, - eff: employee.eff, - sal: employee.sal, - loc: employee.loc, - pos: employee.pos, - }; - }, + return BuyCoffee(corporation, office); + }, + hireAdVert: (ctx) => (_divisionName) => { + checkAccess(ctx, 8); + const divisionName = helpers.string(ctx, "divisionName", _divisionName); + const corporation = getCorporation(); + HireAdVert(corporation, getDivision(divisionName)); + }, + research: (ctx) => (_divisionName, _researchName) => { + checkAccess(ctx, 8); + const divisionName = helpers.string(ctx, "divisionName", _divisionName); + const researchName = helpers.string(ctx, "researchName", _researchName); + Research(getDivision(divisionName), researchName); + }, + getOffice: (ctx) => (_divisionName, _cityName) => { + checkAccess(ctx, 8); + const divisionName = helpers.string(ctx, "divisionName", _divisionName); + const cityName = helpers.city(ctx, "cityName", _cityName); + const office = getOffice(divisionName, cityName); + return { + loc: office.loc, + size: office.size, + minEne: office.minEne, + maxEne: office.maxEne, + minHap: office.minHap, + maxHap: office.maxHap, + minMor: office.minMor, + maxMor: office.maxMor, + employees: office.employees.map((e) => e.name), + employeeProd: { + Operations: office.employeeProd[EmployeePositions.Operations], + Engineer: office.employeeProd[EmployeePositions.Engineer], + Business: office.employeeProd[EmployeePositions.Business], + Management: office.employeeProd[EmployeePositions.Management], + "Research & Development": office.employeeProd[EmployeePositions.RandD], + Training: office.employeeProd[EmployeePositions.Training], + Unassigned: 0, + }, + employeeJobs: { + Operations: office.employeeJobs[EmployeePositions.Operations], + Engineer: office.employeeJobs[EmployeePositions.Engineer], + Business: office.employeeJobs[EmployeePositions.Business], + Management: office.employeeJobs[EmployeePositions.Management], + "Research & Development": office.employeeJobs[EmployeePositions.RandD], + Training: office.employeeJobs[EmployeePositions.Training], + Unassigned: office.employeeJobs[EmployeePositions.Unassigned], + }, + }; + }, + getEmployee: (ctx) => (_divisionName, _cityName, _employeeName) => { + checkAccess(ctx, 8); + 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, + mor: employee.mor, + hap: employee.hap, + ene: employee.ene, + int: employee.int, + cha: employee.cha, + exp: employee.exp, + cre: employee.cre, + eff: employee.eff, + sal: employee.sal, + loc: employee.loc, + pos: employee.pos, + }; + }, }; return { ...warehouseAPI, ...officeAPI, - getMaterialNames: (ctx: NetscriptContext) => (): string[] => { + getMaterialNames: (ctx) => () => { checkAccess(ctx); return [...CorporationConstants.AllMaterials]; }, - getIndustryTypes: (ctx: NetscriptContext) => (): string[] => { + getIndustryTypes: (ctx) => () => { checkAccess(ctx); return [...CorporationConstants.AllIndustryTypes]; }, - getUnlockables: (ctx: NetscriptContext) => (): string[] => { + getUnlockables: (ctx) => () => { checkAccess(ctx); return [...CorporationConstants.AllUnlocks]; }, - getUpgradeNames: (ctx: NetscriptContext) => (): string[] => { + getUpgradeNames: (ctx) => () => { checkAccess(ctx); return [...CorporationConstants.AllUpgrades]; }, - getResearchNames: (ctx: NetscriptContext) => (): string[] => { + getResearchNames: (ctx) => () => { checkAccess(ctx); return [...CorporationConstants.AllResearch]; }, - expandIndustry: - (ctx: NetscriptContext) => - (_industryName: unknown, _divisionName: unknown): void => { - checkAccess(ctx); - const industryName = helpers.string(ctx, "industryName", _industryName); - const divisionName = helpers.string(ctx, "divisionName", _divisionName); - const corporation = getCorporation(); - NewIndustry(corporation, industryName, divisionName); - }, - expandCity: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown): void => { - checkAccess(ctx); - 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); - NewCity(corporation, division, cityName); - }, - unlockUpgrade: - (ctx: NetscriptContext) => - (_upgradeName: unknown): void => { - checkAccess(ctx); - 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}'`); - UnlockUpgrade(corporation, upgrade); - }, - levelUpgrade: - (ctx: NetscriptContext) => - (_upgradeName: unknown): void => { - checkAccess(ctx); - 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}'`); - LevelUpgrade(corporation, upgrade); - }, - issueDividends: - (ctx: NetscriptContext) => - (_rate: unknown): void => { - checkAccess(ctx); - 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 helpers.makeRuntimeErrorMsg(ctx, `Your company has not gone public!`); - IssueDividends(corporation, rate); - }, + expandIndustry: (ctx) => (_industryName, _divisionName) => { + checkAccess(ctx); + const industryName = helpers.string(ctx, "industryName", _industryName); + const divisionName = helpers.string(ctx, "divisionName", _divisionName); + const corporation = getCorporation(); + NewIndustry(corporation, industryName, divisionName); + }, + expandCity: (ctx) => (_divisionName, _cityName) => { + checkAccess(ctx); + 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); + NewCity(corporation, division, cityName); + }, + unlockUpgrade: (ctx) => (_upgradeName) => { + checkAccess(ctx); + 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}'`); + UnlockUpgrade(corporation, upgrade); + }, + levelUpgrade: (ctx) => (_upgradeName) => { + checkAccess(ctx); + 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}'`); + LevelUpgrade(corporation, upgrade); + }, + issueDividends: (ctx) => (_rate) => { + checkAccess(ctx); + 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 helpers.makeRuntimeErrorMsg(ctx, `Your company has not gone public!`); + IssueDividends(corporation, rate); + }, // If you modify these objects you will affect them for real, it's not // copies. - getDivision: - (ctx: NetscriptContext) => - (_divisionName: unknown): NSDivision => { - checkAccess(ctx); - const divisionName = helpers.string(ctx, "divisionName", _divisionName); - const division = getDivision(divisionName); - return getSafeDivision(division); - }, - getCorporation: (ctx: NetscriptContext) => (): CorporationInfo => { + getDivision: (ctx) => (_divisionName) => { + checkAccess(ctx); + const divisionName = helpers.string(ctx, "divisionName", _divisionName); + const division = getDivision(divisionName); + return getSafeDivision(division); + }, + getCorporation: (ctx) => () => { checkAccess(ctx); const corporation = getCorporation(); return { @@ -982,89 +873,71 @@ export function NetscriptCorporation(): InternalAPI { }; }, createCorporation: - (ctx: NetscriptContext) => - (_corporationName: unknown, _selfFund: unknown = true): boolean => { + (ctx) => + (_corporationName, _selfFund = true): boolean => { const corporationName = helpers.string(ctx, "corporationName", _corporationName); const selfFund = !!_selfFund; return createCorporation(corporationName, selfFund); }, - hasUnlockUpgrade: - (ctx: NetscriptContext) => - (_upgradeName: unknown): boolean => { - checkAccess(ctx); - const upgradeName = helpers.string(ctx, "upgradeName", _upgradeName); - return hasUnlockUpgrade(upgradeName); - }, - getUnlockUpgradeCost: - (ctx: NetscriptContext) => - (_upgradeName: unknown): number => { - checkAccess(ctx); - const upgradeName = helpers.string(ctx, "upgradeName", _upgradeName); - return getUnlockUpgradeCost(upgradeName); - }, - getUpgradeLevel: - (ctx: NetscriptContext) => - (_upgradeName: unknown): number => { - checkAccess(ctx); - const upgradeName = helpers.string(ctx, "upgradeName", _upgradeName); - return getUpgradeLevel(ctx, upgradeName); - }, - getUpgradeLevelCost: - (ctx: NetscriptContext) => - (_upgradeName: unknown): number => { - checkAccess(ctx); - const upgradeName = helpers.string(ctx, "upgradeName", _upgradeName); - return getUpgradeLevelCost(ctx, upgradeName); - }, - getExpandIndustryCost: - (ctx: NetscriptContext) => - (_industryName: unknown): number => { - checkAccess(ctx); - const industryName = helpers.string(ctx, "industryName", _industryName); - return getExpandIndustryCost(industryName); - }, - getExpandCityCost: (ctx: NetscriptContext) => (): number => { + hasUnlockUpgrade: (ctx) => (_upgradeName) => { + checkAccess(ctx); + const upgradeName = helpers.string(ctx, "upgradeName", _upgradeName); + return hasUnlockUpgrade(upgradeName); + }, + getUnlockUpgradeCost: (ctx) => (_upgradeName) => { + checkAccess(ctx); + const upgradeName = helpers.string(ctx, "upgradeName", _upgradeName); + return getUnlockUpgradeCost(upgradeName); + }, + getUpgradeLevel: (ctx) => (_upgradeName) => { + checkAccess(ctx); + const upgradeName = helpers.string(ctx, "upgradeName", _upgradeName); + return getUpgradeLevel(ctx, upgradeName); + }, + getUpgradeLevelCost: (ctx) => (_upgradeName) => { + checkAccess(ctx); + const upgradeName = helpers.string(ctx, "upgradeName", _upgradeName); + return getUpgradeLevelCost(ctx, upgradeName); + }, + getExpandIndustryCost: (ctx) => (_industryName) => { + checkAccess(ctx); + const industryName = helpers.string(ctx, "industryName", _industryName); + return getExpandIndustryCost(industryName); + }, + getExpandCityCost: (ctx) => () => { checkAccess(ctx); return getExpandCityCost(); }, - getInvestmentOffer: (ctx: NetscriptContext) => (): InvestmentOffer => { + getInvestmentOffer: (ctx) => () => { checkAccess(ctx); return getInvestmentOffer(); }, - acceptInvestmentOffer: (ctx: NetscriptContext) => (): boolean => { + acceptInvestmentOffer: (ctx) => () => { checkAccess(ctx); return acceptInvestmentOffer(); }, - goPublic: - (ctx: NetscriptContext) => - (_numShares: unknown): boolean => { - checkAccess(ctx); - const numShares = helpers.number(ctx, "numShares", _numShares); - return goPublic(numShares); - }, - sellShares: - (ctx: NetscriptContext) => - (_numShares: unknown): number => { - checkAccess(ctx); - const numShares = helpers.number(ctx, "numShares", _numShares); - return SellShares(getCorporation(), numShares); - }, - buyBackShares: - (ctx: NetscriptContext) => - (_numShares: unknown): boolean => { - checkAccess(ctx); - const numShares = helpers.number(ctx, "numShares", _numShares); - return BuyBackShares(getCorporation(), numShares); - }, - bribe: - (ctx: NetscriptContext) => - (_factionName: unknown, _amountCash: unknown): boolean => { - checkAccess(ctx); - const factionName = helpers.string(ctx, "factionName", _factionName); - const amountCash = helpers.number(ctx, "amountCash", _amountCash); - return bribe(factionName, amountCash); - }, - getBonusTime: (ctx: NetscriptContext) => (): number => { + goPublic: (ctx) => (_numShares) => { + checkAccess(ctx); + const numShares = helpers.number(ctx, "numShares", _numShares); + return goPublic(numShares); + }, + sellShares: (ctx) => (_numShares) => { + checkAccess(ctx); + const numShares = helpers.number(ctx, "numShares", _numShares); + return SellShares(getCorporation(), numShares); + }, + buyBackShares: (ctx) => (_numShares) => { + checkAccess(ctx); + const numShares = helpers.number(ctx, "numShares", _numShares); + return BuyBackShares(getCorporation(), numShares); + }, + bribe: (ctx) => (_factionName, _amountCash) => { + checkAccess(ctx); + const factionName = helpers.string(ctx, "factionName", _factionName); + const amountCash = helpers.number(ctx, "amountCash", _amountCash); + return bribe(factionName, amountCash); + }, + getBonusTime: (ctx) => () => { checkAccess(ctx); return Math.round(getCorporation().storedCycles / 5) * 1000; }, diff --git a/src/NetscriptFunctions/Extra.ts b/src/NetscriptFunctions/Extra.ts index 427a1ec63..014179777 100644 --- a/src/NetscriptFunctions/Extra.ts +++ b/src/NetscriptFunctions/Extra.ts @@ -1,9 +1,10 @@ -import { Player as player } from "../Player"; +import { 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 { InternalAPI } from "../Netscript/APIWrapper"; import { helpers } from "../Netscript/NetscriptHelpers"; +import { Terminal } from "../Terminal"; export interface INetscriptExtra { heart: { @@ -14,40 +15,39 @@ export interface INetscriptExtra { bypass(doc: Document): void; alterReality(): void; rainbow(guess: string): void; + iKnowWhatImDoing(): void; } export function NetscriptExtra(): InternalAPI { return { heart: { // Easter egg function - break: () => (): number => { - return player.karma; + break: () => () => { + return Player.karma; }, }, - openDevMenu: () => (): void => { + openDevMenu: () => () => { devMenu.emit(); }, - exploit: () => (): void => { - player.giveExploit(Exploit.UndocumentedFunctionCall); + exploit: () => () => { + Player.giveExploit(Exploit.UndocumentedFunctionCall); }, - bypass: - (ctx: NetscriptContext) => - (doc: unknown): void => { - // reset both fields first - type temporary = { completely_unused_field: unknown }; - const d = doc as temporary; - d.completely_unused_field = undefined; - const real_document = document as unknown as temporary; - real_document.completely_unused_field = undefined; - // set one to true and check that it affected the other. - real_document.completely_unused_field = true; - if (d.completely_unused_field && ctx.workerScript.ramUsage === 1.6) { - player.giveExploit(Exploit.Bypass); - } - d.completely_unused_field = undefined; - real_document.completely_unused_field = undefined; - }, - alterReality: () => (): void => { + bypass: (ctx) => (doc) => { + // reset both fields first + type temporary = { completely_unused_field: unknown }; + const d = doc as temporary; + d.completely_unused_field = undefined; + const real_document = document as unknown as temporary; + real_document.completely_unused_field = undefined; + // set one to true and check that it affected the other. + real_document.completely_unused_field = true; + if (d.completely_unused_field && ctx.workerScript.ramUsage === 1.6) { + Player.giveExploit(Exploit.Bypass); + } + d.completely_unused_field = undefined; + real_document.completely_unused_field = undefined; + }, + alterReality: () => () => { // We need to trick webpack into not optimizing a variable that is guaranteed to be false (and doesn't use prototypes) let x = false; const recur = function (depth: number): void { @@ -59,25 +59,28 @@ export function NetscriptExtra(): InternalAPI { console.warn("I am sure that this variable is false."); if (x !== false) { console.warn("Reality has been altered!"); - player.giveExploit(Exploit.RealityAlteration); + Player.giveExploit(Exploit.RealityAlteration); } }, - rainbow: - (ctx: NetscriptContext) => - (guess: unknown): boolean => { - function tryGuess(): boolean { - // eslint-disable-next-line no-sync - const verified = bcrypt.compareSync( - helpers.string(ctx, "guess", guess), - "$2a$10$aertxDEkgor8baVtQDZsLuMwwGYmkRM/ohcA6FjmmzIHQeTCsrCcO", - ); - if (verified) { - player.giveExploit(Exploit.INeedARainbow); - return true; - } - return false; + rainbow: (ctx) => (guess) => { + function tryGuess(): boolean { + // eslint-disable-next-line no-sync + const verified = bcrypt.compareSync( + helpers.string(ctx, "guess", guess), + "$2a$10$aertxDEkgor8baVtQDZsLuMwwGYmkRM/ohcA6FjmmzIHQeTCsrCcO", + ); + if (verified) { + Player.giveExploit(Exploit.INeedARainbow); + return true; } - return tryGuess(); - }, + return false; + } + return tryGuess(); + }, + iKnowWhatImDoing: (ctx) => () => { + helpers.log(ctx, () => "Unlocking unsupported feature: window.tprintRaw"); + // @ts-ignore window has no tprintRaw property defined + window.tprintRaw = Terminal.printRaw.bind(Terminal); + }, }; } diff --git a/src/NetscriptFunctions/Formulas.ts b/src/NetscriptFunctions/Formulas.ts index 16164e97c..aa4f621f9 100644 --- a/src/NetscriptFunctions/Formulas.ts +++ b/src/NetscriptFunctions/Formulas.ts @@ -26,11 +26,7 @@ import { calculateWeakenTime, } from "../Hacking"; import { Programs } from "../Programs/Programs"; -import { - Formulas as IFormulas, - HacknetNodeConstants as DefHacknetNodeConstants, - HacknetServerConstants as DefHacknetServerConstants, -} from "../ScriptEditor/NetscriptDefinitions"; +import { Formulas as IFormulas } from "../ScriptEditor/NetscriptDefinitions"; import { calculateRespectGain, calculateWantedLevelGain, @@ -43,7 +39,6 @@ import { favorToRep as calculateFavorToRep, repToFavor as calculateRepToFavor } import { repFromDonation } from "../Faction/formulas/donation"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import { helpers } from "../Netscript/NetscriptHelpers"; -import { WorkStats } from "../Work/WorkStats"; import { calculateCrimeWorkStats } from "../Work/formulas/Crime"; import { Crimes } from "../Crime/Crimes"; import { calculateClassEarnings } from "../Work/formulas/Class"; @@ -52,7 +47,6 @@ import { LocationName } from "../Locations/data/LocationNames"; import { calculateFactionExp, calculateFactionRep } from "../Work/formulas/Faction"; import { FactionWorkType } from "../Work/data/FactionWorkType"; -import { Player as INetscriptPlayer, Server as IServerDef } from "../ScriptEditor/NetscriptDefinitions"; import { defaultMultipliers } from "../PersonObjects/Multipliers"; export function NetscriptFormulas(): InternalAPI { @@ -62,7 +56,7 @@ export function NetscriptFormulas(): InternalAPI { } }; return { - mockServer: () => (): IServerDef => ({ + mockServer: () => () => ({ cpuCores: 0, ftpPortOpen: false, hasAdminRights: false, @@ -88,7 +82,7 @@ export function NetscriptFormulas(): InternalAPI { requiredHackingSkill: 0, serverGrowth: 0, }), - mockPlayer: () => (): INetscriptPlayer => ({ + mockPlayer: () => () => ({ hp: { current: 0, max: 0 }, skills: { hacking: 0, @@ -125,41 +119,35 @@ export function NetscriptFormulas(): InternalAPI { entropy: 0, }), reputation: { - calculateFavorToRep: - (ctx: NetscriptContext) => - (_favor: unknown): number => { - const favor = helpers.number(ctx, "favor", _favor); - checkFormulasAccess(ctx); - return calculateFavorToRep(favor); - }, - calculateRepToFavor: - (ctx: NetscriptContext) => - (_rep: unknown): number => { - const rep = helpers.number(ctx, "rep", _rep); - checkFormulasAccess(ctx); - return calculateRepToFavor(rep); - }, - repFromDonation: - (ctx: NetscriptContext) => - (_amount: unknown, _player: unknown): number => { - const amount = helpers.number(ctx, "amount", _amount); - const player = helpers.player(ctx, _player); - checkFormulasAccess(ctx); - return repFromDonation(amount, player); - }, + calculateFavorToRep: (ctx) => (_favor) => { + const favor = helpers.number(ctx, "favor", _favor); + checkFormulasAccess(ctx); + return calculateFavorToRep(favor); + }, + calculateRepToFavor: (ctx) => (_rep) => { + const rep = helpers.number(ctx, "rep", _rep); + checkFormulasAccess(ctx); + return calculateRepToFavor(rep); + }, + repFromDonation: (ctx) => (_amount, _player) => { + const amount = helpers.number(ctx, "amount", _amount); + const player = helpers.player(ctx, _player); + checkFormulasAccess(ctx); + return repFromDonation(amount, player); + }, }, skills: { calculateSkill: - (ctx: NetscriptContext) => - (_exp: unknown, _mult: unknown = 1): number => { + (ctx) => + (_exp, _mult = 1) => { 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 => { + (ctx) => + (_skill, _mult = 1) => { const skill = helpers.number(ctx, "skill", _skill); const mult = helpers.number(ctx, "mult", _mult); checkFormulasAccess(ctx); @@ -167,33 +155,27 @@ export function NetscriptFormulas(): InternalAPI { }, }, hacking: { - hackChance: - (ctx: NetscriptContext) => - (_server: unknown, _player: unknown): number => { - 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 = 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 = helpers.server(ctx, _server); - const player = helpers.player(ctx, _player); - checkFormulasAccess(ctx); - return calculatePercentMoneyHacked(server, player); - }, + hackChance: (ctx) => (_server, _player) => { + const server = helpers.server(ctx, _server); + const player = helpers.player(ctx, _player); + checkFormulasAccess(ctx); + return calculateHackingChance(server, player); + }, + hackExp: (ctx) => (_server, _player) => { + const server = helpers.server(ctx, _server); + const player = helpers.player(ctx, _player); + checkFormulasAccess(ctx); + return calculateHackingExpGain(server, player); + }, + hackPercent: (ctx) => (_server, _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 => { + (ctx) => + (_server, _threads, _player, _cores = 1) => { const server = helpers.server(ctx, _server); const player = helpers.player(ctx, _player); const threads = helpers.number(ctx, "threads", _threads); @@ -201,35 +183,29 @@ export function NetscriptFormulas(): InternalAPI { checkFormulasAccess(ctx); return calculateServerGrowth(server, threads, player, cores); }, - hackTime: - (ctx: NetscriptContext) => - (_server: unknown, _player: unknown): number => { - 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 = 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 = helpers.server(ctx, _server); - const player = helpers.player(ctx, _player); - checkFormulasAccess(ctx); - return calculateWeakenTime(server, player) * 1000; - }, + hackTime: (ctx) => (_server, _player) => { + const server = helpers.server(ctx, _server); + const player = helpers.player(ctx, _player); + checkFormulasAccess(ctx); + return calculateHackingTime(server, player) * 1000; + }, + growTime: (ctx) => (_server, _player) => { + const server = helpers.server(ctx, _server); + const player = helpers.player(ctx, _player); + checkFormulasAccess(ctx); + return calculateGrowTime(server, player) * 1000; + }, + weakenTime: (ctx) => (_server, _player) => { + const server = helpers.server(ctx, _server); + const player = helpers.player(ctx, _player); + checkFormulasAccess(ctx); + return calculateWeakenTime(server, player) * 1000; + }, }, hacknetNodes: { moneyGainRate: - (ctx: NetscriptContext) => - (_level: unknown, _ram: unknown, _cores: unknown, _mult: unknown = 1): number => { + (ctx) => + (_level, _ram, _cores, _mult = 1) => { const level = helpers.number(ctx, "level", _level); const ram = helpers.number(ctx, "ram", _ram); const cores = helpers.number(ctx, "cores", _cores); @@ -238,8 +214,8 @@ export function NetscriptFormulas(): InternalAPI { return calculateMoneyGainRate(level, ram, cores, mult); }, levelUpgradeCost: - (ctx: NetscriptContext) => - (_startingLevel: unknown, _extraLevels: unknown = 1, _costMult: unknown = 1): number => { + (ctx) => + (_startingLevel, _extraLevels = 1, _costMult = 1) => { const startingLevel = helpers.number(ctx, "startingLevel", _startingLevel); const extraLevels = helpers.number(ctx, "extraLevels", _extraLevels); const costMult = helpers.number(ctx, "costMult", _costMult); @@ -247,8 +223,8 @@ export function NetscriptFormulas(): InternalAPI { return calculateLevelUpgradeCost(startingLevel, extraLevels, costMult); }, ramUpgradeCost: - (ctx: NetscriptContext) => - (_startingRam: unknown, _extraLevels: unknown = 1, _costMult: unknown = 1): number => { + (ctx) => + (_startingRam, _extraLevels = 1, _costMult = 1) => { const startingRam = helpers.number(ctx, "startingRam", _startingRam); const extraLevels = helpers.number(ctx, "extraLevels", _extraLevels); const costMult = helpers.number(ctx, "costMult", _costMult); @@ -256,31 +232,29 @@ export function NetscriptFormulas(): InternalAPI { return calculateRamUpgradeCost(startingRam, extraLevels, costMult); }, coreUpgradeCost: - (ctx: NetscriptContext) => - (_startingCore: unknown, _extraCores: unknown = 1, _costMult: unknown = 1): number => { + (ctx) => + (_startingCore, _extraCores = 1, _costMult = 1) => { 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 = helpers.number(ctx, "n", _n); - const mult = helpers.number(ctx, "mult", _mult); - checkFormulasAccess(ctx); - return calculateNodeCost(n, mult); - }, - constants: (ctx: NetscriptContext) => (): DefHacknetNodeConstants => { + hacknetNodeCost: (ctx) => (_n, _mult) => { + const n = helpers.number(ctx, "n", _n); + const mult = helpers.number(ctx, "mult", _mult); + checkFormulasAccess(ctx); + return calculateNodeCost(n, mult); + }, + constants: (ctx) => () => { checkFormulasAccess(ctx); return Object.assign({}, HacknetNodeConstants); }, }, hacknetServers: { hashGainRate: - (ctx: NetscriptContext) => - (_level: unknown, _ramUsed: unknown, _maxRam: unknown, _cores: unknown, _mult: unknown = 1): number => { + (ctx) => + (_level, _ramUsed, _maxRam, _cores, _mult = 1) => { const level = helpers.number(ctx, "level", _level); const ramUsed = helpers.number(ctx, "ramUsed", _ramUsed); const maxRam = helpers.number(ctx, "maxRam", _maxRam); @@ -290,8 +264,8 @@ export function NetscriptFormulas(): InternalAPI { return HScalculateHashGainRate(level, ramUsed, maxRam, cores, mult); }, levelUpgradeCost: - (ctx: NetscriptContext) => - (_startingLevel: unknown, _extraLevels: unknown = 1, _costMult: unknown = 1): number => { + (ctx) => + (_startingLevel, _extraLevels = 1, _costMult = 1) => { const startingLevel = helpers.number(ctx, "startingLevel", _startingLevel); const extraLevels = helpers.number(ctx, "extraLevels", _extraLevels); const costMult = helpers.number(ctx, "costMult", _costMult); @@ -299,8 +273,8 @@ export function NetscriptFormulas(): InternalAPI { return HScalculateLevelUpgradeCost(startingLevel, extraLevels, costMult); }, ramUpgradeCost: - (ctx: NetscriptContext) => - (_startingRam: unknown, _extraLevels: unknown = 1, _costMult: unknown = 1): number => { + (ctx) => + (_startingRam, _extraLevels = 1, _costMult = 1) => { const startingRam = helpers.number(ctx, "startingRam", _startingRam); const extraLevels = helpers.number(ctx, "extraLevels", _extraLevels); const costMult = helpers.number(ctx, "costMult", _costMult); @@ -308,8 +282,8 @@ export function NetscriptFormulas(): InternalAPI { return HScalculateRamUpgradeCost(startingRam, extraLevels, costMult); }, coreUpgradeCost: - (ctx: NetscriptContext) => - (_startingCore: unknown, _extraCores: unknown = 1, _costMult: unknown = 1): number => { + (ctx) => + (_startingCore, _extraCores = 1, _costMult = 1) => { const startingCore = helpers.number(ctx, "startingCore", _startingCore); const extraCores = helpers.number(ctx, "extraCores", _extraCores); const costMult = helpers.number(ctx, "costMult", _costMult); @@ -317,117 +291,97 @@ export function NetscriptFormulas(): InternalAPI { return HScalculateCoreUpgradeCost(startingCore, extraCores, costMult); }, cacheUpgradeCost: - (ctx: NetscriptContext) => - (_startingCache: unknown, _extraCache: unknown = 1): number => { + (ctx) => + (_startingCache, _extraCache = 1) => { 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 = helpers.string(ctx, "upgName", _upgName); - const level = helpers.number(ctx, "level", _level); - checkFormulasAccess(ctx); - const upg = player.hashManager.getUpgrade(upgName); - if (!upg) { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid Hash Upgrade: ${upgName}`); - } - return upg.getCost(level); - }, + hashUpgradeCost: (ctx) => (_upgName, _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 helpers.makeRuntimeErrorMsg(ctx, `Invalid Hash Upgrade: ${upgName}`); + } + return upg.getCost(level); + }, hacknetServerCost: - (ctx: NetscriptContext) => - (_n: unknown, _mult: unknown = 1): number => { + (ctx) => + (_n, _mult = 1) => { const n = helpers.number(ctx, "n", _n); const mult = helpers.number(ctx, "mult", _mult); checkFormulasAccess(ctx); return HScalculateServerCost(n, mult); }, - constants: (ctx: NetscriptContext) => (): DefHacknetServerConstants => { + constants: (ctx) => () => { checkFormulasAccess(ctx); return Object.assign({}, HacknetServerConstants); }, }, gang: { - wantedPenalty: - (ctx: NetscriptContext) => - (_gang: unknown): number => { - const gang = helpers.gang(ctx, _gang); - checkFormulasAccess(ctx); - return calculateWantedPenalty(gang); - }, - respectGain: - (ctx: NetscriptContext) => - (_gang: unknown, _member: unknown, _task: unknown): number => { - 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 = 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 = 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 = helpers.number(ctx, "exp", _exp); - checkFormulasAccess(ctx); - return calculateAscensionPointsGain(exp); - }, - ascensionMultiplier: - (ctx: NetscriptContext) => - (_points: unknown): number => { - const points = helpers.number(ctx, "points", _points); - checkFormulasAccess(ctx); - return calculateAscensionMult(points); - }, + wantedPenalty: (ctx) => (_gang) => { + const gang = helpers.gang(ctx, _gang); + checkFormulasAccess(ctx); + return calculateWantedPenalty(gang); + }, + respectGain: (ctx) => (_gang, _member, _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) => (_gang, _member, _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) => (_gang, _member, _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) => (_exp) => { + const exp = helpers.number(ctx, "exp", _exp); + checkFormulasAccess(ctx); + return calculateAscensionPointsGain(exp); + }, + ascensionMultiplier: (ctx) => (_points) => { + const points = helpers.number(ctx, "points", _points); + checkFormulasAccess(ctx); + return calculateAscensionMult(points); + }, }, work: { - crimeGains: - (ctx: NetscriptContext) => - (_crimeType: unknown): WorkStats => { - const crimeType = helpers.string(ctx, "crimeType", _crimeType); - const crime = Object.values(Crimes).find((c) => String(c.type) === crimeType); - if (!crime) throw new Error(`Invalid crime type: ${crimeType}`); - return calculateCrimeWorkStats(crime); - }, - classGains: - (ctx: NetscriptContext) => - (_person: unknown, _classType: unknown, _locationName: unknown): WorkStats => { - const person = helpers.player(ctx, _person); - const classType = helpers.string(ctx, "classType", _classType); - const locationName = helpers.string(ctx, "locationName", _locationName); - return calculateClassEarnings(person, classType as ClassType, locationName as LocationName); - }, - factionGains: - (ctx: NetscriptContext) => - (_player: unknown, _workType: unknown, _favor: unknown): WorkStats => { - const player = helpers.player(ctx, _player); - const workType = helpers.string(ctx, "_workType", _workType) as FactionWorkType; - const favor = helpers.number(ctx, "favor", _favor); - const exp = calculateFactionExp(player, workType); - const rep = calculateFactionRep(player, workType, favor); - exp.reputation = rep; - return exp; - }, - // companyGains: (ctx: NetscriptContext) =>_player: unknown (): WorkStats { + crimeGains: (ctx) => (_crimeType) => { + const crimeType = helpers.string(ctx, "crimeType", _crimeType); + const crime = Object.values(Crimes).find((c) => String(c.type) === crimeType); + if (!crime) throw new Error(`Invalid crime type: ${crimeType}`); + return calculateCrimeWorkStats(crime); + }, + classGains: (ctx) => (_person, _classType, _locationName) => { + const person = helpers.player(ctx, _person); + const classType = helpers.string(ctx, "classType", _classType); + const locationName = helpers.string(ctx, "locationName", _locationName); + return calculateClassEarnings(person, classType as ClassType, locationName as LocationName); + }, + factionGains: (ctx) => (_player, _workType, _favor) => { + const player = helpers.player(ctx, _player); + const workType = helpers.string(ctx, "_workType", _workType) as FactionWorkType; + const favor = helpers.number(ctx, "favor", _favor); + const exp = calculateFactionExp(player, workType); + const rep = calculateFactionRep(player, workType, favor); + exp.reputation = rep; + return exp; + }, + // companyGains: (ctx) => (_player) { // const player = helpers.player(ctx, _player); // }, diff --git a/src/NetscriptFunctions/Gang.ts b/src/NetscriptFunctions/Gang.ts index 3608813af..5f36b1b75 100644 --- a/src/NetscriptFunctions/Gang.ts +++ b/src/NetscriptFunctions/Gang.ts @@ -9,16 +9,7 @@ import { GangMember } from "../Gang/GangMember"; import { GangMemberTask } from "../Gang/GangMemberTask"; import { helpers } from "../Netscript/NetscriptHelpers"; -import { - Gang as IGang, - GangGenInfo, - GangOtherInfo, - GangMemberInfo, - GangMemberAscension, - EquipmentStats, - GangTaskStats, - GangOtherInfoObject, -} from "../ScriptEditor/NetscriptDefinitions"; +import { Gang as IGang, EquipmentStats, GangOtherInfoObject } from "../ScriptEditor/NetscriptDefinitions"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; export function NetscriptGang(): InternalAPI { @@ -44,28 +35,26 @@ export function NetscriptGang(): InternalAPI { }; return { - createGang: - (ctx: NetscriptContext) => - (_faction: unknown): boolean => { - const faction = helpers.string(ctx, "faction", _faction); - // this list is copied from Faction/ui/Root.tsx + createGang: (ctx) => (_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; - if (Player.gang) return false; - if (!Player.factions.includes(faction)) return false; + if (!Player.canAccessGang() || !GangConstants.Names.includes(faction)) return false; + if (Player.gang) return false; + if (!Player.factions.includes(faction)) return false; - const isHacking = faction === FactionNames.NiteSec || faction === FactionNames.TheBlackHand; - Player.startGang(faction, isHacking); - return true; - }, - inGang: () => (): boolean => { + const isHacking = faction === FactionNames.NiteSec || faction === FactionNames.TheBlackHand; + Player.startGang(faction, isHacking); + return true; + }, + inGang: () => () => { return Player.gang ? true : false; }, - getMemberNames: (ctx: NetscriptContext) => (): string[] => { + getMemberNames: (ctx) => () => { const gang = getGang(ctx); return gang.members.map((member) => member.name); }, - getGangInformation: (ctx: NetscriptContext) => (): GangGenInfo => { + getGangInformation: (ctx) => () => { const gang = getGang(ctx); return { faction: gang.facName, @@ -82,7 +71,7 @@ export function NetscriptGang(): InternalAPI { wantedPenalty: gang.getWantedPenalty(), }; }, - getOtherGangInformation: (ctx: NetscriptContext) => (): GangOtherInfo => { + getOtherGangInformation: (ctx) => () => { getGang(ctx); const cpy: Record = {}; for (const gang of Object.keys(AllGangs)) { @@ -91,231 +80,206 @@ export function NetscriptGang(): InternalAPI { return cpy; }, - getMemberInformation: - (ctx: NetscriptContext) => - (_memberName: unknown): GangMemberInfo => { - const memberName = helpers.string(ctx, "memberName", _memberName); - const gang = getGang(ctx); - const member = getGangMember(ctx, memberName); - return { - name: member.name, - task: member.task, - earnedRespect: member.earnedRespect, - hack: member.hack, - str: member.str, - def: member.def, - dex: member.dex, - agi: member.agi, - cha: member.cha, + getMemberInformation: (ctx) => (_memberName) => { + const memberName = helpers.string(ctx, "memberName", _memberName); + const gang = getGang(ctx); + const member = getGangMember(ctx, memberName); + return { + name: member.name, + task: member.task, + earnedRespect: member.earnedRespect, + hack: member.hack, + str: member.str, + def: member.def, + dex: member.dex, + agi: member.agi, + cha: member.cha, - hack_exp: member.hack_exp, - str_exp: member.str_exp, - def_exp: member.def_exp, - dex_exp: member.dex_exp, - agi_exp: member.agi_exp, - cha_exp: member.cha_exp, + hack_exp: member.hack_exp, + str_exp: member.str_exp, + def_exp: member.def_exp, + dex_exp: member.dex_exp, + agi_exp: member.agi_exp, + cha_exp: member.cha_exp, - hack_mult: member.hack_mult, - str_mult: member.str_mult, - def_mult: member.def_mult, - dex_mult: member.dex_mult, - agi_mult: member.agi_mult, - cha_mult: member.cha_mult, + hack_mult: member.hack_mult, + str_mult: member.str_mult, + def_mult: member.def_mult, + dex_mult: member.dex_mult, + agi_mult: member.agi_mult, + cha_mult: member.cha_mult, - hack_asc_mult: member.calculateAscensionMult(member.hack_asc_points), - str_asc_mult: member.calculateAscensionMult(member.str_asc_points), - def_asc_mult: member.calculateAscensionMult(member.def_asc_points), - dex_asc_mult: member.calculateAscensionMult(member.dex_asc_points), - agi_asc_mult: member.calculateAscensionMult(member.agi_asc_points), - cha_asc_mult: member.calculateAscensionMult(member.cha_asc_points), + hack_asc_mult: member.calculateAscensionMult(member.hack_asc_points), + str_asc_mult: member.calculateAscensionMult(member.str_asc_points), + def_asc_mult: member.calculateAscensionMult(member.def_asc_points), + dex_asc_mult: member.calculateAscensionMult(member.dex_asc_points), + agi_asc_mult: member.calculateAscensionMult(member.agi_asc_points), + cha_asc_mult: member.calculateAscensionMult(member.cha_asc_points), - hack_asc_points: member.hack_asc_points, - str_asc_points: member.str_asc_points, - def_asc_points: member.def_asc_points, - dex_asc_points: member.dex_asc_points, - agi_asc_points: member.agi_asc_points, - cha_asc_points: member.cha_asc_points, + hack_asc_points: member.hack_asc_points, + str_asc_points: member.str_asc_points, + def_asc_points: member.def_asc_points, + dex_asc_points: member.dex_asc_points, + agi_asc_points: member.agi_asc_points, + cha_asc_points: member.cha_asc_points, - upgrades: member.upgrades.slice(), - augmentations: member.augmentations.slice(), + upgrades: member.upgrades.slice(), + augmentations: member.augmentations.slice(), - respectGain: member.calculateRespectGain(gang), - wantedLevelGain: member.calculateWantedLevelGain(gang), - moneyGain: member.calculateMoneyGain(gang), - }; - }, - canRecruitMember: (ctx: NetscriptContext) => (): boolean => { + respectGain: member.calculateRespectGain(gang), + wantedLevelGain: member.calculateWantedLevelGain(gang), + moneyGain: member.calculateMoneyGain(gang), + }; + }, + canRecruitMember: (ctx) => () => { const gang = getGang(ctx); return gang.canRecruitMember(); }, - recruitMember: - (ctx: NetscriptContext) => - (_memberName: unknown): boolean => { - const memberName = helpers.string(ctx, "memberName", _memberName); - const gang = getGang(ctx); - const recruited = gang.recruitMember(memberName); - if (recruited) { - ctx.workerScript.log("gang.recruitMember", () => `Successfully recruited Gang Member '${memberName}'`); - } else { - ctx.workerScript.log("gang.recruitMember", () => `Failed to recruit Gang Member '${memberName}'`); - } + recruitMember: (ctx) => (_memberName) => { + const memberName = helpers.string(ctx, "memberName", _memberName); + const gang = getGang(ctx); + const recruited = gang.recruitMember(memberName); + if (recruited) { + ctx.workerScript.log("gang.recruitMember", () => `Successfully recruited Gang Member '${memberName}'`); + } else { + ctx.workerScript.log("gang.recruitMember", () => `Failed to recruit Gang Member '${memberName}'`); + } - return recruited; - }, - getTaskNames: (ctx: NetscriptContext) => (): string[] => { + return recruited; + }, + getTaskNames: (ctx) => () => { const gang = getGang(ctx); const tasks = gang.getAllTaskNames(); tasks.unshift("Unassigned"); return tasks; }, - setMemberTask: - (ctx: NetscriptContext) => - (_memberName: unknown, _taskName: unknown): boolean => { - const memberName = helpers.string(ctx, "memberName", _memberName); - const taskName = helpers.string(ctx, "taskName", _taskName); - const gang = getGang(ctx); - const member = getGangMember(ctx, memberName); - if (!gang.getAllTaskNames().includes(taskName)) { - ctx.workerScript.log( - "gang.setMemberTask", - () => - `Failed to assign Gang Member '${memberName}' to Invalid task '${taskName}'. '${memberName}' is now Unassigned`, - ); - return member.assignToTask("Unassigned"); - } - const success = member.assignToTask(taskName); - if (success) { - ctx.workerScript.log( - "gang.setMemberTask", - () => `Successfully assigned Gang Member '${memberName}' to '${taskName}' task`, - ); - } else { - ctx.workerScript.log( - "gang.setMemberTask", - () => - `Failed to assign Gang Member '${memberName}' to '${taskName}' task. '${memberName}' is now Unassigned`, - ); - } + setMemberTask: (ctx) => (_memberName, _taskName) => { + const memberName = helpers.string(ctx, "memberName", _memberName); + const taskName = helpers.string(ctx, "taskName", _taskName); + const gang = getGang(ctx); + const member = getGangMember(ctx, memberName); + if (!gang.getAllTaskNames().includes(taskName)) { + ctx.workerScript.log( + "gang.setMemberTask", + () => + `Failed to assign Gang Member '${memberName}' to Invalid task '${taskName}'. '${memberName}' is now Unassigned`, + ); + return member.assignToTask("Unassigned"); + } + const success = member.assignToTask(taskName); + if (success) { + ctx.workerScript.log( + "gang.setMemberTask", + () => `Successfully assigned Gang Member '${memberName}' to '${taskName}' task`, + ); + } else { + ctx.workerScript.log( + "gang.setMemberTask", + () => `Failed to assign Gang Member '${memberName}' to '${taskName}' task. '${memberName}' is now Unassigned`, + ); + } - return success; - }, - getTaskStats: - (ctx: NetscriptContext) => - (_taskName: unknown): GangTaskStats => { - const taskName = helpers.string(ctx, "taskName", _taskName); - getGang(ctx); - const task = getGangTask(ctx, taskName); - const copy = Object.assign({}, task); - copy.territory = Object.assign({}, task.territory); - return copy; - }, - getEquipmentNames: (ctx: NetscriptContext) => (): string[] => { + return success; + }, + getTaskStats: (ctx) => (_taskName) => { + const taskName = helpers.string(ctx, "taskName", _taskName); + getGang(ctx); + const task = getGangTask(ctx, taskName); + const copy = Object.assign({}, task); + copy.territory = Object.assign({}, task.territory); + return copy; + }, + getEquipmentNames: (ctx) => () => { getGang(ctx); return Object.keys(GangMemberUpgrades); }, - getEquipmentCost: - (ctx: NetscriptContext) => - (_equipName: unknown): number => { - const equipName = helpers.string(ctx, "equipName", _equipName); - const gang = getGang(ctx); - const upg = GangMemberUpgrades[equipName]; - if (upg === null) return Infinity; - return gang.getUpgradeCost(upg); - }, - getEquipmentType: - (ctx: NetscriptContext) => - (_equipName: unknown): string => { - const equipName = helpers.string(ctx, "equipName", _equipName); - getGang(ctx); - const upg = GangMemberUpgrades[equipName]; - if (upg == null) return ""; - return upg.getType(); - }, - getEquipmentStats: - (ctx: NetscriptContext) => - (_equipName: unknown): EquipmentStats => { - const equipName = helpers.string(ctx, "equipName", _equipName); - getGang(ctx); - const equipment = GangMemberUpgrades[equipName]; - if (!equipment) { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid equipment: ${equipName}`); - } - const typecheck: EquipmentStats = equipment.mults; - return Object.assign({}, typecheck) as any; - }, - purchaseEquipment: - (ctx: NetscriptContext) => - (_memberName: unknown, _equipName: unknown): boolean => { - const memberName = helpers.string(ctx, "memberName", _memberName); - const equipName = helpers.string(ctx, "equipName", _equipName); - getGang(ctx); - const member = getGangMember(ctx, memberName); - const equipment = GangMemberUpgrades[equipName]; - if (!equipment) return false; - const res = member.buyUpgrade(equipment); - if (res) { - ctx.workerScript.log( - "gang.purchaseEquipment", - () => `Purchased '${equipName}' for Gang member '${memberName}'`, - ); - } else { - ctx.workerScript.log( - "gang.purchaseEquipment", - () => `Failed to purchase '${equipName}' for Gang member '${memberName}'`, - ); - } + getEquipmentCost: (ctx) => (_equipName) => { + const equipName = helpers.string(ctx, "equipName", _equipName); + const gang = getGang(ctx); + const upg = GangMemberUpgrades[equipName]; + if (upg === null) return Infinity; + return gang.getUpgradeCost(upg); + }, + getEquipmentType: (ctx) => (_equipName) => { + const equipName = helpers.string(ctx, "equipName", _equipName); + getGang(ctx); + const upg = GangMemberUpgrades[equipName]; + if (upg == null) return ""; + return upg.getType(); + }, + getEquipmentStats: (ctx) => (_equipName) => { + const equipName = helpers.string(ctx, "equipName", _equipName); + getGang(ctx); + const equipment = GangMemberUpgrades[equipName]; + if (!equipment) { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid equipment: ${equipName}`); + } + const typecheck: EquipmentStats = equipment.mults; + return Object.assign({}, typecheck); + }, + purchaseEquipment: (ctx) => (_memberName, _equipName) => { + const memberName = helpers.string(ctx, "memberName", _memberName); + const equipName = helpers.string(ctx, "equipName", _equipName); + getGang(ctx); + const member = getGangMember(ctx, memberName); + const equipment = GangMemberUpgrades[equipName]; + if (!equipment) return false; + const res = member.buyUpgrade(equipment); + if (res) { + ctx.workerScript.log( + "gang.purchaseEquipment", + () => `Purchased '${equipName}' for Gang member '${memberName}'`, + ); + } else { + ctx.workerScript.log( + "gang.purchaseEquipment", + () => `Failed to purchase '${equipName}' for Gang member '${memberName}'`, + ); + } - return res; - }, - ascendMember: - (ctx: NetscriptContext) => - (_memberName: unknown): GangMemberAscension | undefined => { - const memberName = helpers.string(ctx, "memberName", _memberName); - const gang = getGang(ctx); - const member = getGangMember(ctx, memberName); - if (!member.canAscend()) return; - return gang.ascendMember(member, ctx.workerScript); - }, - getAscensionResult: - (ctx: NetscriptContext) => - (_memberName: unknown): GangMemberAscension | undefined => { - const memberName = helpers.string(ctx, "memberName", _memberName); - getGang(ctx); - const member = getGangMember(ctx, memberName); - if (!member.canAscend()) return; - return { - respect: member.earnedRespect, - ...member.getAscensionResults(), - }; - }, - setTerritoryWarfare: - (ctx: NetscriptContext) => - (_engage: unknown): void => { - const engage = !!_engage; - const gang = getGang(ctx); - if (engage) { - gang.territoryWarfareEngaged = true; - ctx.workerScript.log("gang.setTerritoryWarfare", () => "Engaging in Gang Territory Warfare"); - } else { - gang.territoryWarfareEngaged = false; - ctx.workerScript.log("gang.setTerritoryWarfare", () => "Disengaging in Gang Territory Warfare"); - } - }, - getChanceToWinClash: - (ctx: NetscriptContext) => - (_otherGang: unknown): number => { - const otherGang = helpers.string(ctx, "otherGang", _otherGang); - const gang = getGang(ctx); - if (AllGangs[otherGang] == null) { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid gang: ${otherGang}`); - } + return res; + }, + ascendMember: (ctx) => (_memberName) => { + const memberName = helpers.string(ctx, "memberName", _memberName); + const gang = getGang(ctx); + const member = getGangMember(ctx, memberName); + if (!member.canAscend()) return; + return gang.ascendMember(member, ctx.workerScript); + }, + getAscensionResult: (ctx) => (_memberName) => { + const memberName = helpers.string(ctx, "memberName", _memberName); + getGang(ctx); + const member = getGangMember(ctx, memberName); + if (!member.canAscend()) return; + return { + respect: member.earnedRespect, + ...member.getAscensionResults(), + }; + }, + setTerritoryWarfare: (ctx) => (_engage) => { + const engage = !!_engage; + const gang = getGang(ctx); + if (engage) { + gang.territoryWarfareEngaged = true; + ctx.workerScript.log("gang.setTerritoryWarfare", () => "Engaging in Gang Territory Warfare"); + } else { + gang.territoryWarfareEngaged = false; + ctx.workerScript.log("gang.setTerritoryWarfare", () => "Disengaging in Gang Territory Warfare"); + } + }, + getChanceToWinClash: (ctx) => (_otherGang) => { + const otherGang = helpers.string(ctx, "otherGang", _otherGang); + const gang = getGang(ctx); + if (AllGangs[otherGang] == null) { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid gang: ${otherGang}`); + } - const playerPower = AllGangs[gang.facName].power; - const otherPower = AllGangs[otherGang].power; + const playerPower = AllGangs[gang.facName].power; + const otherPower = AllGangs[otherGang].power; - return playerPower / (otherPower + playerPower); - }, - getBonusTime: (ctx: NetscriptContext) => (): number => { + return playerPower / (otherPower + playerPower); + }, + getBonusTime: (ctx) => () => { const gang = getGang(ctx); return Math.round(gang.storedCycles / 5) * 1000; }, diff --git a/src/NetscriptFunctions/Grafting.ts b/src/NetscriptFunctions/Grafting.ts index 233a9bae8..75efbe062 100644 --- a/src/NetscriptFunctions/Grafting.ts +++ b/src/NetscriptFunctions/Grafting.ts @@ -21,39 +21,35 @@ export function NetscriptGrafting(): InternalAPI { }; return { - getAugmentationGraftPrice: - (ctx: NetscriptContext) => - (_augName: unknown): number => { - const augName = helpers.string(ctx, "augName", _augName); - checkGraftingAPIAccess(ctx); - if (!getGraftingAvailableAugs().includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid aug: ${augName}`); - } - const graftableAug = new GraftableAugmentation(StaticAugmentations[augName]); - return graftableAug.cost; - }, + getAugmentationGraftPrice: (ctx) => (_augName) => { + const augName = helpers.string(ctx, "augName", _augName); + checkGraftingAPIAccess(ctx); + if (!getGraftingAvailableAugs().includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid aug: ${augName}`); + } + const graftableAug = new GraftableAugmentation(StaticAugmentations[augName]); + return graftableAug.cost; + }, - getAugmentationGraftTime: - (ctx: NetscriptContext) => - (_augName: string): number => { - const augName = helpers.string(ctx, "augName", _augName); - checkGraftingAPIAccess(ctx); - if (!getGraftingAvailableAugs().includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid aug: ${augName}`); - } - const graftableAug = new GraftableAugmentation(StaticAugmentations[augName]); - return calculateGraftingTimeWithBonus(graftableAug); - }, + getAugmentationGraftTime: (ctx) => (_augName) => { + const augName = helpers.string(ctx, "augName", _augName); + checkGraftingAPIAccess(ctx); + if (!getGraftingAvailableAugs().includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid aug: ${augName}`); + } + const graftableAug = new GraftableAugmentation(StaticAugmentations[augName]); + return calculateGraftingTimeWithBonus(graftableAug); + }, - getGraftableAugmentations: (ctx: NetscriptContext) => (): string[] => { + getGraftableAugmentations: (ctx) => () => { checkGraftingAPIAccess(ctx); const graftableAugs = getGraftingAvailableAugs(); return graftableAugs; }, graftAugmentation: - (ctx: NetscriptContext) => - (_augName: string, _focus: unknown = true): boolean => { + (ctx) => + (_augName, _focus = true) => { const augName = helpers.string(ctx, "augName", _augName); const focus = !!_focus; checkGraftingAPIAccess(ctx); diff --git a/src/NetscriptFunctions/Hacknet.ts b/src/NetscriptFunctions/Hacknet.ts index fffa887c2..7f7d5d12f 100644 --- a/src/NetscriptFunctions/Hacknet.ts +++ b/src/NetscriptFunctions/Hacknet.ts @@ -50,76 +50,74 @@ export function NetscriptHacknet(): InternalAPI { }; return { - numNodes: () => (): number => { + numNodes: () => () => { return player.hacknetNodes.length; }, - maxNumNodes: () => (): number => { + maxNumNodes: () => () => { if (hasHacknetServers()) { return HacknetServerConstants.MaxServers; } return Infinity; }, - purchaseNode: () => (): number => { + purchaseNode: () => () => { return purchaseHacknet(); }, - getPurchaseNodeCost: () => (): number => { + getPurchaseNodeCost: () => () => { if (hasHacknetServers()) { return getCostOfNextHacknetServer(); } else { return getCostOfNextHacknetNode(); } }, - getNodeStats: - (ctx: NetscriptContext) => - (_i: unknown): NodeStats => { - const i = helpers.number(ctx, "i", _i); - const node = getHacknetNode(ctx, i); - const hasUpgraded = hasHacknetServers(); - const res: NodeStats = { - name: node instanceof HacknetServer ? node.hostname : node.name, - level: node.level, - ram: node instanceof HacknetServer ? node.maxRam : node.ram, - cores: node.cores, - production: node instanceof HacknetServer ? node.hashRate : node.moneyGainRatePerSecond, - timeOnline: node.onlineTimeSeconds, - totalProduction: node instanceof HacknetServer ? node.totalHashesGenerated : node.totalMoneyGenerated, - }; + getNodeStats: (ctx) => (_i) => { + const i = helpers.number(ctx, "i", _i); + const node = getHacknetNode(ctx, i); + const hasUpgraded = hasHacknetServers(); + const res: NodeStats = { + name: node instanceof HacknetServer ? node.hostname : node.name, + level: node.level, + ram: node instanceof HacknetServer ? node.maxRam : node.ram, + cores: node.cores, + production: node instanceof HacknetServer ? node.hashRate : node.moneyGainRatePerSecond, + timeOnline: node.onlineTimeSeconds, + totalProduction: node instanceof HacknetServer ? node.totalHashesGenerated : node.totalMoneyGenerated, + }; - if (hasUpgraded && node instanceof HacknetServer) { - res.cache = node.cache; - res.hashCapacity = node.hashCapacity; - res.ramUsed = node.ramUsed; - } + if (hasUpgraded && node instanceof HacknetServer) { + res.cache = node.cache; + res.hashCapacity = node.hashCapacity; + res.ramUsed = node.ramUsed; + } - return res; - }, + return res; + }, upgradeLevel: - (ctx: NetscriptContext) => - (_i: unknown, _n: unknown = 1): boolean => { + (ctx) => + (_i, _n = 1) => { const i = helpers.number(ctx, "i", _i); const n = helpers.number(ctx, "n", _n); const node = getHacknetNode(ctx, i); return purchaseLevelUpgrade(node, n); }, upgradeRam: - (ctx: NetscriptContext) => - (_i: unknown, _n: unknown = 1): boolean => { + (ctx) => + (_i, _n = 1) => { const i = helpers.number(ctx, "i", _i); const n = helpers.number(ctx, "n", _n); const node = getHacknetNode(ctx, i); return purchaseRamUpgrade(node, n); }, upgradeCore: - (ctx: NetscriptContext) => - (_i: unknown, _n: unknown = 1): boolean => { + (ctx) => + (_i, _n = 1) => { const i = helpers.number(ctx, "i", _i); const n = helpers.number(ctx, "n", _n); const node = getHacknetNode(ctx, i); return purchaseCoreUpgrade(node, n); }, upgradeCache: - (ctx: NetscriptContext) => - (_i: unknown, _n: unknown = 1): boolean => { + (ctx) => + (_i, _n = 1) => { const i = helpers.number(ctx, "i", _i); const n = helpers.number(ctx, "n", _n); if (!hasHacknetServers()) { @@ -137,32 +135,32 @@ export function NetscriptHacknet(): InternalAPI { return res; }, getLevelUpgradeCost: - (ctx: NetscriptContext) => - (_i: unknown, _n: unknown = 1): number => { + (ctx) => + (_i, _n = 1) => { 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 => { + (ctx) => + (_i, _n = 1) => { 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 => { + (ctx) => + (_i, _n = 1) => { 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 => { + (ctx) => + (_i, _n = 1) => { const i = helpers.number(ctx, "i", _i); const n = helpers.number(ctx, "n", _n); if (!hasHacknetServers()) { @@ -175,21 +173,21 @@ export function NetscriptHacknet(): InternalAPI { } return node.calculateCacheUpgradeCost(n); }, - numHashes: () => (): number => { + numHashes: () => () => { if (!hasHacknetServers()) { return 0; } return player.hashManager.hashes; }, - hashCapacity: () => (): number => { + hashCapacity: () => () => { if (!hasHacknetServers()) { return 0; } return player.hashManager.capacity; }, hashCost: - (ctx: NetscriptContext) => - (_upgName: unknown, _count: unknown = 1): number => { + (ctx) => + (_upgName, _count = 1) => { const upgName = helpers.string(ctx, "upgName", _upgName); const count = helpers.number(ctx, "count", _count); if (!hasHacknetServers()) { @@ -199,8 +197,8 @@ export function NetscriptHacknet(): InternalAPI { return player.hashManager.getUpgradeCost(upgName, count); }, spendHashes: - (ctx: NetscriptContext) => - (_upgName: unknown, _upgTarget: unknown = "", _count: unknown = 1): boolean => { + (ctx) => + (_upgName, _upgTarget = "", _count = 1) => { const upgName = helpers.string(ctx, "upgName", _upgName); const upgTarget = helpers.string(ctx, "upgTarget", _upgTarget); const count = helpers.number(ctx, "count", _count); @@ -209,29 +207,27 @@ export function NetscriptHacknet(): InternalAPI { } return purchaseHashUpgrade(upgName, upgTarget, count); }, - getHashUpgrades: () => (): string[] => { + getHashUpgrades: () => () => { if (!hasHacknetServers()) { return []; } return Object.values(HashUpgrades).map((upgrade: HashUpgrade) => upgrade.name); }, - getHashUpgradeLevel: - (ctx: NetscriptContext) => - (_upgName: unknown): number => { - const upgName = helpers.string(ctx, "upgName", _upgName); - const level = player.hashManager.upgrades[upgName]; - if (level === undefined) { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid Hash Upgrade: ${upgName}`); - } - return level; - }, - getStudyMult: () => (): number => { + getHashUpgradeLevel: (ctx) => (_upgName) => { + const upgName = helpers.string(ctx, "upgName", _upgName); + const level = player.hashManager.upgrades[upgName]; + if (level === undefined) { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid Hash Upgrade: ${upgName}`); + } + return level; + }, + getStudyMult: () => () => { if (!hasHacknetServers()) { return 1; } return player.hashManager.getStudyMult(); }, - getTrainingMult: () => (): number => { + getTrainingMult: () => () => { if (!hasHacknetServers()) { return 1; } diff --git a/src/NetscriptFunctions/Infiltration.ts b/src/NetscriptFunctions/Infiltration.ts index 620e5a4bf..dcd3f0f73 100644 --- a/src/NetscriptFunctions/Infiltration.ts +++ b/src/NetscriptFunctions/Infiltration.ts @@ -1,8 +1,4 @@ -import { - Infiltration as IInfiltration, - InfiltrationLocation, - PossibleInfiltrationLocation, -} from "../ScriptEditor/NetscriptDefinitions"; +import { Infiltration as IInfiltration, InfiltrationLocation } from "../ScriptEditor/NetscriptDefinitions"; import { Location } from "../Locations/Location"; import { Locations } from "../Locations/Locations"; import { calculateDifficulty, calculateReward } from "../Infiltration/formulas/game"; @@ -44,17 +40,15 @@ export function NetscriptInfiltration(): InternalAPI { }; }; return { - getPossibleLocations: () => (): PossibleInfiltrationLocation[] => { + getPossibleLocations: () => () => { return getLocationsWithInfiltrations.map((l) => ({ city: l.city ?? "", name: String(l.name), })); }, - getInfiltration: - (ctx: NetscriptContext) => - (_location: unknown): InfiltrationLocation => { - const location = helpers.string(ctx, "location", _location); - return calculateInfiltrationData(ctx, location); - }, + getInfiltration: (ctx) => (_location) => { + const location = helpers.string(ctx, "location", _location); + return calculateInfiltrationData(ctx, location); + }, }; } diff --git a/src/NetscriptFunctions/Singularity.ts b/src/NetscriptFunctions/Singularity.ts index ddbda7ad3..bec8caee8 100644 --- a/src/NetscriptFunctions/Singularity.ts +++ b/src/NetscriptFunctions/Singularity.ts @@ -11,12 +11,7 @@ import { isString } from "../utils/helpers/isString"; import { RunningScript } from "../Script/RunningScript"; import { calculateAchievements } from "../Achievements/Achievements"; -import { - Multipliers, - CrimeStats, - Singularity as ISingularity, - SourceFileLvl, -} from "../ScriptEditor/NetscriptDefinitions"; +import { Singularity as ISingularity } from "../ScriptEditor/NetscriptDefinitions"; import { findCrime } from "../Crime/CrimeHelpers"; import { CompanyPositions } from "../Company/CompanyPositions"; @@ -79,7 +74,7 @@ export function NetscriptSingularity(): InternalAPI { return company; }; - const runAfterReset = function (cbScript: string | null = null): void { + const runAfterReset = function (cbScript: string | null = null) { //Run a script after reset if (!cbScript) return; const home = Player.getHomeComputer(); @@ -98,190 +93,174 @@ export function NetscriptSingularity(): InternalAPI { }; return { - getOwnedAugmentations: (ctx: NetscriptContext) => - function (_purchased: unknown = false): string[] { - helpers.checkSingularityAccess(ctx); - const purchased = !!_purchased; - const res = []; - for (let i = 0; i < Player.augmentations.length; ++i) { - res.push(Player.augmentations[i].name); + getOwnedAugmentations: (ctx) => (_purchased) => { + helpers.checkSingularityAccess(ctx); + const purchased = !!_purchased; + const res: string[] = []; + for (let i = 0; i < Player.augmentations.length; ++i) { + res.push(Player.augmentations[i].name); + } + if (purchased) { + for (let i = 0; i < Player.queuedAugmentations.length; ++i) { + res.push(Player.queuedAugmentations[i].name); } - if (purchased) { - for (let i = 0; i < Player.queuedAugmentations.length; ++i) { - res.push(Player.queuedAugmentations[i].name); - } - } - return res; - }, - getOwnedSourceFiles: () => (): SourceFileLvl[] => { - const res: SourceFileLvl[] = []; - for (let i = 0; i < Player.sourceFiles.length; ++i) { - res.push({ - n: Player.sourceFiles[i].n, - lvl: Player.sourceFiles[i].lvl, - }); } return res; }, - getAugmentationsFromFaction: (ctx: NetscriptContext) => - function (_facName: unknown): string[] { - helpers.checkSingularityAccess(ctx); - const facName = helpers.string(ctx, "facName", _facName); - const faction = getFaction(ctx, facName); + getOwnedSourceFiles: () => () => { + return Player.sourceFiles.map((sf) => { + return { n: sf.n, lvl: sf.lvl }; + }); + }, + getAugmentationsFromFaction: (ctx) => (_facName) => { + helpers.checkSingularityAccess(ctx); + const facName = helpers.string(ctx, "facName", _facName); + const faction = getFaction(ctx, facName); - return getFactionAugmentationsFiltered(faction); - }, - getAugmentationCost: (ctx: NetscriptContext) => - function (_augName: unknown): [number, number] { - helpers.checkSingularityAccess(ctx); - const augName = helpers.string(ctx, "augName", _augName); - const aug = getAugmentation(ctx, augName); - const costs = aug.getCost(); - return [costs.repCost, costs.moneyCost]; - }, - getAugmentationPrereq: (ctx: NetscriptContext) => - function (_augName: unknown): string[] { - helpers.checkSingularityAccess(ctx); - const augName = helpers.string(ctx, "augName", _augName); - const aug = getAugmentation(ctx, augName); - return aug.prereqs.slice(); - }, - getAugmentationBasePrice: (ctx: NetscriptContext) => - function (_augName: unknown): number { - helpers.checkSingularityAccess(ctx); - const augName = helpers.string(ctx, "augName", _augName); - const aug = getAugmentation(ctx, augName); - return aug.baseCost * BitNodeMultipliers.AugmentationMoneyCost; - }, - getAugmentationPrice: (ctx: NetscriptContext) => - function (_augName: unknown): number { - helpers.checkSingularityAccess(ctx); - const augName = helpers.string(ctx, "augName", _augName); - const aug = getAugmentation(ctx, augName); - return aug.getCost().moneyCost; - }, - getAugmentationRepReq: (ctx: NetscriptContext) => - function (_augName: unknown): number { - helpers.checkSingularityAccess(ctx); - const augName = helpers.string(ctx, "augName", _augName); - const aug = getAugmentation(ctx, augName); - return aug.getCost().repCost; - }, - getAugmentationStats: (ctx: NetscriptContext) => - function (_augName: unknown): Multipliers { - helpers.checkSingularityAccess(ctx); - const augName = helpers.string(ctx, "augName", _augName); - const aug = getAugmentation(ctx, augName); - return Object.assign({}, aug.mults); - }, - purchaseAugmentation: (ctx: NetscriptContext) => - function (_facName: unknown, _augName: unknown): boolean { - helpers.checkSingularityAccess(ctx); - const facName = helpers.string(ctx, "facName", _facName); - const augName = helpers.string(ctx, "augName", _augName); - const fac = getFaction(ctx, facName); - const aug = getAugmentation(ctx, augName); + return getFactionAugmentationsFiltered(faction); + }, + getAugmentationCost: (ctx) => (_augName) => { + helpers.checkSingularityAccess(ctx); + const augName = helpers.string(ctx, "augName", _augName); + const aug = getAugmentation(ctx, augName); + const costs = aug.getCost(); + return [costs.repCost, costs.moneyCost]; + }, + getAugmentationPrereq: (ctx) => (_augName) => { + helpers.checkSingularityAccess(ctx); + const augName = helpers.string(ctx, "augName", _augName); + const aug = getAugmentation(ctx, augName); + return aug.prereqs.slice(); + }, + getAugmentationBasePrice: (ctx) => (_augName) => { + helpers.checkSingularityAccess(ctx); + const augName = helpers.string(ctx, "augName", _augName); + const aug = getAugmentation(ctx, augName); + return aug.baseCost * BitNodeMultipliers.AugmentationMoneyCost; + }, + getAugmentationPrice: (ctx) => (_augName) => { + helpers.checkSingularityAccess(ctx); + const augName = helpers.string(ctx, "augName", _augName); + const aug = getAugmentation(ctx, augName); + return aug.getCost().moneyCost; + }, + getAugmentationRepReq: (ctx) => (_augName) => { + helpers.checkSingularityAccess(ctx); + const augName = helpers.string(ctx, "augName", _augName); + const aug = getAugmentation(ctx, augName); + return aug.getCost().repCost; + }, + getAugmentationStats: (ctx) => (_augName) => { + helpers.checkSingularityAccess(ctx); + const augName = helpers.string(ctx, "augName", _augName); + const aug = getAugmentation(ctx, augName); + return Object.assign({}, aug.mults); + }, + purchaseAugmentation: (ctx) => (_facName, _augName) => { + helpers.checkSingularityAccess(ctx); + const facName = helpers.string(ctx, "facName", _facName); + const augName = helpers.string(ctx, "augName", _augName); + const fac = getFaction(ctx, facName); + const aug = getAugmentation(ctx, augName); - const augs = getFactionAugmentationsFiltered(fac); + const augs = getFactionAugmentationsFiltered(fac); - if (!Player.factions.includes(fac.name)) { - helpers.log(ctx, () => `You can't purchase augmentations from '${facName}' because you aren't a member`); - return false; - } + if (!Player.factions.includes(fac.name)) { + helpers.log(ctx, () => `You can't purchase augmentations from '${facName}' because you aren't a member`); + return false; + } - if (!augs.includes(augName)) { - helpers.log(ctx, () => `Faction '${facName}' does not have the '${augName}' augmentation.`); - return false; - } + if (!augs.includes(augName)) { + helpers.log(ctx, () => `Faction '${facName}' does not have the '${augName}' augmentation.`); + return false; + } - const isNeuroflux = aug.name === AugmentationNames.NeuroFluxGovernor; - if (!isNeuroflux) { - for (let j = 0; j < Player.queuedAugmentations.length; ++j) { - if (Player.queuedAugmentations[j].name === aug.name) { - helpers.log(ctx, () => `You already have the '${augName}' augmentation.`); - return false; - } - } - for (let j = 0; j < Player.augmentations.length; ++j) { - if (Player.augmentations[j].name === aug.name) { - helpers.log(ctx, () => `You already have the '${augName}' augmentation.`); - return false; - } + const isNeuroflux = aug.name === AugmentationNames.NeuroFluxGovernor; + if (!isNeuroflux) { + for (let j = 0; j < Player.queuedAugmentations.length; ++j) { + if (Player.queuedAugmentations[j].name === aug.name) { + helpers.log(ctx, () => `You already have the '${augName}' augmentation.`); + return false; } } - - if (fac.playerReputation < aug.getCost().repCost) { - helpers.log(ctx, () => `You do not have enough reputation with '${fac.name}'.`); - return false; + for (let j = 0; j < Player.augmentations.length; ++j) { + if (Player.augmentations[j].name === aug.name) { + helpers.log(ctx, () => `You already have the '${augName}' augmentation.`); + return false; + } } + } - const res = purchaseAugmentation(aug, fac, true); - helpers.log(ctx, () => res); - if (isString(res) && res.startsWith("You purchased")) { - Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 10); - return true; - } else { - return false; - } - }, - softReset: (ctx: NetscriptContext) => - function (_cbScript: unknown = ""): void { - helpers.checkSingularityAccess(ctx); - const cbScript = helpers.string(ctx, "cbScript", _cbScript); + if (fac.playerReputation < aug.getCost().repCost) { + helpers.log(ctx, () => `You do not have enough reputation with '${fac.name}'.`); + return false; + } - helpers.log(ctx, () => "Soft resetting. This will cause this script to be killed"); - setTimeout(() => { - installAugmentations(true); - runAfterReset(cbScript); - }, 0); - - killWorkerScript(ctx.workerScript); - }, - installAugmentations: (ctx: NetscriptContext) => - function (_cbScript: unknown = ""): boolean { - helpers.checkSingularityAccess(ctx); - const cbScript = helpers.string(ctx, "cbScript", _cbScript); - - if (Player.queuedAugmentations.length === 0) { - helpers.log(ctx, () => "You do not have any Augmentations to be installed."); - return false; - } + const res = purchaseAugmentation(aug, fac, true); + helpers.log(ctx, () => res); + if (isString(res) && res.startsWith("You purchased")) { Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 10); - helpers.log(ctx, () => "Installing Augmentations. This will cause this script to be killed"); - setTimeout(() => { - installAugmentations(); - runAfterReset(cbScript); - }, 0); - - killWorkerScript(ctx.workerScript); return true; - }, + } else { + return false; + } + }, + softReset: (ctx) => (_cbScript) => { + helpers.checkSingularityAccess(ctx); + const cbScript = _cbScript ? helpers.string(ctx, "cbScript", _cbScript) : ""; - goToLocation: (ctx: NetscriptContext) => - function (_locationName: unknown): boolean { - helpers.checkSingularityAccess(ctx); - const locationName = helpers.string(ctx, "locationName", _locationName); - const location = Object.values(Locations).find((l) => l.name === locationName); - if (!location) { - helpers.log(ctx, () => `No location named ${locationName}`); - return false; - } - if (location.city && Player.city !== location.city) { - helpers.log(ctx, () => `No location named ${locationName} in ${Player.city}`); - return false; - } - if (location.name === LocationName.TravelAgency) { - Router.toTravel(); - } else if (location.name === LocationName.WorldStockExchange) { - Router.toStockMarket(); - } else { - Router.toLocation(location); - } - Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 50000); - return true; - }, - universityCourse: (ctx: NetscriptContext) => - function (_universityName: unknown, _className: unknown, _focus: unknown = true): boolean { + helpers.log(ctx, () => "Soft resetting. This will cause this script to be killed"); + setTimeout(() => { + installAugmentations(true); + runAfterReset(cbScript); + }, 0); + + killWorkerScript(ctx.workerScript); + }, + installAugmentations: (ctx) => (_cbScript) => { + helpers.checkSingularityAccess(ctx); + const cbScript = _cbScript ? helpers.string(ctx, "cbScript", _cbScript) : ""; + + if (Player.queuedAugmentations.length === 0) { + helpers.log(ctx, () => "You do not have any Augmentations to be installed."); + return false; + } + Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 10); + helpers.log(ctx, () => "Installing Augmentations. This will cause this script to be killed"); + setTimeout(() => { + installAugmentations(); + runAfterReset(cbScript); + }, 0); + + killWorkerScript(ctx.workerScript); + return true; + }, + + goToLocation: (ctx) => (_locationName) => { + helpers.checkSingularityAccess(ctx); + const locationName = helpers.string(ctx, "locationName", _locationName); + const location = Object.values(Locations).find((l) => l.name === locationName); + if (!location) { + helpers.log(ctx, () => `No location named ${locationName}`); + return false; + } + if (location.city && Player.city !== location.city) { + helpers.log(ctx, () => `No location named ${locationName} in ${Player.city}`); + return false; + } + if (location.name === LocationName.TravelAgency) { + Router.toTravel(); + } else if (location.name === LocationName.WorldStockExchange) { + Router.toStockMarket(); + } else { + Router.toLocation(location); + } + Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 50000); + return true; + }, + universityCourse: + (ctx) => + (_universityName, _className, _focus = true) => { helpers.checkSingularityAccess(ctx); const universityName = helpers.string(ctx, "universityName", _universityName); const className = helpers.string(ctx, "className", _className); @@ -366,8 +345,9 @@ export function NetscriptSingularity(): InternalAPI { return true; }, - gymWorkout: (ctx: NetscriptContext) => - function (_gymName: unknown, _stat: unknown, _focus: unknown = true): boolean { + gymWorkout: + (ctx) => + (_gymName, _stat, _focus = true) => { helpers.checkSingularityAccess(ctx); const gymName = helpers.string(ctx, "gymName", _gymName); const stat = helpers.string(ctx, "stat", _stat); @@ -475,160 +455,154 @@ export function NetscriptSingularity(): InternalAPI { return true; }, - travelToCity: (ctx: NetscriptContext) => - function (_cityName: unknown): boolean { - helpers.checkSingularityAccess(ctx); - const cityName = helpers.city(ctx, "cityName", _cityName); + travelToCity: (ctx) => (_cityName) => { + helpers.checkSingularityAccess(ctx); + const cityName = helpers.city(ctx, "cityName", _cityName); - switch (cityName) { - case CityName.Aevum: - case CityName.Chongqing: - case CityName.Sector12: - case CityName.NewTokyo: - case CityName.Ishima: - case CityName.Volhaven: - if (Player.money < CONSTANTS.TravelCost) { - helpers.log(ctx, () => "Not enough money to travel."); - return false; - } - Player.loseMoney(CONSTANTS.TravelCost, "other"); - Player.city = cityName; - helpers.log(ctx, () => `Traveled to ${cityName}`); - Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 50000); - return true; - default: - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid city name: '${cityName}'.`); - } - }, - - purchaseTor: (ctx: NetscriptContext) => - function (): boolean { - helpers.checkSingularityAccess(ctx); - - if (Player.hasTorRouter()) { - helpers.log(ctx, () => "You already have a TOR router!"); + switch (cityName) { + case CityName.Aevum: + case CityName.Chongqing: + case CityName.Sector12: + case CityName.NewTokyo: + case CityName.Ishima: + case CityName.Volhaven: + if (Player.money < CONSTANTS.TravelCost) { + helpers.log(ctx, () => "Not enough money to travel."); + return false; + } + Player.loseMoney(CONSTANTS.TravelCost, "other"); + Player.city = cityName; + helpers.log(ctx, () => `Traveled to ${cityName}`); + Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 50000); return true; - } + default: + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid city name: '${cityName}'.`); + } + }, - if (Player.money < CONSTANTS.TorRouterCost) { - helpers.log(ctx, () => "You cannot afford to purchase a Tor router."); - return false; - } - Player.loseMoney(CONSTANTS.TorRouterCost, "other"); + purchaseTor: (ctx) => () => { + helpers.checkSingularityAccess(ctx); - const darkweb = GetServer(SpecialServers.DarkWeb); - if (!darkweb) throw helpers.makeRuntimeErrorMsg(ctx, "DarkWeb was not a server but should have been"); - - Player.getHomeComputer().serversOnNetwork.push(darkweb.hostname); - darkweb.serversOnNetwork.push(Player.getHomeComputer().hostname); - Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 500); - helpers.log(ctx, () => "You have purchased a Tor router!"); + if (Player.hasTorRouter()) { + helpers.log(ctx, () => "You already have a TOR router!"); return true; - }, - purchaseProgram: (ctx: NetscriptContext) => - function (_programName: unknown): boolean { - helpers.checkSingularityAccess(ctx); - const programName = helpers.string(ctx, "programName", _programName).toLowerCase(); + } - if (!Player.hasTorRouter()) { - helpers.log(ctx, () => "You do not have the TOR router."); - return false; - } + if (Player.money < CONSTANTS.TorRouterCost) { + helpers.log(ctx, () => "You cannot afford to purchase a Tor router."); + return false; + } + Player.loseMoney(CONSTANTS.TorRouterCost, "other"); - const item = Object.values(DarkWebItems).find((i) => i.program.toLowerCase() === programName); - if (item == null) { - helpers.log(ctx, () => `Invalid program name: '${programName}.`); - return false; - } + const darkweb = GetServer(SpecialServers.DarkWeb); + if (!darkweb) throw helpers.makeRuntimeErrorMsg(ctx, "DarkWeb was not a server but should have been"); - if (Player.money < item.price) { - helpers.log( - ctx, - () => `Not enough money to purchase '${item.program}'. Need ${numeralWrapper.formatMoney(item.price)}`, - ); - return false; - } + Player.getHomeComputer().serversOnNetwork.push(darkweb.hostname); + darkweb.serversOnNetwork.push(Player.getHomeComputer().hostname); + Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 500); + helpers.log(ctx, () => "You have purchased a Tor router!"); + return true; + }, + purchaseProgram: (ctx) => (_programName) => { + helpers.checkSingularityAccess(ctx); + const programName = helpers.string(ctx, "programName", _programName).toLowerCase(); - if (Player.hasProgram(item.program)) { - helpers.log(ctx, () => `You already have the '${item.program}' program`); - return true; - } + if (!Player.hasTorRouter()) { + helpers.log(ctx, () => "You do not have the TOR router."); + return false; + } - Player.getHomeComputer().pushProgram(item.program); - // Cancel if the program is in progress of writing - if (isCreateProgramWork(Player.currentWork) && Player.currentWork.programName === item.program) { - Player.finishWork(true); - } + const item = Object.values(DarkWebItems).find((i) => i.program.toLowerCase() === programName); + if (item == null) { + helpers.log(ctx, () => `Invalid program name: '${programName}.`); + return false; + } - Player.loseMoney(item.price, "other"); + if (Player.money < item.price) { helpers.log( ctx, - () => `You have purchased the '${item.program}' program. The new program can be found on your home computer.`, + () => `Not enough money to purchase '${item.program}'. Need ${numeralWrapper.formatMoney(item.price)}`, ); - Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 5000); + return false; + } + + if (Player.hasProgram(item.program)) { + helpers.log(ctx, () => `You already have the '${item.program}' program`); return true; - }, - getCurrentServer: (ctx: NetscriptContext) => - function (): string { - helpers.checkSingularityAccess(ctx); - return Player.getCurrentServer().hostname; - }, - connect: (ctx: NetscriptContext) => - function (_hostname: unknown): boolean { - helpers.checkSingularityAccess(ctx); - const hostname = helpers.string(ctx, "hostname", _hostname); - if (!hostname) { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid hostname: '${hostname}'`); - } + } - const target = GetServer(hostname); - if (target == null) { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid hostname: '${hostname}'`); - } + Player.getHomeComputer().pushProgram(item.program); + // Cancel if the program is in progress of writing + if (isCreateProgramWork(Player.currentWork) && Player.currentWork.programName === item.program) { + Player.finishWork(true); + } - //Home case - if (hostname === "home") { - Player.getCurrentServer().isConnectedTo = false; - Player.currentServer = Player.getHomeComputer().hostname; - Player.getCurrentServer().isConnectedTo = true; - Terminal.setcwd("/"); - return true; - } + Player.loseMoney(item.price, "other"); + helpers.log( + ctx, + () => `You have purchased the '${item.program}' program. The new program can be found on your home computer.`, + ); + Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 5000); + return true; + }, + getCurrentServer: (ctx) => () => { + helpers.checkSingularityAccess(ctx); + return Player.getCurrentServer().hostname; + }, + connect: (ctx) => (_hostname) => { + helpers.checkSingularityAccess(ctx); + const hostname = helpers.string(ctx, "hostname", _hostname); + if (!hostname) { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid hostname: '${hostname}'`); + } - //Adjacent server case - const server = Player.getCurrentServer(); - for (let i = 0; i < server.serversOnNetwork.length; i++) { - const other = getServerOnNetwork(server, i); - if (other === null) continue; - if (other.hostname == hostname) { - Player.getCurrentServer().isConnectedTo = false; - Player.currentServer = target.hostname; - Player.getCurrentServer().isConnectedTo = true; - Terminal.setcwd("/"); - return true; - } - } + const target = GetServer(hostname); + if (target == null) { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid hostname: '${hostname}'`); + } - //Backdoor case - const other = GetServer(hostname); - if (other !== null && other instanceof Server && other.backdoorInstalled) { + //Home case + if (hostname === "home") { + Player.getCurrentServer().isConnectedTo = false; + Player.currentServer = Player.getHomeComputer().hostname; + Player.getCurrentServer().isConnectedTo = true; + Terminal.setcwd("/"); + return true; + } + + //Adjacent server case + const server = Player.getCurrentServer(); + for (let i = 0; i < server.serversOnNetwork.length; i++) { + const other = getServerOnNetwork(server, i); + if (other === null) continue; + if (other.hostname == hostname) { Player.getCurrentServer().isConnectedTo = false; Player.currentServer = target.hostname; Player.getCurrentServer().isConnectedTo = true; Terminal.setcwd("/"); return true; } + } - //Failure case - return false; - }, - manualHack: (ctx: NetscriptContext) => - function (): Promise { - helpers.checkSingularityAccess(ctx); - const server = Player.getCurrentServer(); - return helpers.hack(ctx, server.hostname, true); - }, - installBackdoor: (ctx: NetscriptContext) => async (): Promise => { + //Backdoor case + const other = GetServer(hostname); + if (other !== null && other instanceof Server && other.backdoorInstalled) { + Player.getCurrentServer().isConnectedTo = false; + Player.currentServer = target.hostname; + Player.getCurrentServer().isConnectedTo = true; + Terminal.setcwd("/"); + return true; + } + + //Failure case + return false; + }, + manualHack: (ctx) => () => { + helpers.checkSingularityAccess(ctx); + const server = Player.getCurrentServer(); + return helpers.hack(ctx, server.hostname, true); + }, + installBackdoor: (ctx) => async (): Promise => { helpers.checkSingularityAccess(ctx); const baseserver = Player.getCurrentServer(); if (!(baseserver instanceof Server)) { @@ -660,122 +634,114 @@ export function NetscriptSingularity(): InternalAPI { return Promise.resolve(); }); }, - isFocused: (ctx: NetscriptContext) => - function (): boolean { - helpers.checkSingularityAccess(ctx); - return Player.focus; - }, - setFocus: (ctx: NetscriptContext) => - function (_focus: unknown): boolean { - helpers.checkSingularityAccess(ctx); - const focus = !!_focus; - if (Player.currentWork === null) { - throw helpers.makeRuntimeErrorMsg(ctx, "Not currently working"); - } + isFocused: (ctx) => () => { + helpers.checkSingularityAccess(ctx); + return Player.focus; + }, + setFocus: (ctx) => (_focus) => { + helpers.checkSingularityAccess(ctx); + const focus = !!_focus; + if (Player.currentWork === null) { + throw helpers.makeRuntimeErrorMsg(ctx, "Not currently working"); + } - if (!Player.focus && focus) { - Player.startFocusing(); - Router.toWork(); - return true; - } else if (Player.focus && !focus) { - Player.stopFocusing(); - Router.toTerminal(); - return true; - } + if (!Player.focus && focus) { + Player.startFocusing(); + Router.toWork(); + return true; + } else if (Player.focus && !focus) { + Player.stopFocusing(); + Router.toTerminal(); + return true; + } + return false; + }, + hospitalize: (ctx) => () => { + helpers.checkSingularityAccess(ctx); + if (Player.currentWork || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse) { + helpers.log(ctx, () => "Cannot go to the hospital because the player is busy."); + return; + } + Player.hospitalize(); + }, + isBusy: (ctx) => () => { + helpers.checkSingularityAccess(ctx); + return Player.currentWork !== null || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse; + }, + stopAction: (ctx) => () => { + helpers.checkSingularityAccess(ctx); + const wasWorking = Player.currentWork !== null; + Player.finishWork(true); + return wasWorking; + }, + upgradeHomeCores: (ctx) => () => { + helpers.checkSingularityAccess(ctx); + + // Check if we're at max cores + const homeComputer = Player.getHomeComputer(); + if (homeComputer.cpuCores >= 8) { + helpers.log(ctx, () => `Your home computer is at max cores.`); return false; - }, - hospitalize: (ctx: NetscriptContext) => - function (): void { - helpers.checkSingularityAccess(ctx); - if (Player.currentWork || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse) { - helpers.log(ctx, () => "Cannot go to the hospital because the player is busy."); - return; - } - Player.hospitalize(); - }, - isBusy: (ctx: NetscriptContext) => - function (): boolean { - helpers.checkSingularityAccess(ctx); - return Player.currentWork !== null || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse; - }, - stopAction: (ctx: NetscriptContext) => - function (): boolean { - helpers.checkSingularityAccess(ctx); - const wasWorking = Player.currentWork !== null; - Player.finishWork(true); - return wasWorking; - }, - upgradeHomeCores: (ctx: NetscriptContext) => - function (): boolean { - helpers.checkSingularityAccess(ctx); + } - // Check if we're at max cores - const homeComputer = Player.getHomeComputer(); - if (homeComputer.cpuCores >= 8) { - helpers.log(ctx, () => `Your home computer is at max cores.`); - return false; - } + const cost = Player.getUpgradeHomeCoresCost(); + if (Player.money < cost) { + helpers.log(ctx, () => `You don't have enough money. Need ${numeralWrapper.formatMoney(cost)}`); + return false; + } - const cost = Player.getUpgradeHomeCoresCost(); - if (Player.money < cost) { - helpers.log(ctx, () => `You don't have enough money. Need ${numeralWrapper.formatMoney(cost)}`); - return false; - } + homeComputer.cpuCores += 1; + Player.loseMoney(cost, "servers"); - homeComputer.cpuCores += 1; - Player.loseMoney(cost, "servers"); + Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 2); + helpers.log( + ctx, + () => `Purchased an additional core for home computer! It now has ${homeComputer.cpuCores} cores.`, + ); + return true; + }, + getUpgradeHomeCoresCost: (ctx) => () => { + helpers.checkSingularityAccess(ctx); - Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 2); - helpers.log( - ctx, - () => `Purchased an additional core for home computer! It now has ${homeComputer.cpuCores} cores.`, - ); - return true; - }, - getUpgradeHomeCoresCost: (ctx: NetscriptContext) => - function (): number { - helpers.checkSingularityAccess(ctx); + return Player.getUpgradeHomeCoresCost(); + }, + upgradeHomeRam: (ctx) => () => { + helpers.checkSingularityAccess(ctx); - return Player.getUpgradeHomeCoresCost(); - }, - upgradeHomeRam: (ctx: NetscriptContext) => - function (): boolean { - helpers.checkSingularityAccess(ctx); + // Check if we're at max RAM + const homeComputer = Player.getHomeComputer(); + if (homeComputer.maxRam >= CONSTANTS.HomeComputerMaxRam) { + helpers.log(ctx, () => `Your home computer is at max RAM.`); + return false; + } - // Check if we're at max RAM - const homeComputer = Player.getHomeComputer(); - if (homeComputer.maxRam >= CONSTANTS.HomeComputerMaxRam) { - helpers.log(ctx, () => `Your home computer is at max RAM.`); - return false; - } + const cost = Player.getUpgradeHomeRamCost(); + if (Player.money < cost) { + helpers.log(ctx, () => `You don't have enough money. Need ${numeralWrapper.formatMoney(cost)}`); + return false; + } - const cost = Player.getUpgradeHomeRamCost(); - if (Player.money < cost) { - helpers.log(ctx, () => `You don't have enough money. Need ${numeralWrapper.formatMoney(cost)}`); - return false; - } + homeComputer.maxRam *= 2; + Player.loseMoney(cost, "servers"); - homeComputer.maxRam *= 2; - Player.loseMoney(cost, "servers"); + Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 2); + helpers.log( + ctx, + () => + `Purchased additional RAM for home computer! It now has ${numeralWrapper.formatRAM( + homeComputer.maxRam, + )} of RAM.`, + ); + return true; + }, + getUpgradeHomeRamCost: (ctx) => () => { + helpers.checkSingularityAccess(ctx); - Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 2); - helpers.log( - ctx, - () => - `Purchased additional RAM for home computer! It now has ${numeralWrapper.formatRAM( - homeComputer.maxRam, - )} of RAM.`, - ); - return true; - }, - getUpgradeHomeRamCost: (ctx: NetscriptContext) => - function (): number { - helpers.checkSingularityAccess(ctx); - - return Player.getUpgradeHomeRamCost(); - }, - workForCompany: (ctx: NetscriptContext) => - function (_companyName: unknown, _focus: unknown = true): boolean { + return Player.getUpgradeHomeRamCost(); + }, + workForCompany: + (ctx) => + (_companyName, _focus = true) => { helpers.checkSingularityAccess(ctx); const companyName = helpers.string(ctx, "companyName", _companyName); const focus = !!_focus; @@ -818,134 +784,128 @@ export function NetscriptSingularity(): InternalAPI { helpers.log(ctx, () => `Began working at '${companyName}' with position '${companyPositionName}'`); return true; }, - applyToCompany: (ctx: NetscriptContext) => - function (_companyName: unknown, _field: unknown): boolean { - helpers.checkSingularityAccess(ctx); - const companyName = helpers.string(ctx, "companyName", _companyName); - const field = helpers.string(ctx, "field", _field); - getCompany(ctx, companyName); + applyToCompany: (ctx) => (_companyName, _field) => { + helpers.checkSingularityAccess(ctx); + const companyName = helpers.string(ctx, "companyName", _companyName); + const field = helpers.string(ctx, "field", _field); + getCompany(ctx, companyName); - Player.location = companyName as LocationName; - let res; - switch (field.toLowerCase()) { - case "software": - res = Player.applyForSoftwareJob(true); - break; - case "software consultant": - res = Player.applyForSoftwareConsultantJob(true); - break; - case "it": - res = Player.applyForItJob(true); - break; - case "security engineer": - res = Player.applyForSecurityEngineerJob(true); - break; - case "network engineer": - res = Player.applyForNetworkEngineerJob(true); - break; - case "business": - res = Player.applyForBusinessJob(true); - break; - case "business consultant": - res = Player.applyForBusinessConsultantJob(true); - break; - case "security": - res = Player.applyForSecurityJob(true); - break; - case "agent": - res = Player.applyForAgentJob(true); - break; - case "employee": - res = Player.applyForEmployeeJob(true); - break; - case "part-time employee": - res = Player.applyForPartTimeEmployeeJob(true); - break; - case "waiter": - res = Player.applyForWaiterJob(true); - break; - case "part-time waiter": - res = Player.applyForPartTimeWaiterJob(true); - break; - default: - helpers.log(ctx, () => `Invalid job: '${field}'.`); - return false; - } - // TODO https://github.com/danielyxie/bitburner/issues/1378 - // The player object's applyForJob function can return string with special error messages - // if (isString(res)) { - // helpers.log(ctx,"applyToCompany",()=> res); - // return false; - // } - if (res) { - helpers.log( - ctx, - () => `You were offered a new job at '${companyName}' with position '${Player.jobs[companyName]}'`, - ); - } else { - helpers.log(ctx, () => `You failed to get a new job/promotion at '${companyName}' in the '${field}' field.`); - } - return res; - }, - quitJob: (ctx: NetscriptContext) => - function (_companyName: unknown): void { - helpers.checkSingularityAccess(ctx); - const companyName = helpers.string(ctx, "companyName", _companyName); - Player.quitJob(companyName); - }, - getCompanyRep: (ctx: NetscriptContext) => - function (_companyName: unknown): number { - helpers.checkSingularityAccess(ctx); - const companyName = helpers.string(ctx, "companyName", _companyName); - const company = getCompany(ctx, companyName); - return company.playerReputation; - }, - getCompanyFavor: (ctx: NetscriptContext) => - function (_companyName: unknown): number { - helpers.checkSingularityAccess(ctx); - const companyName = helpers.string(ctx, "companyName", _companyName); - const company = getCompany(ctx, companyName); - return company.favor; - }, - getCompanyFavorGain: (ctx: NetscriptContext) => - function (_companyName: unknown): number { - helpers.checkSingularityAccess(ctx); - const companyName = helpers.string(ctx, "companyName", _companyName); - const company = getCompany(ctx, companyName); - return company.getFavorGain(); - }, - checkFactionInvitations: (ctx: NetscriptContext) => - function (): string[] { - helpers.checkSingularityAccess(ctx); - // Make a copy of player.factionInvitations - return Player.factionInvitations.slice(); - }, - joinFaction: (ctx: NetscriptContext) => - function (_facName: unknown): boolean { - helpers.checkSingularityAccess(ctx); - const facName = helpers.string(ctx, "facName", _facName); - getFaction(ctx, facName); - - if (!Player.factionInvitations.includes(facName)) { - helpers.log(ctx, () => `You have not been invited by faction '${facName}'`); + Player.location = companyName as LocationName; + let res; + switch (field.toLowerCase()) { + case "software": + res = Player.applyForSoftwareJob(true); + break; + case "software consultant": + res = Player.applyForSoftwareConsultantJob(true); + break; + case "it": + res = Player.applyForItJob(true); + break; + case "security engineer": + res = Player.applyForSecurityEngineerJob(true); + break; + case "network engineer": + res = Player.applyForNetworkEngineerJob(true); + break; + case "business": + res = Player.applyForBusinessJob(true); + break; + case "business consultant": + res = Player.applyForBusinessConsultantJob(true); + break; + case "security": + res = Player.applyForSecurityJob(true); + break; + case "agent": + res = Player.applyForAgentJob(true); + break; + case "employee": + res = Player.applyForEmployeeJob(true); + break; + case "part-time employee": + res = Player.applyForPartTimeEmployeeJob(true); + break; + case "waiter": + res = Player.applyForWaiterJob(true); + break; + case "part-time waiter": + res = Player.applyForPartTimeWaiterJob(true); + break; + default: + helpers.log(ctx, () => `Invalid job: '${field}'.`); return false; - } - const fac = Factions[facName]; - joinFaction(fac); + } + // TODO https://github.com/danielyxie/bitburner/issues/1378 + // The player object's applyForJob function can return string with special error messages + // if (isString(res)) { + // helpers.log(ctx,"applyToCompany",()=> res); + // return false; + // } + if (res) { + helpers.log( + ctx, + () => `You were offered a new job at '${companyName}' with position '${Player.jobs[companyName]}'`, + ); + } else { + helpers.log(ctx, () => `You failed to get a new job/promotion at '${companyName}' in the '${field}' field.`); + } + return res; + }, + quitJob: (ctx) => (_companyName) => { + helpers.checkSingularityAccess(ctx); + const companyName = helpers.string(ctx, "companyName", _companyName); + Player.quitJob(companyName); + }, + getCompanyRep: (ctx) => (_companyName) => { + helpers.checkSingularityAccess(ctx); + const companyName = helpers.string(ctx, "companyName", _companyName); + const company = getCompany(ctx, companyName); + return company.playerReputation; + }, + getCompanyFavor: (ctx) => (_companyName) => { + helpers.checkSingularityAccess(ctx); + const companyName = helpers.string(ctx, "companyName", _companyName); + const company = getCompany(ctx, companyName); + return company.favor; + }, + getCompanyFavorGain: (ctx) => (_companyName) => { + helpers.checkSingularityAccess(ctx); + const companyName = helpers.string(ctx, "companyName", _companyName); + const company = getCompany(ctx, companyName); + return company.getFavorGain(); + }, + checkFactionInvitations: (ctx) => () => { + helpers.checkSingularityAccess(ctx); + // Make a copy of player.factionInvitations + return Player.factionInvitations.slice(); + }, + joinFaction: (ctx) => (_facName) => { + helpers.checkSingularityAccess(ctx); + const facName = helpers.string(ctx, "facName", _facName); + getFaction(ctx, facName); - // Update Faction Invitation list to account for joined + banned factions - for (let i = 0; i < Player.factionInvitations.length; ++i) { - if (Player.factionInvitations[i] == facName || Factions[Player.factionInvitations[i]].isBanned) { - Player.factionInvitations.splice(i, 1); - i--; - } + if (!Player.factionInvitations.includes(facName)) { + helpers.log(ctx, () => `You have not been invited by faction '${facName}'`); + return false; + } + const fac = Factions[facName]; + joinFaction(fac); + + // Update Faction Invitation list to account for joined + banned factions + for (let i = 0; i < Player.factionInvitations.length; ++i) { + if (Player.factionInvitations[i] == facName || Factions[Player.factionInvitations[i]].isBanned) { + Player.factionInvitations.splice(i, 1); + i--; } - Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 5); - helpers.log(ctx, () => `Joined the '${facName}' faction.`); - return true; - }, - workForFaction: (ctx: NetscriptContext) => - function (_facName: unknown, _type: unknown, _focus: unknown = true): boolean { + } + Player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 5); + helpers.log(ctx, () => `Joined the '${facName}' faction.`); + return true; + }, + workForFaction: + (ctx) => + (_facName, _type, _focus = true) => { helpers.checkSingularityAccess(ctx); const facName = helpers.string(ctx, "facName", _facName); const type = helpers.string(ctx, "type", _type); @@ -1040,79 +1000,76 @@ export function NetscriptSingularity(): InternalAPI { return false; } }, - getFactionRep: (ctx: NetscriptContext) => - function (_facName: unknown): number { - helpers.checkSingularityAccess(ctx); - const facName = helpers.string(ctx, "facName", _facName); - const faction = getFaction(ctx, facName); - return faction.playerReputation; - }, - getFactionFavor: (ctx: NetscriptContext) => - function (_facName: unknown): number { - helpers.checkSingularityAccess(ctx); - const facName = helpers.string(ctx, "facName", _facName); - const faction = getFaction(ctx, facName); - return faction.favor; - }, - getFactionFavorGain: (ctx: NetscriptContext) => - function (_facName: unknown): number { - helpers.checkSingularityAccess(ctx); - const facName = helpers.string(ctx, "facName", _facName); - const faction = getFaction(ctx, facName); - return faction.getFavorGain(); - }, - donateToFaction: (ctx: NetscriptContext) => - function (_facName: unknown, _amt: unknown): boolean { - helpers.checkSingularityAccess(ctx); - const facName = helpers.string(ctx, "facName", _facName); - const amt = helpers.number(ctx, "amt", _amt); - const faction = getFaction(ctx, facName); - if (!Player.factions.includes(faction.name)) { - helpers.log(ctx, () => `You can't donate to '${facName}' because you aren't a member`); - return false; - } - if (Player.gang && faction.name === Player.getGangFaction().name) { - helpers.log(ctx, () => `You can't donate to '${facName}' because youre managing a gang for it`); - return false; - } - if (faction.name === FactionNames.ChurchOfTheMachineGod || faction.name === FactionNames.Bladeburners) { - helpers.log(ctx, () => `You can't donate to '${facName}' because they do not accept donations`); - return false; - } - if (typeof amt !== "number" || amt <= 0 || isNaN(amt)) { - helpers.log(ctx, () => `Invalid donation amount: '${amt}'.`); - return false; - } - if (Player.money < amt) { - helpers.log( - ctx, - () => `You do not have enough money to donate ${numeralWrapper.formatMoney(amt)} to '${facName}'`, - ); - return false; - } - const repNeededToDonate = Math.floor(CONSTANTS.BaseFavorToDonate * BitNodeMultipliers.RepToDonateToFaction); - if (faction.favor < repNeededToDonate) { - helpers.log( - ctx, - () => - `You do not have enough favor to donate to this faction. Have ${faction.favor}, need ${repNeededToDonate}`, - ); - return false; - } - const repGain = (amt / CONSTANTS.DonateMoneyToRepDivisor) * Player.mults.faction_rep; - faction.playerReputation += repGain; - Player.loseMoney(amt, "other"); + getFactionRep: (ctx) => (_facName) => { + helpers.checkSingularityAccess(ctx); + const facName = helpers.string(ctx, "facName", _facName); + const faction = getFaction(ctx, facName); + return faction.playerReputation; + }, + getFactionFavor: (ctx) => (_facName) => { + helpers.checkSingularityAccess(ctx); + const facName = helpers.string(ctx, "facName", _facName); + const faction = getFaction(ctx, facName); + return faction.favor; + }, + getFactionFavorGain: (ctx) => (_facName) => { + helpers.checkSingularityAccess(ctx); + const facName = helpers.string(ctx, "facName", _facName); + const faction = getFaction(ctx, facName); + return faction.getFavorGain(); + }, + donateToFaction: (ctx) => (_facName, _amt) => { + helpers.checkSingularityAccess(ctx); + const facName = helpers.string(ctx, "facName", _facName); + const amt = helpers.number(ctx, "amt", _amt); + const faction = getFaction(ctx, facName); + if (!Player.factions.includes(faction.name)) { + helpers.log(ctx, () => `You can't donate to '${facName}' because you aren't a member`); + return false; + } + if (Player.gang && faction.name === Player.getGangFaction().name) { + helpers.log(ctx, () => `You can't donate to '${facName}' because youre managing a gang for it`); + return false; + } + if (faction.name === FactionNames.ChurchOfTheMachineGod || faction.name === FactionNames.Bladeburners) { + helpers.log(ctx, () => `You can't donate to '${facName}' because they do not accept donations`); + return false; + } + if (typeof amt !== "number" || amt <= 0 || isNaN(amt)) { + helpers.log(ctx, () => `Invalid donation amount: '${amt}'.`); + return false; + } + if (Player.money < amt) { + helpers.log( + ctx, + () => `You do not have enough money to donate ${numeralWrapper.formatMoney(amt)} to '${facName}'`, + ); + return false; + } + const repNeededToDonate = Math.floor(CONSTANTS.BaseFavorToDonate * BitNodeMultipliers.RepToDonateToFaction); + if (faction.favor < repNeededToDonate) { helpers.log( ctx, () => - `${numeralWrapper.formatMoney(amt)} donated to '${facName}' for ${numeralWrapper.formatReputation( - repGain, - )} reputation`, + `You do not have enough favor to donate to this faction. Have ${faction.favor}, need ${repNeededToDonate}`, ); - return true; - }, - createProgram: (ctx: NetscriptContext) => - function (_programName: unknown, _focus: unknown = true): boolean { + return false; + } + const repGain = (amt / CONSTANTS.DonateMoneyToRepDivisor) * Player.mults.faction_rep; + faction.playerReputation += repGain; + Player.loseMoney(amt, "other"); + helpers.log( + ctx, + () => + `${numeralWrapper.formatMoney(amt)} donated to '${facName}' for ${numeralWrapper.formatReputation( + repGain, + )} reputation`, + ); + return true; + }, + createProgram: + (ctx) => + (_programName, _focus = true) => { helpers.checkSingularityAccess(ctx); const programName = helpers.string(ctx, "programName", _programName).toLowerCase(); const focus = !!_focus; @@ -1158,8 +1115,9 @@ export function NetscriptSingularity(): InternalAPI { helpers.log(ctx, () => `Began creating program: '${programName}'`); return true; }, - commitCrime: (ctx: NetscriptContext) => - function (_crimeRoughName: unknown, _focus: unknown = true): number { + commitCrime: + (ctx) => + (_crimeRoughName, _focus = true) => { helpers.checkSingularityAccess(ctx); const crimeRoughName = helpers.string(ctx, "crimeRoughName", _crimeRoughName); const focus = !!_focus; @@ -1188,89 +1146,85 @@ export function NetscriptSingularity(): InternalAPI { } return crimeTime; }, - getCrimeChance: (ctx: NetscriptContext) => - function (_crimeRoughName: unknown): number { - helpers.checkSingularityAccess(ctx); - const crimeRoughName = helpers.string(ctx, "crimeRoughName", _crimeRoughName); + getCrimeChance: (ctx) => (_crimeRoughName) => { + helpers.checkSingularityAccess(ctx); + const crimeRoughName = helpers.string(ctx, "crimeRoughName", _crimeRoughName); - const crime = findCrime(crimeRoughName.toLowerCase()); - if (crime == null) { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid crime: ${crimeRoughName}`); - } + const crime = findCrime(crimeRoughName.toLowerCase()); + if (crime == null) { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid crime: ${crimeRoughName}`); + } - return crime.successRate(Player); - }, - getCrimeStats: (ctx: NetscriptContext) => - function (_crimeRoughName: unknown): CrimeStats { - helpers.checkSingularityAccess(ctx); - const crimeRoughName = helpers.string(ctx, "crimeRoughName", _crimeRoughName); + return crime.successRate(Player); + }, + getCrimeStats: (ctx) => (_crimeRoughName) => { + helpers.checkSingularityAccess(ctx); + const crimeRoughName = helpers.string(ctx, "crimeRoughName", _crimeRoughName); - const crime = findCrime(crimeRoughName.toLowerCase()); - if (crime == null) { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid crime: ${crimeRoughName}`); - } + const crime = findCrime(crimeRoughName.toLowerCase()); + if (crime == null) { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid crime: ${crimeRoughName}`); + } - const crimeStatsWithMultipliers = calculateCrimeWorkStats(crime); + const crimeStatsWithMultipliers = calculateCrimeWorkStats(crime); - return Object.assign({}, crime, { - money: crimeStatsWithMultipliers.money, - reputation: crimeStatsWithMultipliers.reputation, - hacking_exp: crimeStatsWithMultipliers.hackExp, - strength_exp: crimeStatsWithMultipliers.strExp, - defense_exp: crimeStatsWithMultipliers.defExp, - dexterity_exp: crimeStatsWithMultipliers.dexExp, - agility_exp: crimeStatsWithMultipliers.agiExp, - charisma_exp: crimeStatsWithMultipliers.chaExp, - intelligence_exp: crimeStatsWithMultipliers.intExp, - }); - }, - getDarkwebPrograms: (ctx: NetscriptContext) => - function (): string[] { - helpers.checkSingularityAccess(ctx); + return Object.assign({}, crime, { + money: crimeStatsWithMultipliers.money, + reputation: crimeStatsWithMultipliers.reputation, + hacking_exp: crimeStatsWithMultipliers.hackExp, + strength_exp: crimeStatsWithMultipliers.strExp, + defense_exp: crimeStatsWithMultipliers.defExp, + dexterity_exp: crimeStatsWithMultipliers.dexExp, + agility_exp: crimeStatsWithMultipliers.agiExp, + charisma_exp: crimeStatsWithMultipliers.chaExp, + intelligence_exp: crimeStatsWithMultipliers.intExp, + }); + }, + getDarkwebPrograms: (ctx) => () => { + helpers.checkSingularityAccess(ctx); - // If we don't have Tor, log it and return [] (empty list) - if (!Player.hasTorRouter()) { - helpers.log(ctx, () => "You do not have the TOR router."); - return []; - } - return Object.values(DarkWebItems).map((p) => p.program); - }, - getDarkwebProgramCost: (ctx: NetscriptContext) => - function (_programName: unknown): number { - helpers.checkSingularityAccess(ctx); - const programName = helpers.string(ctx, "programName", _programName).toLowerCase(); + // If we don't have Tor, log it and return [] (empty list) + if (!Player.hasTorRouter()) { + helpers.log(ctx, () => "You do not have the TOR router."); + return []; + } + return Object.values(DarkWebItems).map((p) => p.program); + }, + getDarkwebProgramCost: (ctx) => (_programName) => { + helpers.checkSingularityAccess(ctx); + const programName = helpers.string(ctx, "programName", _programName).toLowerCase(); - // If we don't have Tor, log it and return -1 - if (!Player.hasTorRouter()) { - helpers.log(ctx, () => "You do not have the TOR router."); - // returning -1 rather than throwing an error to be consistent with purchaseProgram - // which returns false if tor has - return -1; - } + // If we don't have Tor, log it and return -1 + if (!Player.hasTorRouter()) { + helpers.log(ctx, () => "You do not have the TOR router."); + // returning -1 rather than throwing an error to be consistent with purchaseProgram + // which returns false if tor has + return -1; + } - const item = Object.values(DarkWebItems).find((i) => i.program.toLowerCase() === programName); + const item = Object.values(DarkWebItems).find((i) => i.program.toLowerCase() === programName); - // If the program doesn't exist, throw an error. The reasoning here is that the 99% case is that - // the player will be using this in automation scripts, and if they're asking for a program that - // doesn't exist, it's the first time they've run the script. So throw an error to let them know - // that they need to fix it. - if (item == null) { - throw helpers.makeRuntimeErrorMsg( - ctx, - `No such exploit ('${programName}') found on the darkweb! ` + - `\nThis function is not case-sensitive. Did you perhaps forget .exe at the end?`, - ); - } + // If the program doesn't exist, throw an error. The reasoning here is that the 99% case is that + // the player will be using this in automation scripts, and if they're asking for a program that + // doesn't exist, it's the first time they've run the script. So throw an error to let them know + // that they need to fix it. + if (item == null) { + throw helpers.makeRuntimeErrorMsg( + ctx, + `No such exploit ('${programName}') found on the darkweb! ` + + `\nThis function is not case-sensitive. Did you perhaps forget .exe at the end?`, + ); + } - if (Player.hasProgram(item.program)) { - helpers.log(ctx, () => `You already have the '${item.program}' program`); - return 0; - } - return item.price; - }, + if (Player.hasProgram(item.program)) { + helpers.log(ctx, () => `You already have the '${item.program}' program`); + return 0; + } + return item.price; + }, b1tflum3: - (ctx: NetscriptContext) => - (_nextBN: unknown, _callbackScript: unknown = ""): void => { + (ctx) => + (_nextBN, _callbackScript = "") => { helpers.checkSingularityAccess(ctx); const nextBN = helpers.number(ctx, "nextBN", _nextBN); const callbackScript = helpers.string(ctx, "callbackScript", _callbackScript); @@ -1282,20 +1236,20 @@ export function NetscriptSingularity(): InternalAPI { }, 0); }, destroyW0r1dD43m0n: - (ctx: NetscriptContext) => - (_nextBN: unknown, _callbackScript: unknown = ""): void => { + (ctx) => + (_nextBN, _callbackScript = "") => { helpers.checkSingularityAccess(ctx); const nextBN = helpers.number(ctx, "nextBN", _nextBN); const callbackScript = helpers.string(ctx, "callbackScript", _callbackScript); const wd = GetServer(SpecialServers.WorldDaemon); if (!(wd instanceof Server)) throw new Error("WorldDaemon was not a normal server. This is a bug contact dev."); - const hackingRequirements = (): boolean => { + const hackingRequirements = () => { if (Player.skills.hacking < wd.requiredHackingSkill) return false; if (!wd.hasAdminRights) return false; return true; }; - const bladeburnerRequirements = (): boolean => { + const bladeburnerRequirements = () => { if (!Player.inBladeburner()) return false; if (!Player.bladeburner) return false; return Player.bladeburner.blackops[BlackOperationNames.OperationDaedalus]; @@ -1314,16 +1268,16 @@ export function NetscriptSingularity(): InternalAPI { runAfterReset(callbackScript); }, 0); }, - getCurrentWork: () => (): any | null => { + getCurrentWork: () => () => { if (!Player.currentWork) return null; return Player.currentWork.APICopy(); }, - exportGame: (ctx: NetscriptContext) => (): void => { + exportGame: (ctx) => () => { helpers.checkSingularityAccess(ctx); onExport(); return saveObject.exportGame(); }, - exportGameBonus: (ctx: NetscriptContext) => (): boolean => { + exportGameBonus: (ctx) => () => { helpers.checkSingularityAccess(ctx); return canGetBonus(); }, diff --git a/src/NetscriptFunctions/Sleeve.ts b/src/NetscriptFunctions/Sleeve.ts index cf302ee96..f482ff586 100644 --- a/src/NetscriptFunctions/Sleeve.ts +++ b/src/NetscriptFunctions/Sleeve.ts @@ -4,13 +4,7 @@ import { CityName } from "../Locations/data/CityNames"; import { findCrime } from "../Crime/CrimeHelpers"; import { Augmentation } from "../Augmentation/Augmentation"; -import { - AugmentPair, - Sleeve as ISleeve, - SleeveInformation, - SleeveSkills, - SleeveTask, -} from "../ScriptEditor/NetscriptDefinitions"; +import { Sleeve as ISleeve, SleeveSkills } from "../ScriptEditor/NetscriptDefinitions"; import { checkEnum } from "../utils/helpers/checkEnum"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import { isSleeveBladeburnerWork } from "../PersonObjects/Sleeve/Work/SleeveBladeburnerWork"; @@ -19,7 +13,7 @@ import { isSleeveCompanyWork } from "../PersonObjects/Sleeve/Work/SleeveCompanyW import { helpers } from "../Netscript/NetscriptHelpers"; export function NetscriptSleeve(): InternalAPI { - const checkSleeveAPIAccess = function (ctx: NetscriptContext): void { + const checkSleeveAPIAccess = function (ctx: NetscriptContext) { if (Player.bitNodeN !== 10 && !Player.sourceFileLvl(10)) { throw helpers.makeRuntimeErrorMsg( ctx, @@ -28,7 +22,7 @@ export function NetscriptSleeve(): InternalAPI { } }; - const checkSleeveNumber = function (ctx: NetscriptContext, sleeveNumber: number): void { + const checkSleeveNumber = function (ctx: NetscriptContext, sleeveNumber: number) { if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) { const msg = `Invalid sleeve number: ${sleeveNumber}`; helpers.log(ctx, () => msg); @@ -52,282 +46,248 @@ export function NetscriptSleeve(): InternalAPI { }; return { - getNumSleeves: (ctx: NetscriptContext) => (): number => { + getNumSleeves: (ctx) => () => { checkSleeveAPIAccess(ctx); return Player.sleeves.length; }, - setToShockRecovery: - (ctx: NetscriptContext) => - (_sleeveNumber: unknown): boolean => { - const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); - checkSleeveAPIAccess(ctx); - checkSleeveNumber(ctx, sleeveNumber); - return Player.sleeves[sleeveNumber].shockRecovery(); - }, - setToSynchronize: - (ctx: NetscriptContext) => - (_sleeveNumber: unknown): boolean => { - const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); - checkSleeveAPIAccess(ctx); - checkSleeveNumber(ctx, sleeveNumber); - return Player.sleeves[sleeveNumber].synchronize(); - }, - setToCommitCrime: - (ctx: NetscriptContext) => - (_sleeveNumber: unknown, _crimeRoughName: unknown): boolean => { - const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); - const crimeRoughName = helpers.string(ctx, "crimeName", _crimeRoughName); - checkSleeveAPIAccess(ctx); - checkSleeveNumber(ctx, sleeveNumber); - const crime = findCrime(crimeRoughName); - if (crime === null) { - return false; - } - return Player.sleeves[sleeveNumber].commitCrime(crime.name); - }, - setToUniversityCourse: - (ctx: NetscriptContext) => - (_sleeveNumber: unknown, _universityName: unknown, _className: unknown): boolean => { - 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(universityName, className); - }, - travel: - (ctx: NetscriptContext) => - (_sleeveNumber: unknown, _cityName: unknown): boolean => { - 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(cityName); - } else { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid city name: '${cityName}'.`); - } - }, - setToCompanyWork: - (ctx: NetscriptContext) => - (_sleeveNumber: unknown, acompanyName: unknown): boolean => { - const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); - const companyName = helpers.string(ctx, "companyName", acompanyName); - checkSleeveAPIAccess(ctx); - checkSleeveNumber(ctx, sleeveNumber); + setToShockRecovery: (ctx) => (_sleeveNumber) => { + const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); + checkSleeveAPIAccess(ctx); + checkSleeveNumber(ctx, sleeveNumber); + return Player.sleeves[sleeveNumber].shockRecovery(); + }, + setToSynchronize: (ctx) => (_sleeveNumber) => { + const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); + checkSleeveAPIAccess(ctx); + checkSleeveNumber(ctx, sleeveNumber); + return Player.sleeves[sleeveNumber].synchronize(); + }, + setToCommitCrime: (ctx) => (_sleeveNumber, _crimeRoughName) => { + const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); + const crimeRoughName = helpers.string(ctx, "crimeName", _crimeRoughName); + checkSleeveAPIAccess(ctx); + checkSleeveNumber(ctx, sleeveNumber); + const crime = findCrime(crimeRoughName); + if (crime === null) { + return false; + } + return Player.sleeves[sleeveNumber].commitCrime(crime.name); + }, + setToUniversityCourse: (ctx) => (_sleeveNumber, _universityName, _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(universityName, className); + }, + travel: (ctx) => (_sleeveNumber, _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(cityName); + } else { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid city name: '${cityName}'.`); + } + }, + setToCompanyWork: (ctx) => (_sleeveNumber, acompanyName) => { + const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); + const companyName = helpers.string(ctx, "companyName", acompanyName); + checkSleeveAPIAccess(ctx); + checkSleeveNumber(ctx, sleeveNumber); - // Cannot work at the same company that another sleeve is working at - for (let i = 0; i < Player.sleeves.length; ++i) { - if (i === sleeveNumber) { - continue; - } - const other = Player.sleeves[i]; - if (isSleeveCompanyWork(other.currentWork) && other.currentWork.companyName === companyName) { - throw helpers.makeRuntimeErrorMsg( - ctx, - `Sleeve ${sleeveNumber} cannot work for company ${companyName} because Sleeve ${i} is already working for them.`, - ); - } + // Cannot work at the same company that another sleeve is working at + for (let i = 0; i < Player.sleeves.length; ++i) { + if (i === sleeveNumber) { + continue; } - - return Player.sleeves[sleeveNumber].workForCompany(companyName); - }, - setToFactionWork: - (ctx: NetscriptContext) => - (_sleeveNumber: unknown, _factionName: unknown, _workType: unknown): boolean | undefined => { - 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); - - // Cannot work at the same faction that another sleeve is working at - for (let i = 0; i < Player.sleeves.length; ++i) { - if (i === sleeveNumber) { - continue; - } - const other = Player.sleeves[i]; - if (isSleeveFactionWork(other.currentWork) && other.currentWork.factionName === factionName) { - 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) { + const other = Player.sleeves[i]; + if (isSleeveCompanyWork(other.currentWork) && other.currentWork.companyName === companyName) { throw helpers.makeRuntimeErrorMsg( ctx, - `Sleeve ${sleeveNumber} cannot work for faction ${factionName} because you have started a gang with them.`, + `Sleeve ${sleeveNumber} cannot work for company ${companyName} because Sleeve ${i} is already working for them.`, ); } + } - return Player.sleeves[sleeveNumber].workForFaction(factionName, workType); - }, - setToGymWorkout: - (ctx: NetscriptContext) => - (_sleeveNumber: unknown, _gymName: unknown, _stat: unknown): boolean => { - 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); + return Player.sleeves[sleeveNumber].workForCompany(companyName); + }, + setToFactionWork: (ctx) => (_sleeveNumber, _factionName, _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); - return Player.sleeves[sleeveNumber].workoutAtGym(gymName, stat); - }, - getSleeveStats: - (ctx: NetscriptContext) => - (_sleeveNumber: unknown): SleeveSkills => { - const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); - checkSleeveAPIAccess(ctx); - checkSleeveNumber(ctx, sleeveNumber); - return getSleeveStats(sleeveNumber); - }, - getTask: - (ctx: NetscriptContext) => - (_sleeveNumber: unknown): SleeveTask | null => { - const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); - checkSleeveAPIAccess(ctx); - checkSleeveNumber(ctx, sleeveNumber); - - const sl = Player.sleeves[sleeveNumber]; - if (sl.currentWork === null) return null; - return sl.currentWork.APICopy(); - }, - getInformation: - (ctx: NetscriptContext) => - (_sleeveNumber: unknown): SleeveInformation => { - const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); - checkSleeveAPIAccess(ctx); - checkSleeveNumber(ctx, sleeveNumber); - - const sl = Player.sleeves[sleeveNumber]; - return { - tor: false, - city: sl.city, - hp: sl.hp, - jobs: Object.keys(Player.jobs), // technically sleeves have the same jobs as the player. - jobTitle: Object.values(Player.jobs), - - mult: { - agility: sl.mults.agility, - agilityExp: sl.mults.agility_exp, - charisma: sl.mults.charisma, - charismaExp: sl.mults.charisma_exp, - companyRep: sl.mults.company_rep, - crimeMoney: sl.mults.crime_money, - crimeSuccess: sl.mults.crime_success, - defense: sl.mults.defense, - defenseExp: sl.mults.defense_exp, - dexterity: sl.mults.dexterity, - dexterityExp: sl.mults.dexterity_exp, - factionRep: sl.mults.faction_rep, - hacking: sl.mults.hacking, - hackingExp: sl.mults.hacking_exp, - strength: sl.mults.strength, - strengthExp: sl.mults.strength_exp, - workMoney: sl.mults.work_money, - }, - }; - }, - getSleeveAugmentations: - (ctx: NetscriptContext) => - (_sleeveNumber: unknown): string[] => { - const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); - checkSleeveAPIAccess(ctx); - checkSleeveNumber(ctx, sleeveNumber); - - const augs = []; - for (let i = 0; i < Player.sleeves[sleeveNumber].augmentations.length; i++) { - augs.push(Player.sleeves[sleeveNumber].augmentations[i].name); + // Cannot work at the same faction that another sleeve is working at + for (let i = 0; i < Player.sleeves.length; ++i) { + if (i === sleeveNumber) { + continue; } - return augs; - }, - getSleevePurchasableAugs: - (ctx: NetscriptContext) => - (_sleeveNumber: unknown): AugmentPair[] => { - const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); - checkSleeveAPIAccess(ctx); - checkSleeveNumber(ctx, sleeveNumber); - - const purchasableAugs = Player.sleeves[sleeveNumber].findPurchasableAugs(); - const augs = []; - for (let i = 0; i < purchasableAugs.length; i++) { - const aug = purchasableAugs[i]; - augs.push({ - name: aug.name, - cost: aug.baseCost, - }); + const other = Player.sleeves[i]; + if (isSleeveFactionWork(other.currentWork) && other.currentWork.factionName === factionName) { + throw helpers.makeRuntimeErrorMsg( + ctx, + `Sleeve ${sleeveNumber} cannot work for faction ${factionName} because Sleeve ${i} is already working for them.`, + ); } + } - return augs; - }, - purchaseSleeveAug: - (ctx: NetscriptContext) => - (_sleeveNumber: unknown, _augName: unknown): boolean => { - const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); - const augName = helpers.string(ctx, "augName", _augName); - checkSleeveAPIAccess(ctx); - checkSleeveNumber(ctx, sleeveNumber); + if (Player.gang && Player.gang.facName == factionName) { + throw helpers.makeRuntimeErrorMsg( + ctx, + `Sleeve ${sleeveNumber} cannot work for faction ${factionName} because you have started a gang with them.`, + ); + } - if (getSleeveStats(sleeveNumber).shock > 0) { - throw helpers.makeRuntimeErrorMsg(ctx, `Sleeve shock too high: Sleeve ${sleeveNumber}`); - } + return Player.sleeves[sleeveNumber].workForFaction(factionName, workType); + }, + setToGymWorkout: (ctx) => (_sleeveNumber, _gymName, _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); - const aug = StaticAugmentations[augName]; - if (!aug) { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid aug: ${augName}`); - } + return Player.sleeves[sleeveNumber].workoutAtGym(gymName, stat); + }, + getSleeveStats: (ctx) => (_sleeveNumber) => { + const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); + checkSleeveAPIAccess(ctx); + checkSleeveNumber(ctx, sleeveNumber); + return getSleeveStats(sleeveNumber); + }, + getTask: (ctx) => (_sleeveNumber) => { + const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); + checkSleeveAPIAccess(ctx); + checkSleeveNumber(ctx, sleeveNumber); - return Player.sleeves[sleeveNumber].tryBuyAugmentation(aug); - }, - getSleeveAugmentationPrice: - (ctx: NetscriptContext) => - (_augName: unknown): number => { - checkSleeveAPIAccess(ctx); - const augName = helpers.string(ctx, "augName", _augName); - const aug: Augmentation = StaticAugmentations[augName]; - return aug.baseCost; - }, - getSleeveAugmentationRepReq: - (ctx: NetscriptContext) => - (_augName: unknown): number => { - checkSleeveAPIAccess(ctx); - const augName = helpers.string(ctx, "augName", _augName); - const aug: Augmentation = StaticAugmentations[augName]; - return aug.getCost().repCost; - }, - setToBladeburnerAction: - (ctx: NetscriptContext) => - (_sleeveNumber: unknown, _action: unknown, _contract?: unknown): boolean => { - const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); - const action = helpers.string(ctx, "action", _action); - let contract: string; - if (typeof _contract === "undefined") { - contract = "------"; - } else { - contract = helpers.string(ctx, "contract", _contract); - } - checkSleeveAPIAccess(ctx); - checkSleeveNumber(ctx, sleeveNumber); + const sl = Player.sleeves[sleeveNumber]; + if (sl.currentWork === null) return null; + return sl.currentWork.APICopy(); + }, + getInformation: (ctx) => (_sleeveNumber) => { + const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); + checkSleeveAPIAccess(ctx); + checkSleeveNumber(ctx, sleeveNumber); - // Cannot Take on Contracts if another sleeve is performing that action - if (action === "Take on contracts") { - for (let i = 0; i < Player.sleeves.length; ++i) { - if (i === sleeveNumber) { - continue; - } - const other = Player.sleeves[i]; - if (isSleeveBladeburnerWork(other.currentWork) && other.currentWork.actionName === contract) { - throw helpers.makeRuntimeErrorMsg( - ctx, - `Sleeve ${sleeveNumber} cannot take on contracts because Sleeve ${i} is already performing that action.`, - ); - } + const sl = Player.sleeves[sleeveNumber]; + return { + tor: false, + city: sl.city, + hp: sl.hp, + jobs: Object.keys(Player.jobs), // technically sleeves have the same jobs as the player. + jobTitle: Object.values(Player.jobs), + + mult: { + agility: sl.mults.agility, + agilityExp: sl.mults.agility_exp, + charisma: sl.mults.charisma, + charismaExp: sl.mults.charisma_exp, + companyRep: sl.mults.company_rep, + crimeMoney: sl.mults.crime_money, + crimeSuccess: sl.mults.crime_success, + defense: sl.mults.defense, + defenseExp: sl.mults.defense_exp, + dexterity: sl.mults.dexterity, + dexterityExp: sl.mults.dexterity_exp, + factionRep: sl.mults.faction_rep, + hacking: sl.mults.hacking, + hackingExp: sl.mults.hacking_exp, + strength: sl.mults.strength, + strengthExp: sl.mults.strength_exp, + workMoney: sl.mults.work_money, + }, + }; + }, + getSleeveAugmentations: (ctx) => (_sleeveNumber) => { + const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); + checkSleeveAPIAccess(ctx); + checkSleeveNumber(ctx, sleeveNumber); + + const augs = []; + for (let i = 0; i < Player.sleeves[sleeveNumber].augmentations.length; i++) { + augs.push(Player.sleeves[sleeveNumber].augmentations[i].name); + } + return augs; + }, + getSleevePurchasableAugs: (ctx) => (_sleeveNumber) => { + const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); + checkSleeveAPIAccess(ctx); + checkSleeveNumber(ctx, sleeveNumber); + + const purchasableAugs = Player.sleeves[sleeveNumber].findPurchasableAugs(); + const augs = []; + for (let i = 0; i < purchasableAugs.length; i++) { + const aug = purchasableAugs[i]; + augs.push({ + name: aug.name, + cost: aug.baseCost, + }); + } + + return augs; + }, + purchaseSleeveAug: (ctx) => (_sleeveNumber, _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 helpers.makeRuntimeErrorMsg(ctx, `Sleeve shock too high: Sleeve ${sleeveNumber}`); + } + + const aug = StaticAugmentations[augName]; + if (!aug) { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid aug: ${augName}`); + } + + return Player.sleeves[sleeveNumber].tryBuyAugmentation(aug); + }, + getSleeveAugmentationPrice: (ctx) => (_augName) => { + checkSleeveAPIAccess(ctx); + const augName = helpers.string(ctx, "augName", _augName); + const aug: Augmentation = StaticAugmentations[augName]; + return aug.baseCost; + }, + getSleeveAugmentationRepReq: (ctx) => (_augName) => { + checkSleeveAPIAccess(ctx); + const augName = helpers.string(ctx, "augName", _augName); + const aug: Augmentation = StaticAugmentations[augName]; + return aug.getCost().repCost; + }, + setToBladeburnerAction: (ctx) => (_sleeveNumber, _action, _contract?) => { + const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber); + const action = helpers.string(ctx, "action", _action); + let contract: string; + if (typeof _contract === "undefined") { + contract = "------"; + } else { + contract = helpers.string(ctx, "contract", _contract); + } + checkSleeveAPIAccess(ctx); + checkSleeveNumber(ctx, sleeveNumber); + + // Cannot Take on Contracts if another sleeve is performing that action + if (action === "Take on contracts") { + for (let i = 0; i < Player.sleeves.length; ++i) { + if (i === sleeveNumber) { + continue; + } + const other = Player.sleeves[i]; + if (isSleeveBladeburnerWork(other.currentWork) && other.currentWork.actionName === contract) { + throw helpers.makeRuntimeErrorMsg( + ctx, + `Sleeve ${sleeveNumber} cannot take on contracts because Sleeve ${i} is already performing that action.`, + ); } } + } - return Player.sleeves[sleeveNumber].bladeburner(action, contract); - }, + return Player.sleeves[sleeveNumber].bladeburner(action, contract); + }, }; } diff --git a/src/NetscriptFunctions/Stanek.ts b/src/NetscriptFunctions/Stanek.ts index 84401dd9d..459594559 100644 --- a/src/NetscriptFunctions/Stanek.ts +++ b/src/NetscriptFunctions/Stanek.ts @@ -4,11 +4,7 @@ import { staneksGift } from "../CotMG/Helper"; import { Fragments, FragmentById } from "../CotMG/Fragment"; import { FragmentType } from "../CotMG/FragmentType"; -import { - Fragment as IFragment, - ActiveFragment as IActiveFragment, - Stanek as IStanek, -} from "../ScriptEditor/NetscriptDefinitions"; +import { Stanek as IStanek } from "../ScriptEditor/NetscriptDefinitions"; import { AugmentationNames } from "../Augmentation/data/AugmentationNames"; import { NetscriptContext, InternalAPI } from "../Netscript/APIWrapper"; import { applyAugmentation } from "../Augmentation/AugmentationHelpers"; @@ -25,125 +21,114 @@ export function NetscriptStanek(): InternalAPI { } return { - giftWidth: (ctx: NetscriptContext) => - function (): number { - checkStanekAPIAccess(ctx); - return staneksGift.width(); - }, - giftHeight: (ctx: NetscriptContext) => - function (): number { - checkStanekAPIAccess(ctx); - return staneksGift.height(); - }, - chargeFragment: (ctx: NetscriptContext) => - function (_rootX: unknown, _rootY: unknown): Promise { - //Get the fragment object using the given coordinates - 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 helpers.makeRuntimeErrorMsg(ctx, `No fragment with root (${rootX}, ${rootY}).`); - if (fragment.fragment().type == FragmentType.Booster) { - throw helpers.makeRuntimeErrorMsg( + giftWidth: (ctx) => () => { + checkStanekAPIAccess(ctx); + return staneksGift.width(); + }, + giftHeight: (ctx) => () => { + checkStanekAPIAccess(ctx); + return staneksGift.height(); + }, + chargeFragment: (ctx) => (_rootX, _rootY) => { + //Get the fragment object using the given coordinates + 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 helpers.makeRuntimeErrorMsg(ctx, `No fragment with root (${rootX}, ${rootY}).`); + if (fragment.fragment().type == FragmentType.Booster) { + 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 helpers.netscriptDelay(ctx, time).then(function () { + staneksGift.charge(fragment, ctx.workerScript.scriptRef.threads); + helpers.log(ctx, () => `Charged fragment with ${ctx.workerScript.scriptRef.threads} threads.`); + return Promise.resolve(); + }); + }, + fragmentDefinitions: (ctx) => () => { + checkStanekAPIAccess(ctx); + helpers.log(ctx, () => `Returned ${Fragments.length} fragments`); + return Fragments.map((f) => f.copy()); + }, + activeFragments: (ctx) => () => { + checkStanekAPIAccess(ctx); + helpers.log(ctx, () => `Returned ${staneksGift.fragments.length} fragments`); + return staneksGift.fragments.map((af) => { + return { ...af.copy(), ...af.fragment().copy() }; + }); + }, + clearGift: (ctx) => () => { + checkStanekAPIAccess(ctx); + helpers.log(ctx, () => `Cleared Stanek's Gift.`); + staneksGift.clear(); + }, + canPlaceFragment: (ctx) => (_rootX, _rootY, _rotation, _fragmentId) => { + 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 helpers.makeRuntimeErrorMsg(ctx, `Invalid fragment id: ${fragmentId}`); + const can = staneksGift.canPlace(rootX, rootY, rotation, fragment); + return can; + }, + placeFragment: (ctx) => (_rootX, _rootY, _rotation, _fragmentId) => { + 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 helpers.makeRuntimeErrorMsg(ctx, `Invalid fragment id: ${fragmentId}`); + return staneksGift.place(rootX, rootY, rotation, fragment); + }, + getFragment: (ctx) => (_rootX, _rootY) => { + 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) => (_rootX, _rootY) => { + const rootX = helpers.number(ctx, "rootX", _rootX); + const rootY = helpers.number(ctx, "rootY", _rootY); + checkStanekAPIAccess(ctx); + return staneksGift.delete(rootX, rootY); + }, + acceptGift: (ctx) => () => { + //Check if the player is eligible to join the church + if ( + player.canAccessCotMG() && + player.augmentations.filter((a) => a.name !== AugmentationNames.NeuroFluxGovernor).length == 0 && + player.queuedAugmentations.filter((a) => a.name !== AugmentationNames.NeuroFluxGovernor).length == 0 + ) { + //Attempt to join CotMG + joinFaction(Factions[FactionNames.ChurchOfTheMachineGod]); + //Attempt to install the first Stanek aug + if ( + !player.hasAugmentation(AugmentationNames.StaneksGift1) && + !player.queuedAugmentations.some((a) => a.name === AugmentationNames.StaneksGift1) + ) { + applyAugmentation({ name: AugmentationNames.StaneksGift1, level: 1 }); + helpers.log( ctx, - `The fragment with root (${rootX}, ${rootY}) is a Booster Fragment and thus cannot be charged.`, + () => `'${FactionNames.ChurchOfTheMachineGod}' joined and '${AugmentationNames.StaneksGift1}' installed.`, ); } - //Charge the fragment - const time = staneksGift.inBonus() ? 200 : 1000; - return helpers.netscriptDelay(ctx, time).then(function () { - staneksGift.charge(fragment, ctx.workerScript.scriptRef.threads); - helpers.log(ctx, () => `Charged fragment with ${ctx.workerScript.scriptRef.threads} threads.`); - return Promise.resolve(); - }); - }, - fragmentDefinitions: (ctx: NetscriptContext) => - function (): IFragment[] { - checkStanekAPIAccess(ctx); - helpers.log(ctx, () => `Returned ${Fragments.length} fragments`); - return Fragments.map((f) => f.copy()); - }, - activeFragments: (ctx: NetscriptContext) => - function (): IActiveFragment[] { - checkStanekAPIAccess(ctx); - helpers.log(ctx, () => `Returned ${staneksGift.fragments.length} fragments`); - return staneksGift.fragments.map((af) => { - return { ...af.copy(), ...af.fragment().copy() }; - }); - }, - clearGift: (ctx: NetscriptContext) => - function (): void { - checkStanekAPIAccess(ctx); - helpers.log(ctx, () => `Cleared Stanek's Gift.`); - staneksGift.clear(); - }, - canPlaceFragment: (ctx: NetscriptContext) => - function (_rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown): boolean { - 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 helpers.makeRuntimeErrorMsg(ctx, `Invalid fragment id: ${fragmentId}`); - const can = staneksGift.canPlace(rootX, rootY, rotation, fragment); - return can; - }, - placeFragment: (ctx: NetscriptContext) => - function (_rootX: unknown, _rootY: unknown, _rotation: unknown, _fragmentId: unknown): boolean { - 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 helpers.makeRuntimeErrorMsg(ctx, `Invalid fragment id: ${fragmentId}`); - return staneksGift.place(rootX, rootY, rotation, fragment); - }, - getFragment: (ctx: NetscriptContext) => - function (_rootX: unknown, _rootY: unknown): IActiveFragment | undefined { - 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) => - function (_rootX: unknown, _rootY: unknown): boolean { - const rootX = helpers.number(ctx, "rootX", _rootX); - const rootY = helpers.number(ctx, "rootY", _rootY); - checkStanekAPIAccess(ctx); - return staneksGift.delete(rootX, rootY); - }, - acceptGift: (ctx: NetscriptContext) => - function (): boolean { - //Check if the player is eligible to join the church - if ( - player.canAccessCotMG() && - player.augmentations.filter((a) => a.name !== AugmentationNames.NeuroFluxGovernor).length == 0 && - player.queuedAugmentations.filter((a) => a.name !== AugmentationNames.NeuroFluxGovernor).length == 0 - ) { - //Attempt to join CotMG - joinFaction(Factions[FactionNames.ChurchOfTheMachineGod]); - //Attempt to install the first Stanek aug - if ( - !player.hasAugmentation(AugmentationNames.StaneksGift1) && - !player.queuedAugmentations.some((a) => a.name === AugmentationNames.StaneksGift1) - ) { - applyAugmentation({ name: AugmentationNames.StaneksGift1, level: 1 }); - helpers.log( - ctx, - () => `'${FactionNames.ChurchOfTheMachineGod}' joined and '${AugmentationNames.StaneksGift1}' installed.`, - ); - } - } - //Return true iff the player is in CotMG and has the first Stanek aug installed - return ( - Factions[FactionNames.ChurchOfTheMachineGod].isMember && - player.hasAugmentation(AugmentationNames.StaneksGift1, true) - ); - }, + } + //Return true iff the player is in CotMG and has the first Stanek aug installed + return ( + Factions[FactionNames.ChurchOfTheMachineGod].isMember && + player.hasAugmentation(AugmentationNames.StaneksGift1, true) + ); + }, }; } diff --git a/src/NetscriptFunctions/StockMarket.ts b/src/NetscriptFunctions/StockMarket.ts index 273ec8a24..42a56b950 100644 --- a/src/NetscriptFunctions/StockMarket.ts +++ b/src/NetscriptFunctions/StockMarket.ts @@ -37,284 +37,258 @@ export function NetscriptStockMarket(): InternalAPI { }; return { - hasWSEAccount: () => (): boolean => { + hasWSEAccount: () => () => { return player.hasWseAccount; }, - hasTIXAPIAccess: () => (): boolean => { + hasTIXAPIAccess: () => () => { return player.hasTixApiAccess; }, - has4SData: () => (): boolean => { + has4SData: () => () => { return player.has4SData; }, - has4SDataTIXAPI: () => (): boolean => { + has4SDataTIXAPI: () => () => { return player.has4SDataTixApi; }, - getSymbols: (ctx: NetscriptContext) => (): string[] => { + getSymbols: (ctx) => () => { checkTixApiAccess(ctx); return Object.values(StockSymbols); }, - getPrice: - (ctx: NetscriptContext) => - (_symbol: unknown): number => { - const symbol = helpers.string(ctx, "symbol", _symbol); - checkTixApiAccess(ctx); - const stock = getStockFromSymbol(ctx, symbol); + getPrice: (ctx) => (_symbol) => { + const symbol = helpers.string(ctx, "symbol", _symbol); + checkTixApiAccess(ctx); + const stock = getStockFromSymbol(ctx, symbol); - return stock.price; - }, - getAskPrice: - (ctx: NetscriptContext) => - (_symbol: unknown): number => { - const symbol = helpers.string(ctx, "symbol", _symbol); - checkTixApiAccess(ctx); - const stock = getStockFromSymbol(ctx, symbol); + return stock.price; + }, + getAskPrice: (ctx) => (_symbol) => { + const symbol = helpers.string(ctx, "symbol", _symbol); + checkTixApiAccess(ctx); + const stock = getStockFromSymbol(ctx, symbol); - return stock.getAskPrice(); - }, - getBidPrice: - (ctx: NetscriptContext) => - (_symbol: unknown): number => { - const symbol = helpers.string(ctx, "symbol", _symbol); - checkTixApiAccess(ctx); - const stock = getStockFromSymbol(ctx, symbol); + return stock.getAskPrice(); + }, + getBidPrice: (ctx) => (_symbol) => { + const symbol = helpers.string(ctx, "symbol", _symbol); + checkTixApiAccess(ctx); + const stock = getStockFromSymbol(ctx, symbol); - return stock.getBidPrice(); - }, - getPosition: - (ctx: NetscriptContext) => - (_symbol: unknown): [number, number, number, number] => { - const symbol = helpers.string(ctx, "symbol", _symbol); - checkTixApiAccess(ctx); - const stock = SymbolToStockMap[symbol]; - if (stock == null) { - 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 = helpers.string(ctx, "symbol", _symbol); - checkTixApiAccess(ctx); - const stock = getStockFromSymbol(ctx, symbol); + return stock.getBidPrice(); + }, + getPosition: (ctx) => (_symbol) => { + const symbol = helpers.string(ctx, "symbol", _symbol); + checkTixApiAccess(ctx); + const stock = SymbolToStockMap[symbol]; + if (stock == null) { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid stock symbol: ${symbol}`); + } + return [stock.playerShares, stock.playerAvgPx, stock.playerShortShares, stock.playerAvgShortPx]; + }, + getMaxShares: (ctx) => (_symbol) => { + const symbol = helpers.string(ctx, "symbol", _symbol); + checkTixApiAccess(ctx); + const stock = getStockFromSymbol(ctx, symbol); - return stock.maxShares; - }, - getPurchaseCost: - (ctx: NetscriptContext) => - (_symbol: unknown, _shares: unknown, _posType: unknown): number => { - 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); + return stock.maxShares; + }, + getPurchaseCost: (ctx) => (_symbol, _shares, _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); - let pos; - const sanitizedPosType = posType.toLowerCase(); - if (sanitizedPosType.includes("l")) { - pos = PositionTypes.Long; - } else if (sanitizedPosType.includes("s")) { - pos = PositionTypes.Short; - } else { - return Infinity; - } + let pos; + const sanitizedPosType = posType.toLowerCase(); + if (sanitizedPosType.includes("l")) { + pos = PositionTypes.Long; + } else if (sanitizedPosType.includes("s")) { + pos = PositionTypes.Short; + } else { + return Infinity; + } - const res = getBuyTransactionCost(stock, shares, pos); - if (res == null) { - return Infinity; - } + const res = getBuyTransactionCost(stock, shares, pos); + if (res == null) { + return Infinity; + } - return res; - }, - getSaleGain: - (ctx: NetscriptContext) => - (_symbol: unknown, _shares: unknown, _posType: unknown): number => { - 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); + return res; + }, + getSaleGain: (ctx) => (_symbol, _shares, _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); - let pos; - const sanitizedPosType = posType.toLowerCase(); - if (sanitizedPosType.includes("l")) { - pos = PositionTypes.Long; - } else if (sanitizedPosType.includes("s")) { - pos = PositionTypes.Short; - } else { - return 0; - } + let pos; + const sanitizedPosType = posType.toLowerCase(); + if (sanitizedPosType.includes("l")) { + pos = PositionTypes.Long; + } else if (sanitizedPosType.includes("s")) { + pos = PositionTypes.Short; + } else { + return 0; + } - const res = getSellTransactionGain(stock, shares, pos); - if (res == null) { - return 0; - } + const res = getSellTransactionGain(stock, shares, pos); + if (res == null) { + return 0; + } - return res; - }, - buyStock: - (ctx: NetscriptContext) => - (_symbol: unknown, _shares: unknown): number => { - 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, ctx, {}); - return res ? stock.getAskPrice() : 0; - }, - sellStock: - (ctx: NetscriptContext) => - (_symbol: unknown, _shares: unknown): number => { - 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, ctx, {}); + return res; + }, + buyStock: (ctx) => (_symbol, _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, ctx, {}); + return res ? stock.getAskPrice() : 0; + }, + sellStock: (ctx) => (_symbol, _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, ctx, {}); - return res ? stock.getBidPrice() : 0; - }, - buyShort: - (ctx: NetscriptContext) => - (_symbol: unknown, _shares: unknown): number => { - 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 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, ctx, {}); - - return res ? stock.getBidPrice() : 0; - }, - sellShort: - (ctx: NetscriptContext) => - (_symbol: unknown, _shares: unknown): number => { - 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 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, ctx, {}); - - return res ? stock.getAskPrice() : 0; - }, - placeOrder: - (ctx: NetscriptContext) => - (_symbol: unknown, _shares: unknown, _price: unknown, _type: unknown, _pos: unknown): boolean => { - 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 helpers.makeRuntimeErrorMsg( - ctx, - "You must either be in BitNode-8 or you must have Source-File 8 Level 3.", - ); - } - } - const stock = getStockFromSymbol(ctx, symbol); - - let orderType; - let orderPos; - const ltype = type.toLowerCase(); - if (ltype.includes("limit") && ltype.includes("buy")) { - orderType = OrderTypes.LimitBuy; - } else if (ltype.includes("limit") && ltype.includes("sell")) { - orderType = OrderTypes.LimitSell; - } else if (ltype.includes("stop") && ltype.includes("buy")) { - orderType = OrderTypes.StopBuy; - } else if (ltype.includes("stop") && ltype.includes("sell")) { - orderType = OrderTypes.StopSell; - } else { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid order type: ${type}`); - } - - const lpos = pos.toLowerCase(); - if (lpos.includes("l")) { - orderPos = PositionTypes.Long; - } else if (lpos.includes("s")) { - orderPos = PositionTypes.Short; - } else { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid position type: ${pos}`); - } - - return placeOrder(stock, shares, price, orderType, orderPos, ctx); - }, - cancelOrder: - (ctx: NetscriptContext) => - (_symbol: unknown, _shares: unknown, _price: unknown, _type: unknown, _pos: unknown): boolean => { - 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 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)) { + return res ? stock.getBidPrice() : 0; + }, + buyShort: (ctx) => (_symbol, _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 helpers.makeRuntimeErrorMsg( ctx, - `Invalid shares or price. Must be numeric. shares=${shares}, price=${price}`, + "You must either be in BitNode-8 or you must have Source-File 8 Level 2.", ); } - let orderType; - let orderPos; - const ltype = type.toLowerCase(); - if (ltype.includes("limit") && ltype.includes("buy")) { - orderType = OrderTypes.LimitBuy; - } else if (ltype.includes("limit") && ltype.includes("sell")) { - orderType = OrderTypes.LimitSell; - } else if (ltype.includes("stop") && ltype.includes("buy")) { - orderType = OrderTypes.StopBuy; - } else if (ltype.includes("stop") && ltype.includes("sell")) { - orderType = OrderTypes.StopSell; - } else { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid order type: ${type}`); - } + } + const stock = getStockFromSymbol(ctx, symbol); + const res = shortStock(stock, shares, ctx, {}); - const lpos = pos.toLowerCase(); - if (lpos.includes("l")) { - orderPos = PositionTypes.Long; - } else if (lpos.includes("s")) { - orderPos = PositionTypes.Short; - } else { - throw helpers.makeRuntimeErrorMsg(ctx, `Invalid position type: ${pos}`); + return res ? stock.getBidPrice() : 0; + }, + sellShort: (ctx) => (_symbol, _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 helpers.makeRuntimeErrorMsg( + ctx, + "You must either be in BitNode-8 or you must have Source-File 8 Level 2.", + ); } - const params = { - stock: stock, - shares: shares, - price: price, - type: orderType, - pos: orderPos, - }; - return cancelOrder(params, ctx); - }, - getOrders: (ctx: NetscriptContext) => (): StockOrder => { + } + const stock = getStockFromSymbol(ctx, symbol); + const res = sellShort(stock, shares, ctx, {}); + + return res ? stock.getAskPrice() : 0; + }, + placeOrder: (ctx) => (_symbol, _shares, _price, _type, _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 helpers.makeRuntimeErrorMsg( + ctx, + "You must either be in BitNode-8 or you must have Source-File 8 Level 3.", + ); + } + } + const stock = getStockFromSymbol(ctx, symbol); + + let orderType; + let orderPos; + const ltype = type.toLowerCase(); + if (ltype.includes("limit") && ltype.includes("buy")) { + orderType = OrderTypes.LimitBuy; + } else if (ltype.includes("limit") && ltype.includes("sell")) { + orderType = OrderTypes.LimitSell; + } else if (ltype.includes("stop") && ltype.includes("buy")) { + orderType = OrderTypes.StopBuy; + } else if (ltype.includes("stop") && ltype.includes("sell")) { + orderType = OrderTypes.StopSell; + } else { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid order type: ${type}`); + } + + const lpos = pos.toLowerCase(); + if (lpos.includes("l")) { + orderPos = PositionTypes.Long; + } else if (lpos.includes("s")) { + orderPos = PositionTypes.Short; + } else { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid position type: ${pos}`); + } + + return placeOrder(stock, shares, price, orderType, orderPos, ctx); + }, + cancelOrder: (ctx) => (_symbol, _shares, _price, _type, _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 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 helpers.makeRuntimeErrorMsg( + ctx, + `Invalid shares or price. Must be numeric. shares=${shares}, price=${price}`, + ); + } + let orderType; + let orderPos; + const ltype = type.toLowerCase(); + if (ltype.includes("limit") && ltype.includes("buy")) { + orderType = OrderTypes.LimitBuy; + } else if (ltype.includes("limit") && ltype.includes("sell")) { + orderType = OrderTypes.LimitSell; + } else if (ltype.includes("stop") && ltype.includes("buy")) { + orderType = OrderTypes.StopBuy; + } else if (ltype.includes("stop") && ltype.includes("sell")) { + orderType = OrderTypes.StopSell; + } else { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid order type: ${type}`); + } + + const lpos = pos.toLowerCase(); + if (lpos.includes("l")) { + orderPos = PositionTypes.Long; + } else if (lpos.includes("s")) { + orderPos = PositionTypes.Short; + } else { + throw helpers.makeRuntimeErrorMsg(ctx, `Invalid position type: ${pos}`); + } + const params = { + stock: stock, + shares: shares, + price: price, + type: orderType, + pos: orderPos, + }; + return cancelOrder(params, ctx); + }, + getOrders: (ctx) => () => { checkTixApiAccess(ctx); if (player.bitNodeN !== 8) { if (player.sourceFileLvl(8) <= 2) { @@ -342,31 +316,27 @@ export function NetscriptStockMarket(): InternalAPI { return orders; }, - getVolatility: - (ctx: NetscriptContext) => - (_symbol: unknown): number => { - const symbol = helpers.string(ctx, "symbol", _symbol); - if (!player.has4SDataTixApi) { - throw helpers.makeRuntimeErrorMsg(ctx, "You don't have 4S Market Data TIX API Access!"); - } - const stock = getStockFromSymbol(ctx, symbol); + getVolatility: (ctx) => (_symbol) => { + const symbol = helpers.string(ctx, "symbol", _symbol); + if (!player.has4SDataTixApi) { + throw helpers.makeRuntimeErrorMsg(ctx, "You don't have 4S Market Data TIX API Access!"); + } + const stock = getStockFromSymbol(ctx, symbol); - return stock.mv / 100; // Convert from percentage to decimal - }, - getForecast: - (ctx: NetscriptContext) => - (_symbol: unknown): number => { - const symbol = helpers.string(ctx, "symbol", _symbol); - if (!player.has4SDataTixApi) { - throw helpers.makeRuntimeErrorMsg(ctx, "You don't have 4S Market Data TIX API Access!"); - } - const stock = getStockFromSymbol(ctx, symbol); + return stock.mv / 100; // Convert from percentage to decimal + }, + getForecast: (ctx) => (_symbol) => { + const symbol = helpers.string(ctx, "symbol", _symbol); + if (!player.has4SDataTixApi) { + throw helpers.makeRuntimeErrorMsg(ctx, "You don't have 4S Market Data TIX API Access!"); + } + const stock = getStockFromSymbol(ctx, symbol); - let forecast = 50; - stock.b ? (forecast += stock.otlkMag) : (forecast -= stock.otlkMag); - return forecast / 100; // Convert from percentage to decimal - }, - purchase4SMarketData: (ctx: NetscriptContext) => (): boolean => { + let forecast = 50; + stock.b ? (forecast += stock.otlkMag) : (forecast -= stock.otlkMag); + return forecast / 100; // Convert from percentage to decimal + }, + purchase4SMarketData: (ctx) => () => { if (player.has4SData) { helpers.log(ctx, () => "Already purchased 4S Market Data."); return true; @@ -382,7 +352,7 @@ export function NetscriptStockMarket(): InternalAPI { helpers.log(ctx, () => "Purchased 4S Market Data"); return true; }, - purchase4SMarketDataTixApi: (ctx: NetscriptContext) => (): boolean => { + purchase4SMarketDataTixApi: (ctx) => () => { checkTixApiAccess(ctx); if (player.has4SDataTixApi) { @@ -400,7 +370,7 @@ export function NetscriptStockMarket(): InternalAPI { helpers.log(ctx, () => "Purchased 4S Market Data TIX API"); return true; }, - purchaseWseAccount: (ctx: NetscriptContext) => (): boolean => { + purchaseWseAccount: (ctx) => () => { if (player.hasWseAccount) { helpers.log(ctx, () => "Already purchased WSE Account"); return true; @@ -417,7 +387,7 @@ export function NetscriptStockMarket(): InternalAPI { helpers.log(ctx, () => "Purchased WSE Account Access"); return true; }, - purchaseTixApi: (ctx: NetscriptContext) => (): boolean => { + purchaseTixApi: (ctx) => () => { if (player.hasTixApiAccess) { helpers.log(ctx, () => "Already purchased TIX API"); return true; diff --git a/src/NetscriptFunctions/UserInterface.ts b/src/NetscriptFunctions/UserInterface.ts index 03ddf38ca..cf7306030 100644 --- a/src/NetscriptFunctions/UserInterface.ts +++ b/src/NetscriptFunctions/UserInterface.ts @@ -1,38 +1,34 @@ -import { - GameInfo, - IStyleSettings, - UserInterface as IUserInterface, - UserInterfaceTheme, -} from "../ScriptEditor/NetscriptDefinitions"; +import { UserInterface as IUserInterface } from "../ScriptEditor/NetscriptDefinitions"; import { Settings } from "../Settings/Settings"; import { ThemeEvents } from "../Themes/ui/Theme"; import { defaultTheme } from "../Themes/Themes"; import { defaultStyles } from "../Themes/Styles"; import { CONSTANTS } from "../Constants"; import { hash } from "../hash/hash"; -import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; +import { InternalAPI } from "../Netscript/APIWrapper"; import { Terminal } from "../../src/Terminal"; -import { helpers } from "../Netscript/NetscriptHelpers"; +import { helpers, assertObjectType } from "../Netscript/NetscriptHelpers"; export function NetscriptUserInterface(): InternalAPI { return { - windowSize: () => (): [number, number] => { + windowSize: () => () => { return [window.innerWidth, window.innerHeight]; }, - getTheme: () => (): UserInterfaceTheme => { + getTheme: () => () => { return { ...Settings.theme }; }, - getStyles: () => (): IStyleSettings => { + getStyles: () => () => { return { ...Settings.styles }; }, - setTheme: - (ctx: NetscriptContext) => - (newTheme: UserInterfaceTheme): void => { - const hex = /^(#)((?:[A-Fa-f0-9]{2}){3,4}|(?:[A-Fa-f0-9]{3}))$/; - const currentTheme = { ...Settings.theme }; - const errors: string[] = []; + setTheme: (ctx) => (newTheme) => { + const themeValidator: Record = {}; + assertObjectType(ctx, "newTheme", newTheme, themeValidator); + const hex = /^(#)((?:[A-Fa-f0-9]{2}){3,4}|(?:[A-Fa-f0-9]{3}))$/; + const currentTheme = { ...Settings.theme }; + const errors: string[] = []; + if (typeof newTheme !== "object") for (const key of Object.keys(newTheme)) { if (!currentTheme[key]) { // Invalid key @@ -44,51 +40,51 @@ export function NetscriptUserInterface(): InternalAPI { } } - if (errors.length === 0) { - Object.assign(Settings.theme, currentTheme); - ThemeEvents.emit(); - helpers.log(ctx, () => `Successfully set theme`); + if (errors.length === 0) { + Object.assign(Settings.theme, currentTheme); + ThemeEvents.emit(); + helpers.log(ctx, () => `Successfully set theme`); + } else { + helpers.log(ctx, () => `Failed to set theme. Errors: ${errors.join(", ")}`); + } + }, + + setStyles: (ctx) => (newStyles) => { + const styleValidator: Record = {}; + assertObjectType(ctx, "newStyles", newStyles, styleValidator); + const currentStyles = { ...Settings.styles }; + const errors: string[] = []; + for (const key of Object.keys(newStyles)) { + if (!(currentStyles as any)[key]) { + // Invalid key + errors.push(`Invalid key "${key}"`); } else { - helpers.log(ctx, () => `Failed to set theme. Errors: ${errors.join(", ")}`); + (currentStyles as any)[key] = newStyles[key]; } - }, + } - setStyles: - (ctx: NetscriptContext) => - (newStyles: IStyleSettings): void => { - const currentStyles = { ...Settings.styles }; - const errors: string[] = []; - for (const key of Object.keys(newStyles)) { - if (!(currentStyles as any)[key]) { - // Invalid key - errors.push(`Invalid key "${key}"`); - } else { - (currentStyles as any)[key] = (newStyles as any)[key]; - } - } + if (errors.length === 0) { + Object.assign(Settings.styles, currentStyles); + ThemeEvents.emit(); + helpers.log(ctx, () => `Successfully set styles`); + } else { + helpers.log(ctx, () => `Failed to set styles. Errors: ${errors.join(", ")}`); + } + }, - if (errors.length === 0) { - Object.assign(Settings.styles, currentStyles); - ThemeEvents.emit(); - helpers.log(ctx, () => `Successfully set styles`); - } else { - helpers.log(ctx, () => `Failed to set styles. Errors: ${errors.join(", ")}`); - } - }, - - resetTheme: (ctx: NetscriptContext) => (): void => { + resetTheme: (ctx) => () => { Settings.theme = { ...defaultTheme }; ThemeEvents.emit(); helpers.log(ctx, () => `Reinitialized theme to default`); }, - resetStyles: (ctx: NetscriptContext) => (): void => { + resetStyles: (ctx) => () => { Settings.styles = { ...defaultStyles }; ThemeEvents.emit(); helpers.log(ctx, () => `Reinitialized styles to default`); }, - getGameInfo: () => (): GameInfo => { + getGameInfo: () => () => { const version = CONSTANTS.VersionString; const commit = hash(); const platform = navigator.userAgent.toLowerCase().indexOf(" electron/") > -1 ? "Steam" : "Browser"; @@ -102,7 +98,7 @@ export function NetscriptUserInterface(): InternalAPI { return gameInfo; }, - clearTerminal: (ctx: NetscriptContext) => (): void => { + clearTerminal: (ctx) => () => { helpers.log(ctx, () => `Clearing terminal`); Terminal.clear(); }, diff --git a/src/NetscriptPort.ts b/src/NetscriptPort.ts index b26614f69..8ad141dcd 100644 --- a/src/NetscriptPort.ts +++ b/src/NetscriptPort.ts @@ -1,28 +1,39 @@ import { Settings } from "./Settings/Settings"; +type PortData = string | number; export interface IPort { - write: (value: unknown) => unknown; + write: (value: unknown) => PortData | null; tryWrite: (value: unknown) => boolean; - read: () => unknown; - peek: () => unknown; + read: () => PortData; + peek: () => PortData; full: () => boolean; empty: () => boolean; clear: () => void; } export function NetscriptPort(): IPort { - const data: unknown[] = []; + const data: PortData[] = []; return { - write: (value: unknown): unknown => { + write: (value) => { + if (typeof value !== "number" && typeof value !== "string") { + throw new Error( + `port.write: Tried to write type ${typeof value}. Only string and number types may be written to ports.`, + ); + } data.push(value); if (data.length > Settings.MaxPortCapacity) { - return data.shift(); + return data.shift() as PortData; } return null; }, - tryWrite: (value: unknown): boolean => { + tryWrite: (value) => { + if (typeof value != "number" && typeof value != "string") { + throw new Error( + `port.write: Tried to write type ${typeof value}. Only string and number types may be written to ports.`, + ); + } if (data.length >= Settings.MaxPortCapacity) { return false; } @@ -30,31 +41,25 @@ export function NetscriptPort(): IPort { return true; }, - read: (): unknown => { - if (data.length === 0) { - return "NULL PORT DATA"; - } - return data.shift(); + read: () => { + if (data.length === 0) return "NULL PORT DATA"; + return data.shift() as PortData; }, - peek: (): unknown => { - if (data.length === 0) { - return "NULL PORT DATA"; - } else { - const foo = data.slice(); - return foo[0]; - } + peek: () => { + if (data.length === 0) return "NULL PORT DATA"; + return data[0]; }, - full: (): boolean => { + full: () => { return data.length == Settings.MaxPortCapacity; }, - empty: (): boolean => { + empty: () => { return data.length === 0; }, - clear: (): void => { + clear: () => { data.length = 0; }, }; diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index 15a6aaeb5..22d6362ac 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -961,7 +961,7 @@ export interface NetscriptPort { * * @returns The data popped off the queue if it was full. */ - write(value: string | number): null | string | number; + write(value: string | number): PortData | null; /** * Attempt to write data to the port. @@ -981,7 +981,7 @@ export interface NetscriptPort { * If the port is empty, then the string “NULL PORT DATA” will be returned. * @returns the data read. */ - read(): string | number; + read(): PortData; /** * Retrieve the first element from the port without removing it. @@ -993,7 +993,7 @@ export interface NetscriptPort { * the port is empty, the string “NULL PORT DATA” will be returned. * @returns the data read */ - peek(): string | number; + peek(): PortData; /** * Check if the port is full. diff --git a/src/Terminal.ts b/src/Terminal.ts index 99835551e..c28f17050 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -1,3 +1,2 @@ import { Terminal as TTerminal } from "./Terminal/Terminal"; - export const Terminal = new TTerminal(); diff --git a/src/utils/helpers/checkEnum.ts b/src/utils/helpers/checkEnum.ts index b3eb24d48..46354a52f 100644 --- a/src/utils/helpers/checkEnum.ts +++ b/src/utils/helpers/checkEnum.ts @@ -1,4 +1,4 @@ -// This works for both enums and regular objects. +/** Verifies that a supplied value is a member of the provided object/enum. Works for enums as well as enum-like objects (const {} as const). */ export function checkEnum>(obj: T, value: unknown): value is T[keyof T] { return Object.values(obj).includes(value); }