mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-27 16:37:33 +01:00
Wrap most of the API
This commit is contained in:
parent
b46718d188
commit
c6806caca2
@ -82,6 +82,7 @@ import {
|
||||
Gang as IGang,
|
||||
Bladeburner as IBladeburner,
|
||||
Stanek as IStanek,
|
||||
Sleeve as ISleeve,
|
||||
Infiltration as IInfiltration,
|
||||
RunningScript as IRunningScript,
|
||||
RecentScript as IRecentScript,
|
||||
@ -93,6 +94,12 @@ import {
|
||||
BitNodeMultipliers as IBNMults,
|
||||
Server as IServerDef,
|
||||
RunningScript as IRunningScriptDef,
|
||||
Grafting as IGrafting,
|
||||
UserInterface as IUserInterface,
|
||||
TIX as ITIX,
|
||||
Corporation as ICorporation,
|
||||
CodingContract as ICodingContract,
|
||||
Hacknet as IHacknet,
|
||||
// ToastVariant,
|
||||
} from "./ScriptEditor/NetscriptDefinitions";
|
||||
import { NetscriptSingularity } from "./NetscriptFunctions/Singularity";
|
||||
@ -360,7 +367,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
}
|
||||
};
|
||||
|
||||
const hack = function (
|
||||
const hack = async function (
|
||||
hostname: string,
|
||||
manual: boolean,
|
||||
{ threads: requestedThreads, stock }: any = {},
|
||||
@ -524,23 +531,35 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
||||
},
|
||||
};
|
||||
|
||||
const gang = NetscriptGang(Player, workerScript, helper);
|
||||
const sleeve = NetscriptSleeve(Player, workerScript, helper);
|
||||
const extra = NetscriptExtra(Player, workerScript, helper);
|
||||
const hacknet = NetscriptHacknet(Player, workerScript, helper);
|
||||
const formulas = NetscriptFormulas(Player, workerScript, helper);
|
||||
|
||||
const gang = wrapAPI(helper, {}, workerScript, NetscriptGang(Player, workerScript), "gang").gang as unknown as IGang;
|
||||
const sleeve = wrapAPI(helper, {}, workerScript, NetscriptSleeve(Player), "sleeve").sleeve as unknown as ISleeve;
|
||||
const hacknet = wrapAPI(helper, {}, workerScript, NetscriptHacknet(Player, workerScript), "hacknet")
|
||||
.hacknet as unknown as IHacknet;
|
||||
const bladeburner = wrapAPI(helper, {}, workerScript, NetscriptBladeburner(Player, workerScript), "bladeburner")
|
||||
.bladeburner as unknown as IBladeburner;
|
||||
const codingcontract = wrapAPI(
|
||||
helper,
|
||||
{},
|
||||
workerScript,
|
||||
NetscriptCodingContract(Player, workerScript),
|
||||
"codingcontract",
|
||||
).codingcontract as unknown as ICodingContract;
|
||||
const infiltration = wrapAPI(helper, {}, workerScript, NetscriptInfiltration(Player), "infiltration")
|
||||
.infiltration as unknown as IInfiltration;
|
||||
const stanek = wrapAPI(helper, {}, workerScript, NetscriptStanek(Player, workerScript, helper), "stanek")
|
||||
.stanek as unknown as IStanek;
|
||||
const bladeburner = NetscriptBladeburner(Player, workerScript, helper);
|
||||
const codingcontract = NetscriptCodingContract(Player, workerScript, helper);
|
||||
const corporation = NetscriptCorporation(Player, workerScript, helper);
|
||||
const formulas = NetscriptFormulas(Player, workerScript, helper);
|
||||
const corporation = wrapAPI(helper, {}, workerScript, NetscriptCorporation(Player, workerScript), "corporation")
|
||||
.corporation as unknown as ICorporation;
|
||||
const singularity = wrapAPI(helper, {}, workerScript, NetscriptSingularity(Player, workerScript), "singularity")
|
||||
.singularity as unknown as ISingularity;
|
||||
const stockmarket = NetscriptStockMarket(Player, workerScript, helper);
|
||||
const ui = NetscriptUserInterface(Player, workerScript, helper);
|
||||
const grafting = NetscriptGrafting(Player, workerScript, helper);
|
||||
const stockmarket = wrapAPI(helper, {}, workerScript, NetscriptStockMarket(Player, workerScript), "stock")
|
||||
.stock as unknown as ITIX;
|
||||
const ui = wrapAPI(helper, {}, workerScript, NetscriptUserInterface(), "ui").ui as unknown as IUserInterface;
|
||||
const grafting = wrapAPI(helper, {}, workerScript, NetscriptGrafting(Player), "grafting")
|
||||
.grafting as unknown as IGrafting;
|
||||
|
||||
const base: INS = {
|
||||
...singularity,
|
||||
|
@ -1,18 +1,13 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Bladeburner } from "../Bladeburner/Bladeburner";
|
||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import { Bladeburner as INetscriptBladeburner, BladeburnerCurAction } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { IAction } from "src/Bladeburner/IAction";
|
||||
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
||||
|
||||
export function NetscriptBladeburner(
|
||||
player: IPlayer,
|
||||
workerScript: WorkerScript,
|
||||
helper: INetscriptHelper,
|
||||
): INetscriptBladeburner {
|
||||
const checkBladeburnerAccess = function (func: string, skipjoined = false): void {
|
||||
export function NetscriptBladeburner(player: IPlayer, workerScript: WorkerScript): InternalAPI<INetscriptBladeburner> {
|
||||
const checkBladeburnerAccess = function (ctx: NetscriptContext, skipjoined = false): void {
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
||||
const apiAccess =
|
||||
@ -22,353 +17,354 @@ export function NetscriptBladeburner(
|
||||
});
|
||||
if (!apiAccess) {
|
||||
const apiDenied = `You do not currently have access to the Bladeburner API. You must either be in BitNode-7 or have Source-File 7.`;
|
||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, apiDenied);
|
||||
throw ctx.makeRuntimeErrorMsg(apiDenied);
|
||||
}
|
||||
if (!skipjoined) {
|
||||
const bladeburnerAccess = bladeburner instanceof Bladeburner;
|
||||
if (!bladeburnerAccess) {
|
||||
const bladeburnerDenied = `You must be a member of the Bladeburner division to use this API.`;
|
||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, bladeburnerDenied);
|
||||
throw ctx.makeRuntimeErrorMsg(bladeburnerDenied);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const checkBladeburnerCity = function (func: string, city: string): void {
|
||||
const checkBladeburnerCity = function (ctx: NetscriptContext, city: string): void {
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
||||
if (!bladeburner.cities.hasOwnProperty(city)) {
|
||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, `Invalid city: ${city}`);
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid city: ${city}`);
|
||||
}
|
||||
};
|
||||
|
||||
const getBladeburnerActionObject = function (func: string, type: string, name: string): IAction {
|
||||
const getBladeburnerActionObject = function (ctx: NetscriptContext, type: string, name: string): IAction {
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Must have joined bladeburner");
|
||||
const actionId = bladeburner.getActionIdFromTypeAndName(type, name);
|
||||
if (!actionId) {
|
||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, `Invalid action type='${type}', name='${name}'`);
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid action type='${type}', name='${name}'`);
|
||||
}
|
||||
const actionObj = bladeburner.getActionObject(actionId);
|
||||
if (!actionObj) {
|
||||
throw helper.makeRuntimeErrorMsg(`bladeburner.${func}`, `Invalid action type='${type}', name='${name}'`);
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid action type='${type}', name='${name}'`);
|
||||
}
|
||||
|
||||
return actionObj;
|
||||
};
|
||||
|
||||
const updateRam = (funcName: string): void =>
|
||||
helper.updateDynamicRam(funcName, getRamCost(player, "bladeburner", funcName));
|
||||
|
||||
return {
|
||||
getContractNames: function (): string[] {
|
||||
updateRam("getContractNames");
|
||||
checkBladeburnerAccess("getContractNames");
|
||||
getContractNames: (ctx: NetscriptContext) => (): string[] => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getContractNamesNetscriptFn();
|
||||
},
|
||||
getOperationNames: function (): string[] {
|
||||
updateRam("getOperationNames");
|
||||
checkBladeburnerAccess("getOperationNames");
|
||||
getOperationNames: (ctx: NetscriptContext) => (): string[] => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getOperationNamesNetscriptFn();
|
||||
},
|
||||
getBlackOpNames: function (): string[] {
|
||||
updateRam("getBlackOpNames");
|
||||
checkBladeburnerAccess("getBlackOpNames");
|
||||
getBlackOpNames: (ctx: NetscriptContext) => (): string[] => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getBlackOpNamesNetscriptFn();
|
||||
},
|
||||
getBlackOpRank: function (_blackOpName: unknown): number {
|
||||
updateRam("getBlackOpRank");
|
||||
const blackOpName = helper.string("getBlackOpRank", "blackOpName", _blackOpName);
|
||||
checkBladeburnerAccess("getBlackOpRank");
|
||||
const action: any = getBladeburnerActionObject("getBlackOpRank", "blackops", blackOpName);
|
||||
return action.reqdRank;
|
||||
},
|
||||
getGeneralActionNames: function (): string[] {
|
||||
updateRam("getGeneralActionNames");
|
||||
checkBladeburnerAccess("getGeneralActionNames");
|
||||
getBlackOpRank:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_blackOpName: unknown): number => {
|
||||
const blackOpName = ctx.helper.string("blackOpName", _blackOpName);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const action: any = getBladeburnerActionObject(ctx, "blackops", blackOpName);
|
||||
return action.reqdRank;
|
||||
},
|
||||
getGeneralActionNames: (ctx: NetscriptContext) => (): string[] => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getGeneralActionNamesNetscriptFn();
|
||||
},
|
||||
getSkillNames: function (): string[] {
|
||||
updateRam("getSkillNames");
|
||||
checkBladeburnerAccess("getSkillNames");
|
||||
getSkillNames: (ctx: NetscriptContext) => (): string[] => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getSkillNamesNetscriptFn();
|
||||
},
|
||||
startAction: function (_type: unknown, _name: unknown): boolean {
|
||||
updateRam("startAction");
|
||||
const type = helper.string("startAction", "type", _type);
|
||||
const name = helper.string("startAction", "name", _name);
|
||||
checkBladeburnerAccess("startAction");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.startActionNetscriptFn(player, type, name, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.startAction", e);
|
||||
}
|
||||
},
|
||||
stopBladeburnerAction: function (): void {
|
||||
updateRam("stopBladeburnerAction");
|
||||
checkBladeburnerAccess("stopBladeburnerAction");
|
||||
startAction:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown): boolean => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.startActionNetscriptFn(player, type, name, workerScript);
|
||||
} catch (e: any) {
|
||||
throw ctx.makeRuntimeErrorMsg(e);
|
||||
}
|
||||
},
|
||||
stopBladeburnerAction: (ctx: NetscriptContext) => (): void => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.resetAction();
|
||||
},
|
||||
getCurrentAction: function (): BladeburnerCurAction {
|
||||
updateRam("getCurrentAction");
|
||||
checkBladeburnerAccess("getCurrentAction");
|
||||
getCurrentAction: (ctx: NetscriptContext) => (): BladeburnerCurAction => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.getTypeAndNameFromActionId(bladeburner.action);
|
||||
},
|
||||
getActionTime: function (_type: unknown, _name: unknown): number {
|
||||
updateRam("getActionTime");
|
||||
const type = helper.string("getActionTime", "type", _type);
|
||||
const name = helper.string("getActionTime", "name", _name);
|
||||
checkBladeburnerAccess("getActionTime");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getActionTimeNetscriptFn(player, type, name, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.getActionTime", e);
|
||||
}
|
||||
},
|
||||
getActionEstimatedSuccessChance: function (_type: unknown, _name: unknown): [number, number] {
|
||||
updateRam("getActionEstimatedSuccessChance");
|
||||
const type = helper.string("getActionEstimatedSuccessChance", "type", _type);
|
||||
const name = helper.string("getActionEstimatedSuccessChance", "name", _name);
|
||||
checkBladeburnerAccess("getActionEstimatedSuccessChance");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getActionEstimatedSuccessChanceNetscriptFn(player, type, name, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.getActionEstimatedSuccessChance", e);
|
||||
}
|
||||
},
|
||||
getActionRepGain: function (_type: unknown, _name: unknown, _level: unknown): number {
|
||||
updateRam("getActionRepGain");
|
||||
const type = helper.string("getActionRepGain", "type", _type);
|
||||
const name = helper.string("getActionRepGain", "name", _name);
|
||||
const level = helper.number("getActionRepGain", "level", _level);
|
||||
checkBladeburnerAccess("getActionRepGain");
|
||||
const action = getBladeburnerActionObject("getActionRepGain", 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);
|
||||
}
|
||||
getActionTime:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown): number => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getActionTimeNetscriptFn(player, type, name, workerScript);
|
||||
} catch (e: any) {
|
||||
throw ctx.makeRuntimeErrorMsg(e);
|
||||
}
|
||||
},
|
||||
getActionEstimatedSuccessChance:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown): [number, number] => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getActionEstimatedSuccessChanceNetscriptFn(player, type, name, workerScript);
|
||||
} catch (e: any) {
|
||||
throw ctx.makeRuntimeErrorMsg(e);
|
||||
}
|
||||
},
|
||||
getActionRepGain:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown, _level: unknown): number => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
const level = ctx.helper.number("level", _level);
|
||||
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: function (_type: unknown, _name: unknown): number {
|
||||
updateRam("getActionCountRemaining");
|
||||
const type = helper.string("getActionCountRemaining", "type", _type);
|
||||
const name = helper.string("getActionCountRemaining", "name", _name);
|
||||
checkBladeburnerAccess("getActionCountRemaining");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getActionCountRemainingNetscriptFn(type, name, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.getActionCountRemaining", e);
|
||||
}
|
||||
},
|
||||
getActionMaxLevel: function (_type: unknown, _name: unknown): number {
|
||||
updateRam("getActionMaxLevel");
|
||||
const type = helper.string("getActionMaxLevel", "type", _type);
|
||||
const name = helper.string("getActionMaxLevel", "name", _name);
|
||||
checkBladeburnerAccess("getActionMaxLevel");
|
||||
const action = getBladeburnerActionObject("getActionMaxLevel", type, name);
|
||||
return action.maxLevel;
|
||||
},
|
||||
getActionCurrentLevel: function (_type: unknown, _name: unknown): number {
|
||||
updateRam("getActionCurrentLevel");
|
||||
const type = helper.string("getActionCurrentLevel", "type", _type);
|
||||
const name = helper.string("getActionCurrentLevel", "name", _name);
|
||||
checkBladeburnerAccess("getActionCurrentLevel");
|
||||
const action = getBladeburnerActionObject("getActionCurrentLevel", type, name);
|
||||
return action.level;
|
||||
},
|
||||
getActionAutolevel: function (_type: unknown, _name: unknown): boolean {
|
||||
updateRam("getActionAutolevel");
|
||||
const type = helper.string("getActionAutolevel", "type", _type);
|
||||
const name = helper.string("getActionAutolevel", "name", _name);
|
||||
checkBladeburnerAccess("getActionAutolevel");
|
||||
const action = getBladeburnerActionObject("getActionCurrentLevel", type, name);
|
||||
return action.autoLevel;
|
||||
},
|
||||
setActionAutolevel: function (_type: unknown, _name: unknown, _autoLevel: unknown = true): void {
|
||||
updateRam("setActionAutolevel");
|
||||
const type = helper.string("setActionAutolevel", "type", _type);
|
||||
const name = helper.string("setActionAutolevel", "name", _name);
|
||||
const autoLevel = helper.boolean(_autoLevel);
|
||||
checkBladeburnerAccess("setActionAutolevel");
|
||||
const action = getBladeburnerActionObject("setActionAutolevel", type, name);
|
||||
action.autoLevel = autoLevel;
|
||||
},
|
||||
setActionLevel: function (_type: unknown, _name: unknown, _level: unknown = 1): void {
|
||||
updateRam("setActionLevel");
|
||||
const type = helper.string("setActionLevel", "type", _type);
|
||||
const name = helper.string("setActionLevel", "name", _name);
|
||||
const level = helper.number("setActionLevel", "level", _level);
|
||||
checkBladeburnerAccess("setActionLevel");
|
||||
const action = getBladeburnerActionObject("setActionLevel", type, name);
|
||||
if (level < 1 || level > action.maxLevel) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"bladeburner.setActionLevel",
|
||||
`Level must be between 1 and ${action.maxLevel}, is ${level}`,
|
||||
);
|
||||
}
|
||||
action.level = level;
|
||||
},
|
||||
getRank: function (): number {
|
||||
updateRam("getRank");
|
||||
checkBladeburnerAccess("getRank");
|
||||
return action.rankGain * rewardMultiplier * BitNodeMultipliers.BladeburnerRank;
|
||||
},
|
||||
getActionCountRemaining:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown): number => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getActionCountRemainingNetscriptFn(type, name, workerScript);
|
||||
} catch (e: any) {
|
||||
throw ctx.makeRuntimeErrorMsg(e);
|
||||
}
|
||||
},
|
||||
getActionMaxLevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown): number => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const action = getBladeburnerActionObject(ctx, type, name);
|
||||
return action.maxLevel;
|
||||
},
|
||||
getActionCurrentLevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown): number => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const action = getBladeburnerActionObject(ctx, type, name);
|
||||
return action.level;
|
||||
},
|
||||
getActionAutolevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown): boolean => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const action = getBladeburnerActionObject(ctx, type, name);
|
||||
return action.autoLevel;
|
||||
},
|
||||
setActionAutolevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown, _autoLevel: unknown = true): void => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
const autoLevel = ctx.helper.boolean(_autoLevel);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const action = getBladeburnerActionObject(ctx, type, name);
|
||||
action.autoLevel = autoLevel;
|
||||
},
|
||||
setActionLevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown, _level: unknown = 1): void => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
const level = ctx.helper.number("level", _level);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const action = getBladeburnerActionObject(ctx, type, name);
|
||||
if (level < 1 || level > action.maxLevel) {
|
||||
ctx.helper.makeRuntimeErrorMsg(`Level must be between 1 and ${action.maxLevel}, is ${level}`);
|
||||
}
|
||||
action.level = level;
|
||||
},
|
||||
getRank: (ctx: NetscriptContext) => (): number => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.rank;
|
||||
},
|
||||
getSkillPoints: function (): number {
|
||||
updateRam("getSkillPoints");
|
||||
checkBladeburnerAccess("getSkillPoints");
|
||||
getSkillPoints: (ctx: NetscriptContext) => (): number => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.skillPoints;
|
||||
},
|
||||
getSkillLevel: function (_skillName: unknown): number {
|
||||
updateRam("getSkillLevel");
|
||||
const skillName = helper.string("getSkillLevel", "skillName", _skillName);
|
||||
checkBladeburnerAccess("getSkillLevel");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getSkillLevelNetscriptFn(skillName, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.getSkillLevel", e);
|
||||
}
|
||||
},
|
||||
getSkillUpgradeCost: function (_skillName: unknown): number {
|
||||
updateRam("getSkillUpgradeCost");
|
||||
const skillName = helper.string("getSkillUpgradeCost", "skillName", _skillName);
|
||||
checkBladeburnerAccess("getSkillUpgradeCost");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getSkillUpgradeCostNetscriptFn(skillName, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.getSkillUpgradeCost", e);
|
||||
}
|
||||
},
|
||||
upgradeSkill: function (_skillName: unknown): boolean {
|
||||
updateRam("upgradeSkill");
|
||||
const skillName = helper.string("upgradeSkill", "skillName", _skillName);
|
||||
checkBladeburnerAccess("upgradeSkill");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.upgradeSkillNetscriptFn(skillName, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.upgradeSkill", e);
|
||||
}
|
||||
},
|
||||
getTeamSize: function (_type: unknown, _name: unknown): number {
|
||||
updateRam("getTeamSize");
|
||||
const type = helper.string("getTeamSize", "type", _type);
|
||||
const name = helper.string("getTeamSize", "name", _name);
|
||||
checkBladeburnerAccess("getTeamSize");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getTeamSizeNetscriptFn(type, name, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.getTeamSize", e);
|
||||
}
|
||||
},
|
||||
setTeamSize: function (_type: unknown, _name: unknown, _size: unknown): number {
|
||||
updateRam("setTeamSize");
|
||||
const type = helper.string("setTeamSize", "type", _type);
|
||||
const name = helper.string("setTeamSize", "name", _name);
|
||||
const size = helper.number("setTeamSize", "size", _size);
|
||||
checkBladeburnerAccess("setTeamSize");
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.setTeamSizeNetscriptFn(type, name, size, workerScript);
|
||||
} catch (e: any) {
|
||||
throw helper.makeRuntimeErrorMsg("bladeburner.setTeamSize", e);
|
||||
}
|
||||
},
|
||||
getCityEstimatedPopulation: function (_cityName: unknown): number {
|
||||
updateRam("getCityEstimatedPopulation");
|
||||
const cityName = helper.string("getCityEstimatedPopulation", "cityName", _cityName);
|
||||
checkBladeburnerAccess("getCityEstimatedPopulation");
|
||||
checkBladeburnerCity("getCityEstimatedPopulation", cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.cities[cityName].popEst;
|
||||
},
|
||||
getCityCommunities: function (_cityName: unknown): number {
|
||||
updateRam("getCityCommunities");
|
||||
const cityName = helper.string("getCityCommunities", "cityName", _cityName);
|
||||
checkBladeburnerAccess("getCityCommunities");
|
||||
checkBladeburnerCity("getCityCommunities", cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.cities[cityName].comms;
|
||||
},
|
||||
getCityChaos: function (_cityName: unknown): number {
|
||||
updateRam("getCityChaos");
|
||||
const cityName = helper.string("getCityChaos", "cityName", _cityName);
|
||||
checkBladeburnerAccess("getCityChaos");
|
||||
checkBladeburnerCity("getCityChaos", cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.cities[cityName].chaos;
|
||||
},
|
||||
getCity: function (): string {
|
||||
updateRam("getCity");
|
||||
checkBladeburnerAccess("getCityChaos");
|
||||
getSkillLevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_skillName: unknown): number => {
|
||||
const skillName = ctx.helper.string("skillName", _skillName);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getSkillLevelNetscriptFn(skillName, workerScript);
|
||||
} catch (e: any) {
|
||||
throw ctx.makeRuntimeErrorMsg(e);
|
||||
}
|
||||
},
|
||||
getSkillUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_skillName: unknown): number => {
|
||||
const skillName = ctx.helper.string("skillName", _skillName);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getSkillUpgradeCostNetscriptFn(skillName, workerScript);
|
||||
} catch (e: any) {
|
||||
throw ctx.makeRuntimeErrorMsg(e);
|
||||
}
|
||||
},
|
||||
upgradeSkill:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_skillName: unknown): boolean => {
|
||||
const skillName = ctx.helper.string("skillName", _skillName);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.upgradeSkillNetscriptFn(skillName, workerScript);
|
||||
} catch (e: any) {
|
||||
throw ctx.makeRuntimeErrorMsg(e);
|
||||
}
|
||||
},
|
||||
getTeamSize:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown): number => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.getTeamSizeNetscriptFn(type, name, workerScript);
|
||||
} catch (e: any) {
|
||||
throw ctx.makeRuntimeErrorMsg(e);
|
||||
}
|
||||
},
|
||||
setTeamSize:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_type: unknown, _name: unknown, _size: unknown): number => {
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const name = ctx.helper.string("name", _name);
|
||||
const size = ctx.helper.number("size", _size);
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
try {
|
||||
return bladeburner.setTeamSizeNetscriptFn(type, name, size, workerScript);
|
||||
} catch (e: any) {
|
||||
throw ctx.makeRuntimeErrorMsg(e);
|
||||
}
|
||||
},
|
||||
getCityEstimatedPopulation:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_cityName: unknown): number => {
|
||||
const cityName = ctx.helper.string("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 = ctx.helper.string("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 = ctx.helper.string("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 => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.city;
|
||||
},
|
||||
switchCity: function (_cityName: unknown): boolean {
|
||||
updateRam("switchCity");
|
||||
const cityName = helper.string("switchCity", "cityName", _cityName);
|
||||
checkBladeburnerAccess("switchCity");
|
||||
checkBladeburnerCity("switchCity", cityName);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
bladeburner.city = cityName;
|
||||
return true;
|
||||
},
|
||||
getStamina: function (): [number, number] {
|
||||
updateRam("getStamina");
|
||||
checkBladeburnerAccess("getStamina");
|
||||
switchCity:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_cityName: unknown): boolean => {
|
||||
const cityName = ctx.helper.string("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] => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return [bladeburner.stamina, bladeburner.maxStamina];
|
||||
},
|
||||
joinBladeburnerFaction: function (): boolean {
|
||||
updateRam("joinBladeburnerFaction");
|
||||
checkBladeburnerAccess("joinBladeburnerFaction", true);
|
||||
joinBladeburnerFaction: (ctx: NetscriptContext) => (): boolean => {
|
||||
checkBladeburnerAccess(ctx, true);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return bladeburner.joinBladeburnerFactionNetscriptFn(workerScript);
|
||||
},
|
||||
joinBladeburnerDivision: function (): boolean {
|
||||
updateRam("joinBladeburnerDivision");
|
||||
joinBladeburnerDivision: (ctx: NetscriptContext) => (): boolean => {
|
||||
if (player.bitNodeN === 7 || player.sourceFileLvl(7) > 0) {
|
||||
if (player.bitNodeN === 8) {
|
||||
return false;
|
||||
@ -382,22 +378,18 @@ export function NetscriptBladeburner(
|
||||
player.agility >= 100
|
||||
) {
|
||||
player.bladeburner = new Bladeburner(player);
|
||||
workerScript.log("joinBladeburnerDivision", () => "You have been accepted into the Bladeburner division");
|
||||
ctx.log(() => "You have been accepted into the Bladeburner division");
|
||||
|
||||
return true;
|
||||
} else {
|
||||
workerScript.log(
|
||||
"joinBladeburnerDivision",
|
||||
() => "You do not meet the requirements for joining the Bladeburner division",
|
||||
);
|
||||
ctx.log(() => "You do not meet the requirements for joining the Bladeburner division");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
getBonusTime: function (): number {
|
||||
updateRam("getBonusTime");
|
||||
checkBladeburnerAccess("getBonusTime");
|
||||
getBonusTime: (ctx: NetscriptContext) => (): number => {
|
||||
checkBladeburnerAccess(ctx);
|
||||
const bladeburner = player.bladeburner;
|
||||
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
|
||||
return Math.round(bladeburner.storedCycles / 5) * 1000;
|
||||
|
@ -1,132 +1,124 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||
import { is2DArray } from "../utils/helpers/is2DArray";
|
||||
import { CodingContract } from "../CodingContracts";
|
||||
import { CodingAttemptOptions, CodingContract as ICodingContract } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
||||
|
||||
export function NetscriptCodingContract(
|
||||
player: IPlayer,
|
||||
workerScript: WorkerScript,
|
||||
helper: INetscriptHelper,
|
||||
): ICodingContract {
|
||||
const getCodingContract = function (func: string, hostname: string, filename: string): CodingContract {
|
||||
const server = helper.getServer(hostname, func);
|
||||
export function NetscriptCodingContract(player: IPlayer, workerScript: WorkerScript): InternalAPI<ICodingContract> {
|
||||
const getCodingContract = function (
|
||||
ctx: NetscriptContext,
|
||||
func: string,
|
||||
hostname: string,
|
||||
filename: string,
|
||||
): CodingContract {
|
||||
const server = ctx.helper.getServer(hostname);
|
||||
const contract = server.getContract(filename);
|
||||
if (contract == null) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
`codingcontract.${func}`,
|
||||
`Cannot find contract '${filename}' on server '${hostname}'`,
|
||||
);
|
||||
throw ctx.makeRuntimeErrorMsg(`Cannot find contract '${filename}' on server '${hostname}'`);
|
||||
}
|
||||
|
||||
return contract;
|
||||
};
|
||||
|
||||
const updateRam = (funcName: string): void =>
|
||||
helper.updateDynamicRam(funcName, getRamCost(player, "codingcontract", funcName));
|
||||
|
||||
return {
|
||||
attempt: function (
|
||||
answer: any,
|
||||
_filename: unknown,
|
||||
_hostname: unknown = workerScript.hostname,
|
||||
{ returnReward }: CodingAttemptOptions = { returnReward: false },
|
||||
): boolean | string {
|
||||
updateRam("attempt");
|
||||
const filename = helper.string("attempt", "filename", _filename);
|
||||
const hostname = helper.string("attempt", "hostname", _hostname);
|
||||
const contract = getCodingContract("attempt", hostname, filename);
|
||||
attempt:
|
||||
(ctx: NetscriptContext) =>
|
||||
(
|
||||
answer: any,
|
||||
_filename: unknown,
|
||||
_hostname: unknown = workerScript.hostname,
|
||||
{ returnReward }: CodingAttemptOptions = { returnReward: false },
|
||||
): boolean | string => {
|
||||
const filename = ctx.helper.string("filename", _filename);
|
||||
const hostname = ctx.helper.string("hostname", _hostname);
|
||||
const contract = getCodingContract(ctx, "attempt", hostname, filename);
|
||||
|
||||
// Convert answer to string. If the answer is a 2D array, then we have to
|
||||
// manually add brackets for the inner arrays
|
||||
if (is2DArray(answer)) {
|
||||
const answerComponents = [];
|
||||
for (let i = 0; i < answer.length; ++i) {
|
||||
answerComponents.push(["[", answer[i].toString(), "]"].join(""));
|
||||
}
|
||||
|
||||
answer = answerComponents.join(",");
|
||||
} else {
|
||||
answer = String(answer);
|
||||
}
|
||||
|
||||
const creward = contract.reward;
|
||||
if (creward === null) throw new Error("Somehow solved a contract that didn't have a reward");
|
||||
|
||||
const serv = helper.getServer(hostname, "codingcontract.attempt");
|
||||
if (contract.isSolution(answer)) {
|
||||
const reward = player.gainCodingContractReward(creward, contract.getDifficulty());
|
||||
workerScript.log(
|
||||
"codingcontract.attempt",
|
||||
() => `Successfully completed Coding Contract '${filename}'. Reward: ${reward}`,
|
||||
);
|
||||
serv.removeContract(filename);
|
||||
return returnReward ? reward : true;
|
||||
} else {
|
||||
++contract.tries;
|
||||
if (contract.tries >= contract.getMaxNumTries()) {
|
||||
workerScript.log(
|
||||
"codingcontract.attempt",
|
||||
() => `Coding Contract attempt '${filename}' failed. Contract is now self-destructing`,
|
||||
);
|
||||
serv.removeContract(filename);
|
||||
} else {
|
||||
workerScript.log(
|
||||
"codingcontract.attempt",
|
||||
() =>
|
||||
`Coding Contract attempt '${filename}' failed. ${
|
||||
contract.getMaxNumTries() - contract.tries
|
||||
} attempts remaining.`,
|
||||
);
|
||||
}
|
||||
|
||||
return returnReward ? "" : false;
|
||||
}
|
||||
},
|
||||
getContractType: function (_filename: unknown, _hostname: unknown = workerScript.hostname): string {
|
||||
updateRam("getContractType");
|
||||
const filename = helper.string("getContractType", "filename", _filename);
|
||||
const hostname = helper.string("getContractType", "hostname", _hostname);
|
||||
const contract = getCodingContract("getContractType", hostname, filename);
|
||||
return contract.getType();
|
||||
},
|
||||
getData: function (_filename: unknown, _hostname: unknown = workerScript.hostname): any {
|
||||
updateRam("getData");
|
||||
const filename = helper.string("getContractType", "filename", _filename);
|
||||
const hostname = helper.string("getContractType", "hostname", _hostname);
|
||||
const contract = getCodingContract("getData", hostname, filename);
|
||||
const data = contract.getData();
|
||||
if (data.constructor === Array) {
|
||||
// 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();
|
||||
// Convert answer to string. If the answer is a 2D array, then we have to
|
||||
// manually add brackets for the inner arrays
|
||||
if (is2DArray(answer)) {
|
||||
const answerComponents = [];
|
||||
for (let i = 0; i < answer.length; ++i) {
|
||||
answerComponents.push(["[", answer[i].toString(), "]"].join(""));
|
||||
}
|
||||
|
||||
answer = answerComponents.join(",");
|
||||
} else {
|
||||
answer = String(answer);
|
||||
}
|
||||
|
||||
return copy;
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
},
|
||||
getDescription: function (_filename: unknown, _hostname: unknown = workerScript.hostname): string {
|
||||
updateRam("getDescription");
|
||||
const filename = helper.string("getDescription", "filename", _filename);
|
||||
const hostname = helper.string("getDescription", "hostname", _hostname);
|
||||
const contract = getCodingContract("getDescription", hostname, filename);
|
||||
return contract.getDescription();
|
||||
},
|
||||
getNumTriesRemaining: function (_filename: unknown, _hostname: unknown = workerScript.hostname): number {
|
||||
updateRam("getNumTriesRemaining");
|
||||
const filename = helper.string("getNumTriesRemaining", "filename", _filename);
|
||||
const hostname = helper.string("getNumTriesRemaining", "hostname", _hostname);
|
||||
const contract = getCodingContract("getNumTriesRemaining", hostname, filename);
|
||||
return contract.getMaxNumTries() - contract.tries;
|
||||
},
|
||||
const creward = contract.reward;
|
||||
if (creward === null) throw new Error("Somehow solved a contract that didn't have a reward");
|
||||
|
||||
const serv = ctx.helper.getServer(hostname);
|
||||
if (contract.isSolution(answer)) {
|
||||
const reward = player.gainCodingContractReward(creward, contract.getDifficulty());
|
||||
ctx.log(() => `Successfully completed Coding Contract '${filename}'. Reward: ${reward}`);
|
||||
serv.removeContract(filename);
|
||||
return returnReward ? reward : true;
|
||||
} else {
|
||||
++contract.tries;
|
||||
if (contract.tries >= contract.getMaxNumTries()) {
|
||||
ctx.log(() => `Coding Contract attempt '${filename}' failed. Contract is now self-destructing`);
|
||||
serv.removeContract(filename);
|
||||
} else {
|
||||
ctx.log(
|
||||
() =>
|
||||
`Coding Contract attempt '${filename}' failed. ${
|
||||
contract.getMaxNumTries() - contract.tries
|
||||
} attempts remaining.`,
|
||||
);
|
||||
}
|
||||
|
||||
return returnReward ? "" : false;
|
||||
}
|
||||
},
|
||||
getContractType:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_filename: unknown, _hostname: unknown = workerScript.hostname): string => {
|
||||
const filename = ctx.helper.string("filename", _filename);
|
||||
const hostname = ctx.helper.string("hostname", _hostname);
|
||||
const contract = getCodingContract(ctx, "getContractType", hostname, filename);
|
||||
return contract.getType();
|
||||
},
|
||||
getData:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_filename: unknown, _hostname: unknown = workerScript.hostname): any => {
|
||||
const filename = ctx.helper.string("filename", _filename);
|
||||
const hostname = ctx.helper.string("hostname", _hostname);
|
||||
const contract = getCodingContract(ctx, "getData", hostname, filename);
|
||||
const data = contract.getData();
|
||||
if (data.constructor === Array) {
|
||||
// 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;
|
||||
}
|
||||
},
|
||||
getDescription:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_filename: unknown, _hostname: unknown = workerScript.hostname): string => {
|
||||
const filename = ctx.helper.string("filename", _filename);
|
||||
const hostname = ctx.helper.string("hostname", _hostname);
|
||||
const contract = getCodingContract(ctx, "getDescription", hostname, filename);
|
||||
return contract.getDescription();
|
||||
},
|
||||
getNumTriesRemaining:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_filename: unknown, _hostname: unknown = workerScript.hostname): number => {
|
||||
const filename = ctx.helper.string("filename", _filename);
|
||||
const hostname = ctx.helper.string("hostname", _hostname);
|
||||
const contract = getCodingContract(ctx, "getNumTriesRemaining", hostname, filename);
|
||||
return contract.getMaxNumTries() - contract.tries;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,6 @@
|
||||
import { FactionNames } from "../Faction/data/FactionNames";
|
||||
import { GangConstants } from "../Gang/data/Constants";
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||
import { Gang } from "../Gang/Gang";
|
||||
import { AllGangs } from "../Gang/AllGangs";
|
||||
import { GangMemberTasks } from "../Gang/GangMemberTasks";
|
||||
@ -20,63 +18,60 @@ import {
|
||||
EquipmentStats,
|
||||
GangTaskStats,
|
||||
} from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
|
||||
export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): IGang {
|
||||
const checkGangApiAccess = function (func: string): void {
|
||||
export function NetscriptGang(player: IPlayer, workerScript: WorkerScript): InternalAPI<IGang> {
|
||||
const checkGangApiAccess = function (ctx: NetscriptContext): void {
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Must have joined gang");
|
||||
const hasAccess = gang instanceof Gang;
|
||||
if (!hasAccess) {
|
||||
throw helper.makeRuntimeErrorMsg(`gang.${func}`, `You do not currently have a Gang`);
|
||||
throw ctx.makeRuntimeErrorMsg(`You do not currently have a Gang`);
|
||||
}
|
||||
};
|
||||
|
||||
const getGangMember = function (func: string, name: string): GangMember {
|
||||
const getGangMember = function (ctx: NetscriptContext, name: string): GangMember {
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Must have joined gang");
|
||||
for (const member of gang.members) if (member.name === name) return member;
|
||||
throw helper.makeRuntimeErrorMsg(`gang.${func}`, `Invalid gang member: '${name}'`);
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid gang member: '${name}'`);
|
||||
};
|
||||
|
||||
const getGangTask = function (func: string, name: string): GangMemberTask {
|
||||
const getGangTask = function (ctx: NetscriptContext, name: string): GangMemberTask {
|
||||
const task = GangMemberTasks[name];
|
||||
if (!task) {
|
||||
throw helper.makeRuntimeErrorMsg(`gang.${func}`, `Invalid task: '${name}'`);
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid task: '${name}'`);
|
||||
}
|
||||
|
||||
return task;
|
||||
};
|
||||
|
||||
const updateRam = (funcName: string): void => helper.updateDynamicRam(funcName, getRamCost(player, "gang", funcName));
|
||||
|
||||
return {
|
||||
createGang: function (_faction: unknown): boolean {
|
||||
updateRam("createGang");
|
||||
const faction = helper.string("createGang", "faction", _faction);
|
||||
// this list is copied from Faction/ui/Root.tsx
|
||||
createGang:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_faction: unknown): boolean => {
|
||||
const faction = ctx.helper.string("faction", _faction);
|
||||
// this list is copied from Faction/ui/Root.tsx
|
||||
|
||||
if (!player.canAccessGang() || !GangConstants.Names.includes(faction)) return false;
|
||||
if (player.inGang()) return false;
|
||||
if (!player.factions.includes(faction)) return false;
|
||||
if (!player.canAccessGang() || !GangConstants.Names.includes(faction)) return false;
|
||||
if (player.inGang()) return false;
|
||||
if (!player.factions.includes(faction)) return false;
|
||||
|
||||
const isHacking = faction === FactionNames.NiteSec || faction === FactionNames.TheBlackHand;
|
||||
player.startGang(faction, isHacking);
|
||||
return true;
|
||||
},
|
||||
inGang: function (): boolean {
|
||||
updateRam("inGang");
|
||||
const isHacking = faction === FactionNames.NiteSec || faction === FactionNames.TheBlackHand;
|
||||
player.startGang(faction, isHacking);
|
||||
return true;
|
||||
},
|
||||
inGang: () => (): boolean => {
|
||||
return player.inGang();
|
||||
},
|
||||
getMemberNames: function (): string[] {
|
||||
updateRam("getMemberNames");
|
||||
checkGangApiAccess("getMemberNames");
|
||||
getMemberNames: (ctx: NetscriptContext) => (): string[] => {
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
return gang.members.map((member) => member.name);
|
||||
},
|
||||
getGangInformation: function (): GangGenInfo {
|
||||
updateRam("getGangInformation");
|
||||
checkGangApiAccess("getGangInformation");
|
||||
getGangInformation: (ctx: NetscriptContext) => (): GangGenInfo => {
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
return {
|
||||
@ -94,9 +89,8 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
wantedPenalty: gang.getWantedPenalty(),
|
||||
};
|
||||
},
|
||||
getOtherGangInformation: function (): GangOtherInfo {
|
||||
updateRam("getOtherGangInformation");
|
||||
checkGangApiAccess("getOtherGangInformation");
|
||||
getOtherGangInformation: (ctx: NetscriptContext) => (): GangOtherInfo => {
|
||||
checkGangApiAccess(ctx);
|
||||
const cpy: any = {};
|
||||
for (const gang of Object.keys(AllGangs)) {
|
||||
cpy[gang] = Object.assign({}, AllGangs[gang]);
|
||||
@ -104,242 +98,251 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
|
||||
|
||||
return cpy;
|
||||
},
|
||||
getMemberInformation: function (_memberName: unknown): GangMemberInfo {
|
||||
updateRam("getMemberInformation");
|
||||
const memberName = helper.string("getMemberInformation", "memberName", _memberName);
|
||||
checkGangApiAccess("getMemberInformation");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
const member = getGangMember("getMemberInformation", 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: NetscriptContext) =>
|
||||
(_memberName: unknown): GangMemberInfo => {
|
||||
const memberName = ctx.helper.string("memberName", _memberName);
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
const member = getGangMember(ctx, memberName);
|
||||
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: function (): boolean {
|
||||
updateRam("canRecruitMember");
|
||||
checkGangApiAccess("canRecruitMember");
|
||||
respectGain: member.calculateRespectGain(gang),
|
||||
wantedLevelGain: member.calculateWantedLevelGain(gang),
|
||||
moneyGain: member.calculateMoneyGain(gang),
|
||||
};
|
||||
},
|
||||
canRecruitMember: (ctx: NetscriptContext) => (): boolean => {
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
return gang.canRecruitMember();
|
||||
},
|
||||
recruitMember: function (_memberName: unknown): boolean {
|
||||
updateRam("recruitMember");
|
||||
const memberName = helper.string("recruitMember", "memberName", _memberName);
|
||||
checkGangApiAccess("recruitMember");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
const recruited = gang.recruitMember(memberName);
|
||||
if (recruited) {
|
||||
workerScript.log("gang.recruitMember", () => `Successfully recruited Gang Member '${memberName}'`);
|
||||
} else {
|
||||
workerScript.log("gang.recruitMember", () => `Failed to recruit Gang Member '${memberName}'`);
|
||||
}
|
||||
recruitMember:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_memberName: unknown): boolean => {
|
||||
const memberName = ctx.helper.string("memberName", _memberName);
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
const recruited = gang.recruitMember(memberName);
|
||||
if (recruited) {
|
||||
workerScript.log("gang.recruitMember", () => `Successfully recruited Gang Member '${memberName}'`);
|
||||
} else {
|
||||
workerScript.log("gang.recruitMember", () => `Failed to recruit Gang Member '${memberName}'`);
|
||||
}
|
||||
|
||||
return recruited;
|
||||
},
|
||||
getTaskNames: function (): string[] {
|
||||
updateRam("getTaskNames");
|
||||
checkGangApiAccess("getTaskNames");
|
||||
return recruited;
|
||||
},
|
||||
getTaskNames: (ctx: NetscriptContext) => (): string[] => {
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
const tasks = gang.getAllTaskNames();
|
||||
tasks.unshift("Unassigned");
|
||||
return tasks;
|
||||
},
|
||||
setMemberTask: function (_memberName: unknown, _taskName: unknown): boolean {
|
||||
updateRam("setMemberTask");
|
||||
const memberName = helper.string("setMemberTask", "memberName", _memberName);
|
||||
const taskName = helper.string("setMemberTask", "taskName", _taskName);
|
||||
checkGangApiAccess("setMemberTask");
|
||||
const member = getGangMember("setMemberTask", memberName);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
if (!gang.getAllTaskNames().includes(taskName)) {
|
||||
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) {
|
||||
workerScript.log(
|
||||
"gang.setMemberTask",
|
||||
() => `Successfully assigned Gang Member '${memberName}' to '${taskName}' task`,
|
||||
);
|
||||
} else {
|
||||
workerScript.log(
|
||||
"gang.setMemberTask",
|
||||
() => `Failed to assign Gang Member '${memberName}' to '${taskName}' task. '${memberName}' is now Unassigned`,
|
||||
);
|
||||
}
|
||||
setMemberTask:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_memberName: unknown, _taskName: unknown): boolean => {
|
||||
const memberName = ctx.helper.string("memberName", _memberName);
|
||||
const taskName = ctx.helper.string("taskName", _taskName);
|
||||
checkGangApiAccess(ctx);
|
||||
const member = getGangMember(ctx, memberName);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
if (!gang.getAllTaskNames().includes(taskName)) {
|
||||
workerScript.log(
|
||||
"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) {
|
||||
workerScript.log(
|
||||
"gang.setMemberTask",
|
||||
() => `Successfully assigned Gang Member '${memberName}' to '${taskName}' task`,
|
||||
);
|
||||
} else {
|
||||
workerScript.log(
|
||||
"gang.setMemberTask",
|
||||
() =>
|
||||
`Failed to assign Gang Member '${memberName}' to '${taskName}' task. '${memberName}' is now Unassigned`,
|
||||
);
|
||||
}
|
||||
|
||||
return success;
|
||||
},
|
||||
getTaskStats: function (_taskName: unknown): GangTaskStats {
|
||||
updateRam("getTaskStats");
|
||||
const taskName = helper.string("getTaskStats", "taskName", _taskName);
|
||||
checkGangApiAccess("getTaskStats");
|
||||
const task = getGangTask("getTaskStats", taskName);
|
||||
const copy = Object.assign({}, task);
|
||||
copy.territory = Object.assign({}, task.territory);
|
||||
return copy;
|
||||
},
|
||||
getEquipmentNames: function (): string[] {
|
||||
updateRam("getEquipmentNames");
|
||||
checkGangApiAccess("getEquipmentNames");
|
||||
return success;
|
||||
},
|
||||
getTaskStats:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_taskName: unknown): GangTaskStats => {
|
||||
const taskName = ctx.helper.string("taskName", _taskName);
|
||||
checkGangApiAccess(ctx);
|
||||
const task = getGangTask(ctx, taskName);
|
||||
const copy = Object.assign({}, task);
|
||||
copy.territory = Object.assign({}, task.territory);
|
||||
return copy;
|
||||
},
|
||||
getEquipmentNames: (ctx: NetscriptContext) => (): string[] => {
|
||||
checkGangApiAccess(ctx);
|
||||
return Object.keys(GangMemberUpgrades);
|
||||
},
|
||||
getEquipmentCost: function (_equipName: any): number {
|
||||
updateRam("getEquipmentCost");
|
||||
const equipName = helper.string("getEquipmentCost", "equipName", _equipName);
|
||||
checkGangApiAccess("getEquipmentCost");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
const upg = GangMemberUpgrades[equipName];
|
||||
if (upg === null) return Infinity;
|
||||
return gang.getUpgradeCost(upg);
|
||||
},
|
||||
getEquipmentType: function (_equipName: unknown): string {
|
||||
updateRam("getEquipmentType");
|
||||
const equipName = helper.string("getEquipmentType", "equipName", _equipName);
|
||||
checkGangApiAccess("getEquipmentType");
|
||||
const upg = GangMemberUpgrades[equipName];
|
||||
if (upg == null) return "";
|
||||
return upg.getType();
|
||||
},
|
||||
getEquipmentStats: function (_equipName: unknown): EquipmentStats {
|
||||
updateRam("getEquipmentStats");
|
||||
const equipName = helper.string("getEquipmentStats", "equipName", _equipName);
|
||||
checkGangApiAccess("getEquipmentStats");
|
||||
const equipment = GangMemberUpgrades[equipName];
|
||||
if (!equipment) {
|
||||
throw helper.makeRuntimeErrorMsg("getEquipmentStats", `Invalid equipment: ${equipName}`);
|
||||
}
|
||||
const typecheck: EquipmentStats = equipment.mults;
|
||||
return Object.assign({}, typecheck) as any;
|
||||
},
|
||||
purchaseEquipment: function (_memberName: unknown, _equipName: unknown): boolean {
|
||||
updateRam("purchaseEquipment");
|
||||
const memberName = helper.string("purchaseEquipment", "memberName", _memberName);
|
||||
const equipName = helper.string("purchaseEquipment", "equipName", _equipName);
|
||||
checkGangApiAccess("purchaseEquipment");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
const member = getGangMember("purchaseEquipment", memberName);
|
||||
const equipment = GangMemberUpgrades[equipName];
|
||||
if (!equipment) return false;
|
||||
const res = member.buyUpgrade(equipment, player, gang);
|
||||
if (res) {
|
||||
workerScript.log("gang.purchaseEquipment", () => `Purchased '${equipName}' for Gang member '${memberName}'`);
|
||||
} else {
|
||||
workerScript.log(
|
||||
"gang.purchaseEquipment",
|
||||
() => `Failed to purchase '${equipName}' for Gang member '${memberName}'`,
|
||||
);
|
||||
}
|
||||
getEquipmentCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_equipName: any): number => {
|
||||
const equipName = ctx.helper.string("equipName", _equipName);
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
const upg = GangMemberUpgrades[equipName];
|
||||
if (upg === null) return Infinity;
|
||||
return gang.getUpgradeCost(upg);
|
||||
},
|
||||
getEquipmentType:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_equipName: unknown): string => {
|
||||
const equipName = ctx.helper.string("equipName", _equipName);
|
||||
checkGangApiAccess(ctx);
|
||||
const upg = GangMemberUpgrades[equipName];
|
||||
if (upg == null) return "";
|
||||
return upg.getType();
|
||||
},
|
||||
getEquipmentStats:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_equipName: unknown): EquipmentStats => {
|
||||
const equipName = ctx.helper.string("equipName", _equipName);
|
||||
checkGangApiAccess(ctx);
|
||||
const equipment = GangMemberUpgrades[equipName];
|
||||
if (!equipment) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid equipment: ${equipName}`);
|
||||
}
|
||||
const typecheck: EquipmentStats = equipment.mults;
|
||||
return Object.assign({}, typecheck) as any;
|
||||
},
|
||||
purchaseEquipment:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_memberName: unknown, _equipName: unknown): boolean => {
|
||||
const memberName = ctx.helper.string("memberName", _memberName);
|
||||
const equipName = ctx.helper.string("equipName", _equipName);
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
const member = getGangMember(ctx, memberName);
|
||||
const equipment = GangMemberUpgrades[equipName];
|
||||
if (!equipment) return false;
|
||||
const res = member.buyUpgrade(equipment, player, gang);
|
||||
if (res) {
|
||||
workerScript.log("gang.purchaseEquipment", () => `Purchased '${equipName}' for Gang member '${memberName}'`);
|
||||
} else {
|
||||
workerScript.log(
|
||||
"gang.purchaseEquipment",
|
||||
() => `Failed to purchase '${equipName}' for Gang member '${memberName}'`,
|
||||
);
|
||||
}
|
||||
|
||||
return res;
|
||||
},
|
||||
ascendMember: function (_memberName: unknown): GangMemberAscension | undefined {
|
||||
updateRam("ascendMember");
|
||||
const memberName = helper.string("ascendMember", "memberName", _memberName);
|
||||
checkGangApiAccess("ascendMember");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
const member = getGangMember("ascendMember", memberName);
|
||||
if (!member.canAscend()) return;
|
||||
return gang.ascendMember(member, workerScript);
|
||||
},
|
||||
getAscensionResult: function (_memberName: unknown): GangMemberAscension | undefined {
|
||||
updateRam("getAscensionResult");
|
||||
const memberName = helper.string("getAscensionResult", "memberName", _memberName);
|
||||
checkGangApiAccess("getAscensionResult");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
const member = getGangMember("getAscensionResult", memberName);
|
||||
if (!member.canAscend()) return;
|
||||
return {
|
||||
respect: member.earnedRespect,
|
||||
...member.getAscensionResults(),
|
||||
};
|
||||
},
|
||||
setTerritoryWarfare: function (_engage: unknown): void {
|
||||
updateRam("setTerritoryWarfare");
|
||||
const engage = helper.boolean(_engage);
|
||||
checkGangApiAccess("setTerritoryWarfare");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
if (engage) {
|
||||
gang.territoryWarfareEngaged = true;
|
||||
workerScript.log("gang.setTerritoryWarfare", () => "Engaging in Gang Territory Warfare");
|
||||
} else {
|
||||
gang.territoryWarfareEngaged = false;
|
||||
workerScript.log("gang.setTerritoryWarfare", () => "Disengaging in Gang Territory Warfare");
|
||||
}
|
||||
},
|
||||
getChanceToWinClash: function (_otherGang: unknown): number {
|
||||
updateRam("getChanceToWinClash");
|
||||
const otherGang = helper.string("getChanceToWinClash", "otherGang", _otherGang);
|
||||
checkGangApiAccess("getChanceToWinClash");
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
if (AllGangs[otherGang] == null) {
|
||||
throw helper.makeRuntimeErrorMsg(`gang.getChanceToWinClash`, `Invalid gang: ${otherGang}`);
|
||||
}
|
||||
return res;
|
||||
},
|
||||
ascendMember:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_memberName: unknown): GangMemberAscension | undefined => {
|
||||
const memberName = ctx.helper.string("memberName", _memberName);
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
const member = getGangMember(ctx, memberName);
|
||||
if (!member.canAscend()) return;
|
||||
return gang.ascendMember(member, workerScript);
|
||||
},
|
||||
getAscensionResult:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_memberName: unknown): GangMemberAscension | undefined => {
|
||||
const memberName = ctx.helper.string("memberName", _memberName);
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
const member = getGangMember(ctx, memberName);
|
||||
if (!member.canAscend()) return;
|
||||
return {
|
||||
respect: member.earnedRespect,
|
||||
...member.getAscensionResults(),
|
||||
};
|
||||
},
|
||||
setTerritoryWarfare:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_engage: unknown): void => {
|
||||
const engage = ctx.helper.boolean(_engage);
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
if (engage) {
|
||||
gang.territoryWarfareEngaged = true;
|
||||
workerScript.log("gang.setTerritoryWarfare", () => "Engaging in Gang Territory Warfare");
|
||||
} else {
|
||||
gang.territoryWarfareEngaged = false;
|
||||
workerScript.log("gang.setTerritoryWarfare", () => "Disengaging in Gang Territory Warfare");
|
||||
}
|
||||
},
|
||||
getChanceToWinClash:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_otherGang: unknown): number => {
|
||||
const otherGang = ctx.helper.string("otherGang", _otherGang);
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
if (AllGangs[otherGang] == null) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid gang: ${otherGang}`);
|
||||
}
|
||||
|
||||
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: function (): number {
|
||||
updateRam("getBonusTime");
|
||||
checkGangApiAccess("getBonusTime");
|
||||
return playerPower / (otherPower + playerPower);
|
||||
},
|
||||
getBonusTime: (ctx: NetscriptContext) => (): number => {
|
||||
checkGangApiAccess(ctx);
|
||||
const gang = player.gang;
|
||||
if (gang === null) throw new Error("Should not be called without Gang");
|
||||
return Math.round(gang.storedCycles / 5) * 1000;
|
||||
|
@ -1,104 +1,97 @@
|
||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
import { StaticAugmentations } from "../Augmentation/StaticAugmentations";
|
||||
import { hasAugmentationPrereqs } from "../Faction/FactionHelpers";
|
||||
import { CityName } from "../Locations/data/CityNames";
|
||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { GraftableAugmentation } from "../PersonObjects/Grafting/GraftableAugmentation";
|
||||
import { getGraftingAvailableAugs, calculateGraftingTimeWithBonus } from "../PersonObjects/Grafting/GraftingHelpers";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { Grafting as IGrafting } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { Router } from "../ui/GameRoot";
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
|
||||
export function NetscriptGrafting(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): IGrafting {
|
||||
const checkGraftingAPIAccess = (func: string): void => {
|
||||
export function NetscriptGrafting(player: IPlayer): InternalAPI<IGrafting> {
|
||||
const checkGraftingAPIAccess = (ctx: NetscriptContext): void => {
|
||||
if (!player.canAccessGrafting()) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
`grafting.${func}`,
|
||||
throw ctx.makeRuntimeErrorMsg(
|
||||
"You do not currently have access to the Grafting API. This is either because you are not in BitNode 10 or because you do not have Source-File 10",
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const updateRam = (funcName: string): void =>
|
||||
helper.updateDynamicRam(funcName, getRamCost(player, "grafting", funcName));
|
||||
|
||||
return {
|
||||
getAugmentationGraftPrice: (_augName: unknown): number => {
|
||||
updateRam("getAugmentationGraftPrice");
|
||||
const augName = helper.string("getAugmentationGraftPrice", "augName", _augName);
|
||||
checkGraftingAPIAccess("getAugmentationGraftPrice");
|
||||
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||
throw helper.makeRuntimeErrorMsg("grafting.getAugmentationGraftPrice", `Invalid aug: ${augName}`);
|
||||
}
|
||||
const graftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
||||
return graftableAug.cost;
|
||||
},
|
||||
getAugmentationGraftPrice:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_augName: unknown): number => {
|
||||
const augName = ctx.helper.string("augName", _augName);
|
||||
checkGraftingAPIAccess(ctx);
|
||||
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid aug: ${augName}`);
|
||||
}
|
||||
const graftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
||||
return graftableAug.cost;
|
||||
},
|
||||
|
||||
getAugmentationGraftTime: (_augName: string): number => {
|
||||
updateRam("getAugmentationGraftTime");
|
||||
const augName = helper.string("getAugmentationGraftTime", "augName", _augName);
|
||||
checkGraftingAPIAccess("getAugmentationGraftTime");
|
||||
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||
throw helper.makeRuntimeErrorMsg("grafting.getAugmentationGraftTime", `Invalid aug: ${augName}`);
|
||||
}
|
||||
const graftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
||||
return calculateGraftingTimeWithBonus(player, graftableAug);
|
||||
},
|
||||
getAugmentationGraftTime:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_augName: string): number => {
|
||||
const augName = ctx.helper.string("augName", _augName);
|
||||
checkGraftingAPIAccess(ctx);
|
||||
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid aug: ${augName}`);
|
||||
}
|
||||
const graftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
||||
return calculateGraftingTimeWithBonus(player, graftableAug);
|
||||
},
|
||||
|
||||
getGraftableAugmentations: (): string[] => {
|
||||
updateRam("getGraftableAugmentations");
|
||||
checkGraftingAPIAccess("getGraftableAugmentations");
|
||||
getGraftableAugmentations: (ctx: NetscriptContext) => (): string[] => {
|
||||
checkGraftingAPIAccess(ctx);
|
||||
const graftableAugs = getGraftingAvailableAugs(player);
|
||||
return graftableAugs;
|
||||
},
|
||||
|
||||
graftAugmentation: (_augName: string, _focus: unknown = true): boolean => {
|
||||
updateRam("graftAugmentation");
|
||||
const augName = helper.string("graftAugmentation", "augName", _augName);
|
||||
const focus = helper.boolean(_focus);
|
||||
checkGraftingAPIAccess("graftAugmentation");
|
||||
if (player.city !== CityName.NewTokyo) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"grafting.graftAugmentation",
|
||||
"You must be in New Tokyo to begin grafting an Augmentation.",
|
||||
);
|
||||
}
|
||||
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||
workerScript.log("grafting.graftAugmentation", () => `Invalid aug: ${augName}`);
|
||||
return false;
|
||||
}
|
||||
graftAugmentation:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_augName: string, _focus: unknown = true): boolean => {
|
||||
const augName = ctx.helper.string("augName", _augName);
|
||||
const focus = ctx.helper.boolean(_focus);
|
||||
checkGraftingAPIAccess(ctx);
|
||||
if (player.city !== CityName.NewTokyo) {
|
||||
throw ctx.makeRuntimeErrorMsg("You must be in New Tokyo to begin grafting an Augmentation.");
|
||||
}
|
||||
if (!getGraftingAvailableAugs(player).includes(augName) || !StaticAugmentations.hasOwnProperty(augName)) {
|
||||
ctx.log(() => `Invalid aug: ${augName}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const wasFocusing = player.focus;
|
||||
if (player.isWorking) {
|
||||
const txt = player.singularityStopWork();
|
||||
workerScript.log("graftAugmentation", () => txt);
|
||||
}
|
||||
const wasFocusing = player.focus;
|
||||
if (player.isWorking) {
|
||||
const txt = player.singularityStopWork();
|
||||
ctx.log(() => txt);
|
||||
}
|
||||
|
||||
const craftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
||||
if (player.money < craftableAug.cost) {
|
||||
workerScript.log("grafting.graftAugmentation", () => `You don't have enough money to craft ${augName}`);
|
||||
return false;
|
||||
}
|
||||
const craftableAug = new GraftableAugmentation(StaticAugmentations[augName]);
|
||||
if (player.money < craftableAug.cost) {
|
||||
ctx.log(() => `You don't have enough money to craft ${augName}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasAugmentationPrereqs(craftableAug.augmentation)) {
|
||||
workerScript.log("grafting.graftAugmentation", () => `You don't have the pre-requisites for ${augName}`);
|
||||
return false;
|
||||
}
|
||||
if (!hasAugmentationPrereqs(craftableAug.augmentation)) {
|
||||
ctx.log(() => `You don't have the pre-requisites for ${augName}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
player.loseMoney(craftableAug.cost, "augmentations");
|
||||
player.startGraftAugmentationWork(augName, craftableAug.time);
|
||||
player.loseMoney(craftableAug.cost, "augmentations");
|
||||
player.startGraftAugmentationWork(augName, craftableAug.time);
|
||||
|
||||
if (focus) {
|
||||
player.startFocusing();
|
||||
Router.toWork();
|
||||
} else if (wasFocusing) {
|
||||
player.stopFocusing();
|
||||
Router.toTerminal();
|
||||
}
|
||||
if (focus) {
|
||||
player.startFocusing();
|
||||
Router.toWork();
|
||||
} else if (wasFocusing) {
|
||||
player.stopFocusing();
|
||||
Router.toTerminal();
|
||||
}
|
||||
|
||||
workerScript.log("grafting.graftAugmentation", () => `Began grafting Augmentation ${augName}.`);
|
||||
return true;
|
||||
},
|
||||
ctx.log(() => `Began grafting Augmentation ${augName}.`);
|
||||
return true;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { HacknetServerConstants } from "../Hacknet/data/Constants";
|
||||
@ -21,12 +20,13 @@ import { HashUpgrade } from "../Hacknet/HashUpgrade";
|
||||
import { GetServer } from "../Server/AllServers";
|
||||
|
||||
import { Hacknet as IHacknet, NodeStats } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
|
||||
export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): IHacknet {
|
||||
export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript): InternalAPI<IHacknet> {
|
||||
// Utility function to get Hacknet Node object
|
||||
const getHacknetNode = function (i: number, callingFn = ""): HacknetNode | HacknetServer {
|
||||
const getHacknetNode = function (ctx: NetscriptContext, i: number): HacknetNode | HacknetServer {
|
||||
if (i < 0 || i >= player.hacknetNodes.length) {
|
||||
throw helper.makeRuntimeErrorMsg(callingFn, "Index specified for Hacknet Node is out-of-bounds: " + i);
|
||||
throw ctx.makeRuntimeErrorMsg("Index specified for Hacknet Node is out-of-bounds: " + i);
|
||||
}
|
||||
|
||||
if (hasHacknetServers(player)) {
|
||||
@ -35,8 +35,7 @@ export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript, he
|
||||
const hserver = GetServer(hi);
|
||||
if (!(hserver instanceof HacknetServer)) throw new Error("hacknet server was not actually hacknet server");
|
||||
if (hserver == null) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
callingFn,
|
||||
throw ctx.makeRuntimeErrorMsg(
|
||||
`Could not get Hacknet Server for index ${i}. This is probably a bug, please report to game dev`,
|
||||
);
|
||||
}
|
||||
@ -50,162 +49,186 @@ export function NetscriptHacknet(player: IPlayer, workerScript: WorkerScript, he
|
||||
};
|
||||
|
||||
return {
|
||||
numNodes: function (): number {
|
||||
numNodes: () => (): number => {
|
||||
return player.hacknetNodes.length;
|
||||
},
|
||||
maxNumNodes: function (): number {
|
||||
maxNumNodes: () => (): number => {
|
||||
if (hasHacknetServers(player)) {
|
||||
return HacknetServerConstants.MaxServers;
|
||||
}
|
||||
return Infinity;
|
||||
},
|
||||
purchaseNode: function (): number {
|
||||
purchaseNode: () => (): number => {
|
||||
return purchaseHacknet(player);
|
||||
},
|
||||
getPurchaseNodeCost: function (): number {
|
||||
getPurchaseNodeCost: () => (): number => {
|
||||
if (hasHacknetServers(player)) {
|
||||
return getCostOfNextHacknetServer(player);
|
||||
} else {
|
||||
return getCostOfNextHacknetNode(player);
|
||||
}
|
||||
},
|
||||
getNodeStats: function (_i: unknown): NodeStats {
|
||||
const i = helper.number("getNodeStats", "i", _i);
|
||||
const node = getHacknetNode(i, "getNodeStats");
|
||||
const hasUpgraded = hasHacknetServers(player);
|
||||
const res: any = {
|
||||
name: node instanceof HacknetServer ? node.hostname : node.name,
|
||||
level: node.level,
|
||||
ram: node instanceof HacknetServer ? node.maxRam : node.ram,
|
||||
ramUsed: node instanceof HacknetServer ? node.ramUsed : undefined,
|
||||
cores: node.cores,
|
||||
production: node instanceof HacknetServer ? node.hashRate : node.moneyGainRatePerSecond,
|
||||
timeOnline: node.onlineTimeSeconds,
|
||||
totalProduction: node instanceof HacknetServer ? node.totalHashesGenerated : node.totalMoneyGenerated,
|
||||
};
|
||||
getNodeStats:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown): NodeStats => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
const hasUpgraded = hasHacknetServers(player);
|
||||
const res: any = {
|
||||
name: node instanceof HacknetServer ? node.hostname : node.name,
|
||||
level: node.level,
|
||||
ram: node instanceof HacknetServer ? node.maxRam : node.ram,
|
||||
ramUsed: node instanceof HacknetServer ? node.ramUsed : undefined,
|
||||
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;
|
||||
}
|
||||
if (hasUpgraded && node instanceof HacknetServer) {
|
||||
res.cache = node.cache;
|
||||
res.hashCapacity = node.hashCapacity;
|
||||
}
|
||||
|
||||
return res;
|
||||
},
|
||||
upgradeLevel: function (_i: unknown, _n: unknown = 1): boolean {
|
||||
const i = helper.number("upgradeLevel", "i", _i);
|
||||
const n = helper.number("upgradeLevel", "n", _n);
|
||||
const node = getHacknetNode(i, "upgradeLevel");
|
||||
return purchaseLevelUpgrade(player, node, n);
|
||||
},
|
||||
upgradeRam: function (_i: unknown, _n: unknown = 1): boolean {
|
||||
const i = helper.number("upgradeRam", "i", _i);
|
||||
const n = helper.number("upgradeRam", "n", _n);
|
||||
const node = getHacknetNode(i, "upgradeRam");
|
||||
return purchaseRamUpgrade(player, node, n);
|
||||
},
|
||||
upgradeCore: function (_i: unknown, _n: unknown = 1): boolean {
|
||||
const i = helper.number("upgradeCore", "i", _i);
|
||||
const n = helper.number("upgradeCore", "n", _n);
|
||||
const node = getHacknetNode(i, "upgradeCore");
|
||||
return purchaseCoreUpgrade(player, node, n);
|
||||
},
|
||||
upgradeCache: function (_i: unknown, _n: unknown = 1): boolean {
|
||||
const i = helper.number("upgradeCache", "i", _i);
|
||||
const n = helper.number("upgradeCache", "n", _n);
|
||||
if (!hasHacknetServers(player)) {
|
||||
return false;
|
||||
}
|
||||
const node = getHacknetNode(i, "upgradeCache");
|
||||
if (!(node instanceof HacknetServer)) {
|
||||
workerScript.log("hacknet.upgradeCache", () => "Can only be called on hacknet servers");
|
||||
return false;
|
||||
}
|
||||
const res = purchaseCacheUpgrade(player, node, n);
|
||||
if (res) {
|
||||
updateHashManagerCapacity(player);
|
||||
}
|
||||
return res;
|
||||
},
|
||||
getLevelUpgradeCost: function (_i: unknown, _n: unknown = 1): number {
|
||||
const i = helper.number("getLevelUpgradeCost", "i", _i);
|
||||
const n = helper.number("getLevelUpgradeCost", "n", _n);
|
||||
const node = getHacknetNode(i, "upgradeLevel");
|
||||
return node.calculateLevelUpgradeCost(n, player.hacknet_node_level_cost_mult);
|
||||
},
|
||||
getRamUpgradeCost: function (_i: unknown, _n: unknown = 1): number {
|
||||
const i = helper.number("getRamUpgradeCost", "i", _i);
|
||||
const n = helper.number("getRamUpgradeCost", "n", _n);
|
||||
const node = getHacknetNode(i, "upgradeRam");
|
||||
return node.calculateRamUpgradeCost(n, player.hacknet_node_ram_cost_mult);
|
||||
},
|
||||
getCoreUpgradeCost: function (_i: unknown, _n: unknown = 1): number {
|
||||
const i = helper.number("getCoreUpgradeCost", "i", _i);
|
||||
const n = helper.number("getCoreUpgradeCost", "n", _n);
|
||||
const node = getHacknetNode(i, "upgradeCore");
|
||||
return node.calculateCoreUpgradeCost(n, player.hacknet_node_core_cost_mult);
|
||||
},
|
||||
getCacheUpgradeCost: function (_i: unknown, _n: unknown = 1): number {
|
||||
const i = helper.number("getCacheUpgradeCost", "i", _i);
|
||||
const n = helper.number("getCacheUpgradeCost", "n", _n);
|
||||
if (!hasHacknetServers(player)) {
|
||||
return Infinity;
|
||||
}
|
||||
const node = getHacknetNode(i, "upgradeCache");
|
||||
if (!(node instanceof HacknetServer)) {
|
||||
workerScript.log("hacknet.getCacheUpgradeCost", () => "Can only be called on hacknet servers");
|
||||
return -1;
|
||||
}
|
||||
return node.calculateCacheUpgradeCost(n);
|
||||
},
|
||||
numHashes: function (): number {
|
||||
return res;
|
||||
},
|
||||
upgradeLevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): boolean => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const n = ctx.helper.number("n", _n);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
return purchaseLevelUpgrade(player, node, n);
|
||||
},
|
||||
upgradeRam:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): boolean => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const n = ctx.helper.number("n", _n);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
return purchaseRamUpgrade(player, node, n);
|
||||
},
|
||||
upgradeCore:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): boolean => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const n = ctx.helper.number("n", _n);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
return purchaseCoreUpgrade(player, node, n);
|
||||
},
|
||||
upgradeCache:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): boolean => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const n = ctx.helper.number("n", _n);
|
||||
if (!hasHacknetServers(player)) {
|
||||
return false;
|
||||
}
|
||||
const node = getHacknetNode(ctx, i);
|
||||
if (!(node instanceof HacknetServer)) {
|
||||
workerScript.log("hacknet.upgradeCache", () => "Can only be called on hacknet servers");
|
||||
return false;
|
||||
}
|
||||
const res = purchaseCacheUpgrade(player, node, n);
|
||||
if (res) {
|
||||
updateHashManagerCapacity(player);
|
||||
}
|
||||
return res;
|
||||
},
|
||||
getLevelUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): number => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const n = ctx.helper.number("n", _n);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
return node.calculateLevelUpgradeCost(n, player.hacknet_node_level_cost_mult);
|
||||
},
|
||||
getRamUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): number => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const n = ctx.helper.number("n", _n);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
return node.calculateRamUpgradeCost(n, player.hacknet_node_ram_cost_mult);
|
||||
},
|
||||
getCoreUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): number => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const n = ctx.helper.number("n", _n);
|
||||
const node = getHacknetNode(ctx, i);
|
||||
return node.calculateCoreUpgradeCost(n, player.hacknet_node_core_cost_mult);
|
||||
},
|
||||
getCacheUpgradeCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_i: unknown, _n: unknown = 1): number => {
|
||||
const i = ctx.helper.number("i", _i);
|
||||
const n = ctx.helper.number("n", _n);
|
||||
if (!hasHacknetServers(player)) {
|
||||
return Infinity;
|
||||
}
|
||||
const node = getHacknetNode(ctx, i);
|
||||
if (!(node instanceof HacknetServer)) {
|
||||
workerScript.log("hacknet.getCacheUpgradeCost", () => "Can only be called on hacknet servers");
|
||||
return -1;
|
||||
}
|
||||
return node.calculateCacheUpgradeCost(n);
|
||||
},
|
||||
numHashes: () => (): number => {
|
||||
if (!hasHacknetServers(player)) {
|
||||
return 0;
|
||||
}
|
||||
return player.hashManager.hashes;
|
||||
},
|
||||
hashCapacity: function (): number {
|
||||
hashCapacity: () => (): number => {
|
||||
if (!hasHacknetServers(player)) {
|
||||
return 0;
|
||||
}
|
||||
return player.hashManager.capacity;
|
||||
},
|
||||
hashCost: function (_upgName: unknown): number {
|
||||
const upgName = helper.string("hashCost", "upgName", _upgName);
|
||||
if (!hasHacknetServers(player)) {
|
||||
return Infinity;
|
||||
}
|
||||
hashCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_upgName: unknown): number => {
|
||||
const upgName = ctx.helper.string("upgName", _upgName);
|
||||
if (!hasHacknetServers(player)) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
return player.hashManager.getUpgradeCost(upgName);
|
||||
},
|
||||
spendHashes: function (_upgName: unknown, _upgTarget: unknown = ""): boolean {
|
||||
const upgName = helper.string("spendHashes", "upgName", _upgName);
|
||||
const upgTarget = helper.string("spendHashes", "upgTarget", _upgTarget);
|
||||
if (!hasHacknetServers(player)) {
|
||||
return false;
|
||||
}
|
||||
return purchaseHashUpgrade(player, upgName, upgTarget);
|
||||
},
|
||||
getHashUpgrades: function (): string[] {
|
||||
return player.hashManager.getUpgradeCost(upgName);
|
||||
},
|
||||
spendHashes:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_upgName: unknown, _upgTarget: unknown = ""): boolean => {
|
||||
const upgName = ctx.helper.string("upgName", _upgName);
|
||||
const upgTarget = ctx.helper.string("upgTarget", _upgTarget);
|
||||
if (!hasHacknetServers(player)) {
|
||||
return false;
|
||||
}
|
||||
return purchaseHashUpgrade(player, upgName, upgTarget);
|
||||
},
|
||||
getHashUpgrades: () => (): string[] => {
|
||||
if (!hasHacknetServers(player)) {
|
||||
return [];
|
||||
}
|
||||
return Object.values(HashUpgrades).map((upgrade: HashUpgrade) => upgrade.name);
|
||||
},
|
||||
getHashUpgradeLevel: function (_upgName: unknown): number {
|
||||
const upgName = helper.string("getHashUpgradeLevel", "upgName", _upgName);
|
||||
const level = player.hashManager.upgrades[upgName];
|
||||
if (level === undefined) {
|
||||
throw helper.makeRuntimeErrorMsg("hacknet.hashUpgradeLevel", `Invalid Hash Upgrade: ${upgName}`);
|
||||
}
|
||||
return level;
|
||||
},
|
||||
getStudyMult: function (): number {
|
||||
getHashUpgradeLevel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_upgName: unknown): number => {
|
||||
const upgName = ctx.helper.string("upgName", _upgName);
|
||||
const level = player.hashManager.upgrades[upgName];
|
||||
if (level === undefined) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid Hash Upgrade: ${upgName}`);
|
||||
}
|
||||
return level;
|
||||
},
|
||||
getStudyMult: () => (): number => {
|
||||
if (!hasHacknetServers(player)) {
|
||||
return 1;
|
||||
}
|
||||
return player.hashManager.getStudyMult();
|
||||
},
|
||||
getTrainingMult: function (): number {
|
||||
getTrainingMult: () => (): number => {
|
||||
if (!hasHacknetServers(player)) {
|
||||
return 1;
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||
import { FactionWorkType } from "../Faction/FactionWorkTypeEnum";
|
||||
import { SleeveTaskType } from "../PersonObjects/Sleeve/SleeveTaskTypesEnum";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { findSleevePurchasableAugs } from "../PersonObjects/Sleeve/SleeveHelpers";
|
||||
import { StaticAugmentations } from "../Augmentation/StaticAugmentations";
|
||||
import { CityName } from "../Locations/data/CityNames";
|
||||
@ -17,22 +14,22 @@ import {
|
||||
SleeveTask,
|
||||
} from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { checkEnum } from "../utils/helpers/checkEnum";
|
||||
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
|
||||
|
||||
export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): ISleeve {
|
||||
const checkSleeveAPIAccess = function (func: string): void {
|
||||
export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
||||
const checkSleeveAPIAccess = function (ctx: NetscriptContext): void {
|
||||
if (player.bitNodeN !== 10 && !player.sourceFileLvl(10)) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
`sleeve.${func}`,
|
||||
throw ctx.makeRuntimeErrorMsg(
|
||||
"You do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10",
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const checkSleeveNumber = function (func: string, sleeveNumber: number): void {
|
||||
const checkSleeveNumber = function (ctx: NetscriptContext, sleeveNumber: number): void {
|
||||
if (sleeveNumber >= player.sleeves.length || sleeveNumber < 0) {
|
||||
const msg = `Invalid sleeve number: ${sleeveNumber}`;
|
||||
workerScript.log(func, () => msg);
|
||||
throw helper.makeRuntimeErrorMsg(`sleeve.${func}`, msg);
|
||||
ctx.log(() => msg);
|
||||
throw ctx.makeRuntimeErrorMsg(msg);
|
||||
}
|
||||
};
|
||||
|
||||
@ -50,265 +47,268 @@ export function NetscriptSleeve(player: IPlayer, workerScript: WorkerScript, hel
|
||||
};
|
||||
};
|
||||
|
||||
const updateRam = (funcName: string): void =>
|
||||
helper.updateDynamicRam(funcName, getRamCost(player, "sleeve", funcName));
|
||||
|
||||
return {
|
||||
getNumSleeves: function (): number {
|
||||
updateRam("getNumSleeves");
|
||||
checkSleeveAPIAccess("getNumSleeves");
|
||||
getNumSleeves: (ctx: NetscriptContext) => (): number => {
|
||||
checkSleeveAPIAccess(ctx);
|
||||
return player.sleeves.length;
|
||||
},
|
||||
setToShockRecovery: function (_sleeveNumber: unknown): boolean {
|
||||
updateRam("setToShockRecovery");
|
||||
const sleeveNumber = helper.number("setToShockRecovery", "sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess("setToShockRecovery");
|
||||
checkSleeveNumber("setToShockRecovery", sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].shockRecovery(player);
|
||||
},
|
||||
setToSynchronize: function (_sleeveNumber: unknown): boolean {
|
||||
updateRam("setToSynchronize");
|
||||
const sleeveNumber = helper.number("setToSynchronize", "sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess("setToSynchronize");
|
||||
checkSleeveNumber("setToSynchronize", sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].synchronize(player);
|
||||
},
|
||||
setToCommitCrime: function (_sleeveNumber: unknown, _crimeRoughName: unknown): boolean {
|
||||
updateRam("setToCommitCrime");
|
||||
const sleeveNumber = helper.number("setToCommitCrime", "sleeveNumber", _sleeveNumber);
|
||||
const crimeRoughName = helper.string("setToCommitCrime", "crimeName", _crimeRoughName);
|
||||
checkSleeveAPIAccess("setToCommitCrime");
|
||||
checkSleeveNumber("setToCommitCrime", sleeveNumber);
|
||||
const crime = findCrime(crimeRoughName);
|
||||
if (crime === null) {
|
||||
return false;
|
||||
}
|
||||
return player.sleeves[sleeveNumber].commitCrime(player, crime.name);
|
||||
},
|
||||
setToUniversityCourse: function (_sleeveNumber: unknown, _universityName: unknown, _className: unknown): boolean {
|
||||
updateRam("setToUniversityCourse");
|
||||
const sleeveNumber = helper.number("setToUniversityCourse", "sleeveNumber", _sleeveNumber);
|
||||
const universityName = helper.string("setToUniversityCourse", "universityName", _universityName);
|
||||
const className = helper.string("setToUniversityCourse", "className", _className);
|
||||
checkSleeveAPIAccess("setToUniversityCourse");
|
||||
checkSleeveNumber("setToUniversityCourse", sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].takeUniversityCourse(player, universityName, className);
|
||||
},
|
||||
travel: function (_sleeveNumber: unknown, _cityName: unknown): boolean {
|
||||
updateRam("travel");
|
||||
const sleeveNumber = helper.number("travel", "sleeveNumber", _sleeveNumber);
|
||||
const cityName = helper.string("travel", "cityName", _cityName);
|
||||
checkSleeveAPIAccess("travel");
|
||||
checkSleeveNumber("travel", sleeveNumber);
|
||||
if (checkEnum(CityName, cityName)) {
|
||||
return player.sleeves[sleeveNumber].travel(player, cityName);
|
||||
} else {
|
||||
throw helper.makeRuntimeErrorMsg("sleeve.setToCompanyWork", `Invalid city name: '${cityName}'.`);
|
||||
}
|
||||
},
|
||||
setToCompanyWork: function (_sleeveNumber: unknown, acompanyName: unknown): boolean {
|
||||
updateRam("setToCompanyWork");
|
||||
const sleeveNumber = helper.number("setToCompanyWork", "sleeveNumber", _sleeveNumber);
|
||||
const companyName = helper.string("setToCompanyWork", "companyName", acompanyName);
|
||||
checkSleeveAPIAccess("setToCompanyWork");
|
||||
checkSleeveNumber("setToCompanyWork", 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;
|
||||
setToShockRecovery:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].shockRecovery(player);
|
||||
},
|
||||
setToSynchronize:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].synchronize(player);
|
||||
},
|
||||
setToCommitCrime:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown, _crimeRoughName: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const crimeRoughName = ctx.helper.string("crimeName", _crimeRoughName);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
const crime = findCrime(crimeRoughName);
|
||||
if (crime === null) {
|
||||
return false;
|
||||
}
|
||||
const other = player.sleeves[i];
|
||||
if (other.currentTask === SleeveTaskType.Company && other.currentTaskLocation === companyName) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"sleeve.setToCompanyWork",
|
||||
`Sleeve ${sleeveNumber} cannot work for company ${companyName} because Sleeve ${i} is already working for them.`,
|
||||
return player.sleeves[sleeveNumber].commitCrime(player, crime.name);
|
||||
},
|
||||
setToUniversityCourse:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown, _universityName: unknown, _className: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const universityName = ctx.helper.string("universityName", _universityName);
|
||||
const className = ctx.helper.string("className", _className);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].takeUniversityCourse(player, universityName, className);
|
||||
},
|
||||
travel:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown, _cityName: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const cityName = ctx.helper.string("cityName", _cityName);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
if (checkEnum(CityName, cityName)) {
|
||||
return player.sleeves[sleeveNumber].travel(player, cityName);
|
||||
} else {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid city name: '${cityName}'.`);
|
||||
}
|
||||
},
|
||||
setToCompanyWork:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown, acompanyName: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const companyName = ctx.helper.string("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 (other.currentTask === SleeveTaskType.Company && other.currentTaskLocation === companyName) {
|
||||
throw ctx.makeRuntimeErrorMsg(
|
||||
`Sleeve ${sleeveNumber} cannot work for company ${companyName} because Sleeve ${i} is already working for them.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return player.sleeves[sleeveNumber].workForCompany(player, companyName);
|
||||
},
|
||||
setToFactionWork:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown, _factionName: unknown, _workType: unknown): boolean | undefined => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const factionName = ctx.helper.string("factionName", _factionName);
|
||||
const workType = ctx.helper.string("workType", _workType);
|
||||
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 (other.currentTask === SleeveTaskType.Faction && other.currentTaskLocation === factionName) {
|
||||
throw ctx.makeRuntimeErrorMsg(
|
||||
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because Sleeve ${i} is already working for them.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (player.gang && player.gang.facName == factionName) {
|
||||
throw ctx.makeRuntimeErrorMsg(
|
||||
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because you have started a gang with them.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return player.sleeves[sleeveNumber].workForCompany(player, companyName);
|
||||
},
|
||||
setToFactionWork: function (
|
||||
_sleeveNumber: unknown,
|
||||
_factionName: unknown,
|
||||
_workType: unknown,
|
||||
): boolean | undefined {
|
||||
updateRam("setToFactionWork");
|
||||
const sleeveNumber = helper.number("setToFactionWork", "sleeveNumber", _sleeveNumber);
|
||||
const factionName = helper.string("setToFactionWork", "factionName", _factionName);
|
||||
const workType = helper.string("setToFactionWork", "workType", _workType);
|
||||
checkSleeveAPIAccess("setToFactionWork");
|
||||
checkSleeveNumber("setToFactionWork", sleeveNumber);
|
||||
return player.sleeves[sleeveNumber].workForFaction(player, factionName, workType);
|
||||
},
|
||||
setToGymWorkout:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown, _gymName: unknown, _stat: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const gymName = ctx.helper.string("gymName", _gymName);
|
||||
const stat = ctx.helper.string("stat", _stat);
|
||||
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;
|
||||
return player.sleeves[sleeveNumber].workoutAtGym(player, gymName, stat);
|
||||
},
|
||||
getSleeveStats:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown): SleeveSkills => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
return getSleeveStats(sleeveNumber);
|
||||
},
|
||||
getTask:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown): SleeveTask => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
const sl = player.sleeves[sleeveNumber];
|
||||
return {
|
||||
task: SleeveTaskType[sl.currentTask],
|
||||
crime: sl.crimeType,
|
||||
location: sl.currentTaskLocation,
|
||||
gymStatType: sl.gymStatType,
|
||||
factionWorkType: FactionWorkType[sl.factionWorkType],
|
||||
};
|
||||
},
|
||||
getInformation:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown): SleeveInformation => {
|
||||
const sleeveNumber = ctx.helper.number("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),
|
||||
maxHp: sl.max_hp,
|
||||
|
||||
mult: {
|
||||
agility: sl.agility_mult,
|
||||
agilityExp: sl.agility_exp_mult,
|
||||
charisma: sl.charisma_mult,
|
||||
charismaExp: sl.charisma_exp_mult,
|
||||
companyRep: sl.company_rep_mult,
|
||||
crimeMoney: sl.crime_money_mult,
|
||||
crimeSuccess: sl.crime_success_mult,
|
||||
defense: sl.defense_mult,
|
||||
defenseExp: sl.defense_exp_mult,
|
||||
dexterity: sl.dexterity_mult,
|
||||
dexterityExp: sl.dexterity_exp_mult,
|
||||
factionRep: sl.faction_rep_mult,
|
||||
hacking: sl.hacking_mult,
|
||||
hackingExp: sl.hacking_exp_mult,
|
||||
strength: sl.strength_mult,
|
||||
strengthExp: sl.strength_exp_mult,
|
||||
workMoney: sl.work_money_mult,
|
||||
},
|
||||
|
||||
timeWorked: sl.currentTaskTime,
|
||||
earningsForSleeves: {
|
||||
workHackExpGain: sl.earningsForSleeves.hack,
|
||||
workStrExpGain: sl.earningsForSleeves.str,
|
||||
workDefExpGain: sl.earningsForSleeves.def,
|
||||
workDexExpGain: sl.earningsForSleeves.dex,
|
||||
workAgiExpGain: sl.earningsForSleeves.agi,
|
||||
workChaExpGain: sl.earningsForSleeves.cha,
|
||||
workMoneyGain: sl.earningsForSleeves.money,
|
||||
},
|
||||
earningsForPlayer: {
|
||||
workHackExpGain: sl.earningsForPlayer.hack,
|
||||
workStrExpGain: sl.earningsForPlayer.str,
|
||||
workDefExpGain: sl.earningsForPlayer.def,
|
||||
workDexExpGain: sl.earningsForPlayer.dex,
|
||||
workAgiExpGain: sl.earningsForPlayer.agi,
|
||||
workChaExpGain: sl.earningsForPlayer.cha,
|
||||
workMoneyGain: sl.earningsForPlayer.money,
|
||||
},
|
||||
earningsForTask: {
|
||||
workHackExpGain: sl.earningsForTask.hack,
|
||||
workStrExpGain: sl.earningsForTask.str,
|
||||
workDefExpGain: sl.earningsForTask.def,
|
||||
workDexExpGain: sl.earningsForTask.dex,
|
||||
workAgiExpGain: sl.earningsForTask.agi,
|
||||
workChaExpGain: sl.earningsForTask.cha,
|
||||
workMoneyGain: sl.earningsForTask.money,
|
||||
},
|
||||
workRepGain: sl.getRepGain(player),
|
||||
};
|
||||
},
|
||||
getSleeveAugmentations:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown): string[] => {
|
||||
const sleeveNumber = ctx.helper.number("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);
|
||||
}
|
||||
const other = player.sleeves[i];
|
||||
if (other.currentTask === SleeveTaskType.Faction && other.currentTaskLocation === factionName) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"sleeve.setToFactionWork",
|
||||
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because Sleeve ${i} is already working for them.`,
|
||||
);
|
||||
return augs;
|
||||
},
|
||||
getSleevePurchasableAugs:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown): AugmentPair[] => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
const purchasableAugs = findSleevePurchasableAugs(player.sleeves[sleeveNumber], player);
|
||||
const augs = [];
|
||||
for (let i = 0; i < purchasableAugs.length; i++) {
|
||||
const aug = purchasableAugs[i];
|
||||
augs.push({
|
||||
name: aug.name,
|
||||
cost: aug.baseCost,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (player.gang && player.gang.facName == factionName) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"sleeve.setToFactionWork",
|
||||
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because you have started a gang with them.`,
|
||||
);
|
||||
}
|
||||
return augs;
|
||||
},
|
||||
purchaseSleeveAug:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_sleeveNumber: unknown, _augName: unknown): boolean => {
|
||||
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
||||
const augName = ctx.helper.string("augName", _augName);
|
||||
checkSleeveAPIAccess(ctx);
|
||||
checkSleeveNumber(ctx, sleeveNumber);
|
||||
|
||||
return player.sleeves[sleeveNumber].workForFaction(player, factionName, workType);
|
||||
},
|
||||
setToGymWorkout: function (_sleeveNumber: unknown, _gymName: unknown, _stat: unknown): boolean {
|
||||
updateRam("setToGymWorkout");
|
||||
const sleeveNumber = helper.number("setToGymWorkout", "sleeveNumber", _sleeveNumber);
|
||||
const gymName = helper.string("setToGymWorkout", "gymName", _gymName);
|
||||
const stat = helper.string("setToGymWorkout", "stat", _stat);
|
||||
checkSleeveAPIAccess("setToGymWorkout");
|
||||
checkSleeveNumber("setToGymWorkout", sleeveNumber);
|
||||
if (getSleeveStats(sleeveNumber).shock > 0) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Sleeve shock too high: Sleeve ${sleeveNumber}`);
|
||||
}
|
||||
|
||||
return player.sleeves[sleeveNumber].workoutAtGym(player, gymName, stat);
|
||||
},
|
||||
getSleeveStats: function (_sleeveNumber: unknown): SleeveSkills {
|
||||
updateRam("getSleeveStats");
|
||||
const sleeveNumber = helper.number("getSleeveStats", "sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess("getSleeveStats");
|
||||
checkSleeveNumber("getSleeveStats", sleeveNumber);
|
||||
return getSleeveStats(sleeveNumber);
|
||||
},
|
||||
getTask: function (_sleeveNumber: unknown): SleeveTask {
|
||||
updateRam("getTask");
|
||||
const sleeveNumber = helper.number("getTask", "sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess("getTask");
|
||||
checkSleeveNumber("getTask", sleeveNumber);
|
||||
const aug = StaticAugmentations[augName];
|
||||
if (!aug) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid aug: ${augName}`);
|
||||
}
|
||||
|
||||
const sl = player.sleeves[sleeveNumber];
|
||||
return {
|
||||
task: SleeveTaskType[sl.currentTask],
|
||||
crime: sl.crimeType,
|
||||
location: sl.currentTaskLocation,
|
||||
gymStatType: sl.gymStatType,
|
||||
factionWorkType: FactionWorkType[sl.factionWorkType],
|
||||
};
|
||||
},
|
||||
getInformation: function (_sleeveNumber: unknown): SleeveInformation {
|
||||
updateRam("getInformation");
|
||||
const sleeveNumber = helper.number("getInformation", "sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess("getInformation");
|
||||
checkSleeveNumber("getInformation", 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),
|
||||
maxHp: sl.max_hp,
|
||||
|
||||
mult: {
|
||||
agility: sl.agility_mult,
|
||||
agilityExp: sl.agility_exp_mult,
|
||||
charisma: sl.charisma_mult,
|
||||
charismaExp: sl.charisma_exp_mult,
|
||||
companyRep: sl.company_rep_mult,
|
||||
crimeMoney: sl.crime_money_mult,
|
||||
crimeSuccess: sl.crime_success_mult,
|
||||
defense: sl.defense_mult,
|
||||
defenseExp: sl.defense_exp_mult,
|
||||
dexterity: sl.dexterity_mult,
|
||||
dexterityExp: sl.dexterity_exp_mult,
|
||||
factionRep: sl.faction_rep_mult,
|
||||
hacking: sl.hacking_mult,
|
||||
hackingExp: sl.hacking_exp_mult,
|
||||
strength: sl.strength_mult,
|
||||
strengthExp: sl.strength_exp_mult,
|
||||
workMoney: sl.work_money_mult,
|
||||
},
|
||||
|
||||
timeWorked: sl.currentTaskTime,
|
||||
earningsForSleeves: {
|
||||
workHackExpGain: sl.earningsForSleeves.hack,
|
||||
workStrExpGain: sl.earningsForSleeves.str,
|
||||
workDefExpGain: sl.earningsForSleeves.def,
|
||||
workDexExpGain: sl.earningsForSleeves.dex,
|
||||
workAgiExpGain: sl.earningsForSleeves.agi,
|
||||
workChaExpGain: sl.earningsForSleeves.cha,
|
||||
workMoneyGain: sl.earningsForSleeves.money,
|
||||
},
|
||||
earningsForPlayer: {
|
||||
workHackExpGain: sl.earningsForPlayer.hack,
|
||||
workStrExpGain: sl.earningsForPlayer.str,
|
||||
workDefExpGain: sl.earningsForPlayer.def,
|
||||
workDexExpGain: sl.earningsForPlayer.dex,
|
||||
workAgiExpGain: sl.earningsForPlayer.agi,
|
||||
workChaExpGain: sl.earningsForPlayer.cha,
|
||||
workMoneyGain: sl.earningsForPlayer.money,
|
||||
},
|
||||
earningsForTask: {
|
||||
workHackExpGain: sl.earningsForTask.hack,
|
||||
workStrExpGain: sl.earningsForTask.str,
|
||||
workDefExpGain: sl.earningsForTask.def,
|
||||
workDexExpGain: sl.earningsForTask.dex,
|
||||
workAgiExpGain: sl.earningsForTask.agi,
|
||||
workChaExpGain: sl.earningsForTask.cha,
|
||||
workMoneyGain: sl.earningsForTask.money,
|
||||
},
|
||||
workRepGain: sl.getRepGain(player),
|
||||
};
|
||||
},
|
||||
getSleeveAugmentations: function (_sleeveNumber: unknown): string[] {
|
||||
updateRam("getSleeveAugmentations");
|
||||
const sleeveNumber = helper.number("getSleeveAugmentations", "sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess("getSleeveAugmentations");
|
||||
checkSleeveNumber("getSleeveAugmentations", 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: function (_sleeveNumber: unknown): AugmentPair[] {
|
||||
updateRam("getSleevePurchasableAugs");
|
||||
const sleeveNumber = helper.number("getSleevePurchasableAugs", "sleeveNumber", _sleeveNumber);
|
||||
checkSleeveAPIAccess("getSleevePurchasableAugs");
|
||||
checkSleeveNumber("getSleevePurchasableAugs", sleeveNumber);
|
||||
|
||||
const purchasableAugs = findSleevePurchasableAugs(player.sleeves[sleeveNumber], player);
|
||||
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: function (_sleeveNumber: unknown, _augName: unknown): boolean {
|
||||
updateRam("purchaseSleeveAug");
|
||||
const sleeveNumber = helper.number("purchaseSleeveAug", "sleeveNumber", _sleeveNumber);
|
||||
const augName = helper.string("purchaseSleeveAug", "augName", _augName);
|
||||
checkSleeveAPIAccess("purchaseSleeveAug");
|
||||
checkSleeveNumber("purchaseSleeveAug", sleeveNumber);
|
||||
|
||||
if (getSleeveStats(sleeveNumber).shock > 0) {
|
||||
throw helper.makeRuntimeErrorMsg("sleeve.purchaseSleeveAug", `Sleeve shock too high: Sleeve ${sleeveNumber}`);
|
||||
}
|
||||
|
||||
const aug = StaticAugmentations[augName];
|
||||
if (!aug) {
|
||||
throw helper.makeRuntimeErrorMsg("sleeve.purchaseSleeveAug", `Invalid aug: ${augName}`);
|
||||
}
|
||||
|
||||
return player.sleeves[sleeveNumber].tryBuyAugmentation(player, aug);
|
||||
},
|
||||
return player.sleeves[sleeveNumber].tryBuyAugmentation(player, aug);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,7 +1,5 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||
import { buyStock, sellStock, shortStock, sellShort } from "../StockMarket/BuyingAndSelling";
|
||||
import { StockMarket, SymbolToStockMap, placeOrder, cancelOrder, initStockMarketFn } from "../StockMarket/StockMarket";
|
||||
import { getBuyTransactionCost, getSellTransactionGain } from "../StockMarket/StockMarketHelpers";
|
||||
@ -16,301 +14,286 @@ import {
|
||||
} from "../StockMarket/StockMarketCosts";
|
||||
import { Stock } from "../StockMarket/Stock";
|
||||
import { TIX } from "../ScriptEditor/NetscriptDefinitions";
|
||||
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
||||
|
||||
export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): TIX {
|
||||
export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript): InternalAPI<TIX> {
|
||||
/**
|
||||
* Checks if the player has TIX API access. Throws an error if the player does not
|
||||
*/
|
||||
const checkTixApiAccess = function (callingFn: string): void {
|
||||
const checkTixApiAccess = function (ctx: NetscriptContext): void {
|
||||
if (!player.hasWseAccount) {
|
||||
throw helper.makeRuntimeErrorMsg(callingFn, `You don't have WSE Access! Cannot use ${callingFn}()`);
|
||||
throw ctx.makeRuntimeErrorMsg(`You don't have WSE Access! Cannot use ${ctx.function}()`);
|
||||
}
|
||||
if (!player.hasTixApiAccess) {
|
||||
throw helper.makeRuntimeErrorMsg(callingFn, `You don't have TIX API Access! Cannot use ${callingFn}()`);
|
||||
throw ctx.makeRuntimeErrorMsg(`You don't have TIX API Access! Cannot use ${ctx.function}()`);
|
||||
}
|
||||
};
|
||||
|
||||
const getStockFromSymbol = function (symbol: string, callingFn: string): Stock {
|
||||
const getStockFromSymbol = function (ctx: NetscriptContext, symbol: string): Stock {
|
||||
const stock = SymbolToStockMap[symbol];
|
||||
if (stock == null) {
|
||||
throw helper.makeRuntimeErrorMsg(callingFn, `Invalid stock symbol: '${symbol}'`);
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid stock symbol: '${symbol}'`);
|
||||
}
|
||||
|
||||
return stock;
|
||||
};
|
||||
|
||||
const updateRam = (funcName: string): void =>
|
||||
helper.updateDynamicRam(funcName, getRamCost(player, "stock", funcName));
|
||||
|
||||
return {
|
||||
getSymbols: function (): string[] {
|
||||
updateRam("getSymbols");
|
||||
checkTixApiAccess("getSymbols");
|
||||
getSymbols: (ctx: NetscriptContext) => (): string[] => {
|
||||
checkTixApiAccess(ctx);
|
||||
return Object.values(StockSymbols);
|
||||
},
|
||||
getPrice: function (_symbol: unknown): number {
|
||||
updateRam("getPrice");
|
||||
const symbol = helper.string("getPrice", "symbol", _symbol);
|
||||
checkTixApiAccess("getPrice");
|
||||
const stock = getStockFromSymbol(symbol, "getPrice");
|
||||
getPrice:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
checkTixApiAccess(ctx);
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
|
||||
return stock.price;
|
||||
},
|
||||
getAskPrice: function (_symbol: unknown): number {
|
||||
updateRam("getAskPrice");
|
||||
const symbol = helper.string("getAskPrice", "symbol", _symbol);
|
||||
checkTixApiAccess("getAskPrice");
|
||||
const stock = getStockFromSymbol(symbol, "getAskPrice");
|
||||
return stock.price;
|
||||
},
|
||||
getAskPrice:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
checkTixApiAccess(ctx);
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
|
||||
return stock.getAskPrice();
|
||||
},
|
||||
getBidPrice: function (_symbol: unknown): number {
|
||||
updateRam("getBidPrice");
|
||||
const symbol = helper.string("getBidPrice", "symbol", _symbol);
|
||||
checkTixApiAccess("getBidPrice");
|
||||
const stock = getStockFromSymbol(symbol, "getBidPrice");
|
||||
return stock.getAskPrice();
|
||||
},
|
||||
getBidPrice:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
checkTixApiAccess(ctx);
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
|
||||
return stock.getBidPrice();
|
||||
},
|
||||
getPosition: function (_symbol: unknown): [number, number, number, number] {
|
||||
updateRam("getPosition");
|
||||
const symbol = helper.string("getPosition", "symbol", _symbol);
|
||||
checkTixApiAccess("getPosition");
|
||||
const stock = SymbolToStockMap[symbol];
|
||||
if (stock == null) {
|
||||
throw helper.makeRuntimeErrorMsg("getPosition", `Invalid stock symbol: ${symbol}`);
|
||||
}
|
||||
return [stock.playerShares, stock.playerAvgPx, stock.playerShortShares, stock.playerAvgShortPx];
|
||||
},
|
||||
getMaxShares: function (_symbol: unknown): number {
|
||||
updateRam("getMaxShares");
|
||||
const symbol = helper.string("getMaxShares", "symbol", _symbol);
|
||||
checkTixApiAccess("getMaxShares");
|
||||
const stock = getStockFromSymbol(symbol, "getMaxShares");
|
||||
|
||||
return stock.maxShares;
|
||||
},
|
||||
getPurchaseCost: function (_symbol: unknown, _shares: unknown, _posType: unknown): number {
|
||||
updateRam("getPurchaseCost");
|
||||
const symbol = helper.string("getPurchaseCost", "symbol", _symbol);
|
||||
let shares = helper.number("getPurchaseCost", "shares", _shares);
|
||||
const posType = helper.string("getPurchaseCost", "posType", _posType);
|
||||
checkTixApiAccess("getPurchaseCost");
|
||||
const stock = getStockFromSymbol(symbol, "getPurchaseCost");
|
||||
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;
|
||||
}
|
||||
|
||||
const res = getBuyTransactionCost(stock, shares, pos);
|
||||
if (res == null) {
|
||||
return Infinity;
|
||||
}
|
||||
|
||||
return res;
|
||||
},
|
||||
getSaleGain: function (_symbol: unknown, _shares: unknown, _posType: unknown): number {
|
||||
updateRam("getSaleGain");
|
||||
const symbol = helper.string("getSaleGain", "symbol", _symbol);
|
||||
let shares = helper.number("getSaleGain", "shares", _shares);
|
||||
const posType = helper.string("getSaleGain", "posType", _posType);
|
||||
checkTixApiAccess("getSaleGain");
|
||||
const stock = getStockFromSymbol(symbol, "getSaleGain");
|
||||
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;
|
||||
}
|
||||
|
||||
const res = getSellTransactionGain(stock, shares, pos);
|
||||
if (res == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
},
|
||||
buy: function (_symbol: unknown, _shares: unknown): number {
|
||||
updateRam("buy");
|
||||
const symbol = helper.string("buy", "symbol", _symbol);
|
||||
const shares = helper.number("buy", "shares", _shares);
|
||||
checkTixApiAccess("buy");
|
||||
const stock = getStockFromSymbol(symbol, "buy");
|
||||
const res = buyStock(stock, shares, workerScript, {});
|
||||
return res ? stock.getAskPrice() : 0;
|
||||
},
|
||||
sell: function (_symbol: unknown, _shares: unknown): number {
|
||||
updateRam("sell");
|
||||
const symbol = helper.string("sell", "symbol", _symbol);
|
||||
const shares = helper.number("sell", "shares", _shares);
|
||||
checkTixApiAccess("sell");
|
||||
const stock = getStockFromSymbol(symbol, "sell");
|
||||
const res = sellStock(stock, shares, workerScript, {});
|
||||
|
||||
return res ? stock.getBidPrice() : 0;
|
||||
},
|
||||
short: function (_symbol: unknown, _shares: unknown): number {
|
||||
updateRam("short");
|
||||
const symbol = helper.string("short", "symbol", _symbol);
|
||||
const shares = helper.number("short", "shares", _shares);
|
||||
checkTixApiAccess("short");
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 1) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"short",
|
||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 2.",
|
||||
);
|
||||
return stock.getBidPrice();
|
||||
},
|
||||
getPosition:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown): [number, number, number, number] => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
checkTixApiAccess(ctx);
|
||||
const stock = SymbolToStockMap[symbol];
|
||||
if (stock == null) {
|
||||
throw ctx.makeRuntimeErrorMsg(`Invalid stock symbol: ${symbol}`);
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(symbol, "short");
|
||||
const res = shortStock(stock, shares, workerScript, {});
|
||||
return [stock.playerShares, stock.playerAvgPx, stock.playerShortShares, stock.playerAvgShortPx];
|
||||
},
|
||||
getMaxShares:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
checkTixApiAccess(ctx);
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
|
||||
return res ? stock.getBidPrice() : 0;
|
||||
},
|
||||
sellShort: function (_symbol: unknown, _shares: unknown): number {
|
||||
updateRam("sellShort");
|
||||
const symbol = helper.string("sellShort", "symbol", _symbol);
|
||||
const shares = helper.number("sellShort", "shares", _shares);
|
||||
checkTixApiAccess("sellShort");
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 1) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"sellShort",
|
||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 2.",
|
||||
);
|
||||
return stock.maxShares;
|
||||
},
|
||||
getPurchaseCost:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown, _shares: unknown, _posType: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
let shares = ctx.helper.number("shares", _shares);
|
||||
const posType = ctx.helper.string("posType", _posType);
|
||||
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;
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(symbol, "sellShort");
|
||||
const res = sellShort(stock, shares, workerScript, {});
|
||||
|
||||
return res ? stock.getAskPrice() : 0;
|
||||
},
|
||||
placeOrder: function (_symbol: unknown, _shares: unknown, _price: unknown, _type: unknown, _pos: unknown): boolean {
|
||||
updateRam("placeOrder");
|
||||
const symbol = helper.string("placeOrder", "symbol", _symbol);
|
||||
const shares = helper.number("placeOrder", "shares", _shares);
|
||||
const price = helper.number("placeOrder", "price", _price);
|
||||
const type = helper.string("placeOrder", "type", _type);
|
||||
const pos = helper.string("placeOrder", "pos", _pos);
|
||||
checkTixApiAccess("placeOrder");
|
||||
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 = ctx.helper.string("symbol", _symbol);
|
||||
let shares = ctx.helper.number("shares", _shares);
|
||||
const posType = ctx.helper.string("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;
|
||||
}
|
||||
|
||||
const res = getSellTransactionGain(stock, shares, pos);
|
||||
if (res == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
},
|
||||
buy:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown, _shares: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const shares = ctx.helper.number("shares", _shares);
|
||||
checkTixApiAccess(ctx);
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
const res = buyStock(stock, shares, workerScript, {});
|
||||
return res ? stock.getAskPrice() : 0;
|
||||
},
|
||||
sell:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown, _shares: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const shares = ctx.helper.number("shares", _shares);
|
||||
checkTixApiAccess(ctx);
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
const res = sellStock(stock, shares, workerScript, {});
|
||||
|
||||
return res ? stock.getBidPrice() : 0;
|
||||
},
|
||||
short:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown, _shares: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const shares = ctx.helper.number("shares", _shares);
|
||||
checkTixApiAccess(ctx);
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 1) {
|
||||
throw ctx.makeRuntimeErrorMsg("You must either be in BitNode-8 or you must have Source-File 8 Level 2.");
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
const res = shortStock(stock, shares, workerScript, {});
|
||||
|
||||
return res ? stock.getBidPrice() : 0;
|
||||
},
|
||||
sellShort:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown, _shares: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const shares = ctx.helper.number("shares", _shares);
|
||||
checkTixApiAccess(ctx);
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 1) {
|
||||
throw ctx.makeRuntimeErrorMsg("You must either be in BitNode-8 or you must have Source-File 8 Level 2.");
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
const res = sellShort(stock, shares, workerScript, {});
|
||||
|
||||
return res ? stock.getAskPrice() : 0;
|
||||
},
|
||||
placeOrder:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown, _shares: unknown, _price: unknown, _type: unknown, _pos: unknown): boolean => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const shares = ctx.helper.number("shares", _shares);
|
||||
const price = ctx.helper.number("price", _price);
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const pos = ctx.helper.string("pos", _pos);
|
||||
checkTixApiAccess(ctx);
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 2) {
|
||||
throw ctx.makeRuntimeErrorMsg("You must either be in BitNode-8 or you must have Source-File 8 Level 3.");
|
||||
}
|
||||
}
|
||||
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 ctx.makeRuntimeErrorMsg(`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 ctx.makeRuntimeErrorMsg(`Invalid position type: ${pos}`);
|
||||
}
|
||||
|
||||
return placeOrder(stock, shares, price, orderType, orderPos, workerScript);
|
||||
},
|
||||
cancelOrder:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown, _shares: unknown, _price: unknown, _type: unknown, _pos: unknown): boolean => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
const shares = ctx.helper.number("shares", _shares);
|
||||
const price = ctx.helper.number("price", _price);
|
||||
const type = ctx.helper.string("type", _type);
|
||||
const pos = ctx.helper.string("pos", _pos);
|
||||
checkTixApiAccess(ctx);
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 2) {
|
||||
throw ctx.makeRuntimeErrorMsg("You must either be in BitNode-8 or you must have Source-File 8 Level 3.");
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(ctx, symbol);
|
||||
if (isNaN(shares) || isNaN(price)) {
|
||||
throw ctx.makeRuntimeErrorMsg(`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 ctx.makeRuntimeErrorMsg(`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 ctx.makeRuntimeErrorMsg(`Invalid position type: ${pos}`);
|
||||
}
|
||||
const params = {
|
||||
stock: stock,
|
||||
shares: shares,
|
||||
price: price,
|
||||
type: orderType,
|
||||
pos: orderPos,
|
||||
};
|
||||
return cancelOrder(params, workerScript);
|
||||
},
|
||||
getOrders: (ctx: NetscriptContext) => (): any => {
|
||||
checkTixApiAccess(ctx);
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 2) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"placeOrder",
|
||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 3.",
|
||||
);
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(symbol, "placeOrder");
|
||||
|
||||
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 helper.makeRuntimeErrorMsg("placeOrder", `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 helper.makeRuntimeErrorMsg("placeOrder", `Invalid position type: ${pos}`);
|
||||
}
|
||||
|
||||
return placeOrder(stock, shares, price, orderType, orderPos, workerScript);
|
||||
},
|
||||
cancelOrder: function (
|
||||
_symbol: unknown,
|
||||
_shares: unknown,
|
||||
_price: unknown,
|
||||
_type: unknown,
|
||||
_pos: unknown,
|
||||
): boolean {
|
||||
updateRam("cancelOrder");
|
||||
const symbol = helper.string("cancelOrder", "symbol", _symbol);
|
||||
const shares = helper.number("cancelOrder", "shares", _shares);
|
||||
const price = helper.number("cancelOrder", "price", _price);
|
||||
const type = helper.string("cancelOrder", "type", _type);
|
||||
const pos = helper.string("cancelOrder", "pos", _pos);
|
||||
checkTixApiAccess("cancelOrder");
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 2) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"cancelOrder",
|
||||
"You must either be in BitNode-8 or you must have Source-File 8 Level 3.",
|
||||
);
|
||||
}
|
||||
}
|
||||
const stock = getStockFromSymbol(symbol, "cancelOrder");
|
||||
if (isNaN(shares) || isNaN(price)) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"cancelOrder",
|
||||
`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 helper.makeRuntimeErrorMsg("cancelOrder", `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 helper.makeRuntimeErrorMsg("cancelOrder", `Invalid position type: ${pos}`);
|
||||
}
|
||||
const params = {
|
||||
stock: stock,
|
||||
shares: shares,
|
||||
price: price,
|
||||
type: orderType,
|
||||
pos: orderPos,
|
||||
};
|
||||
return cancelOrder(params, workerScript);
|
||||
},
|
||||
getOrders: function (): any {
|
||||
updateRam("getOrders");
|
||||
checkTixApiAccess("getOrders");
|
||||
if (player.bitNodeN !== 8) {
|
||||
if (player.sourceFileLvl(8) <= 2) {
|
||||
throw helper.makeRuntimeErrorMsg(
|
||||
"getOrders",
|
||||
"You must either be in BitNode-8 or have Source-File 8 Level 3.",
|
||||
);
|
||||
throw ctx.makeRuntimeErrorMsg("You must either be in BitNode-8 or have Source-File 8 Level 3.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -334,103 +317,95 @@ export function NetscriptStockMarket(player: IPlayer, workerScript: WorkerScript
|
||||
|
||||
return orders;
|
||||
},
|
||||
getVolatility: function (_symbol: unknown): number {
|
||||
updateRam("getVolatility");
|
||||
const symbol = helper.string("getVolatility", "symbol", _symbol);
|
||||
if (!player.has4SDataTixApi) {
|
||||
throw helper.makeRuntimeErrorMsg("getVolatility", "You don't have 4S Market Data TIX API Access!");
|
||||
}
|
||||
const stock = getStockFromSymbol(symbol, "getVolatility");
|
||||
getVolatility:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
if (!player.has4SDataTixApi) {
|
||||
throw ctx.makeRuntimeErrorMsg("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: function (_symbol: unknown): number {
|
||||
updateRam("getForecast");
|
||||
const symbol = helper.string("getForecast", "symbol", _symbol);
|
||||
if (!player.has4SDataTixApi) {
|
||||
throw helper.makeRuntimeErrorMsg("getForecast", "You don't have 4S Market Data TIX API Access!");
|
||||
}
|
||||
const stock = getStockFromSymbol(symbol, "getForecast");
|
||||
|
||||
let forecast = 50;
|
||||
stock.b ? (forecast += stock.otlkMag) : (forecast -= stock.otlkMag);
|
||||
return forecast / 100; // Convert from percentage to decimal
|
||||
},
|
||||
purchase4SMarketData: function (): boolean {
|
||||
updateRam("purchase4SMarketData");
|
||||
return stock.mv / 100; // Convert from percentage to decimal
|
||||
},
|
||||
getForecast:
|
||||
(ctx: NetscriptContext) =>
|
||||
(_symbol: unknown): number => {
|
||||
const symbol = ctx.helper.string("symbol", _symbol);
|
||||
if (!player.has4SDataTixApi) {
|
||||
throw ctx.makeRuntimeErrorMsg("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 => {
|
||||
if (player.has4SData) {
|
||||
workerScript.log("stock.purchase4SMarketData", () => "Already purchased 4S Market Data.");
|
||||
ctx.log(() => "Already purchased 4S Market Data.");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.money < getStockMarket4SDataCost()) {
|
||||
workerScript.log("stock.purchase4SMarketData", () => "Not enough money to purchase 4S Market Data.");
|
||||
ctx.log(() => "Not enough money to purchase 4S Market Data.");
|
||||
return false;
|
||||
}
|
||||
|
||||
player.has4SData = true;
|
||||
player.loseMoney(getStockMarket4SDataCost(), "stock");
|
||||
workerScript.log("stock.purchase4SMarketData", () => "Purchased 4S Market Data");
|
||||
ctx.log(() => "Purchased 4S Market Data");
|
||||
return true;
|
||||
},
|
||||
purchase4SMarketDataTixApi: function (): boolean {
|
||||
updateRam("purchase4SMarketDataTixApi");
|
||||
checkTixApiAccess("purchase4SMarketDataTixApi");
|
||||
purchase4SMarketDataTixApi: (ctx: NetscriptContext) => (): boolean => {
|
||||
checkTixApiAccess(ctx);
|
||||
|
||||
if (player.has4SDataTixApi) {
|
||||
workerScript.log("stock.purchase4SMarketDataTixApi", () => "Already purchased 4S Market Data TIX API");
|
||||
ctx.log(() => "Already purchased 4S Market Data TIX API");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.money < getStockMarket4STixApiCost()) {
|
||||
workerScript.log(
|
||||
"stock.purchase4SMarketDataTixApi",
|
||||
() => "Not enough money to purchase 4S Market Data TIX API",
|
||||
);
|
||||
ctx.log(() => "Not enough money to purchase 4S Market Data TIX API");
|
||||
return false;
|
||||
}
|
||||
|
||||
player.has4SDataTixApi = true;
|
||||
player.loseMoney(getStockMarket4STixApiCost(), "stock");
|
||||
workerScript.log("stock.purchase4SMarketDataTixApi", () => "Purchased 4S Market Data TIX API");
|
||||
ctx.log(() => "Purchased 4S Market Data TIX API");
|
||||
return true;
|
||||
},
|
||||
purchaseWseAccount: function (): boolean {
|
||||
updateRam("PurchaseWseAccount");
|
||||
|
||||
purchaseWseAccount: (ctx: NetscriptContext) => (): boolean => {
|
||||
if (player.hasWseAccount) {
|
||||
workerScript.log("stock.purchaseWseAccount", () => "Already purchased WSE Account");
|
||||
ctx.log(() => "Already purchased WSE Account");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.money < getStockMarketWseCost()) {
|
||||
workerScript.log("stock.purchaseWseAccount", () => "Not enough money to purchase WSE Account Access");
|
||||
ctx.log(() => "Not enough money to purchase WSE Account Access");
|
||||
return false;
|
||||
}
|
||||
|
||||
player.hasWseAccount = true;
|
||||
initStockMarketFn();
|
||||
player.loseMoney(getStockMarketWseCost(), "stock");
|
||||
workerScript.log("stock.purchaseWseAccount", () => "Purchased WSE Account Access");
|
||||
ctx.log(() => "Purchased WSE Account Access");
|
||||
return true;
|
||||
},
|
||||
purchaseTixApi: function (): boolean {
|
||||
updateRam("purchaseTixApi");
|
||||
|
||||
purchaseTixApi: (ctx: NetscriptContext) => (): boolean => {
|
||||
if (player.hasTixApiAccess) {
|
||||
workerScript.log("stock.purchaseTixApi", () => "Already purchased TIX API");
|
||||
ctx.log(() => "Already purchased TIX API");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.money < getStockMarketTixApiCost()) {
|
||||
workerScript.log("stock.purchaseTixApi", () => "Not enough money to purchase TIX API Access");
|
||||
ctx.log(() => "Not enough money to purchase TIX API Access");
|
||||
return false;
|
||||
}
|
||||
|
||||
player.hasTixApiAccess = true;
|
||||
player.loseMoney(getStockMarketTixApiCost(), "stock");
|
||||
workerScript.log("stock.purchaseTixApi", () => "Purchased TIX API");
|
||||
ctx.log(() => "Purchased TIX API");
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
@ -1,7 +1,3 @@
|
||||
import { INetscriptHelper } from "./INetscriptHelper";
|
||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||
import { getRamCost } from "../Netscript/RamCostGenerator";
|
||||
import {
|
||||
GameInfo,
|
||||
IStyleSettings,
|
||||
@ -14,88 +10,80 @@ import { defaultTheme } from "../Themes/Themes";
|
||||
import { defaultStyles } from "../Themes/Styles";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { hash } from "../hash/hash";
|
||||
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
||||
|
||||
export function NetscriptUserInterface(
|
||||
player: IPlayer,
|
||||
workerScript: WorkerScript,
|
||||
helper: INetscriptHelper,
|
||||
): IUserInterface {
|
||||
const updateRam = (funcName: string): void => helper.updateDynamicRam(funcName, getRamCost(player, "ui", funcName));
|
||||
export function NetscriptUserInterface(): InternalAPI<IUserInterface> {
|
||||
return {
|
||||
getTheme: function (): UserInterfaceTheme {
|
||||
updateRam("getTheme");
|
||||
getTheme: () => (): UserInterfaceTheme => {
|
||||
return { ...Settings.theme };
|
||||
},
|
||||
|
||||
getStyles: function (): IStyleSettings {
|
||||
updateRam("getStyles");
|
||||
getStyles: () => (): IStyleSettings => {
|
||||
return { ...Settings.styles };
|
||||
},
|
||||
|
||||
setTheme: function (newTheme: UserInterfaceTheme): void {
|
||||
updateRam("setTheme");
|
||||
const hex = /^(#)((?:[A-Fa-f0-9]{2}){3,4}|(?:[A-Fa-f0-9]{3}))$/;
|
||||
const currentTheme = { ...Settings.theme };
|
||||
const errors: string[] = [];
|
||||
for (const key of Object.keys(newTheme)) {
|
||||
if (!currentTheme[key]) {
|
||||
// Invalid key
|
||||
errors.push(`Invalid key "${key}"`);
|
||||
} else if (!hex.test(newTheme[key] ?? "")) {
|
||||
errors.push(`Invalid color "${key}": ${newTheme[key]}`);
|
||||
} else {
|
||||
currentTheme[key] = newTheme[key];
|
||||
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[] = [];
|
||||
for (const key of Object.keys(newTheme)) {
|
||||
if (!currentTheme[key]) {
|
||||
// Invalid key
|
||||
errors.push(`Invalid key "${key}"`);
|
||||
} else if (!hex.test(newTheme[key] ?? "")) {
|
||||
errors.push(`Invalid color "${key}": ${newTheme[key]}`);
|
||||
} else {
|
||||
currentTheme[key] = newTheme[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length === 0) {
|
||||
Object.assign(Settings.theme, currentTheme);
|
||||
ThemeEvents.emit();
|
||||
workerScript.log("ui.setTheme", () => `Successfully set theme`);
|
||||
} else {
|
||||
workerScript.log("ui.setTheme", () => `Failed to set theme. Errors: ${errors.join(", ")}`);
|
||||
}
|
||||
},
|
||||
|
||||
setStyles: function (newStyles: IStyleSettings): void {
|
||||
updateRam("setStyles");
|
||||
|
||||
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}"`);
|
||||
if (errors.length === 0) {
|
||||
Object.assign(Settings.theme, currentTheme);
|
||||
ThemeEvents.emit();
|
||||
ctx.log(() => `Successfully set theme`);
|
||||
} else {
|
||||
(currentStyles as any)[key] = (newStyles as any)[key];
|
||||
ctx.log(() => `Failed to set theme. Errors: ${errors.join(", ")}`);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
if (errors.length === 0) {
|
||||
Object.assign(Settings.styles, currentStyles);
|
||||
ThemeEvents.emit();
|
||||
workerScript.log("ui.setStyles", () => `Successfully set styles`);
|
||||
} else {
|
||||
workerScript.log("ui.setStyles", () => `Failed to set styles. Errors: ${errors.join(", ")}`);
|
||||
}
|
||||
},
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
resetTheme: function (): void {
|
||||
updateRam("resetTheme");
|
||||
if (errors.length === 0) {
|
||||
Object.assign(Settings.styles, currentStyles);
|
||||
ThemeEvents.emit();
|
||||
ctx.log(() => `Successfully set styles`);
|
||||
} else {
|
||||
ctx.log(() => `Failed to set styles. Errors: ${errors.join(", ")}`);
|
||||
}
|
||||
},
|
||||
|
||||
resetTheme: (ctx: NetscriptContext) => (): void => {
|
||||
Settings.theme = { ...defaultTheme };
|
||||
ThemeEvents.emit();
|
||||
workerScript.log("ui.resetTheme", () => `Reinitialized theme to default`);
|
||||
ctx.log(() => `Reinitialized theme to default`);
|
||||
},
|
||||
|
||||
resetStyles: function (): void {
|
||||
updateRam("resetStyles");
|
||||
resetStyles: (ctx: NetscriptContext) => (): void => {
|
||||
Settings.styles = { ...defaultStyles };
|
||||
ThemeEvents.emit();
|
||||
workerScript.log("ui.resetStyles", () => `Reinitialized styles to default`);
|
||||
ctx.log(() => `Reinitialized styles to default`);
|
||||
},
|
||||
|
||||
getGameInfo: function (): GameInfo {
|
||||
updateRam("getGameInfo");
|
||||
getGameInfo: () => (): GameInfo => {
|
||||
const version = CONSTANTS.VersionString;
|
||||
const commit = hash();
|
||||
const platform = navigator.userAgent.toLowerCase().indexOf(" electron/") > -1 ? "Steam" : "Browser";
|
||||
|
Loading…
Reference in New Issue
Block a user