bitburner-src/src/NetscriptFunctions/Sleeve.ts

334 lines
13 KiB
TypeScript
Raw Normal View History

import { Player } from "@player";
import { StaticAugmentations } from "../Augmentation/StaticAugmentations";
import { CityName } from "../Locations/data/CityNames";
import { findCrime } from "../Crime/CrimeHelpers";
2022-07-21 08:42:48 +02:00
import { Augmentation } from "../Augmentation/Augmentation";
2022-03-30 02:05:40 +02:00
import {
AugmentPair,
Sleeve as ISleeve,
SleeveInformation,
SleeveSkills,
SleeveTask,
} from "../ScriptEditor/NetscriptDefinitions";
2022-04-14 18:07:47 +02:00
import { checkEnum } from "../utils/helpers/checkEnum";
2022-05-08 01:08:07 +02:00
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
2022-07-28 09:08:39 +02:00
import { isSleeveBladeburnerWork } from "../PersonObjects/Sleeve/Work/SleeveBladeburnerWork";
import { isSleeveFactionWork } from "../PersonObjects/Sleeve/Work/SleeveFactionWork";
import { isSleeveCompanyWork } from "../PersonObjects/Sleeve/Work/SleeveCompanyWork";
2022-08-08 19:43:41 +02:00
import { helpers } from "../Netscript/NetscriptHelpers";
2022-08-09 21:41:47 +02:00
export function NetscriptSleeve(): InternalAPI<ISleeve> {
2022-05-08 01:08:07 +02:00
const checkSleeveAPIAccess = function (ctx: NetscriptContext): void {
2022-09-06 15:07:12 +02:00
if (Player.bitNodeN !== 10 && !Player.sourceFileLvl(10)) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(
ctx,
"You do not currently have access to the Sleeve API. This is either because you are not in BitNode-10 or because you do not have Source-File 10",
);
}
};
2022-05-08 01:08:07 +02:00
const checkSleeveNumber = function (ctx: NetscriptContext, sleeveNumber: number): void {
2022-09-06 15:07:12 +02:00
if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) {
const msg = `Invalid sleeve number: ${sleeveNumber}`;
2022-08-08 21:51:50 +02:00
helpers.log(ctx, () => msg);
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, msg);
}
};
2022-03-30 02:05:40 +02:00
const getSleeveStats = function (sleeveNumber: number): SleeveSkills {
2022-09-06 15:07:12 +02:00
const sl = Player.sleeves[sleeveNumber];
return {
shock: 100 - sl.shock,
sync: sl.sync,
memory: sl.memory,
hacking: sl.skills.hacking,
strength: sl.skills.strength,
defense: sl.skills.defense,
dexterity: sl.skills.dexterity,
agility: sl.skills.agility,
charisma: sl.skills.charisma,
};
2022-03-30 02:05:40 +02:00
};
return {
2022-05-08 01:08:07 +02:00
getNumSleeves: (ctx: NetscriptContext) => (): number => {
checkSleeveAPIAccess(ctx);
2022-09-06 15:07:12 +02:00
return Player.sleeves.length;
},
2022-05-08 01:08:07 +02:00
setToShockRecovery:
(ctx: NetscriptContext) =>
(_sleeveNumber: unknown): boolean => {
2022-08-08 19:43:41 +02:00
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
2022-05-08 01:08:07 +02:00
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
2022-09-06 15:07:12 +02:00
return Player.sleeves[sleeveNumber].shockRecovery();
2022-05-08 01:08:07 +02:00
},
setToSynchronize:
(ctx: NetscriptContext) =>
(_sleeveNumber: unknown): boolean => {
2022-08-08 19:43:41 +02:00
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
2022-05-08 01:08:07 +02:00
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
2022-09-06 15:07:12 +02:00
return Player.sleeves[sleeveNumber].synchronize();
2022-05-08 01:08:07 +02:00
},
setToCommitCrime:
(ctx: NetscriptContext) =>
(_sleeveNumber: unknown, _crimeRoughName: unknown): boolean => {
2022-08-08 19:43:41 +02:00
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
const crimeRoughName = helpers.string(ctx, "crimeName", _crimeRoughName);
2022-05-08 01:08:07 +02:00
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
const crime = findCrime(crimeRoughName);
if (crime === null) {
return false;
}
2022-09-06 15:07:12 +02:00
return Player.sleeves[sleeveNumber].commitCrime(crime.name);
2022-05-08 01:08:07 +02:00
},
setToUniversityCourse:
(ctx: NetscriptContext) =>
(_sleeveNumber: unknown, _universityName: unknown, _className: unknown): boolean => {
2022-08-08 19:43:41 +02:00
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
const universityName = helpers.string(ctx, "universityName", _universityName);
const className = helpers.string(ctx, "className", _className);
2022-05-08 01:08:07 +02:00
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
2022-09-06 15:07:12 +02:00
return Player.sleeves[sleeveNumber].takeUniversityCourse(universityName, className);
2022-05-08 01:08:07 +02:00
},
travel:
(ctx: NetscriptContext) =>
(_sleeveNumber: unknown, _cityName: unknown): boolean => {
2022-08-08 19:43:41 +02:00
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
const cityName = helpers.string(ctx, "cityName", _cityName);
2022-05-08 01:08:07 +02:00
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
if (checkEnum(CityName, cityName)) {
2022-09-06 15:07:12 +02:00
return Player.sleeves[sleeveNumber].travel(cityName);
2022-05-08 01:08:07 +02:00
} else {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid city name: '${cityName}'.`);
}
2022-05-08 01:08:07 +02:00
},
setToCompanyWork:
(ctx: NetscriptContext) =>
(_sleeveNumber: unknown, acompanyName: unknown): boolean => {
2022-08-08 19:43:41 +02:00
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
const companyName = helpers.string(ctx, "companyName", acompanyName);
2022-05-08 01:08:07 +02:00
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
2022-05-08 01:08:07 +02:00
// Cannot work at the same company that another sleeve is working at
2022-09-06 15:07:12 +02:00
for (let i = 0; i < Player.sleeves.length; ++i) {
2022-05-08 01:08:07 +02:00
if (i === sleeveNumber) {
continue;
}
2022-09-06 15:07:12 +02:00
const other = Player.sleeves[i];
2022-07-28 09:08:39 +02:00
if (isSleeveCompanyWork(other.currentWork) && other.currentWork.companyName === companyName) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(
ctx,
2022-05-08 01:08:07 +02:00
`Sleeve ${sleeveNumber} cannot work for company ${companyName} because Sleeve ${i} is already working for them.`,
);
}
}
2022-09-06 15:07:12 +02:00
return Player.sleeves[sleeveNumber].workForCompany(companyName);
2022-05-08 01:08:07 +02:00
},
setToFactionWork:
(ctx: NetscriptContext) =>
(_sleeveNumber: unknown, _factionName: unknown, _workType: unknown): boolean | undefined => {
2022-08-08 19:43:41 +02:00
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
const factionName = helpers.string(ctx, "factionName", _factionName);
const workType = helpers.string(ctx, "workType", _workType);
2022-05-08 01:08:07 +02:00
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
2022-05-08 01:08:07 +02:00
// Cannot work at the same faction that another sleeve is working at
2022-09-06 15:07:12 +02:00
for (let i = 0; i < Player.sleeves.length; ++i) {
2022-05-08 01:08:07 +02:00
if (i === sleeveNumber) {
continue;
}
2022-09-06 15:07:12 +02:00
const other = Player.sleeves[i];
2022-07-28 09:08:39 +02:00
if (isSleeveFactionWork(other.currentWork) && other.currentWork.factionName === factionName) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(
ctx,
2022-05-08 01:08:07 +02:00
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because Sleeve ${i} is already working for them.`,
);
}
}
2022-05-08 01:08:07 +02:00
2022-09-06 15:07:12 +02:00
if (Player.gang && Player.gang.facName == factionName) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(
ctx,
2022-05-08 01:08:07 +02:00
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because you have started a gang with them.`,
);
}
2022-09-06 15:07:12 +02:00
return Player.sleeves[sleeveNumber].workForFaction(factionName, workType);
2022-05-08 01:08:07 +02:00
},
setToGymWorkout:
(ctx: NetscriptContext) =>
(_sleeveNumber: unknown, _gymName: unknown, _stat: unknown): boolean => {
2022-08-08 19:43:41 +02:00
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
const gymName = helpers.string(ctx, "gymName", _gymName);
const stat = helpers.string(ctx, "stat", _stat);
2022-05-08 01:08:07 +02:00
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
2022-09-06 15:07:12 +02:00
return Player.sleeves[sleeveNumber].workoutAtGym(gymName, stat);
2022-05-08 01:08:07 +02:00
},
getSleeveStats:
(ctx: NetscriptContext) =>
(_sleeveNumber: unknown): SleeveSkills => {
2022-08-08 19:43:41 +02:00
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
2022-05-08 01:08:07 +02:00
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
return getSleeveStats(sleeveNumber);
},
getTask:
(ctx: NetscriptContext) =>
2022-07-28 08:46:34 +02:00
(_sleeveNumber: unknown): SleeveTask | null => {
2022-08-08 19:43:41 +02:00
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
2022-05-08 01:08:07 +02:00
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
2022-09-06 15:07:12 +02:00
const sl = Player.sleeves[sleeveNumber];
2022-07-28 08:46:34 +02:00
if (sl.currentWork === null) return null;
return sl.currentWork.APICopy();
2022-05-08 01:08:07 +02:00
},
getInformation:
(ctx: NetscriptContext) =>
(_sleeveNumber: unknown): SleeveInformation => {
2022-08-08 19:43:41 +02:00
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
2022-05-08 01:08:07 +02:00
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
2022-09-06 15:07:12 +02:00
const sl = Player.sleeves[sleeveNumber];
2022-05-08 01:08:07 +02:00
return {
tor: false,
city: sl.city,
2022-07-27 06:08:07 +02:00
hp: sl.hp,
2022-09-06 15:07:12 +02:00
jobs: Object.keys(Player.jobs), // technically sleeves have the same jobs as the player.
jobTitle: Object.values(Player.jobs),
2022-05-08 01:08:07 +02:00
mult: {
2022-07-15 00:43:33 +02:00
agility: sl.mults.agility,
agilityExp: sl.mults.agility_exp,
charisma: sl.mults.charisma,
charismaExp: sl.mults.charisma_exp,
companyRep: sl.mults.company_rep,
crimeMoney: sl.mults.crime_money,
crimeSuccess: sl.mults.crime_success,
defense: sl.mults.defense,
defenseExp: sl.mults.defense_exp,
dexterity: sl.mults.dexterity,
dexterityExp: sl.mults.dexterity_exp,
factionRep: sl.mults.faction_rep,
hacking: sl.mults.hacking,
hackingExp: sl.mults.hacking_exp,
strength: sl.mults.strength,
strengthExp: sl.mults.strength_exp,
workMoney: sl.mults.work_money,
2022-05-08 01:08:07 +02:00
},
};
},
getSleeveAugmentations:
(ctx: NetscriptContext) =>
(_sleeveNumber: unknown): string[] => {
2022-08-08 19:43:41 +02:00
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
2022-05-08 01:08:07 +02:00
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
2022-05-08 01:08:07 +02:00
const augs = [];
2022-09-06 15:07:12 +02:00
for (let i = 0; i < Player.sleeves[sleeveNumber].augmentations.length; i++) {
augs.push(Player.sleeves[sleeveNumber].augmentations[i].name);
2022-05-08 01:08:07 +02:00
}
return augs;
},
getSleevePurchasableAugs:
(ctx: NetscriptContext) =>
(_sleeveNumber: unknown): AugmentPair[] => {
2022-08-08 19:43:41 +02:00
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
2022-05-08 01:08:07 +02:00
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
const purchasableAugs = Player.sleeves[sleeveNumber].findPurchasableAugs();
2022-05-08 01:08:07 +02:00
const augs = [];
for (let i = 0; i < purchasableAugs.length; i++) {
const aug = purchasableAugs[i];
augs.push({
name: aug.name,
cost: aug.baseCost,
});
}
2022-05-08 01:08:07 +02:00
return augs;
},
purchaseSleeveAug:
(ctx: NetscriptContext) =>
(_sleeveNumber: unknown, _augName: unknown): boolean => {
2022-08-08 19:43:41 +02:00
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
const augName = helpers.string(ctx, "augName", _augName);
2022-05-08 01:08:07 +02:00
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
2022-03-19 04:37:59 +01:00
2022-05-08 01:08:07 +02:00
if (getSleeveStats(sleeveNumber).shock > 0) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, `Sleeve shock too high: Sleeve ${sleeveNumber}`);
2022-05-08 01:08:07 +02:00
}
2022-03-19 04:37:59 +01:00
2022-05-08 01:08:07 +02:00
const aug = StaticAugmentations[augName];
if (!aug) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid aug: ${augName}`);
2022-05-08 01:08:07 +02:00
}
2022-09-06 15:07:12 +02:00
return Player.sleeves[sleeveNumber].tryBuyAugmentation(aug);
2022-05-08 01:08:07 +02:00
},
2022-07-21 08:42:48 +02:00
getSleeveAugmentationPrice:
(ctx: NetscriptContext) =>
(_augName: unknown): number => {
checkSleeveAPIAccess(ctx);
2022-08-08 19:43:41 +02:00
const augName = helpers.string(ctx, "augName", _augName);
2022-07-21 08:42:48 +02:00
const aug: Augmentation = StaticAugmentations[augName];
return aug.baseCost;
},
getSleeveAugmentationRepReq:
(ctx: NetscriptContext) =>
2022-07-27 06:08:07 +02:00
(_augName: unknown): number => {
2022-07-21 08:42:48 +02:00
checkSleeveAPIAccess(ctx);
2022-08-08 19:43:41 +02:00
const augName = helpers.string(ctx, "augName", _augName);
2022-07-21 08:42:48 +02:00
const aug: Augmentation = StaticAugmentations[augName];
2022-09-06 15:07:12 +02:00
return aug.getCost().repCost;
2022-07-21 08:42:48 +02:00
},
2022-05-20 21:58:33 +02:00
setToBladeburnerAction:
(ctx: NetscriptContext) =>
(_sleeveNumber: unknown, _action: unknown, _contract?: unknown): boolean => {
2022-08-08 19:43:41 +02:00
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
const action = helpers.string(ctx, "action", _action);
2022-05-20 21:58:33 +02:00
let contract: string;
if (typeof _contract === "undefined") {
contract = "------";
} else {
2022-08-08 19:43:41 +02:00
contract = helpers.string(ctx, "contract", _contract);
2022-05-20 21:58:33 +02:00
}
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
2022-05-20 21:58:33 +02:00
// Cannot Take on Contracts if another sleeve is performing that action
if (action === "Take on contracts") {
2022-09-06 15:07:12 +02:00
for (let i = 0; i < Player.sleeves.length; ++i) {
2022-05-20 21:58:33 +02:00
if (i === sleeveNumber) {
continue;
}
2022-09-06 15:07:12 +02:00
const other = Player.sleeves[i];
2022-07-28 09:08:39 +02:00
if (isSleeveBladeburnerWork(other.currentWork) && other.currentWork.actionName === contract) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(
ctx,
2022-05-27 17:59:37 +02:00
`Sleeve ${sleeveNumber} cannot take on contracts because Sleeve ${i} is already performing that action.`,
2022-05-20 21:58:33 +02:00
);
}
}
}
2022-09-06 15:07:12 +02:00
return Player.sleeves[sleeveNumber].bladeburner(action, contract);
2022-05-20 21:58:33 +02:00
},
};
}