bitburner-src/src/NetscriptFunctions/Bladeburner.ts

430 lines
19 KiB
TypeScript
Raw Normal View History

2022-08-09 21:41:47 +02:00
import { Player as player } from "../Player";
2021-10-14 09:22:02 +02:00
import { Bladeburner } from "../Bladeburner/Bladeburner";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { Bladeburner as INetscriptBladeburner, BladeburnerCurAction } from "../ScriptEditor/NetscriptDefinitions";
2022-03-30 02:44:27 +02:00
import { IAction } from "src/Bladeburner/IAction";
2022-05-08 01:08:07 +02:00
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
2022-07-20 00:25:06 +02:00
import { BlackOperation } from "../Bladeburner/BlackOperation";
2022-08-08 19:43:41 +02:00
import { helpers } from "../Netscript/NetscriptHelpers";
2021-10-14 09:22:02 +02:00
2022-08-09 21:41:47 +02:00
export function NetscriptBladeburner(): InternalAPI<INetscriptBladeburner> {
2022-05-08 01:08:07 +02:00
const checkBladeburnerAccess = function (ctx: NetscriptContext, skipjoined = false): void {
2021-10-14 09:22:02 +02:00
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Must have joined bladeburner");
const apiAccess =
player.bitNodeN === 7 ||
player.sourceFiles.some((a) => {
return a.n === 7;
});
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.`;
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, apiDenied);
2021-10-14 09:22:02 +02:00
}
if (!skipjoined) {
const bladeburnerAccess = bladeburner instanceof Bladeburner;
if (!bladeburnerAccess) {
const bladeburnerDenied = `You must be a member of the Bladeburner division to use this API.`;
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, bladeburnerDenied);
2021-10-14 09:22:02 +02:00
}
}
};
2022-05-08 01:08:07 +02:00
const checkBladeburnerCity = function (ctx: NetscriptContext, city: string): void {
2021-10-14 09:22:02 +02:00
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Must have joined bladeburner");
if (!bladeburner.cities.hasOwnProperty(city)) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid city: ${city}`);
2021-10-14 09:22:02 +02:00
}
};
2022-05-08 01:08:07 +02:00
const getBladeburnerActionObject = function (ctx: NetscriptContext, type: string, name: string): IAction {
2021-10-14 09:22:02 +02:00
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Must have joined bladeburner");
const actionId = bladeburner.getActionIdFromTypeAndName(type, name);
if (!actionId) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid action type='${type}', name='${name}'`);
2021-10-14 09:22:02 +02:00
}
const actionObj = bladeburner.getActionObject(actionId);
if (!actionObj) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid action type='${type}', name='${name}'`);
2021-10-14 09:22:02 +02:00
}
return actionObj;
};
return {
2022-05-08 01:08:07 +02:00
getContractNames: (ctx: NetscriptContext) => (): string[] => {
checkBladeburnerAccess(ctx);
2021-10-14 09:22:02 +02:00
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.getContractNamesNetscriptFn();
},
2022-05-08 01:08:07 +02:00
getOperationNames: (ctx: NetscriptContext) => (): string[] => {
checkBladeburnerAccess(ctx);
2021-10-14 09:22:02 +02:00
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.getOperationNamesNetscriptFn();
},
2022-05-08 01:08:07 +02:00
getBlackOpNames: (ctx: NetscriptContext) => (): string[] => {
checkBladeburnerAccess(ctx);
2021-10-14 09:22:02 +02:00
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.getBlackOpNamesNetscriptFn();
},
2022-05-08 01:08:07 +02:00
getBlackOpRank:
(ctx: NetscriptContext) =>
(_blackOpName: unknown): number => {
2022-08-08 19:43:41 +02:00
const blackOpName = helpers.string(ctx, "blackOpName", _blackOpName);
2022-05-08 01:08:07 +02:00
checkBladeburnerAccess(ctx);
2022-07-20 00:25:06 +02:00
const action = getBladeburnerActionObject(ctx, "blackops", blackOpName);
if (!(action instanceof BlackOperation)) throw new Error("action was not a black operation");
2022-05-08 01:08:07 +02:00
return action.reqdRank;
},
getGeneralActionNames: (ctx: NetscriptContext) => (): string[] => {
checkBladeburnerAccess(ctx);
2021-10-14 09:22:02 +02:00
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.getGeneralActionNamesNetscriptFn();
},
2022-05-08 01:08:07 +02:00
getSkillNames: (ctx: NetscriptContext) => (): string[] => {
checkBladeburnerAccess(ctx);
2021-10-14 09:22:02 +02:00
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.getSkillNamesNetscriptFn();
},
2022-05-08 01:08:07 +02:00
startAction:
(ctx: NetscriptContext) =>
(_type: unknown, _name: unknown): boolean => {
2022-08-08 19:43:41 +02:00
const type = helpers.string(ctx, "type", _type);
const name = helpers.string(ctx, "name", _name);
2022-05-08 01:08:07 +02:00
checkBladeburnerAccess(ctx);
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try {
2022-08-09 21:41:47 +02:00
return bladeburner.startActionNetscriptFn(player, type, name, ctx.workerScript);
2022-07-15 07:51:30 +02:00
} catch (e: unknown) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
2022-05-08 01:08:07 +02:00
}
},
stopBladeburnerAction: (ctx: NetscriptContext) => (): void => {
checkBladeburnerAccess(ctx);
2021-10-14 09:22:02 +02:00
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.resetAction();
},
2022-05-08 01:08:07 +02:00
getCurrentAction: (ctx: NetscriptContext) => (): BladeburnerCurAction => {
checkBladeburnerAccess(ctx);
2021-10-14 09:22:02 +02:00
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.getTypeAndNameFromActionId(bladeburner.action);
},
2022-05-08 01:08:07 +02:00
getActionTime:
(ctx: NetscriptContext) =>
(_type: unknown, _name: unknown): number => {
2022-08-08 19:43:41 +02:00
const type = helpers.string(ctx, "type", _type);
const name = helpers.string(ctx, "name", _name);
2022-05-08 01:08:07 +02:00
checkBladeburnerAccess(ctx);
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try {
2022-05-20 21:58:33 +02:00
const time = bladeburner.getActionTimeNetscriptFn(player, type, name);
if (typeof time === "string") {
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
2022-08-08 21:51:50 +02:00
helpers.log(ctx, () => errorLogText);
2022-05-20 21:58:33 +02:00
return -1;
} else {
return time;
}
2022-07-15 07:51:30 +02:00
} catch (e: unknown) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
}
2022-05-08 01:08:07 +02:00
},
getActionCurrentTime: (ctx: NetscriptContext) => (): number => {
checkBladeburnerAccess(ctx);
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try {
2022-05-22 06:40:32 +02:00
const timecomputed =
Math.min(bladeburner.actionTimeCurrent + bladeburner.actionTimeOverflow, bladeburner.actionTimeToComplete) *
1000;
return timecomputed;
2022-07-15 07:51:30 +02:00
} catch (e: unknown) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
}
},
2022-05-08 01:08:07 +02:00
getActionEstimatedSuccessChance:
(ctx: NetscriptContext) =>
(_type: unknown, _name: unknown): [number, number] => {
2022-08-08 19:43:41 +02:00
const type = helpers.string(ctx, "type", _type);
const name = helpers.string(ctx, "name", _name);
2022-05-08 01:08:07 +02:00
checkBladeburnerAccess(ctx);
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try {
2022-05-20 21:58:33 +02:00
const chance = bladeburner.getActionEstimatedSuccessChanceNetscriptFn(player, type, name);
if (typeof chance === "string") {
const errorLogText = `Invalid action: type='${type}' name='${name}'`;
2022-08-08 21:51:50 +02:00
helpers.log(ctx, () => errorLogText);
2022-05-20 21:58:33 +02:00
return [-1, -1];
} else {
return chance;
}
2022-07-15 07:51:30 +02:00
} catch (e: unknown) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
2022-05-08 01:08:07 +02:00
}
},
getActionRepGain:
(ctx: NetscriptContext) =>
(_type: unknown, _name: unknown, _level: unknown): number => {
2022-08-08 19:43:41 +02:00
const type = helpers.string(ctx, "type", _type);
const name = helpers.string(ctx, "name", _name);
const level = helpers.number(ctx, "level", _level);
2022-05-08 01:08:07 +02:00
checkBladeburnerAccess(ctx);
const action = getBladeburnerActionObject(ctx, type, name);
let rewardMultiplier;
if (level == null || isNaN(level)) {
rewardMultiplier = Math.pow(action.rewardFac, action.level - 1);
} else {
2022-05-08 01:08:07 +02:00
rewardMultiplier = Math.pow(action.rewardFac, level - 1);
}
2021-10-14 09:22:02 +02:00
2022-05-08 01:08:07 +02:00
return action.rankGain * rewardMultiplier * BitNodeMultipliers.BladeburnerRank;
},
getActionCountRemaining:
(ctx: NetscriptContext) =>
(_type: unknown, _name: unknown): number => {
2022-08-08 19:43:41 +02:00
const type = helpers.string(ctx, "type", _type);
const name = helpers.string(ctx, "name", _name);
2022-05-08 01:08:07 +02:00
checkBladeburnerAccess(ctx);
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try {
2022-08-09 21:41:47 +02:00
return bladeburner.getActionCountRemainingNetscriptFn(type, name, ctx.workerScript);
2022-07-15 07:51:30 +02:00
} catch (e: unknown) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
2022-05-08 01:08:07 +02:00
}
},
getActionMaxLevel:
(ctx: NetscriptContext) =>
(_type: unknown, _name: unknown): number => {
2022-08-08 19:43:41 +02:00
const type = helpers.string(ctx, "type", _type);
const name = helpers.string(ctx, "name", _name);
2022-05-08 01:08:07 +02:00
checkBladeburnerAccess(ctx);
const action = getBladeburnerActionObject(ctx, type, name);
return action.maxLevel;
},
getActionCurrentLevel:
(ctx: NetscriptContext) =>
(_type: unknown, _name: unknown): number => {
2022-08-08 19:43:41 +02:00
const type = helpers.string(ctx, "type", _type);
const name = helpers.string(ctx, "name", _name);
2022-05-08 01:08:07 +02:00
checkBladeburnerAccess(ctx);
const action = getBladeburnerActionObject(ctx, type, name);
return action.level;
},
getActionAutolevel:
(ctx: NetscriptContext) =>
(_type: unknown, _name: unknown): boolean => {
2022-08-08 19:43:41 +02:00
const type = helpers.string(ctx, "type", _type);
const name = helpers.string(ctx, "name", _name);
2022-05-08 01:08:07 +02:00
checkBladeburnerAccess(ctx);
const action = getBladeburnerActionObject(ctx, type, name);
return action.autoLevel;
},
setActionAutolevel:
(ctx: NetscriptContext) =>
(_type: unknown, _name: unknown, _autoLevel: unknown = true): void => {
2022-08-08 19:43:41 +02:00
const type = helpers.string(ctx, "type", _type);
const name = helpers.string(ctx, "name", _name);
const autoLevel = !!_autoLevel;
2022-05-08 01:08:07 +02:00
checkBladeburnerAccess(ctx);
const action = getBladeburnerActionObject(ctx, type, name);
action.autoLevel = autoLevel;
},
setActionLevel:
(ctx: NetscriptContext) =>
(_type: unknown, _name: unknown, _level: unknown = 1): void => {
2022-08-08 19:43:41 +02:00
const type = helpers.string(ctx, "type", _type);
const name = helpers.string(ctx, "name", _name);
const level = helpers.number(ctx, "level", _level);
2022-05-08 01:08:07 +02:00
checkBladeburnerAccess(ctx);
const action = getBladeburnerActionObject(ctx, type, name);
if (level < 1 || level > action.maxLevel) {
throw helpers.makeRuntimeErrorMsg(ctx, `Level must be between 1 and ${action.maxLevel}, is ${level}`);
2022-05-08 01:08:07 +02:00
}
action.level = level;
},
getRank: (ctx: NetscriptContext) => (): number => {
checkBladeburnerAccess(ctx);
2021-10-14 09:22:02 +02:00
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.rank;
},
2022-05-08 01:08:07 +02:00
getSkillPoints: (ctx: NetscriptContext) => (): number => {
checkBladeburnerAccess(ctx);
2021-10-14 09:22:02 +02:00
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.skillPoints;
},
2022-05-08 01:08:07 +02:00
getSkillLevel:
(ctx: NetscriptContext) =>
(_skillName: unknown): number => {
2022-08-08 19:43:41 +02:00
const skillName = helpers.string(ctx, "skillName", _skillName);
2022-05-08 01:08:07 +02:00
checkBladeburnerAccess(ctx);
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try {
2022-08-09 21:41:47 +02:00
return bladeburner.getSkillLevelNetscriptFn(skillName, ctx.workerScript);
2022-07-15 07:51:30 +02:00
} catch (e: unknown) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
2022-05-08 01:08:07 +02:00
}
},
getSkillUpgradeCost:
(ctx: NetscriptContext) =>
2022-06-01 04:27:04 +02:00
(_skillName: unknown, _count: unknown = 1): number => {
2022-08-08 19:43:41 +02:00
const skillName = helpers.string(ctx, "skillName", _skillName);
const count = helpers.number(ctx, "count", _count);
2022-05-08 01:08:07 +02:00
checkBladeburnerAccess(ctx);
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try {
2022-08-09 21:41:47 +02:00
return bladeburner.getSkillUpgradeCostNetscriptFn(skillName, count, ctx.workerScript);
2022-07-15 07:51:30 +02:00
} catch (e: unknown) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
2022-05-08 01:08:07 +02:00
}
},
upgradeSkill:
(ctx: NetscriptContext) =>
2022-06-01 04:27:04 +02:00
(_skillName: unknown, _count: unknown = 1): boolean => {
2022-08-08 19:43:41 +02:00
const skillName = helpers.string(ctx, "skillName", _skillName);
const count = helpers.number(ctx, "count", _count);
2022-05-08 01:08:07 +02:00
checkBladeburnerAccess(ctx);
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try {
2022-08-09 21:41:47 +02:00
return bladeburner.upgradeSkillNetscriptFn(skillName, count, ctx.workerScript);
2022-07-15 07:51:30 +02:00
} catch (e: unknown) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
2022-05-08 01:08:07 +02:00
}
},
getTeamSize:
(ctx: NetscriptContext) =>
(_type: unknown, _name: unknown): number => {
2022-08-08 19:43:41 +02:00
const type = helpers.string(ctx, "type", _type);
const name = helpers.string(ctx, "name", _name);
2022-05-08 01:08:07 +02:00
checkBladeburnerAccess(ctx);
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try {
2022-08-09 21:41:47 +02:00
return bladeburner.getTeamSizeNetscriptFn(type, name, ctx.workerScript);
2022-07-15 07:51:30 +02:00
} catch (e: unknown) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
2022-05-08 01:08:07 +02:00
}
},
setTeamSize:
(ctx: NetscriptContext) =>
(_type: unknown, _name: unknown, _size: unknown): number => {
2022-08-08 19:43:41 +02:00
const type = helpers.string(ctx, "type", _type);
const name = helpers.string(ctx, "name", _name);
const size = helpers.number(ctx, "size", _size);
2022-05-08 01:08:07 +02:00
checkBladeburnerAccess(ctx);
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
try {
2022-08-09 21:41:47 +02:00
return bladeburner.setTeamSizeNetscriptFn(type, name, size, ctx.workerScript);
2022-07-15 07:51:30 +02:00
} catch (e: unknown) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, String(e));
2022-05-08 01:08:07 +02:00
}
},
getCityEstimatedPopulation:
(ctx: NetscriptContext) =>
(_cityName: unknown): number => {
2022-08-08 19:43:41 +02:00
const cityName = helpers.string(ctx, "cityName", _cityName);
2022-05-08 01:08:07 +02:00
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 => {
2022-08-08 19:43:41 +02:00
const cityName = helpers.string(ctx, "cityName", _cityName);
2022-05-08 01:08:07 +02:00
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 => {
2022-08-08 19:43:41 +02:00
const cityName = helpers.string(ctx, "cityName", _cityName);
2022-05-08 01:08:07 +02:00
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);
2021-10-14 09:22:02 +02:00
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return bladeburner.city;
},
2022-05-08 01:08:07 +02:00
switchCity:
(ctx: NetscriptContext) =>
(_cityName: unknown): boolean => {
2022-08-08 19:43:41 +02:00
const cityName = helpers.string(ctx, "cityName", _cityName);
2022-05-08 01:08:07 +02:00
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);
2021-10-14 09:22:02 +02:00
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
return [bladeburner.stamina, bladeburner.maxStamina];
},
2022-05-08 01:08:07 +02:00
joinBladeburnerFaction: (ctx: NetscriptContext) => (): boolean => {
checkBladeburnerAccess(ctx, true);
2021-10-14 09:22:02 +02:00
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
2022-08-09 21:41:47 +02:00
return bladeburner.joinBladeburnerFactionNetscriptFn(ctx.workerScript);
2021-10-14 09:22:02 +02:00
},
2022-05-08 01:08:07 +02:00
joinBladeburnerDivision: (ctx: NetscriptContext) => (): boolean => {
2021-10-14 09:22:02 +02:00
if (player.bitNodeN === 7 || player.sourceFileLvl(7) > 0) {
if (BitNodeMultipliers.BladeburnerRank == 0) {
return false; // Disabled in this bitnode
2021-10-14 09:22:02 +02:00
}
if (player.bladeburner instanceof Bladeburner) {
return true; // Already member
} else if (
player.skills.strength >= 100 &&
player.skills.defense >= 100 &&
player.skills.dexterity >= 100 &&
player.skills.agility >= 100
2021-10-14 09:22:02 +02:00
) {
player.bladeburner = new Bladeburner(player);
2022-08-08 21:51:50 +02:00
helpers.log(ctx, () => "You have been accepted into the Bladeburner division");
2021-10-14 09:22:02 +02:00
return true;
} else {
2022-08-08 21:51:50 +02:00
helpers.log(ctx, () => "You do not meet the requirements for joining the Bladeburner division");
2021-10-14 09:22:02 +02:00
return false;
}
}
return false;
2021-10-14 09:22:02 +02:00
},
2022-05-08 01:08:07 +02:00
getBonusTime: (ctx: NetscriptContext) => (): number => {
checkBladeburnerAccess(ctx);
2021-10-14 09:22:02 +02:00
const bladeburner = player.bladeburner;
if (bladeburner === null) throw new Error("Should not be called without Bladeburner");
2022-03-30 02:44:27 +02:00
return Math.round(bladeburner.storedCycles / 5) * 1000;
2021-10-14 09:22:02 +02:00
},
};
}