mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-17 21:23:54 +01:00
NETSCRIPT: Expose more enums for player use (#198)
* Add support for enums at other ns layers * APIWrapper: simplified wrapping algorithm and modified to just use cloneDeep to copy enums instead of recursively wrapping enums as if they were new API layers * Improve APIWrapper typing * Changed some typings at RamCostGenerator to allow for enums at different levels without enums needing a ram cost * Added enums to ns.corporation, removed getter functions that were being used instead. * Add FactionWorkType for player use * Add ClassType and CompanyWorkPos enums * Change netscriptDefinitions to expect members of these new enums where appropriate.
This commit is contained in:
parent
8e0e0eaa88
commit
b275f88053
@ -1,4 +1,4 @@
|
||||
// Defs for job titles, stored in arrays and categorized by job "type"
|
||||
// TODO: Convert all to CompanyPosNames[] and make everything that uses these expect a CompanyPosNames enum member.
|
||||
|
||||
export const SoftwareCompanyPositions: string[] = [
|
||||
"Software Engineering Intern",
|
||||
|
@ -2,30 +2,40 @@ import { getRamCost } from "./RamCostGenerator";
|
||||
import type { WorkerScript } from "./WorkerScript";
|
||||
import { helpers } from "./NetscriptHelpers";
|
||||
import { ScriptArg } from "./ScriptArg";
|
||||
import { NSEnums } from "src/ScriptEditor/NetscriptDefinitions";
|
||||
import { NSFull } from "src/NetscriptFunctions";
|
||||
import { cloneDeep } from "lodash";
|
||||
|
||||
type ExternalFunction = (...args: any[]) => void;
|
||||
/** Generic type for an enums object */
|
||||
type Enums = Record<string, Record<string, string>>;
|
||||
/** Permissive type for the documented API functions */
|
||||
type APIFn = (...args: any[]) => void;
|
||||
/** Type for the actual wrapped function given to the player */
|
||||
type WrappedFn = (...args: unknown[]) => unknown;
|
||||
/** Type for internal, unwrapped ctx function that produces an APIFunction */
|
||||
type InternalFn<F extends APIFn> = (ctx: NetscriptContext) => ((...args: unknown[]) => ReturnType<F>) & F;
|
||||
type Key<API> = keyof API & string;
|
||||
|
||||
export type ExternalAPILayer = {
|
||||
[key: string]: ExternalAPILayer | ExternalFunction | ScriptArg[];
|
||||
export type ExternalAPI<API> = {
|
||||
[key in keyof API]: API[key] extends Enums
|
||||
? Enums
|
||||
: key extends "args"
|
||||
? ScriptArg[] // "args" required to be ScriptArg[]
|
||||
: API[key] extends APIFn
|
||||
? WrappedFn
|
||||
: ExternalAPI<API[key]>;
|
||||
};
|
||||
|
||||
type InternalFunction<F extends ExternalFunction> = (
|
||||
ctx: NetscriptContext,
|
||||
) => ((...args: unknown[]) => ReturnType<F>) & F;
|
||||
|
||||
export type InternalAPI<API> = {
|
||||
[Property in keyof API]: API[Property] extends ExternalFunction
|
||||
? InternalFunction<API[Property]>
|
||||
: API[Property] extends NSEnums
|
||||
? NSEnums
|
||||
: API[Property] extends ScriptArg[]
|
||||
[key in keyof API]: API[key] extends Enums
|
||||
? API[key] & Enums
|
||||
: key extends "args"
|
||||
? ScriptArg[]
|
||||
: API[Property] extends object
|
||||
? InternalAPI<API[Property]>
|
||||
: never;
|
||||
: API[key] extends APIFn
|
||||
? InternalFn<API[key]>
|
||||
: InternalAPI<API[key]>;
|
||||
};
|
||||
/** Any of the possible values on a internal API layer */
|
||||
type InternalValues = Enums | ScriptArg[] | InternalFn<APIFn> | InternalAPI<unknown>;
|
||||
|
||||
export type NetscriptContext = {
|
||||
workerScript: WorkerScript;
|
||||
@ -33,77 +43,36 @@ export type NetscriptContext = {
|
||||
functionPath: string;
|
||||
};
|
||||
|
||||
function wrapFunction(
|
||||
wrappedAPI: ExternalAPILayer,
|
||||
workerScript: WorkerScript,
|
||||
func: (_ctx: NetscriptContext) => (...args: unknown[]) => unknown,
|
||||
...tree: string[]
|
||||
): void {
|
||||
const functionPath = tree.join(".");
|
||||
const functionName = tree.pop();
|
||||
if (typeof functionName !== "string") {
|
||||
throw helpers.makeBasicErrorMsg(workerScript, "Failure occurred while wrapping netscript api", "INITIALIZATION");
|
||||
}
|
||||
const ctx = {
|
||||
workerScript,
|
||||
function: functionName,
|
||||
functionPath,
|
||||
};
|
||||
function wrappedFunction(...args: unknown[]): unknown {
|
||||
helpers.checkEnvFlags(ctx);
|
||||
helpers.updateDynamicRam(ctx, getRamCost(...tree, ctx.function));
|
||||
return func(ctx)(...args);
|
||||
}
|
||||
const parent = getNestedProperty(wrappedAPI, tree);
|
||||
Object.defineProperty(parent, functionName, {
|
||||
value: wrappedFunction,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
});
|
||||
}
|
||||
|
||||
export function wrapAPI(workerScript: WorkerScript, namespace: object, args: ScriptArg[]): NSFull {
|
||||
const wrappedAPI = wrapAPILayer({}, workerScript, namespace);
|
||||
wrappedAPI.args = args;
|
||||
return wrappedAPI as unknown as NSFull;
|
||||
}
|
||||
|
||||
export function wrapAPILayer(
|
||||
wrappedAPI: ExternalAPILayer,
|
||||
workerScript: WorkerScript,
|
||||
namespace: object,
|
||||
...tree: string[]
|
||||
) {
|
||||
for (const [key, value] of Object.entries(namespace)) {
|
||||
if (typeof value === "function") {
|
||||
wrapFunction(wrappedAPI, workerScript, value, ...tree, key);
|
||||
} else if (Array.isArray(value)) {
|
||||
setNestedProperty(wrappedAPI, value.slice(), key);
|
||||
} else if (typeof value === "object") {
|
||||
wrapAPILayer(wrappedAPI, workerScript, value, ...tree, key);
|
||||
} else {
|
||||
setNestedProperty(wrappedAPI, value, ...tree, key);
|
||||
export function wrapAPI(ws: WorkerScript, internalAPI: InternalAPI<NSFull>, args: ScriptArg[]): ExternalAPI<NSFull> {
|
||||
function wrapAPILayer<API>(eLayer: ExternalAPI<API>, iLayer: InternalAPI<API>, tree: string[]): ExternalAPI<API> {
|
||||
for (const [key, value] of Object.entries(iLayer) as [Key<API>, InternalValues][]) {
|
||||
if (key === "enums") {
|
||||
(eLayer[key] as Enums) = cloneDeep(value as Enums);
|
||||
} else if (key === "args") continue;
|
||||
// Args are added in wrapAPI function and should only exist at top level
|
||||
else if (typeof value === "function") {
|
||||
wrapFunction(eLayer, value as InternalFn<APIFn>, tree, key);
|
||||
} else if (typeof value === "object") {
|
||||
wrapAPILayer((eLayer[key] = {} as ExternalAPI<API>[Key<API>]), value, [...tree, key as string]);
|
||||
} else {
|
||||
console.warn(`Unexpected data while wrapping API.`, "tree:", tree, "key:", key, "value:", value);
|
||||
throw new Error("Error while wrapping netscript API. See console.");
|
||||
}
|
||||
}
|
||||
return eLayer;
|
||||
}
|
||||
function wrapFunction<API>(eLayer: ExternalAPI<API>, func: InternalFn<APIFn>, tree: string[], key: Key<API>) {
|
||||
const arrayPath = [...tree, key];
|
||||
const functionPath = arrayPath.join(".");
|
||||
const ctx = { workerScript: ws, function: key, functionPath };
|
||||
function wrappedFunction(...args: unknown[]): unknown {
|
||||
helpers.checkEnvFlags(ctx);
|
||||
helpers.updateDynamicRam(ctx, getRamCost(...tree, key));
|
||||
return func(ctx)(...args);
|
||||
}
|
||||
(eLayer[key] as WrappedFn) = wrappedFunction;
|
||||
}
|
||||
|
||||
const wrappedAPI = wrapAPILayer({ args } as ExternalAPI<NSFull>, internalAPI, []);
|
||||
return wrappedAPI;
|
||||
}
|
||||
|
||||
function setNestedProperty(root: any, value: unknown, ...tree: string[]): void {
|
||||
let target = root;
|
||||
const key = tree.pop();
|
||||
if (!key) throw new Error("Failure occurred while wrapping netscript api (setNestedProperty)");
|
||||
for (const branch of tree) {
|
||||
target[branch] ??= {};
|
||||
target = target[branch];
|
||||
}
|
||||
target[key] = value;
|
||||
}
|
||||
|
||||
function getNestedProperty(root: any, tree: string[]): unknown {
|
||||
let target = root;
|
||||
for (const branch of tree) {
|
||||
target[branch] ??= {};
|
||||
target = target[branch];
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { NS } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { ExternalAPI } from "./APIWrapper";
|
||||
|
||||
/**
|
||||
* The environment in which a script runs. The environment holds
|
||||
@ -13,5 +14,5 @@ export class Environment {
|
||||
runningFn = "";
|
||||
|
||||
/** Environment variables (currently only Netscript functions) */
|
||||
vars: NS | null = null;
|
||||
vars: ExternalAPI<NS> | null = null;
|
||||
}
|
||||
|
@ -2,9 +2,12 @@ import { Player } from "@player";
|
||||
import { NSFull } from "../NetscriptFunctions";
|
||||
|
||||
/** This type assumes any value that isn't an API layer or a function has been omitted (args and enum) */
|
||||
type RamCostTree<API> = {
|
||||
[Property in keyof API]: API[Property] extends () => unknown ? number | (() => number) : RamCostTree<API[Property]>;
|
||||
};
|
||||
type RamCostTree<API> = Omit<
|
||||
{
|
||||
[Property in keyof API]: API[Property] extends () => unknown ? number | (() => number) : RamCostTree<API[Property]>;
|
||||
},
|
||||
"enums" | "args"
|
||||
>;
|
||||
|
||||
/** Constants for assigning costs to ns functions */
|
||||
export const RamCostConstants: Record<string, number> = {
|
||||
@ -414,7 +417,7 @@ const corporation = {
|
||||
* An error will be generated if there are missing OR additional ram costs defined.
|
||||
* To avoid errors, define every function in NetscriptDefinition.d.ts and NetscriptFunctions,
|
||||
* and have a ram cost associated here. */
|
||||
export const RamCosts: RamCostTree<Omit<NSFull, "args" | "enums">> = {
|
||||
export const RamCosts: RamCostTree<NSFull> = {
|
||||
corporation,
|
||||
hacknet,
|
||||
stock,
|
||||
|
@ -16,6 +16,7 @@ import { BaseServer } from "../Server/BaseServer";
|
||||
import { NS } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { ScriptDeath } from "./ScriptDeath";
|
||||
import { ScriptArg } from "./ScriptArg";
|
||||
import { ExternalAPI } from "./APIWrapper";
|
||||
|
||||
export class WorkerScript {
|
||||
/** Script's arguments */
|
||||
@ -82,7 +83,7 @@ export class WorkerScript {
|
||||
/** Function called when the script ends. */
|
||||
atExit?: () => void;
|
||||
|
||||
constructor(runningScriptObj: RunningScript, pid: number, nsFuncsGenerator?: (ws: WorkerScript) => NS) {
|
||||
constructor(runningScriptObj: RunningScript, pid: number, nsFuncsGenerator?: (ws: WorkerScript) => ExternalAPI<NS>) {
|
||||
this.name = runningScriptObj.filename;
|
||||
this.hostname = runningScriptObj.server;
|
||||
|
||||
|
@ -61,7 +61,7 @@ import { NetscriptCorporation } from "./NetscriptFunctions/Corporation";
|
||||
import { NetscriptFormulas } from "./NetscriptFunctions/Formulas";
|
||||
import { NetscriptStockMarket } from "./NetscriptFunctions/StockMarket";
|
||||
import { NetscriptGrafting } from "./NetscriptFunctions/Grafting";
|
||||
import { NS, RecentScript as IRecentScript, BasicHGWOptions, ProcessInfo } from "./ScriptEditor/NetscriptDefinitions";
|
||||
import { NS, RecentScript, BasicHGWOptions, ProcessInfo, NSEnums } from "./ScriptEditor/NetscriptDefinitions";
|
||||
import { NetscriptSingularity } from "./NetscriptFunctions/Singularity";
|
||||
|
||||
import { dialogBoxCreate } from "./ui/React/DialogBox";
|
||||
@ -72,22 +72,27 @@ import { Flags } from "./NetscriptFunctions/Flags";
|
||||
import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence";
|
||||
import { CalculateShareMult, StartSharing } from "./NetworkShare/Share";
|
||||
import { recentScripts } from "./Netscript/RecentScripts";
|
||||
import { InternalAPI, wrapAPI } from "./Netscript/APIWrapper";
|
||||
import { ExternalAPI, InternalAPI, wrapAPI } from "./Netscript/APIWrapper";
|
||||
import { INetscriptExtra } from "./NetscriptFunctions/Extra";
|
||||
import { ScriptDeath } from "./Netscript/ScriptDeath";
|
||||
import { getBitNodeMultipliers } from "./BitNode/BitNode";
|
||||
import { assert, arrayAssert, stringAssert, objectAssert } from "./utils/helpers/typeAssertion";
|
||||
import { CrimeType } from "./utils/WorkType";
|
||||
import { CompanyPosNames, CrimeType } from "./utils/WorkType";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { FactionWorkType } from "./Work/data/FactionWorkType";
|
||||
import { ClassType } from "./Work/ClassWork";
|
||||
|
||||
export const enums = {
|
||||
export const enums: NSEnums = {
|
||||
toast: ToastVariant,
|
||||
CrimeType,
|
||||
FactionWorkType,
|
||||
ClassType,
|
||||
CompanyPosNames,
|
||||
};
|
||||
|
||||
export type NSFull = Readonly<NS & INetscriptExtra>;
|
||||
|
||||
export function NetscriptFunctions(workerScript: WorkerScript): NSFull {
|
||||
export function NetscriptFunctions(workerScript: WorkerScript): ExternalAPI<NSFull> {
|
||||
return wrapAPI(workerScript, ns, workerScript.args.slice());
|
||||
}
|
||||
|
||||
@ -968,7 +973,7 @@ const base: InternalAPI<NS> = {
|
||||
allFiles.sort();
|
||||
return allFiles;
|
||||
},
|
||||
getRecentScripts: () => (): IRecentScript[] => {
|
||||
getRecentScripts: () => (): RecentScript[] => {
|
||||
return recentScripts.map((rs) => ({
|
||||
timeOfDeath: rs.timeOfDeath,
|
||||
...helpers.createPublicRunningScript(rs.runningScript),
|
||||
|
@ -703,6 +703,10 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
};
|
||||
|
||||
return {
|
||||
enums: {
|
||||
EmployeePositions,
|
||||
IndustryType,
|
||||
},
|
||||
...warehouseAPI,
|
||||
...officeAPI,
|
||||
hasCorporation: () => () => !!Player.corporation,
|
||||
@ -711,14 +715,6 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
checkAccess(ctx);
|
||||
return [...CorporationConstants.AllMaterials];
|
||||
},
|
||||
getIndustryTypes: (ctx) => () => {
|
||||
checkAccess(ctx);
|
||||
return Object.values(IndustryType);
|
||||
},
|
||||
getEmployeePositions: (ctx) => () => {
|
||||
checkAccess(ctx);
|
||||
return Object.values(EmployeePositions);
|
||||
},
|
||||
getUnlockables: (ctx) => () => {
|
||||
checkAccess(ctx);
|
||||
return [...CorporationConstants.AllUnlocks];
|
||||
@ -776,9 +772,6 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
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) => (_divisionName) => {
|
||||
checkAccess(ctx);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
|
@ -51,7 +51,7 @@ import { FactionWorkType } from "../Work/data/FactionWorkType";
|
||||
|
||||
import { defaultMultipliers } from "../PersonObjects/Multipliers";
|
||||
import { checkEnum } from "../utils/helpers/checkEnum";
|
||||
import { CrimeType } from "../utils/WorkType";
|
||||
import { CompanyPosNames, CrimeType } from "../utils/WorkType";
|
||||
import { CompanyPositions } from "../Company/CompanyPositions";
|
||||
|
||||
export function NetscriptFormulas(): InternalAPI<IFormulas> {
|
||||
@ -354,46 +354,50 @@ export function NetscriptFormulas(): InternalAPI<IFormulas> {
|
||||
},
|
||||
work: {
|
||||
crimeSuccessChance: (ctx) => (_person, _crimeType) => {
|
||||
checkFormulasAccess(ctx);
|
||||
const person = helpers.person(ctx, _person);
|
||||
const crimeType = helpers.string(ctx, "crimeType", _crimeType);
|
||||
if (!checkEnum(CrimeType, crimeType)) throw new Error(`Invalid crime type: ${crimeType}`);
|
||||
return Crimes[crimeType].successRate(person);
|
||||
},
|
||||
crimeGains: (ctx) => (_person, _crimeType) => {
|
||||
checkFormulasAccess(ctx);
|
||||
const person = helpers.person(ctx, _person);
|
||||
const crimeType = helpers.string(ctx, "crimeType", _crimeType);
|
||||
if (!checkEnum(CrimeType, crimeType)) throw new Error(`Invalid crime type: ${crimeType}`);
|
||||
return calculateCrimeWorkStats(person, Crimes[crimeType]);
|
||||
},
|
||||
classGains: (ctx) => (_person, _classType, _locationName) => {
|
||||
checkFormulasAccess(ctx);
|
||||
const person = helpers.person(ctx, _person);
|
||||
const classType = helpers.string(ctx, "classType", _classType);
|
||||
if (!checkEnum(ClassType, classType)) throw new Error(`Invalid class type: ${classType}`);
|
||||
const locationName = helpers.string(ctx, "locationName", _locationName);
|
||||
return calculateClassEarnings(person, classType as ClassType, locationName as LocationName);
|
||||
if (!checkEnum(LocationName, locationName)) throw new Error(`Invalid location name: ${locationName}`);
|
||||
return calculateClassEarnings(person, classType, locationName);
|
||||
},
|
||||
factionGains: (ctx) => (_player, _workType, _favor) => {
|
||||
checkFormulasAccess(ctx);
|
||||
const player = helpers.person(ctx, _player);
|
||||
const workType = helpers.string(ctx, "_workType", _workType) as FactionWorkType;
|
||||
const workType = helpers.string(ctx, "_workType", _workType);
|
||||
if (!checkEnum(FactionWorkType, workType)) throw new Error(`Invalid faction work type: ${workType}`);
|
||||
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, _companyName, _positionName, _favor) => {
|
||||
const player = helpers.person(ctx, _player);
|
||||
CompanyPositions;
|
||||
companyGains: (ctx) => (_person, _companyName, _positionName, _favor) => {
|
||||
checkFormulasAccess(ctx);
|
||||
const person = helpers.person(ctx, _person);
|
||||
const positionName = helpers.string(ctx, "_positionName", _positionName);
|
||||
const position = Object.values(CompanyPositions).find((c) => c.name === positionName);
|
||||
if (!position) throw new Error(`Invalid position name: ${positionName}`);
|
||||
|
||||
if (!checkEnum(CompanyPosNames, positionName)) throw new Error(`Invalid company position: ${positionName}`);
|
||||
const position = CompanyPositions[positionName];
|
||||
const companyName = helpers.string(ctx, "_companyName", _companyName);
|
||||
const company = Object.values(Companies).find((c) => c.name === companyName);
|
||||
if (!company) throw new Error(`Invalid company name: ${companyName}`);
|
||||
|
||||
const favor = helpers.number(ctx, "favor", _favor);
|
||||
|
||||
return calculateCompanyWorkStats(player, company, position, favor);
|
||||
return calculateCompanyWorkStats(person, company, position, favor);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -79,9 +79,8 @@ async function startNetscript1Script(workerScript: WorkerScript): Promise<void>
|
||||
throw `Error processing Imports in ${workerScript.name}@${workerScript.hostname}:\n\n${e}`;
|
||||
}
|
||||
|
||||
interface BasicObject {
|
||||
[key: string]: any;
|
||||
}
|
||||
//TODO: Make NS1 wrapping type safe instead of using BasicObject
|
||||
type BasicObject = Record<string, any>;
|
||||
function wrapNS1Layer(int: Interpreter, intLayer: unknown, nsLayer = workerScript.env.vars as BasicObject) {
|
||||
for (const [name, entry] of Object.entries(nsLayer)) {
|
||||
if (typeof entry === "function") {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { ExternalAPI } from "../Netscript/APIWrapper";
|
||||
import { AutocompleteData, NS } from "../ScriptEditor/NetscriptDefinitions";
|
||||
|
||||
export interface ScriptModule {
|
||||
main?: (ns: NS) => unknown;
|
||||
main?: (ns: ExternalAPI<NS>) => unknown;
|
||||
autocomplete?: (data: AutocompleteData, flags: string[]) => unknown;
|
||||
}
|
||||
|
362
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
362
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -1768,7 +1768,7 @@ export interface Singularity {
|
||||
* @param focus - Acquire player focus on this work operation. Optional. Defaults to true.
|
||||
* @returns True if the player starts working, and false otherwise.
|
||||
*/
|
||||
workForFaction(faction: string, workType: "hacking" | "field" | "security", focus?: boolean): boolean;
|
||||
workForFaction(faction: string, workType: FactionWorkType | `${FactionWorkType}`, focus?: boolean): boolean;
|
||||
|
||||
/**
|
||||
* Get faction reputation.
|
||||
@ -1887,7 +1887,7 @@ export interface Singularity {
|
||||
* @param focus - Acquire player focus on this crime. Optional. Defaults to true.
|
||||
* @returns The number of milliseconds it takes to attempt the specified crime.
|
||||
*/
|
||||
commitCrime(crime: CrimeType | CrimeNames, focus?: boolean): number;
|
||||
commitCrime(crime: CrimeType | `${CrimeType}`, focus?: boolean): number;
|
||||
|
||||
/**
|
||||
* Get chance to successfully commit a crime.
|
||||
@ -1900,7 +1900,7 @@ export interface Singularity {
|
||||
* @param crime - Name of crime.
|
||||
* @returns Chance of success at committing the specified crime.
|
||||
*/
|
||||
getCrimeChance(crime: CrimeType | CrimeNames): number;
|
||||
getCrimeChance(crime: CrimeType | `${CrimeType}`): number;
|
||||
|
||||
/**
|
||||
* Get stats related to a crime.
|
||||
@ -1913,7 +1913,7 @@ export interface Singularity {
|
||||
* @param crime - Name of crime.
|
||||
* @returns The stats of the crime.
|
||||
*/
|
||||
getCrimeStats(crime: CrimeType | CrimeNames): CrimeStats;
|
||||
getCrimeStats(crime: CrimeType | `${CrimeType}`): CrimeStats;
|
||||
|
||||
/**
|
||||
* Get a list of owned augmentation.
|
||||
@ -3572,7 +3572,7 @@ export interface sleeve {
|
||||
* @param name - Name of the crime.
|
||||
* @returns True if this action was set successfully, false otherwise.
|
||||
*/
|
||||
setToCommitCrime(sleeveNumber: number, crimeType: CrimeType | CrimeNames): boolean;
|
||||
setToCommitCrime(sleeveNumber: number, crimeType: CrimeType | `${CrimeType}`): boolean;
|
||||
|
||||
/**
|
||||
* Set a sleeve to work for a faction.
|
||||
@ -3586,7 +3586,11 @@ export interface sleeve {
|
||||
* @param factionWorkType - Name of the action to perform for this faction.
|
||||
* @returns True if the sleeve started working on this faction, false otherwise, can also throw on errors
|
||||
*/
|
||||
setToFactionWork(sleeveNumber: number, factionName: string, factionWorkType: string): boolean | undefined;
|
||||
setToFactionWork(
|
||||
sleeveNumber: number,
|
||||
factionName: string,
|
||||
factionWorkType: FactionWorkType | `${FactionWorkType}`,
|
||||
): boolean | undefined;
|
||||
|
||||
/**
|
||||
* Set a sleeve to work for a company.
|
||||
@ -3811,10 +3815,15 @@ export interface WorkStats {
|
||||
*/
|
||||
interface WorkFormulas {
|
||||
crimeSuccessChance(person: Person, crimeType: CrimeType | CrimeNames): number;
|
||||
crimeGains(person: Person, crimeType: CrimeType | CrimeNames): WorkStats;
|
||||
classGains(person: Person, classType: string, locationName: string): WorkStats;
|
||||
factionGains(person: Person, workType: string, favor: number): WorkStats;
|
||||
companyGains(person: Person, companyName: string, workType: string, favor: number): WorkStats;
|
||||
crimeGains(person: Person, crimeType: CrimeType | `${CrimeType}`): WorkStats;
|
||||
classGains(person: Person, classType: ClassType | `${ClassType}`, locationName: string): WorkStats;
|
||||
factionGains(person: Person, workType: FactionWorkType | `${FactionWorkType}`, favor: number): WorkStats;
|
||||
companyGains(
|
||||
person: Person,
|
||||
companyName: string,
|
||||
workType: CompanyPosNames | `${CompanyPosNames}`,
|
||||
favor: number,
|
||||
): WorkStats;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -6592,7 +6601,7 @@ export interface NS {
|
||||
* @param variant - Type of toast. Must be one of success, info, warning, error. Defaults to success.
|
||||
* @param duration - Duration of toast in ms. Can also be `null` to create a persistent toast. Defaults to 2000.
|
||||
*/
|
||||
toast(msg: string, variant?: ToastTypes | ToastVariant, duration?: number | null): void;
|
||||
toast(msg: string, variant?: ToastVariant | `${ToastVariant}`, duration?: number | null): void;
|
||||
|
||||
/**
|
||||
* Download a file from the internet.
|
||||
@ -6791,33 +6800,7 @@ export interface NS {
|
||||
enums: NSEnums;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
type EmployeePosName =
|
||||
| "Operations"
|
||||
| "Engineer"
|
||||
| "Business"
|
||||
| "Management"
|
||||
| "Research & Development"
|
||||
| "Training"
|
||||
| "Unassigned";
|
||||
|
||||
/** @public */
|
||||
type IndustryTypeName =
|
||||
| "Energy"
|
||||
| "Water Utilities"
|
||||
| "Agriculture"
|
||||
| "Fishing"
|
||||
| "Mining"
|
||||
| "Food"
|
||||
| "Tobacco"
|
||||
| "Chemical"
|
||||
| "Pharmaceutical"
|
||||
| "Computer Hardware"
|
||||
| "Robotics"
|
||||
| "Software"
|
||||
| "Healthcare"
|
||||
| "RealEstate";
|
||||
|
||||
// BASE ENUMS
|
||||
/** @public */
|
||||
declare enum ToastVariant {
|
||||
SUCCESS = "success",
|
||||
@ -6825,8 +6808,6 @@ declare enum ToastVariant {
|
||||
ERROR = "error",
|
||||
INFO = "info",
|
||||
}
|
||||
/** @public */
|
||||
export type ToastTypes = `${ToastVariant}`;
|
||||
|
||||
/** @public */
|
||||
declare enum CrimeType {
|
||||
@ -6843,13 +6824,107 @@ declare enum CrimeType {
|
||||
ASSASSINATION = "ASSASSINATION",
|
||||
HEIST = "HEIST",
|
||||
}
|
||||
|
||||
/** @public */
|
||||
type CrimeNames = `${CrimeType}`;
|
||||
declare enum FactionWorkType {
|
||||
HACKING = "HACKING",
|
||||
FIELD = "FIELD",
|
||||
SECURITY = "SECURITY",
|
||||
}
|
||||
|
||||
// TODO: split ClassType enum into separate enums for gym and uni so they can actually be used for player input.
|
||||
/** @public */
|
||||
declare enum ClassType {
|
||||
StudyComputerScience = "STUDYCOMPUTERSCIENCE",
|
||||
DataStructures = "DATASTRUCTURES",
|
||||
Networks = "NETWORKS",
|
||||
Algorithms = "ALGORITHMS",
|
||||
Management = "MANAGEMENT",
|
||||
Leadership = "LEADERSHIP",
|
||||
GymStrength = "GYMSTRENGTH",
|
||||
GymDefense = "GYMDEFENSE",
|
||||
GymDexterity = "GYMDEXTERITY",
|
||||
GymAgility = "GYMAGILITY",
|
||||
}
|
||||
|
||||
declare enum CompanyPosNames {
|
||||
sw0 = "Software Engineering Intern",
|
||||
sw1 = "Junior Software Engineer",
|
||||
sw2 = "Senior Software Engineer",
|
||||
sw3 = "Lead Software Developer",
|
||||
sw4 = "Head of Software",
|
||||
sw5 = "Head of Engineering",
|
||||
sw6 = "Vice President of Technology",
|
||||
sw7 = "Chief Technology Officer",
|
||||
IT0 = "IT Intern",
|
||||
IT1 = "IT Analyst",
|
||||
IT2 = "IT Manager",
|
||||
IT3 = "Systems Administrator",
|
||||
secEng = "Security Engineer",
|
||||
netEng0 = "Network Engineer",
|
||||
netEng1 = "Network Administrator",
|
||||
bus0 = "Business Intern",
|
||||
bus1 = "Business Analyst",
|
||||
bus2 = "Business Manager",
|
||||
bus3 = "Operations Manager",
|
||||
bus4 = "Chief Financial Officer",
|
||||
bus5 = "Chief Executive Officer",
|
||||
sec0 = "Police Officer",
|
||||
sec1 = "Police Chief",
|
||||
sec2 = "Security Guard",
|
||||
sec3 = "Security Officer",
|
||||
sec4 = "Security Supervisor",
|
||||
sec5 = "Head of Security",
|
||||
agent0 = "Field Agent",
|
||||
agent1 = "Secret Agent",
|
||||
agent2 = "Special Operative",
|
||||
waiter = "Waiter",
|
||||
employee = "Employee",
|
||||
softCons0 = "Software Consultant",
|
||||
softCons1 = "Senior Software Consultant",
|
||||
busCons0 = "Business Consultant",
|
||||
busCons1 = "Senior Business Consultant",
|
||||
waiterPT = "Part-time Waiter",
|
||||
employeePT = "Part-time Employee",
|
||||
}
|
||||
|
||||
// CORP ENUMS
|
||||
/** @public */
|
||||
declare enum EmployeePositions {
|
||||
Operations = "Operations",
|
||||
Engineer = "Engineer",
|
||||
Business = "Business",
|
||||
Management = "Management",
|
||||
RandD = "Research & Development",
|
||||
Training = "Training",
|
||||
Unassigned = "Unassigned",
|
||||
}
|
||||
|
||||
/** @public */
|
||||
declare enum IndustryType {
|
||||
Energy = "Energy",
|
||||
Utilities = "Water Utilities",
|
||||
Agriculture = "Agriculture",
|
||||
Fishing = "Fishing",
|
||||
Mining = "Mining",
|
||||
Food = "Food",
|
||||
Tobacco = "Tobacco",
|
||||
Chemical = "Chemical",
|
||||
Pharmaceutical = "Pharmaceutical",
|
||||
Computers = "Computer Hardware",
|
||||
Robotics = "Robotics",
|
||||
Software = "Software",
|
||||
Healthcare = "Healthcare",
|
||||
RealEstate = "RealEstate",
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export type NSEnums = {
|
||||
toast: typeof ToastVariant;
|
||||
CrimeType: typeof CrimeType;
|
||||
FactionWorkType: typeof FactionWorkType;
|
||||
ClassType: typeof ClassType;
|
||||
CompanyPosNames: typeof CompanyPosNames;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -6867,7 +6942,11 @@ export interface OfficeAPI {
|
||||
* @param employeePosition - Position to place into. Defaults to "Unassigned".
|
||||
* @returns True if an employee was hired, false otherwise
|
||||
*/
|
||||
hireEmployee(divisionName: string, cityName: string, employeePosition?: EmployeePosName): boolean;
|
||||
hireEmployee(
|
||||
divisionName: string,
|
||||
cityName: string,
|
||||
employeePosition?: EmployeePositions | `${EmployeePositions}`,
|
||||
): boolean;
|
||||
/**
|
||||
* Upgrade office size.
|
||||
* @param divisionName - Name of the division
|
||||
@ -7179,164 +7258,131 @@ export interface WarehouseAPI {
|
||||
* @public
|
||||
*/
|
||||
export interface Corporation extends WarehouseAPI, OfficeAPI {
|
||||
/** Enums specific to the corporation game mechanic. */
|
||||
enums: {
|
||||
EmployeePositions: typeof EmployeePositions;
|
||||
IndustryType: typeof IndustryType;
|
||||
};
|
||||
|
||||
/** Returns whether the player has a corporation. Does not require API access.
|
||||
* @returns whether the player has a corporation */
|
||||
hasCorporation(): boolean;
|
||||
|
||||
/** Create a Corporation
|
||||
* @param divisionName - Name of the division
|
||||
* @param corporationName - Name of the corporation
|
||||
* @param selfFund - If you should self fund, defaults to true, false will only work on Bitnode 3
|
||||
* @returns true if created and false if not */
|
||||
createCorporation(corporationName: string, selfFund: boolean): boolean;
|
||||
/**
|
||||
* Check if you have a one time unlockable upgrade
|
||||
|
||||
/** Check if you have a one time unlockable upgrade
|
||||
* @param upgradeName - Name of the upgrade
|
||||
* @returns true if unlocked and false if not
|
||||
*/
|
||||
* @returns true if unlocked and false if not */
|
||||
hasUnlockUpgrade(upgradeName: string): boolean;
|
||||
/**
|
||||
* Gets the cost to unlock a one time unlockable upgrade
|
||||
|
||||
/** Gets the cost to unlock a one time unlockable upgrade
|
||||
* @param upgradeName - Name of the upgrade
|
||||
* @returns cost of the upgrade
|
||||
*/
|
||||
* @returns cost of the upgrade */
|
||||
getUnlockUpgradeCost(upgradeName: string): number;
|
||||
/**
|
||||
* Get the level of a levelable upgrade
|
||||
|
||||
/** Get the level of a levelable upgrade
|
||||
* @param upgradeName - Name of the upgrade
|
||||
* @returns the level of the upgrade
|
||||
*/
|
||||
* @returns the level of the upgrade */
|
||||
getUpgradeLevel(upgradeName: string): number;
|
||||
/**
|
||||
* Gets the cost to unlock the next level of a levelable upgrade
|
||||
|
||||
/** Gets the cost to unlock the next level of a levelable upgrade
|
||||
* @param upgradeName - Name of the upgrade
|
||||
* @returns cost of the upgrade
|
||||
*/
|
||||
* @returns cost of the upgrade */
|
||||
getUpgradeLevelCost(upgradeName: string): number;
|
||||
/**
|
||||
* Gets the cost to expand into a new industry
|
||||
|
||||
/** Gets the cost to expand into a new industry
|
||||
* @param industryName - Name of the industry
|
||||
* @returns cost
|
||||
*/
|
||||
getExpandIndustryCost(industryName: string): number;
|
||||
/**
|
||||
* Gets the cost to expand into a new city
|
||||
* @returns cost
|
||||
*/
|
||||
* @returns cost */
|
||||
getExpandIndustryCost(industryName: IndustryType | `${IndustryType}`): number;
|
||||
|
||||
/** Gets the cost to expand into a new city
|
||||
* @returns cost */
|
||||
getExpandCityCost(): number;
|
||||
/**
|
||||
* Get an offer for investment based on you companies current valuation
|
||||
* @returns An offer of investment
|
||||
*/
|
||||
|
||||
/** Get an offer for investment based on you companies current valuation
|
||||
* @returns An offer of investment */
|
||||
getInvestmentOffer(): InvestmentOffer;
|
||||
/**
|
||||
* Get list of materials
|
||||
* @returns material names
|
||||
*/
|
||||
|
||||
/** Get list of materials
|
||||
* @returns material names */
|
||||
getMaterialNames(): string[];
|
||||
/**
|
||||
* Get list of industry types
|
||||
* @returns industry names
|
||||
*/
|
||||
getIndustryTypes(): IndustryTypeName[];
|
||||
/**
|
||||
* Get list of industry types
|
||||
* @returns industry names
|
||||
*/
|
||||
getEmployeePositions(): EmployeePosName[];
|
||||
/**
|
||||
* Get list of one-time unlockable upgrades
|
||||
* @returns unlockable upgrades names
|
||||
*/
|
||||
|
||||
/** Get list of one-time unlockable upgrades
|
||||
* @returns unlockable upgrades names */
|
||||
getUnlockables(): string[];
|
||||
/**
|
||||
* Get list of upgrade names
|
||||
* @returns upgrade names
|
||||
*/
|
||||
|
||||
/** Get list of upgrade names
|
||||
* @returns upgrade names */
|
||||
getUpgradeNames(): string[];
|
||||
/**
|
||||
* Get list of research names
|
||||
* @returns research names
|
||||
*/
|
||||
|
||||
/** Get list of research names
|
||||
* @returns research names */
|
||||
getResearchNames(): string[];
|
||||
/**
|
||||
* Accept investment based on you companies current valuation
|
||||
|
||||
/** Accept investment based on you companies current valuation
|
||||
* @remarks
|
||||
* Is based on current valuation and will not honer a specific Offer
|
||||
* @returns An offer of investment
|
||||
*/
|
||||
* @returns An offer of investment */
|
||||
acceptInvestmentOffer(): boolean;
|
||||
/**
|
||||
* Go public
|
||||
|
||||
/** Go public
|
||||
* @param numShares - number of shares you would like to issue for your IPO
|
||||
* @returns true if you successfully go public, false if not
|
||||
*/
|
||||
* @returns true if you successfully go public, false if not */
|
||||
goPublic(numShares: number): boolean;
|
||||
/**
|
||||
* Bribe a faction
|
||||
|
||||
/** Bribe a faction
|
||||
* @param factionName - Faction name
|
||||
* @param amountCash - Amount of money to bribe
|
||||
* @returns True if successful, false if not
|
||||
*/
|
||||
* @returns True if successful, false if not */
|
||||
bribe(factionName: string, amountCash: number): boolean;
|
||||
/**
|
||||
* Get corporation data
|
||||
* @returns Corporation data
|
||||
*/
|
||||
|
||||
/** Get corporation data
|
||||
* @returns Corporation data */
|
||||
getCorporation(): CorporationInfo;
|
||||
/**
|
||||
* Get division data
|
||||
|
||||
/** Get division data
|
||||
* @param divisionName - Name of the division
|
||||
* @returns Division data
|
||||
*/
|
||||
* @returns Division data */
|
||||
getDivision(divisionName: string): Division;
|
||||
/**
|
||||
* Expand to a new industry
|
||||
|
||||
/** Expand to a new industry
|
||||
* @param industryType - Name of the industry
|
||||
* @param divisionName - Name of the division */
|
||||
expandIndustry(industryType: IndustryType | `${IndustryType}`, divisionName: string): void;
|
||||
|
||||
/** Expand to a new city
|
||||
* @param divisionName - Name of the division
|
||||
*/
|
||||
expandIndustry(industryType: string, divisionName: string): void;
|
||||
/**
|
||||
* Expand to a new city
|
||||
* @param divisionName - Name of the division
|
||||
* @param cityName - Name of the city
|
||||
*/
|
||||
* @param cityName - Name of the city */
|
||||
expandCity(divisionName: string, cityName: string): void;
|
||||
/**
|
||||
* Unlock an upgrade
|
||||
* @param upgradeName - Name of the upgrade
|
||||
*/
|
||||
|
||||
/** Unlock an upgrade
|
||||
* @param upgradeName - Name of the upgrade */
|
||||
unlockUpgrade(upgradeName: string): void;
|
||||
/**
|
||||
* Level an upgrade.
|
||||
* @param upgradeName - Name of the upgrade
|
||||
*/
|
||||
|
||||
/** Level an upgrade.
|
||||
* @param upgradeName - Name of the upgrade */
|
||||
levelUpgrade(upgradeName: string): void;
|
||||
/**
|
||||
* Issue dividends
|
||||
* @param rate - Fraction of profit to issue as dividends.
|
||||
*/
|
||||
|
||||
/** Issue dividends
|
||||
* @param rate - Fraction of profit to issue as dividends. */
|
||||
issueDividends(rate: number): void;
|
||||
/**
|
||||
* Buyback Shares
|
||||
* @param amount - Amount of shares to buy back.
|
||||
*
|
||||
*/
|
||||
|
||||
/** Buyback Shares
|
||||
* @param amount - Amount of shares to buy back. */
|
||||
buyBackShares(amount: number): void;
|
||||
/**
|
||||
* Sell Shares
|
||||
* @param amount - Amount of shares to sell.
|
||||
*
|
||||
*/
|
||||
|
||||
/** Sell Shares
|
||||
* @param amount - Amount of shares to sell. */
|
||||
sellShares(amount: number): void;
|
||||
/**
|
||||
* Get bonus time.
|
||||
*
|
||||
|
||||
/** Get bonus time.
|
||||
* “Bonus time” is accumulated when the game is offline or if the game is inactive in the browser.
|
||||
*
|
||||
* “Bonus time” makes the game progress faster.
|
||||
*
|
||||
* @returns Bonus time for the Corporation mechanic in milliseconds.
|
||||
*/
|
||||
* @returns Bonus time for the Corporation mechanic in milliseconds. */
|
||||
getBonusTime(): number;
|
||||
}
|
||||
|
||||
@ -7491,9 +7537,9 @@ export interface Office {
|
||||
/** Average morale of the employees */
|
||||
avgMor: number;
|
||||
/** Production of the employees */
|
||||
employeeProd: Record<EmployeePosName, number>;
|
||||
employeeProd: Record<`${EmployeePositions}`, number>;
|
||||
/** Positions of the employees */
|
||||
employeeJobs: Record<EmployeePosName, number>;
|
||||
employeeJobs: Record<`${EmployeePositions}`, number>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -12,3 +12,44 @@ export enum CrimeType {
|
||||
ASSASSINATION = "ASSASSINATION", //"assassinate a high-profile target",
|
||||
HEIST = "HEIST", //"pull off the ultimate heist",
|
||||
}
|
||||
|
||||
export enum CompanyPosNames {
|
||||
sw0 = "Software Engineering Intern",
|
||||
sw1 = "Junior Software Engineer",
|
||||
sw2 = "Senior Software Engineer",
|
||||
sw3 = "Lead Software Developer",
|
||||
sw4 = "Head of Software",
|
||||
sw5 = "Head of Engineering",
|
||||
sw6 = "Vice President of Technology",
|
||||
sw7 = "Chief Technology Officer",
|
||||
IT0 = "IT Intern",
|
||||
IT1 = "IT Analyst",
|
||||
IT2 = "IT Manager",
|
||||
IT3 = "Systems Administrator",
|
||||
secEng = "Security Engineer",
|
||||
netEng0 = "Network Engineer",
|
||||
netEng1 = "Network Administrator",
|
||||
bus0 = "Business Intern",
|
||||
bus1 = "Business Analyst",
|
||||
bus2 = "Business Manager",
|
||||
bus3 = "Operations Manager",
|
||||
bus4 = "Chief Financial Officer",
|
||||
bus5 = "Chief Executive Officer",
|
||||
sec0 = "Police Officer",
|
||||
sec1 = "Police Chief",
|
||||
sec2 = "Security Guard",
|
||||
sec3 = "Security Officer",
|
||||
sec4 = "Security Supervisor",
|
||||
sec5 = "Head of Security",
|
||||
agent0 = "Field Agent",
|
||||
agent1 = "Secret Agent",
|
||||
agent2 = "Special Operative",
|
||||
waiter = "Waiter",
|
||||
employee = "Employee",
|
||||
softCons0 = "Software Consultant",
|
||||
softCons1 = "Senior Software Consultant",
|
||||
busCons0 = "Business Consultant",
|
||||
busCons1 = "Senior Business Consultant",
|
||||
waiterPT = "Part-time Waiter",
|
||||
employeePT = "Part-time Employee",
|
||||
}
|
||||
|
@ -120,6 +120,8 @@ describe("Netscript RAM Calculation/Generation Tests", function () {
|
||||
const expectedRam = grabCost(ramLayer, newPath);
|
||||
it(`${fnName}()`, () => combinedRamCheck(val, newPath, expectedRam, extraLayerCost));
|
||||
}
|
||||
//Skip enums layers
|
||||
else if (key === "enums") return;
|
||||
//A layer should be the only other option.
|
||||
else testLayer(val, ramLayer[key] as RamLayer, newPath, 0);
|
||||
});
|
||||
@ -141,7 +143,12 @@ describe("Netscript RAM Calculation/Generation Tests", function () {
|
||||
it(`SF4.${lvl} check for x${lvlToMult[lvl]} costs`, () => {
|
||||
sf4.lvl = lvl;
|
||||
singObjects.forEach((obj) =>
|
||||
combinedRamCheck(obj.fn, ["singularity", obj.name], obj.baseRam * lvlToMult[lvl], 0),
|
||||
combinedRamCheck(
|
||||
obj.fn as PotentiallyAsyncFunction,
|
||||
["singularity", obj.name],
|
||||
obj.baseRam * lvlToMult[lvl],
|
||||
0,
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user