2021-10-05 04:25:21 +02:00
|
|
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
|
|
|
import { findSleevePurchasableAugs } from "../PersonObjects/Sleeve/SleeveHelpers";
|
2022-04-14 19:19:51 +02:00
|
|
|
import { StaticAugmentations } from "../Augmentation/StaticAugmentations";
|
2021-10-05 04:25:21 +02:00
|
|
|
import { CityName } from "../Locations/data/CityNames";
|
2021-10-11 23:12:08 +02:00
|
|
|
import { findCrime } from "../Crime/CrimeHelpers";
|
2022-07-21 08:42:48 +02:00
|
|
|
import { Augmentation } from "../Augmentation/Augmentation";
|
2021-10-05 04:25:21 +02:00
|
|
|
|
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";
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-05-08 01:08:07 +02:00
|
|
|
export function NetscriptSleeve(player: IPlayer): InternalAPI<ISleeve> {
|
|
|
|
const checkSleeveAPIAccess = function (ctx: NetscriptContext): void {
|
2022-04-14 07:22:50 +02:00
|
|
|
if (player.bitNodeN !== 10 && !player.sourceFileLvl(10)) {
|
2022-05-08 01:08:07 +02:00
|
|
|
throw ctx.makeRuntimeErrorMsg(
|
2021-10-05 04:25:21 +02:00
|
|
|
"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 {
|
2021-10-05 04:25:21 +02:00
|
|
|
if (sleeveNumber >= player.sleeves.length || sleeveNumber < 0) {
|
|
|
|
const msg = `Invalid sleeve number: ${sleeveNumber}`;
|
2022-05-08 01:08:07 +02:00
|
|
|
ctx.log(() => msg);
|
|
|
|
throw ctx.makeRuntimeErrorMsg(msg);
|
2021-10-05 04:25:21 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-03-30 02:05:40 +02:00
|
|
|
const getSleeveStats = function (sleeveNumber: number): SleeveSkills {
|
2022-03-20 13:56:33 +01:00
|
|
|
const sl = player.sleeves[sleeveNumber];
|
|
|
|
return {
|
|
|
|
shock: 100 - sl.shock,
|
|
|
|
sync: sl.sync,
|
2022-05-23 19:50:32 +02:00
|
|
|
memory: sl.memory,
|
2022-07-27 05:54:17 +02:00
|
|
|
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-20 13:56:33 +01:00
|
|
|
};
|
2022-03-30 02:05:40 +02:00
|
|
|
};
|
2022-03-20 13:56:33 +01:00
|
|
|
|
2021-10-05 04:25:21 +02:00
|
|
|
return {
|
2022-05-08 01:08:07 +02:00
|
|
|
getNumSleeves: (ctx: NetscriptContext) => (): number => {
|
|
|
|
checkSleeveAPIAccess(ctx);
|
2021-10-05 04:25:21 +02:00
|
|
|
return player.sleeves.length;
|
|
|
|
},
|
2022-05-08 01:08:07 +02:00
|
|
|
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;
|
2021-10-05 04:25:21 +02:00
|
|
|
}
|
2022-05-08 01:08:07 +02:00
|
|
|
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}'.`);
|
2021-10-05 04:25:21 +02:00
|
|
|
}
|
2022-05-08 01:08:07 +02:00
|
|
|
},
|
|
|
|
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);
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-05-08 01:08:07 +02:00
|
|
|
// 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];
|
2022-07-28 09:08:39 +02:00
|
|
|
if (isSleeveCompanyWork(other.currentWork) && other.currentWork.companyName === companyName) {
|
2022-05-08 01:08:07 +02:00
|
|
|
throw ctx.makeRuntimeErrorMsg(
|
|
|
|
`Sleeve ${sleeveNumber} cannot work for company ${companyName} because Sleeve ${i} is already working for them.`,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-05-08 01:08:07 +02:00
|
|
|
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);
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-05-08 01:08:07 +02:00
|
|
|
// 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];
|
2022-07-28 09:08:39 +02:00
|
|
|
if (isSleeveFactionWork(other.currentWork) && other.currentWork.factionName === factionName) {
|
2022-05-08 01:08:07 +02:00
|
|
|
throw ctx.makeRuntimeErrorMsg(
|
|
|
|
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because Sleeve ${i} is already working for them.`,
|
|
|
|
);
|
|
|
|
}
|
2021-10-05 04:25:21 +02:00
|
|
|
}
|
2022-05-08 01:08:07 +02:00
|
|
|
|
|
|
|
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.`,
|
2021-10-05 04:25:21 +02:00
|
|
|
);
|
|
|
|
}
|
2022-04-04 12:10:21 +02:00
|
|
|
|
2022-05-08 01:08:07 +02:00
|
|
|
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);
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-05-08 01:08:07 +02:00
|
|
|
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) =>
|
2022-07-28 08:46:34 +02:00
|
|
|
(_sleeveNumber: unknown): SleeveTask | null => {
|
2022-05-08 01:08:07 +02:00
|
|
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-05-08 01:08:07 +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 => {
|
|
|
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-05-08 01:08:07 +02:00
|
|
|
const sl = player.sleeves[sleeveNumber];
|
|
|
|
return {
|
|
|
|
tor: false,
|
|
|
|
city: sl.city,
|
2022-07-27 06:08:07 +02:00
|
|
|
hp: sl.hp,
|
2022-05-08 01:08:07 +02:00
|
|
|
jobs: Object.keys(player.jobs), // technically sleeves have the same jobs as the player.
|
|
|
|
jobTitle: Object.values(player.jobs),
|
2021-10-05 04:25:21 +02:00
|
|
|
|
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[] => {
|
|
|
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-05-08 01:08:07 +02:00
|
|
|
const augs = [];
|
|
|
|
for (let i = 0; i < player.sleeves[sleeveNumber].augmentations.length; i++) {
|
|
|
|
augs.push(player.sleeves[sleeveNumber].augmentations[i].name);
|
|
|
|
}
|
|
|
|
return augs;
|
|
|
|
},
|
|
|
|
getSleevePurchasableAugs:
|
|
|
|
(ctx: NetscriptContext) =>
|
|
|
|
(_sleeveNumber: unknown): AugmentPair[] => {
|
|
|
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-05-08 01:08:07 +02:00
|
|
|
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,
|
|
|
|
});
|
|
|
|
}
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-05-08 01:08:07 +02:00
|
|
|
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);
|
2022-03-19 04:37:59 +01:00
|
|
|
|
2022-05-08 01:08:07 +02:00
|
|
|
if (getSleeveStats(sleeveNumber).shock > 0) {
|
|
|
|
throw ctx.makeRuntimeErrorMsg(`Sleeve shock too high: Sleeve ${sleeveNumber}`);
|
|
|
|
}
|
2022-03-19 04:37:59 +01:00
|
|
|
|
2022-05-08 01:08:07 +02:00
|
|
|
const aug = StaticAugmentations[augName];
|
|
|
|
if (!aug) {
|
|
|
|
throw ctx.makeRuntimeErrorMsg(`Invalid aug: ${augName}`);
|
|
|
|
}
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-05-08 01:08:07 +02:00
|
|
|
return player.sleeves[sleeveNumber].tryBuyAugmentation(player, aug);
|
|
|
|
},
|
2022-07-21 08:42:48 +02:00
|
|
|
getSleeveAugmentationPrice:
|
|
|
|
(ctx: NetscriptContext) =>
|
|
|
|
(_augName: unknown): number => {
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
const augName = ctx.helper.string("augName", _augName);
|
|
|
|
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);
|
|
|
|
const augName = ctx.helper.string("augName", _augName);
|
|
|
|
const aug: Augmentation = StaticAugmentations[augName];
|
|
|
|
return aug.getCost(player).repCost;
|
|
|
|
},
|
2022-05-20 21:58:33 +02:00
|
|
|
setToBladeburnerAction:
|
|
|
|
(ctx: NetscriptContext) =>
|
|
|
|
(_sleeveNumber: unknown, _action: unknown, _contract?: unknown): boolean => {
|
|
|
|
const sleeveNumber = ctx.helper.number("sleeveNumber", _sleeveNumber);
|
|
|
|
const action = ctx.helper.string("action", _action);
|
|
|
|
let contract: string;
|
|
|
|
if (typeof _contract === "undefined") {
|
|
|
|
contract = "------";
|
|
|
|
} else {
|
|
|
|
contract = ctx.helper.string("contract", _contract);
|
|
|
|
}
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
2022-04-30 21:25:36 +02:00
|
|
|
|
2022-05-20 21:58:33 +02:00
|
|
|
// Cannot Take on Contracts if another sleeve is performing that action
|
|
|
|
if (action === "Take on contracts") {
|
|
|
|
for (let i = 0; i < player.sleeves.length; ++i) {
|
|
|
|
if (i === sleeveNumber) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const other = player.sleeves[i];
|
2022-07-28 09:08:39 +02:00
|
|
|
if (isSleeveBladeburnerWork(other.currentWork) && other.currentWork.actionName === contract) {
|
2022-05-20 21:58:33 +02:00
|
|
|
throw ctx.helper.makeRuntimeErrorMsg(
|
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-04-30 21:25:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-20 21:58:33 +02:00
|
|
|
return player.sleeves[sleeveNumber].bladeburner(player, action, contract);
|
|
|
|
},
|
2021-10-05 04:25:21 +02:00
|
|
|
};
|
|
|
|
}
|