2022-10-10 00:42:14 +02:00
|
|
|
import { Player } from "@player";
|
2022-04-14 19:19:51 +02:00
|
|
|
import { StaticAugmentations } from "../Augmentation/StaticAugmentations";
|
2022-12-30 02:28:53 +01:00
|
|
|
import { CityName } from "../Enums";
|
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-12-30 02:28:53 +01:00
|
|
|
import { Sleeve } from "@nsdefs";
|
2022-11-20 14:37:11 +01:00
|
|
|
import { checkEnum } from "../utils/helpers/enum";
|
2022-12-30 02:28:53 +01:00
|
|
|
import { InternalAPI, NetscriptContext, removedFunction } 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-11-06 23:27:04 +01:00
|
|
|
import { cloneDeep } from "lodash";
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-11-24 14:19:51 +01:00
|
|
|
export function NetscriptSleeve(): InternalAPI<Sleeve> {
|
2022-10-12 14:49:27 +02:00
|
|
|
const checkSleeveAPIAccess = function (ctx: NetscriptContext) {
|
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,
|
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-10-12 14:49:27 +02:00
|
|
|
const checkSleeveNumber = function (ctx: NetscriptContext, sleeveNumber: number) {
|
2022-09-06 15:07:12 +02:00
|
|
|
if (sleeveNumber >= Player.sleeves.length || sleeveNumber < 0) {
|
2021-10-05 04:25:21 +02:00
|
|
|
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);
|
2021-10-05 04:25:21 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-12-30 02:28:53 +01:00
|
|
|
const sleeveFunctions: InternalAPI<Sleeve> = {
|
2022-10-12 14:49:27 +02:00
|
|
|
getNumSleeves: (ctx) => () => {
|
2022-05-08 01:08:07 +02:00
|
|
|
checkSleeveAPIAccess(ctx);
|
2022-09-06 15:07:12 +02:00
|
|
|
return Player.sleeves.length;
|
2021-10-05 04:25:21 +02:00
|
|
|
},
|
2022-10-12 14:49:27 +02:00
|
|
|
setToShockRecovery: (ctx) => (_sleeveNumber) => {
|
|
|
|
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
|
|
|
return Player.sleeves[sleeveNumber].shockRecovery();
|
|
|
|
},
|
|
|
|
setToSynchronize: (ctx) => (_sleeveNumber) => {
|
|
|
|
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
|
|
|
return Player.sleeves[sleeveNumber].synchronize();
|
|
|
|
},
|
2022-10-21 17:57:37 +02:00
|
|
|
setToCommitCrime: (ctx) => (_sleeveNumber, _crimeType) => {
|
2022-10-12 14:49:27 +02:00
|
|
|
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
2022-10-21 17:57:37 +02:00
|
|
|
const crimeType = helpers.string(ctx, "crimeType", _crimeType);
|
2022-10-12 14:49:27 +02:00
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
2022-11-10 17:05:42 +01:00
|
|
|
const crime = findCrime(crimeType);
|
2022-10-21 17:57:37 +02:00
|
|
|
if (crime == null) return false;
|
2022-11-03 13:39:34 +01:00
|
|
|
return Player.sleeves[sleeveNumber].commitCrime(crime.type);
|
2022-10-12 14:49:27 +02:00
|
|
|
},
|
|
|
|
setToUniversityCourse: (ctx) => (_sleeveNumber, _universityName, _className) => {
|
|
|
|
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
|
|
|
const universityName = helpers.string(ctx, "universityName", _universityName);
|
|
|
|
const className = helpers.string(ctx, "className", _className);
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
|
|
|
return Player.sleeves[sleeveNumber].takeUniversityCourse(universityName, className);
|
|
|
|
},
|
|
|
|
travel: (ctx) => (_sleeveNumber, _cityName) => {
|
|
|
|
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
|
|
|
const cityName = helpers.string(ctx, "cityName", _cityName);
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
|
|
|
if (checkEnum(CityName, cityName)) {
|
|
|
|
return Player.sleeves[sleeveNumber].travel(cityName);
|
|
|
|
} else {
|
|
|
|
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid city name: '${cityName}'.`);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
setToCompanyWork: (ctx) => (_sleeveNumber, acompanyName) => {
|
|
|
|
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
|
|
|
const companyName = helpers.string(ctx, "companyName", acompanyName);
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-10-12 14:49:27 +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;
|
2022-05-08 01:08:07 +02:00
|
|
|
}
|
2022-10-12 14:49:27 +02:00
|
|
|
const other = Player.sleeves[i];
|
|
|
|
if (isSleeveCompanyWork(other.currentWork) && other.currentWork.companyName === companyName) {
|
|
|
|
throw helpers.makeRuntimeErrorMsg(
|
|
|
|
ctx,
|
|
|
|
`Sleeve ${sleeveNumber} cannot work for company ${companyName} because Sleeve ${i} is already working for them.`,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-10-12 14:49:27 +02:00
|
|
|
return Player.sleeves[sleeveNumber].workForCompany(companyName);
|
|
|
|
},
|
|
|
|
setToFactionWork: (ctx) => (_sleeveNumber, _factionName, _workType) => {
|
|
|
|
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
|
|
|
const factionName = helpers.string(ctx, "factionName", _factionName);
|
|
|
|
const workType = helpers.string(ctx, "workType", _workType);
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-10-12 14:49:27 +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;
|
2021-10-05 04:25:21 +02:00
|
|
|
}
|
2022-10-12 14:49:27 +02:00
|
|
|
const other = Player.sleeves[i];
|
|
|
|
if (isSleeveFactionWork(other.currentWork) && other.currentWork.factionName === factionName) {
|
2022-08-08 19:43:41 +02:00
|
|
|
throw helpers.makeRuntimeErrorMsg(
|
|
|
|
ctx,
|
2022-10-12 14:49:27 +02:00
|
|
|
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because Sleeve ${i} is already working for them.`,
|
2021-10-05 04:25:21 +02:00
|
|
|
);
|
|
|
|
}
|
2022-10-12 14:49:27 +02:00
|
|
|
}
|
2022-04-04 12:10:21 +02:00
|
|
|
|
2022-10-12 14:49:27 +02:00
|
|
|
if (Player.gang && Player.gang.facName == factionName) {
|
|
|
|
throw helpers.makeRuntimeErrorMsg(
|
|
|
|
ctx,
|
|
|
|
`Sleeve ${sleeveNumber} cannot work for faction ${factionName} because you have started a gang with them.`,
|
|
|
|
);
|
|
|
|
}
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-10-12 14:49:27 +02:00
|
|
|
return Player.sleeves[sleeveNumber].workForFaction(factionName, workType);
|
|
|
|
},
|
|
|
|
setToGymWorkout: (ctx) => (_sleeveNumber, _gymName, _stat) => {
|
|
|
|
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
|
|
|
const gymName = helpers.string(ctx, "gymName", _gymName);
|
|
|
|
const stat = helpers.string(ctx, "stat", _stat);
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-10-12 14:49:27 +02:00
|
|
|
return Player.sleeves[sleeveNumber].workoutAtGym(gymName, stat);
|
|
|
|
},
|
|
|
|
getTask: (ctx) => (_sleeveNumber) => {
|
|
|
|
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-10-12 14:49:27 +02:00
|
|
|
const sl = Player.sleeves[sleeveNumber];
|
|
|
|
if (sl.currentWork === null) return null;
|
|
|
|
return sl.currentWork.APICopy();
|
|
|
|
},
|
2022-11-09 13:26:26 +01:00
|
|
|
getSleeve: (ctx) => (_sleeveNumber) => {
|
2022-10-12 14:49:27 +02:00
|
|
|
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-10-12 14:49:27 +02:00
|
|
|
const sl = Player.sleeves[sleeveNumber];
|
2022-11-09 13:26:26 +01:00
|
|
|
|
|
|
|
const data = {
|
|
|
|
hp: cloneDeep(sl.hp),
|
2022-11-06 23:27:04 +01:00
|
|
|
skills: cloneDeep(sl.skills),
|
2022-11-09 13:26:26 +01:00
|
|
|
exp: cloneDeep(sl.exp),
|
|
|
|
mults: cloneDeep(sl.mults),
|
|
|
|
city: sl.city,
|
|
|
|
shock: sl.shock,
|
|
|
|
sync: sl.sync,
|
|
|
|
memory: sl.memory,
|
2023-01-02 15:45:51 +01:00
|
|
|
storedCycles: sl.storedCycles,
|
2022-10-12 14:49:27 +02:00
|
|
|
};
|
2022-11-09 13:26:26 +01:00
|
|
|
|
|
|
|
return data;
|
2022-10-12 14:49:27 +02:00
|
|
|
},
|
|
|
|
getSleeveAugmentations: (ctx) => (_sleeveNumber) => {
|
|
|
|
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-10-12 14:49:27 +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) => (_sleeveNumber) => {
|
|
|
|
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-10-12 14:49:27 +02:00
|
|
|
const purchasableAugs = Player.sleeves[sleeveNumber].findPurchasableAugs();
|
|
|
|
const augs = [];
|
|
|
|
for (let i = 0; i < purchasableAugs.length; i++) {
|
|
|
|
const aug = purchasableAugs[i];
|
|
|
|
augs.push({
|
|
|
|
name: aug.name,
|
|
|
|
cost: aug.baseCost,
|
|
|
|
});
|
|
|
|
}
|
2022-03-19 04:37:59 +01:00
|
|
|
|
2022-10-12 14:49:27 +02:00
|
|
|
return augs;
|
|
|
|
},
|
|
|
|
purchaseSleeveAug: (ctx) => (_sleeveNumber, _augName) => {
|
|
|
|
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
|
|
|
const augName = helpers.string(ctx, "augName", _augName);
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
2022-03-19 04:37:59 +01:00
|
|
|
|
2022-11-09 13:26:26 +01:00
|
|
|
if (Player.sleeves[sleeveNumber].shock > 0) {
|
2022-10-12 14:49:27 +02:00
|
|
|
throw helpers.makeRuntimeErrorMsg(ctx, `Sleeve shock too high: Sleeve ${sleeveNumber}`);
|
|
|
|
}
|
2021-10-05 04:25:21 +02:00
|
|
|
|
2022-10-12 14:49:27 +02:00
|
|
|
const aug = StaticAugmentations[augName];
|
|
|
|
if (!aug) {
|
|
|
|
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid aug: ${augName}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Player.sleeves[sleeveNumber].tryBuyAugmentation(aug);
|
|
|
|
},
|
|
|
|
getSleeveAugmentationPrice: (ctx) => (_augName) => {
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
const augName = helpers.string(ctx, "augName", _augName);
|
|
|
|
const aug: Augmentation = StaticAugmentations[augName];
|
|
|
|
return aug.baseCost;
|
|
|
|
},
|
|
|
|
getSleeveAugmentationRepReq: (ctx) => (_augName) => {
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
const augName = helpers.string(ctx, "augName", _augName);
|
|
|
|
const aug: Augmentation = StaticAugmentations[augName];
|
|
|
|
return aug.getCost().repCost;
|
|
|
|
},
|
|
|
|
setToBladeburnerAction: (ctx) => (_sleeveNumber, _action, _contract?) => {
|
|
|
|
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
|
|
|
|
const action = helpers.string(ctx, "action", _action);
|
|
|
|
let contract: string;
|
|
|
|
if (typeof _contract === "undefined") {
|
|
|
|
contract = "------";
|
|
|
|
} else {
|
|
|
|
contract = helpers.string(ctx, "contract", _contract);
|
|
|
|
}
|
|
|
|
checkSleeveAPIAccess(ctx);
|
|
|
|
checkSleeveNumber(ctx, sleeveNumber);
|
2022-04-30 21:25:36 +02:00
|
|
|
|
2022-10-12 14:49:27 +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];
|
|
|
|
if (isSleeveBladeburnerWork(other.currentWork) && other.currentWork.actionName === contract) {
|
|
|
|
throw helpers.makeRuntimeErrorMsg(
|
|
|
|
ctx,
|
|
|
|
`Sleeve ${sleeveNumber} cannot take on contracts because Sleeve ${i} is already performing that action.`,
|
|
|
|
);
|
2022-04-30 21:25:36 +02:00
|
|
|
}
|
|
|
|
}
|
2022-10-12 14:49:27 +02:00
|
|
|
}
|
2022-04-30 21:25:36 +02:00
|
|
|
|
2022-10-12 14:49:27 +02:00
|
|
|
return Player.sleeves[sleeveNumber].bladeburner(action, contract);
|
|
|
|
},
|
2021-10-05 04:25:21 +02:00
|
|
|
};
|
2022-12-30 02:28:53 +01:00
|
|
|
// Removed undocumented functions added using Object.assign because typescript.
|
|
|
|
// TODO: Remove these at 3.0
|
|
|
|
Object.assign(sleeveFunctions, {
|
2023-01-02 19:18:02 +01:00
|
|
|
getSleeveStats: removedFunction("v2.2.0", "sleeve.getSleeve"),
|
|
|
|
getInformation: removedFunction("v2.2.0", "sleeve.getSleeve"),
|
2022-12-30 02:28:53 +01:00
|
|
|
});
|
|
|
|
return sleeveFunctions;
|
2021-10-05 04:25:21 +02:00
|
|
|
}
|