2021-11-03 23:16:10 +01:00
|
|
|
import { WorkerScript } from "../Netscript/WorkerScript";
|
|
|
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
2022-03-30 03:10:07 +02:00
|
|
|
import { purchaseAugmentation, joinFaction, getFactionAugmentationsFiltered } from "../Faction/FactionHelpers";
|
2021-11-03 23:16:10 +01:00
|
|
|
import { startWorkerScript } from "../NetscriptWorker";
|
|
|
|
import { Augmentation } from "../Augmentation/Augmentation";
|
2022-04-14 19:19:51 +02:00
|
|
|
import { StaticAugmentations } from "../Augmentation/StaticAugmentations";
|
2021-11-03 23:16:10 +01:00
|
|
|
import { augmentationExists, installAugmentations } from "../Augmentation/AugmentationHelpers";
|
|
|
|
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
|
|
|
import { killWorkerScript } from "../Netscript/killWorkerScript";
|
|
|
|
import { CONSTANTS } from "../Constants";
|
|
|
|
import { isString } from "../utils/helpers/isString";
|
|
|
|
import { RunningScript } from "../Script/RunningScript";
|
|
|
|
|
2022-03-30 01:49:37 +02:00
|
|
|
import {
|
|
|
|
AugmentationStats,
|
|
|
|
CharacterInfo,
|
|
|
|
CrimeStats,
|
|
|
|
PlayerSkills,
|
|
|
|
Singularity as ISingularity,
|
|
|
|
} from "../ScriptEditor/NetscriptDefinitions";
|
2021-11-03 23:16:10 +01:00
|
|
|
|
|
|
|
import { findCrime } from "../Crime/CrimeHelpers";
|
|
|
|
import { CompanyPosition } from "../Company/CompanyPosition";
|
|
|
|
import { CompanyPositions } from "../Company/CompanyPositions";
|
|
|
|
import { DarkWebItems } from "../DarkWeb/DarkWebItems";
|
|
|
|
import { AllGangs } from "../Gang/AllGangs";
|
|
|
|
import { CityName } from "../Locations/data/CityNames";
|
|
|
|
import { LocationName } from "../Locations/data/LocationNames";
|
|
|
|
import { Router } from "../ui/GameRoot";
|
|
|
|
import { SpecialServers } from "../Server/data/SpecialServers";
|
|
|
|
import { Page } from "../ui/Router";
|
|
|
|
import { Locations } from "../Locations/Locations";
|
|
|
|
import { GetServer, AddToAllServers, createUniqueRandomIp } from "../Server/AllServers";
|
|
|
|
import { Programs } from "../Programs/Programs";
|
|
|
|
import { numeralWrapper } from "../ui/numeralFormat";
|
|
|
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
|
|
|
import { Company } from "../Company/Company";
|
|
|
|
import { Companies } from "../Company/Companies";
|
|
|
|
import { Factions, factionExists } from "../Faction/Factions";
|
|
|
|
import { Faction } from "../Faction/Faction";
|
|
|
|
import { netscriptDelay } from "../NetscriptEvaluator";
|
|
|
|
import { convertTimeMsToTimeElapsedString } from "../utils/StringHelperFunctions";
|
|
|
|
import { getServerOnNetwork, safetlyCreateUniqueServer } from "../Server/ServerHelpers";
|
|
|
|
import { Terminal } from "../Terminal";
|
|
|
|
import { calculateHackingTime } from "../Hacking";
|
|
|
|
import { Server } from "../Server/Server";
|
|
|
|
import { netscriptCanHack } from "../Hacking/netscriptCanHack";
|
2022-03-21 04:27:53 +01:00
|
|
|
import { FactionInfos } from "../Faction/FactionInfo";
|
2022-04-12 08:51:10 +02:00
|
|
|
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
2022-04-13 23:34:02 +02:00
|
|
|
import { BlackOperationNames } from "../Bladeburner/data/BlackOperationNames";
|
|
|
|
import { enterBitNode } from "../RedPill";
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript): InternalAPI<ISingularity> {
|
|
|
|
const getAugmentation = function (_ctx: NetscriptContext, name: string): Augmentation {
|
2021-11-03 23:16:10 +01:00
|
|
|
if (!augmentationExists(name)) {
|
2022-04-12 08:51:10 +02:00
|
|
|
throw _ctx.helper.makeRuntimeErrorMsg(`Invalid augmentation: '${name}'`);
|
2021-11-03 23:16:10 +01:00
|
|
|
}
|
|
|
|
|
2022-04-14 19:19:51 +02:00
|
|
|
return StaticAugmentations[name];
|
2021-11-03 23:16:10 +01:00
|
|
|
};
|
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
const getFaction = function (_ctx: NetscriptContext, name: string): Faction {
|
2021-11-03 23:16:10 +01:00
|
|
|
if (!factionExists(name)) {
|
2022-04-12 08:51:10 +02:00
|
|
|
throw _ctx.helper.makeRuntimeErrorMsg(`Invalid faction name: '${name}`);
|
2021-11-03 23:16:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return Factions[name];
|
|
|
|
};
|
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
const getCompany = function (_ctx: NetscriptContext, name: string): Company {
|
2021-11-03 23:16:10 +01:00
|
|
|
const company = Companies[name];
|
|
|
|
if (company == null || !(company instanceof Company)) {
|
2022-04-12 08:51:10 +02:00
|
|
|
throw _ctx.helper.makeRuntimeErrorMsg(`Invalid company name: '${name}'`);
|
2021-11-03 23:16:10 +01:00
|
|
|
}
|
|
|
|
return company;
|
|
|
|
};
|
|
|
|
|
2022-03-30 01:49:37 +02:00
|
|
|
const runAfterReset = function (cbScript: string | null = null): void {
|
2021-11-03 23:16:10 +01:00
|
|
|
//Run a script after reset
|
2022-03-30 01:49:37 +02:00
|
|
|
if (!cbScript) return;
|
|
|
|
const home = player.getHomeComputer();
|
|
|
|
for (const script of home.scripts) {
|
|
|
|
if (script.filename === cbScript) {
|
|
|
|
const ramUsage = script.ramUsage;
|
|
|
|
const ramAvailable = home.maxRam - home.ramUsed;
|
|
|
|
if (ramUsage > ramAvailable) {
|
|
|
|
return; // Not enough RAM
|
2021-11-03 23:16:10 +01:00
|
|
|
}
|
2022-03-30 01:49:37 +02:00
|
|
|
const runningScriptObj = new RunningScript(script, []); // No args
|
|
|
|
runningScriptObj.threads = 1; // Only 1 thread
|
|
|
|
startWorkerScript(player, runningScriptObj, home);
|
2021-11-03 23:16:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2022-03-31 15:41:19 +02:00
|
|
|
|
2021-11-03 23:16:10 +01:00
|
|
|
return {
|
2022-04-12 08:51:10 +02:00
|
|
|
getOwnedAugmentations: (_ctx: NetscriptContext) =>
|
|
|
|
function (_purchased: unknown = false): string[] {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const purchased = _ctx.helper.boolean(_purchased);
|
2022-04-12 08:51:10 +02:00
|
|
|
const res = [];
|
|
|
|
for (let i = 0; i < player.augmentations.length; ++i) {
|
|
|
|
res.push(player.augmentations[i].name);
|
2021-11-03 23:16:10 +01:00
|
|
|
}
|
2022-04-12 08:51:10 +02:00
|
|
|
if (purchased) {
|
|
|
|
for (let i = 0; i < player.queuedAugmentations.length; ++i) {
|
|
|
|
res.push(player.queuedAugmentations[i].name);
|
2021-11-03 23:16:10 +01:00
|
|
|
}
|
|
|
|
}
|
2022-04-12 08:51:10 +02:00
|
|
|
return res;
|
|
|
|
},
|
|
|
|
getAugmentationsFromFaction: (_ctx: NetscriptContext) =>
|
|
|
|
function (_facName: unknown): string[] {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const facName = _ctx.helper.string("facName", _facName);
|
2022-04-12 08:51:10 +02:00
|
|
|
const faction = getFaction(_ctx, facName);
|
|
|
|
|
|
|
|
return getFactionAugmentationsFiltered(player, faction);
|
|
|
|
},
|
|
|
|
getAugmentationCost: (_ctx: NetscriptContext) =>
|
|
|
|
function (_augName: unknown): [number, number] {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const augName = _ctx.helper.string("augName", _augName);
|
2022-04-12 08:51:10 +02:00
|
|
|
const aug = getAugmentation(_ctx, augName);
|
|
|
|
return [aug.baseRepRequirement, aug.baseCost];
|
|
|
|
},
|
|
|
|
getAugmentationPrereq: (_ctx: NetscriptContext) =>
|
|
|
|
function (_augName: unknown): string[] {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const augName = _ctx.helper.string("augName", _augName);
|
2022-04-12 08:51:10 +02:00
|
|
|
const aug = getAugmentation(_ctx, augName);
|
|
|
|
return aug.prereqs.slice();
|
|
|
|
},
|
|
|
|
getAugmentationPrice: (_ctx: NetscriptContext) =>
|
|
|
|
function (_augName: unknown): number {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const augName = _ctx.helper.string("augName", _augName);
|
2022-04-12 08:51:10 +02:00
|
|
|
const aug = getAugmentation(_ctx, augName);
|
|
|
|
return aug.baseCost;
|
|
|
|
},
|
|
|
|
getAugmentationRepReq: (_ctx: NetscriptContext) =>
|
|
|
|
function (_augName: unknown): number {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const augName = _ctx.helper.string("augName", _augName);
|
2022-04-12 08:51:10 +02:00
|
|
|
const aug = getAugmentation(_ctx, augName);
|
|
|
|
return aug.baseRepRequirement;
|
|
|
|
},
|
|
|
|
getAugmentationStats: (_ctx: NetscriptContext) =>
|
|
|
|
function (_augName: unknown): AugmentationStats {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const augName = _ctx.helper.string("augName", _augName);
|
2022-04-12 08:51:10 +02:00
|
|
|
const aug = getAugmentation(_ctx, augName);
|
|
|
|
return Object.assign({}, aug.mults);
|
|
|
|
},
|
|
|
|
purchaseAugmentation: (_ctx: NetscriptContext) =>
|
|
|
|
function (_facName: unknown, _augName: unknown): boolean {
|
2022-04-14 00:13:28 +02:00
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-12 08:51:10 +02:00
|
|
|
const facName = _ctx.helper.string("facName", _facName);
|
|
|
|
const augName = _ctx.helper.string("augName", _augName);
|
|
|
|
const fac = getFaction(_ctx, facName);
|
|
|
|
const aug = getAugmentation(_ctx, augName);
|
|
|
|
|
|
|
|
const augs = getFactionAugmentationsFiltered(player, fac);
|
|
|
|
|
|
|
|
if (!augs.includes(augName)) {
|
|
|
|
workerScript.log(
|
|
|
|
"purchaseAugmentation",
|
|
|
|
() => `Faction '${facName}' does not have the '${augName}' augmentation.`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const isNeuroflux = aug.name === AugmentationNames.NeuroFluxGovernor;
|
|
|
|
if (!isNeuroflux) {
|
|
|
|
for (let j = 0; j < player.queuedAugmentations.length; ++j) {
|
|
|
|
if (player.queuedAugmentations[j].name === aug.name) {
|
|
|
|
workerScript.log("purchaseAugmentation", () => `You already have the '${augName}' augmentation.`);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (let j = 0; j < player.augmentations.length; ++j) {
|
|
|
|
if (player.augmentations[j].name === aug.name) {
|
|
|
|
workerScript.log("purchaseAugmentation", () => `You already have the '${augName}' augmentation.`);
|
|
|
|
return false;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
if (fac.playerReputation < aug.baseRepRequirement) {
|
|
|
|
workerScript.log("purchaseAugmentation", () => `You do not have enough reputation with '${fac.name}'.`);
|
|
|
|
return false;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
const res = purchaseAugmentation(aug, fac, true);
|
|
|
|
workerScript.log("purchaseAugmentation", () => res);
|
|
|
|
if (isString(res) && res.startsWith("You purchased")) {
|
|
|
|
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 10);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
softReset: (_ctx: NetscriptContext) =>
|
|
|
|
function (_cbScript: unknown = ""): void {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const cbScript = _ctx.helper.string("cbScript", _cbScript);
|
2022-04-12 08:51:10 +02:00
|
|
|
|
|
|
|
workerScript.log("softReset", () => "Soft resetting. This will cause this script to be killed");
|
|
|
|
setTimeout(() => {
|
|
|
|
installAugmentations(true);
|
|
|
|
runAfterReset(cbScript);
|
|
|
|
}, 0);
|
|
|
|
|
|
|
|
// Prevent workerScript from "finishing execution naturally"
|
|
|
|
workerScript.running = false;
|
|
|
|
killWorkerScript(workerScript);
|
|
|
|
},
|
|
|
|
installAugmentations: (_ctx: NetscriptContext) =>
|
|
|
|
function (_cbScript: unknown = ""): boolean {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const cbScript = _ctx.helper.string("cbScript", _cbScript);
|
2022-04-12 08:51:10 +02:00
|
|
|
|
|
|
|
if (player.queuedAugmentations.length === 0) {
|
|
|
|
workerScript.log("installAugmentations", () => "You do not have any Augmentations to be installed.");
|
|
|
|
return false;
|
|
|
|
}
|
2022-01-09 21:22:23 +01:00
|
|
|
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 10);
|
2022-04-12 08:51:10 +02:00
|
|
|
workerScript.log(
|
|
|
|
"installAugmentations",
|
|
|
|
() => "Installing Augmentations. This will cause this script to be killed",
|
|
|
|
);
|
|
|
|
setTimeout(() => {
|
|
|
|
installAugmentations();
|
|
|
|
runAfterReset(cbScript);
|
|
|
|
}, 0);
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
workerScript.running = false; // Prevent workerScript from "finishing execution naturally"
|
|
|
|
killWorkerScript(workerScript);
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
|
|
|
goToLocation: (_ctx: NetscriptContext) =>
|
|
|
|
function (_locationName: unknown): boolean {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const locationName = _ctx.helper.string("locationName", _locationName);
|
2022-04-12 08:51:10 +02:00
|
|
|
const location = Object.values(Locations).find((l) => l.name === locationName);
|
|
|
|
if (!location) {
|
|
|
|
workerScript.log("goToLocation", () => `No location named ${locationName}`);
|
2021-11-03 23:16:10 +01:00
|
|
|
return false;
|
2022-04-12 08:51:10 +02:00
|
|
|
}
|
|
|
|
if (player.city !== location.city) {
|
|
|
|
workerScript.log("goToLocation", () => `No location named ${locationName} in ${player.city}`);
|
2021-11-03 23:16:10 +01:00
|
|
|
return false;
|
2022-04-12 08:51:10 +02:00
|
|
|
}
|
|
|
|
Router.toLocation(location);
|
|
|
|
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 50000);
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
universityCourse: (_ctx: NetscriptContext) =>
|
|
|
|
function (_universityName: unknown, _className: unknown, _focus: unknown = true): boolean {
|
2022-04-14 00:13:28 +02:00
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-12 08:51:10 +02:00
|
|
|
const universityName = _ctx.helper.string("universityName", _universityName);
|
|
|
|
const className = _ctx.helper.string("className", _className);
|
|
|
|
const focus = _ctx.helper.boolean(_focus);
|
|
|
|
const wasFocusing = player.focus;
|
|
|
|
if (player.isWorking) {
|
|
|
|
const txt = player.singularityStopWork();
|
|
|
|
workerScript.log("universityCourse", () => txt);
|
|
|
|
}
|
|
|
|
|
|
|
|
let costMult, expMult;
|
|
|
|
switch (universityName.toLowerCase()) {
|
|
|
|
case LocationName.AevumSummitUniversity.toLowerCase():
|
|
|
|
if (player.city != CityName.Aevum) {
|
|
|
|
workerScript.log(
|
|
|
|
"universityCourse",
|
|
|
|
() => `You cannot study at 'Summit University' because you are not in '${CityName.Aevum}'.`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
player.gotoLocation(LocationName.AevumSummitUniversity);
|
|
|
|
costMult = 4;
|
|
|
|
expMult = 3;
|
|
|
|
break;
|
|
|
|
case LocationName.Sector12RothmanUniversity.toLowerCase():
|
|
|
|
if (player.city != CityName.Sector12) {
|
|
|
|
workerScript.log(
|
|
|
|
"universityCourse",
|
|
|
|
() => `You cannot study at 'Rothman University' because you are not in '${CityName.Sector12}'.`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
player.location = LocationName.Sector12RothmanUniversity;
|
|
|
|
costMult = 3;
|
|
|
|
expMult = 2;
|
|
|
|
break;
|
|
|
|
case LocationName.VolhavenZBInstituteOfTechnology.toLowerCase():
|
|
|
|
if (player.city != CityName.Volhaven) {
|
|
|
|
workerScript.log(
|
|
|
|
"universityCourse",
|
|
|
|
() => `You cannot study at 'ZB Institute of Technology' because you are not in '${CityName.Volhaven}'.`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
player.location = LocationName.VolhavenZBInstituteOfTechnology;
|
|
|
|
costMult = 5;
|
|
|
|
expMult = 4;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
workerScript.log("universityCourse", () => `Invalid university name: '${universityName}'.`);
|
2021-11-03 23:16:10 +01:00
|
|
|
return false;
|
2022-04-12 08:51:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
let task = "";
|
|
|
|
switch (className.toLowerCase()) {
|
|
|
|
case "Study Computer Science".toLowerCase():
|
|
|
|
task = CONSTANTS.ClassStudyComputerScience;
|
|
|
|
break;
|
|
|
|
case "Data Structures".toLowerCase():
|
|
|
|
task = CONSTANTS.ClassDataStructures;
|
|
|
|
break;
|
|
|
|
case "Networks".toLowerCase():
|
|
|
|
task = CONSTANTS.ClassNetworks;
|
|
|
|
break;
|
|
|
|
case "Algorithms".toLowerCase():
|
|
|
|
task = CONSTANTS.ClassAlgorithms;
|
|
|
|
break;
|
|
|
|
case "Management".toLowerCase():
|
|
|
|
task = CONSTANTS.ClassManagement;
|
|
|
|
break;
|
|
|
|
case "Leadership".toLowerCase():
|
|
|
|
task = CONSTANTS.ClassLeadership;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
workerScript.log("universityCourse", () => `Invalid class name: ${className}.`);
|
2021-11-03 23:16:10 +01:00
|
|
|
return false;
|
2022-04-12 08:51:10 +02:00
|
|
|
}
|
|
|
|
player.startClass(costMult, expMult, task);
|
|
|
|
if (focus) {
|
|
|
|
player.startFocusing();
|
|
|
|
Router.toWork();
|
|
|
|
} else if (wasFocusing) {
|
|
|
|
player.stopFocusing();
|
|
|
|
Router.toTerminal();
|
|
|
|
}
|
|
|
|
workerScript.log("universityCourse", () => `Started ${task} at ${universityName}`);
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
|
|
|
gymWorkout: (_ctx: NetscriptContext) =>
|
|
|
|
function (_gymName: unknown, _stat: unknown, _focus: unknown = true): boolean {
|
2022-04-14 00:13:28 +02:00
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-12 08:51:10 +02:00
|
|
|
const gymName = _ctx.helper.string("gymName", _gymName);
|
|
|
|
const stat = _ctx.helper.string("stat", _stat);
|
|
|
|
const focus = _ctx.helper.boolean(_focus);
|
|
|
|
const wasFocusing = player.focus;
|
|
|
|
if (player.isWorking) {
|
|
|
|
const txt = player.singularityStopWork();
|
|
|
|
workerScript.log("gymWorkout", () => txt);
|
|
|
|
}
|
|
|
|
let costMult, expMult;
|
|
|
|
switch (gymName.toLowerCase()) {
|
|
|
|
case LocationName.AevumCrushFitnessGym.toLowerCase():
|
|
|
|
if (player.city != CityName.Aevum) {
|
|
|
|
workerScript.log(
|
|
|
|
"gymWorkout",
|
|
|
|
() =>
|
|
|
|
`You cannot workout at '${LocationName.AevumCrushFitnessGym}' because you are not in '${CityName.Aevum}'.`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
player.location = LocationName.AevumCrushFitnessGym;
|
|
|
|
costMult = 3;
|
|
|
|
expMult = 2;
|
|
|
|
break;
|
|
|
|
case LocationName.AevumSnapFitnessGym.toLowerCase():
|
|
|
|
if (player.city != CityName.Aevum) {
|
|
|
|
workerScript.log(
|
|
|
|
"gymWorkout",
|
|
|
|
() =>
|
|
|
|
`You cannot workout at '${LocationName.AevumSnapFitnessGym}' because you are not in '${CityName.Aevum}'.`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
player.location = LocationName.AevumSnapFitnessGym;
|
|
|
|
costMult = 10;
|
|
|
|
expMult = 5;
|
|
|
|
break;
|
|
|
|
case LocationName.Sector12IronGym.toLowerCase():
|
|
|
|
if (player.city != CityName.Sector12) {
|
|
|
|
workerScript.log(
|
|
|
|
"gymWorkout",
|
|
|
|
() =>
|
|
|
|
`You cannot workout at '${LocationName.Sector12IronGym}' because you are not in '${CityName.Sector12}'.`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
player.location = LocationName.Sector12IronGym;
|
|
|
|
costMult = 1;
|
|
|
|
expMult = 1;
|
|
|
|
break;
|
|
|
|
case LocationName.Sector12PowerhouseGym.toLowerCase():
|
|
|
|
if (player.city != CityName.Sector12) {
|
|
|
|
workerScript.log(
|
|
|
|
"gymWorkout",
|
|
|
|
() =>
|
|
|
|
`You cannot workout at '${LocationName.Sector12PowerhouseGym}' because you are not in '${CityName.Sector12}'.`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
player.location = LocationName.Sector12PowerhouseGym;
|
|
|
|
costMult = 20;
|
|
|
|
expMult = 10;
|
|
|
|
break;
|
|
|
|
case LocationName.VolhavenMilleniumFitnessGym.toLowerCase():
|
|
|
|
if (player.city != CityName.Volhaven) {
|
|
|
|
workerScript.log(
|
|
|
|
"gymWorkout",
|
|
|
|
() =>
|
|
|
|
`You cannot workout at '${LocationName.VolhavenMilleniumFitnessGym}' because you are not in '${CityName.Volhaven}'.`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
player.location = LocationName.VolhavenMilleniumFitnessGym;
|
|
|
|
costMult = 7;
|
|
|
|
expMult = 4;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
workerScript.log("gymWorkout", () => `Invalid gym name: ${gymName}. gymWorkout() failed`);
|
2021-11-03 23:16:10 +01:00
|
|
|
return false;
|
2022-04-12 08:51:10 +02:00
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
switch (stat.toLowerCase()) {
|
|
|
|
case "strength".toLowerCase():
|
|
|
|
case "str".toLowerCase():
|
|
|
|
player.startClass(costMult, expMult, CONSTANTS.ClassGymStrength);
|
|
|
|
break;
|
|
|
|
case "defense".toLowerCase():
|
|
|
|
case "def".toLowerCase():
|
|
|
|
player.startClass(costMult, expMult, CONSTANTS.ClassGymDefense);
|
|
|
|
break;
|
|
|
|
case "dexterity".toLowerCase():
|
|
|
|
case "dex".toLowerCase():
|
|
|
|
player.startClass(costMult, expMult, CONSTANTS.ClassGymDexterity);
|
|
|
|
break;
|
|
|
|
case "agility".toLowerCase():
|
|
|
|
case "agi".toLowerCase():
|
|
|
|
player.startClass(costMult, expMult, CONSTANTS.ClassGymAgility);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
workerScript.log("gymWorkout", () => `Invalid stat: ${stat}.`);
|
2022-03-21 03:49:46 +01:00
|
|
|
return false;
|
2022-04-12 08:51:10 +02:00
|
|
|
}
|
|
|
|
if (focus) {
|
|
|
|
player.startFocusing();
|
|
|
|
Router.toWork();
|
|
|
|
} else if (wasFocusing) {
|
|
|
|
player.stopFocusing();
|
|
|
|
Router.toTerminal();
|
|
|
|
}
|
|
|
|
workerScript.log("gymWorkout", () => `Started training ${stat} at ${gymName}`);
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
|
|
|
travelToCity: (_ctx: NetscriptContext) =>
|
|
|
|
function (_cityName: unknown): boolean {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const cityName = _ctx.helper.city("cityName", _cityName);
|
2022-04-12 08:51:10 +02:00
|
|
|
|
|
|
|
switch (cityName) {
|
|
|
|
case CityName.Aevum:
|
|
|
|
case CityName.Chongqing:
|
|
|
|
case CityName.Sector12:
|
|
|
|
case CityName.NewTokyo:
|
|
|
|
case CityName.Ishima:
|
|
|
|
case CityName.Volhaven:
|
|
|
|
if (player.money < CONSTANTS.TravelCost) {
|
|
|
|
workerScript.log("travelToCity", () => "Not enough money to travel.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
player.loseMoney(CONSTANTS.TravelCost, "other");
|
|
|
|
player.city = cityName;
|
|
|
|
workerScript.log("travelToCity", () => `Traveled to ${cityName}`);
|
|
|
|
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 50000);
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
throw _ctx.helper.makeRuntimeErrorMsg(`Invalid city name: '${cityName}'.`);
|
|
|
|
}
|
|
|
|
},
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
purchaseTor: (_ctx: NetscriptContext) =>
|
|
|
|
function (): boolean {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
|
|
|
|
|
|
|
if (player.hasTorRouter()) {
|
|
|
|
workerScript.log("purchaseTor", () => "You already have a TOR router!");
|
|
|
|
return true;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
if (player.money < CONSTANTS.TorRouterCost) {
|
|
|
|
workerScript.log("purchaseTor", () => "You cannot afford to purchase a Tor router.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
player.loseMoney(CONSTANTS.TorRouterCost, "other");
|
|
|
|
|
|
|
|
const darkweb = safetlyCreateUniqueServer({
|
|
|
|
ip: createUniqueRandomIp(),
|
|
|
|
hostname: "darkweb",
|
|
|
|
organizationName: "",
|
|
|
|
isConnectedTo: false,
|
|
|
|
adminRights: false,
|
|
|
|
purchasedByPlayer: false,
|
|
|
|
maxRam: 1,
|
|
|
|
});
|
|
|
|
AddToAllServers(darkweb);
|
|
|
|
|
|
|
|
player.getHomeComputer().serversOnNetwork.push(darkweb.hostname);
|
|
|
|
darkweb.serversOnNetwork.push(player.getHomeComputer().hostname);
|
|
|
|
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 500);
|
|
|
|
workerScript.log("purchaseTor", () => "You have purchased a Tor router!");
|
2022-03-25 18:06:12 +01:00
|
|
|
return true;
|
2022-04-12 08:51:10 +02:00
|
|
|
},
|
|
|
|
purchaseProgram: (_ctx: NetscriptContext) =>
|
|
|
|
function (_programName: unknown): boolean {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const programName = _ctx.helper.string("programName", _programName).toLowerCase();
|
2022-04-12 08:51:10 +02:00
|
|
|
|
|
|
|
if (!player.hasTorRouter()) {
|
|
|
|
workerScript.log("purchaseProgram", () => "You do not have the TOR router.");
|
|
|
|
return false;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
const item = Object.values(DarkWebItems).find((i) => i.program.toLowerCase() === programName);
|
|
|
|
if (item == null) {
|
|
|
|
workerScript.log("purchaseProgram", () => `Invalid program name: '${programName}.`);
|
|
|
|
return false;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
if (player.money < item.price) {
|
|
|
|
workerScript.log(
|
|
|
|
"purchaseProgram",
|
|
|
|
() => `Not enough money to purchase '${item.program}'. Need ${numeralWrapper.formatMoney(item.price)}`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
if (player.hasProgram(item.program)) {
|
|
|
|
workerScript.log("purchaseProgram", () => `You already have the '${item.program}' program`);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-04-13 06:21:51 +02:00
|
|
|
player.getHomeComputer().pushProgram(item.program);
|
|
|
|
// Cancel if the program is in progress of writing
|
|
|
|
if (player.createProgramName === item.program) {
|
|
|
|
player.isWorking = false;
|
|
|
|
player.resetWorkStatus();
|
|
|
|
}
|
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
player.loseMoney(item.price, "other");
|
2021-11-03 23:16:10 +01:00
|
|
|
workerScript.log(
|
|
|
|
"purchaseProgram",
|
2022-04-12 08:51:10 +02:00
|
|
|
() => `You have purchased the '${item.program}' program. The new program can be found on your home computer.`,
|
2021-11-03 23:16:10 +01:00
|
|
|
);
|
2022-04-12 08:51:10 +02:00
|
|
|
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 5000);
|
2021-11-03 23:16:10 +01:00
|
|
|
return true;
|
2022-04-12 08:51:10 +02:00
|
|
|
},
|
|
|
|
getCurrentServer: (_ctx: NetscriptContext) =>
|
|
|
|
function (): string {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
|
|
|
return player.getCurrentServer().hostname;
|
|
|
|
},
|
|
|
|
connect: (_ctx: NetscriptContext) =>
|
|
|
|
function (_hostname: unknown): boolean {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const hostname = _ctx.helper.string("hostname", _hostname);
|
2022-04-12 08:51:10 +02:00
|
|
|
if (!hostname) {
|
|
|
|
throw _ctx.helper.makeRuntimeErrorMsg(`Invalid hostname: '${hostname}'`);
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
const target = GetServer(hostname);
|
|
|
|
if (target == null) {
|
|
|
|
throw _ctx.helper.makeRuntimeErrorMsg(`Invalid hostname: '${hostname}'`);
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-13 18:03:17 +02:00
|
|
|
//Home case
|
2022-04-12 08:51:10 +02:00
|
|
|
if (hostname === "home") {
|
2021-11-03 23:16:10 +01:00
|
|
|
player.getCurrentServer().isConnectedTo = false;
|
2022-04-12 08:51:10 +02:00
|
|
|
player.currentServer = player.getHomeComputer().hostname;
|
2021-11-03 23:16:10 +01:00
|
|
|
player.getCurrentServer().isConnectedTo = true;
|
|
|
|
Terminal.setcwd("/");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-04-13 18:03:17 +02:00
|
|
|
//Adjacent server case
|
2022-04-12 08:51:10 +02:00
|
|
|
const server = player.getCurrentServer();
|
|
|
|
for (let i = 0; i < server.serversOnNetwork.length; i++) {
|
|
|
|
const other = getServerOnNetwork(server, i);
|
|
|
|
if (other === null) continue;
|
|
|
|
if (other.hostname == hostname) {
|
|
|
|
player.getCurrentServer().isConnectedTo = false;
|
|
|
|
player.currentServer = target.hostname;
|
|
|
|
player.getCurrentServer().isConnectedTo = true;
|
|
|
|
Terminal.setcwd("/");
|
|
|
|
return true;
|
|
|
|
}
|
2021-12-16 02:44:08 +01:00
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-13 18:03:17 +02:00
|
|
|
//Backdoor case
|
|
|
|
const other = GetServer(hostname);
|
|
|
|
if (other !== null && other instanceof Server && other.backdoorInstalled) {
|
|
|
|
player.getCurrentServer().isConnectedTo = false;
|
|
|
|
player.currentServer = target.hostname;
|
|
|
|
player.getCurrentServer().isConnectedTo = true;
|
|
|
|
Terminal.setcwd("/");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Failure case
|
2021-11-03 23:16:10 +01:00
|
|
|
return false;
|
2022-04-12 08:51:10 +02:00
|
|
|
},
|
|
|
|
manualHack: (_ctx: NetscriptContext) =>
|
|
|
|
function (): Promise<number> {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
|
|
|
const server = player.getCurrentServer();
|
|
|
|
return _ctx.helper.hack(server.hostname, true);
|
|
|
|
},
|
|
|
|
installBackdoor: (_ctx: NetscriptContext) =>
|
|
|
|
function (): Promise<void> {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
|
|
|
const baseserver = player.getCurrentServer();
|
|
|
|
if (!(baseserver instanceof Server)) {
|
|
|
|
workerScript.log("installBackdoor", () => "cannot backdoor this kind of server");
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
const server = baseserver as Server;
|
|
|
|
const installTime = (calculateHackingTime(server, player) / 4) * 1000;
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
// No root access or skill level too low
|
|
|
|
const canHack = netscriptCanHack(server, player);
|
|
|
|
if (!canHack.res) {
|
|
|
|
throw _ctx.helper.makeRuntimeErrorMsg(canHack.msg || "");
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2021-11-27 00:30:58 +01:00
|
|
|
workerScript.log(
|
2022-04-12 08:51:10 +02:00
|
|
|
"installBackdoor",
|
|
|
|
() => `Installing backdoor on '${server.hostname}' in ${convertTimeMsToTimeElapsedString(installTime, true)}`,
|
2021-11-27 00:30:58 +01:00
|
|
|
);
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
return netscriptDelay(installTime, workerScript).then(function () {
|
|
|
|
workerScript.log("installBackdoor", () => `Successfully installed backdoor on '${server.hostname}'`);
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
server.backdoorInstalled = true;
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
if (SpecialServers.WorldDaemon === server.hostname) {
|
|
|
|
Router.toBitVerse(false, false);
|
|
|
|
}
|
|
|
|
return Promise.resolve();
|
|
|
|
});
|
|
|
|
},
|
|
|
|
isFocused: (_ctx: NetscriptContext) =>
|
|
|
|
function (): boolean {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
|
|
|
return player.focus;
|
|
|
|
},
|
|
|
|
setFocus: (_ctx: NetscriptContext) =>
|
|
|
|
function (_focus: unknown): boolean {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const focus = _ctx.helper.boolean(_focus);
|
2022-04-12 08:51:10 +02:00
|
|
|
if (!player.isWorking) {
|
|
|
|
throw _ctx.helper.makeRuntimeErrorMsg("Not currently working");
|
|
|
|
}
|
|
|
|
if (
|
|
|
|
!(
|
|
|
|
player.workType == CONSTANTS.WorkTypeFaction ||
|
|
|
|
player.workType == CONSTANTS.WorkTypeCompany ||
|
|
|
|
player.workType == CONSTANTS.WorkTypeCompanyPartTime ||
|
|
|
|
player.workType == CONSTANTS.WorkTypeCreateProgram ||
|
|
|
|
player.workType == CONSTANTS.WorkTypeStudyClass
|
|
|
|
)
|
|
|
|
) {
|
|
|
|
throw _ctx.helper.makeRuntimeErrorMsg("Cannot change focus for current job");
|
|
|
|
}
|
|
|
|
if (!player.focus && focus) {
|
|
|
|
player.startFocusing();
|
|
|
|
Router.toWork();
|
|
|
|
return true;
|
|
|
|
} else if (player.focus && !focus) {
|
|
|
|
player.stopFocusing();
|
|
|
|
Router.toTerminal();
|
|
|
|
return true;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
return false;
|
2022-04-12 08:51:10 +02:00
|
|
|
},
|
|
|
|
getStats: (_ctx: NetscriptContext) =>
|
|
|
|
function (): PlayerSkills {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
|
|
|
workerScript.log("getStats", () => `getStats is deprecated, please use getplayer`);
|
|
|
|
|
|
|
|
return {
|
|
|
|
hacking: player.hacking,
|
|
|
|
strength: player.strength,
|
|
|
|
defense: player.defense,
|
|
|
|
dexterity: player.dexterity,
|
|
|
|
agility: player.agility,
|
|
|
|
charisma: player.charisma,
|
|
|
|
intelligence: player.intelligence,
|
|
|
|
};
|
|
|
|
},
|
|
|
|
getCharacterInformation: (_ctx: NetscriptContext) =>
|
|
|
|
function (): CharacterInfo {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
|
|
|
workerScript.log(
|
|
|
|
"getCharacterInformation",
|
|
|
|
() => `getCharacterInformation is deprecated, please use getplayer`,
|
|
|
|
);
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
return {
|
|
|
|
bitnode: player.bitNodeN,
|
|
|
|
city: player.city,
|
|
|
|
factions: player.factions.slice(),
|
|
|
|
hp: player.hp,
|
|
|
|
jobs: Object.keys(player.jobs),
|
|
|
|
jobTitles: Object.values(player.jobs),
|
|
|
|
maxHp: player.max_hp,
|
|
|
|
mult: {
|
|
|
|
agility: player.agility_mult,
|
|
|
|
agilityExp: player.agility_exp_mult,
|
|
|
|
charisma: player.charisma,
|
|
|
|
charismaExp: player.charisma_exp,
|
|
|
|
companyRep: player.company_rep_mult,
|
|
|
|
crimeMoney: player.crime_money_mult,
|
|
|
|
crimeSuccess: player.crime_success_mult,
|
|
|
|
defense: player.defense_mult,
|
|
|
|
defenseExp: player.defense_exp_mult,
|
|
|
|
dexterity: player.dexterity_mult,
|
|
|
|
dexterityExp: player.dexterity_exp_mult,
|
|
|
|
factionRep: player.faction_rep_mult,
|
|
|
|
hacking: player.hacking_mult,
|
|
|
|
hackingExp: player.hacking_exp_mult,
|
|
|
|
strength: player.strength_mult,
|
|
|
|
strengthExp: player.strength_exp_mult,
|
|
|
|
workMoney: player.work_money_mult,
|
|
|
|
},
|
|
|
|
timeWorked: player.timeWorked,
|
|
|
|
tor: player.hasTorRouter(),
|
|
|
|
workHackExpGain: player.workHackExpGained,
|
|
|
|
workStrExpGain: player.workStrExpGained,
|
|
|
|
workDefExpGain: player.workDefExpGained,
|
|
|
|
workDexExpGain: player.workDexExpGained,
|
|
|
|
workAgiExpGain: player.workAgiExpGained,
|
|
|
|
workChaExpGain: player.workChaExpGained,
|
|
|
|
workRepGain: player.workRepGained,
|
|
|
|
workMoneyGain: player.workMoneyGained,
|
|
|
|
hackingExp: player.hacking_exp,
|
|
|
|
strengthExp: player.strength_exp,
|
|
|
|
defenseExp: player.defense_exp,
|
|
|
|
dexterityExp: player.dexterity_exp,
|
|
|
|
agilityExp: player.agility_exp,
|
|
|
|
charismaExp: player.charisma_exp,
|
|
|
|
};
|
|
|
|
},
|
|
|
|
hospitalize: (_ctx: NetscriptContext) =>
|
|
|
|
function (): void {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
|
|
|
if (player.isWorking || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse) {
|
|
|
|
workerScript.log("hospitalize", () => "Cannot go to the hospital because the player is busy.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
player.hospitalize();
|
|
|
|
},
|
|
|
|
isBusy: (_ctx: NetscriptContext) =>
|
|
|
|
function (): boolean {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
|
|
|
return player.isWorking || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse;
|
|
|
|
},
|
|
|
|
stopAction: (_ctx: NetscriptContext) =>
|
|
|
|
function (): boolean {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
|
|
|
if (player.isWorking) {
|
|
|
|
if (player.focus) {
|
|
|
|
player.stopFocusing();
|
|
|
|
Router.toTerminal();
|
|
|
|
}
|
|
|
|
const txt = player.singularityStopWork();
|
|
|
|
workerScript.log("stopAction", () => txt);
|
|
|
|
return true;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
return false;
|
2022-04-12 08:51:10 +02:00
|
|
|
},
|
|
|
|
upgradeHomeCores: (_ctx: NetscriptContext) =>
|
|
|
|
function (): boolean {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
|
|
|
|
|
|
|
// Check if we're at max cores
|
|
|
|
const homeComputer = player.getHomeComputer();
|
|
|
|
if (homeComputer.cpuCores >= 8) {
|
|
|
|
workerScript.log("upgradeHomeCores", () => `Your home computer is at max cores.`);
|
|
|
|
return false;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
const cost = player.getUpgradeHomeCoresCost();
|
|
|
|
if (player.money < cost) {
|
|
|
|
workerScript.log(
|
|
|
|
"upgradeHomeCores",
|
|
|
|
() => `You don't have enough money. Need ${numeralWrapper.formatMoney(cost)}`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
homeComputer.cpuCores += 1;
|
|
|
|
player.loseMoney(cost, "servers");
|
2021-12-16 18:02:46 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 2);
|
2021-11-03 23:16:10 +01:00
|
|
|
workerScript.log(
|
2022-04-12 08:51:10 +02:00
|
|
|
"upgradeHomeCores",
|
|
|
|
() => `Purchased an additional core for home computer! It now has ${homeComputer.cpuCores} cores.`,
|
2021-11-03 23:16:10 +01:00
|
|
|
);
|
2022-04-12 08:51:10 +02:00
|
|
|
return true;
|
|
|
|
},
|
|
|
|
getUpgradeHomeCoresCost: (_ctx: NetscriptContext) =>
|
|
|
|
function (): number {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
|
|
|
|
|
|
|
return player.getUpgradeHomeCoresCost();
|
|
|
|
},
|
|
|
|
upgradeHomeRam: (_ctx: NetscriptContext) =>
|
|
|
|
function (): boolean {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
|
|
|
|
|
|
|
// Check if we're at max RAM
|
|
|
|
const homeComputer = player.getHomeComputer();
|
|
|
|
if (homeComputer.maxRam >= CONSTANTS.HomeComputerMaxRam) {
|
|
|
|
workerScript.log("upgradeHomeRam", () => `Your home computer is at max RAM.`);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const cost = player.getUpgradeHomeRamCost();
|
|
|
|
if (player.money < cost) {
|
|
|
|
workerScript.log(
|
|
|
|
"upgradeHomeRam",
|
|
|
|
() => `You don't have enough money. Need ${numeralWrapper.formatMoney(cost)}`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
homeComputer.maxRam *= 2;
|
|
|
|
player.loseMoney(cost, "servers");
|
|
|
|
|
|
|
|
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 2);
|
2021-11-03 23:16:10 +01:00
|
|
|
workerScript.log(
|
2022-04-12 08:51:10 +02:00
|
|
|
"upgradeHomeRam",
|
|
|
|
() =>
|
|
|
|
`Purchased additional RAM for home computer! It now has ${numeralWrapper.formatRAM(
|
|
|
|
homeComputer.maxRam,
|
|
|
|
)} of RAM.`,
|
2021-11-03 23:16:10 +01:00
|
|
|
);
|
2022-04-12 08:51:10 +02:00
|
|
|
return true;
|
|
|
|
},
|
|
|
|
getUpgradeHomeRamCost: (_ctx: NetscriptContext) =>
|
|
|
|
function (): number {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
|
|
|
|
|
|
|
return player.getUpgradeHomeRamCost();
|
|
|
|
},
|
|
|
|
workForCompany: (_ctx: NetscriptContext) =>
|
|
|
|
function (_companyName: unknown, _focus: unknown = true): boolean {
|
2022-04-14 00:13:28 +02:00
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-12 08:51:10 +02:00
|
|
|
let companyName = _ctx.helper.string("companyName", _companyName);
|
|
|
|
const focus = _ctx.helper.boolean(_focus);
|
|
|
|
|
|
|
|
// Sanitize input
|
|
|
|
if (companyName == null) {
|
|
|
|
companyName = player.companyName;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
// Make sure its a valid company
|
|
|
|
if (companyName == null || companyName === "" || !(Companies[companyName] instanceof Company)) {
|
|
|
|
workerScript.log("workForCompany", () => `Invalid company: '${companyName}'`);
|
|
|
|
return false;
|
2021-11-03 23:16:10 +01:00
|
|
|
}
|
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
// Make sure player is actually employed at the comapny
|
|
|
|
if (!Object.keys(player.jobs).includes(companyName)) {
|
|
|
|
workerScript.log("workForCompany", () => `You do not have a job at '${companyName}'`);
|
|
|
|
return false;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
// Check to make sure company position data is valid
|
|
|
|
const companyPositionName = player.jobs[companyName];
|
|
|
|
const companyPosition = CompanyPositions[companyPositionName];
|
|
|
|
if (companyPositionName === "" || !(companyPosition instanceof CompanyPosition)) {
|
|
|
|
workerScript.log("workForCompany", () => "You do not have a job");
|
|
|
|
return false;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
const wasFocused = player.focus;
|
|
|
|
if (player.isWorking) {
|
|
|
|
const txt = player.singularityStopWork();
|
|
|
|
workerScript.log("workForCompany", () => txt);
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
if (companyPosition.isPartTimeJob()) {
|
|
|
|
player.startWorkPartTime(companyName);
|
|
|
|
} else {
|
|
|
|
player.startWork(companyName);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (focus) {
|
|
|
|
player.startFocusing();
|
|
|
|
Router.toWork();
|
|
|
|
} else if (wasFocused) {
|
|
|
|
player.stopFocusing();
|
|
|
|
Router.toTerminal();
|
|
|
|
}
|
|
|
|
workerScript.log(
|
|
|
|
"workForCompany",
|
|
|
|
() => `Began working at '${player.companyName}' as a '${companyPositionName}'`,
|
|
|
|
);
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
applyToCompany: (_ctx: NetscriptContext) =>
|
|
|
|
function (_companyName: unknown, _field: unknown): boolean {
|
2022-04-14 00:13:28 +02:00
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-12 08:51:10 +02:00
|
|
|
const companyName = _ctx.helper.string("companyName", _companyName);
|
|
|
|
const field = _ctx.helper.string("field", _field);
|
|
|
|
getCompany(_ctx, companyName);
|
|
|
|
|
|
|
|
player.location = companyName as LocationName;
|
|
|
|
let res;
|
|
|
|
switch (field.toLowerCase()) {
|
|
|
|
case "software":
|
|
|
|
res = player.applyForSoftwareJob(true);
|
|
|
|
break;
|
|
|
|
case "software consultant":
|
|
|
|
res = player.applyForSoftwareConsultantJob(true);
|
|
|
|
break;
|
|
|
|
case "it":
|
|
|
|
res = player.applyForItJob(true);
|
|
|
|
break;
|
|
|
|
case "security engineer":
|
|
|
|
res = player.applyForSecurityEngineerJob(true);
|
|
|
|
break;
|
|
|
|
case "network engineer":
|
|
|
|
res = player.applyForNetworkEngineerJob(true);
|
|
|
|
break;
|
|
|
|
case "business":
|
|
|
|
res = player.applyForBusinessJob(true);
|
|
|
|
break;
|
|
|
|
case "business consultant":
|
|
|
|
res = player.applyForBusinessConsultantJob(true);
|
|
|
|
break;
|
|
|
|
case "security":
|
|
|
|
res = player.applyForSecurityJob(true);
|
|
|
|
break;
|
|
|
|
case "agent":
|
|
|
|
res = player.applyForAgentJob(true);
|
|
|
|
break;
|
|
|
|
case "employee":
|
|
|
|
res = player.applyForEmployeeJob(true);
|
|
|
|
break;
|
|
|
|
case "part-time employee":
|
|
|
|
res = player.applyForPartTimeEmployeeJob(true);
|
|
|
|
break;
|
|
|
|
case "waiter":
|
|
|
|
res = player.applyForWaiterJob(true);
|
|
|
|
break;
|
|
|
|
case "part-time waiter":
|
|
|
|
res = player.applyForPartTimeWaiterJob(true);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
workerScript.log("applyToCompany", () => `Invalid job: '${field}'.`);
|
2021-11-03 23:16:10 +01:00
|
|
|
return false;
|
2022-04-12 08:51:10 +02:00
|
|
|
}
|
|
|
|
// TODO https://github.com/danielyxie/bitburner/issues/1378
|
|
|
|
// The player object's applyForJob function can return string with special error messages
|
|
|
|
// if (isString(res)) {
|
|
|
|
// workerScript.log("applyToCompany",()=> res);
|
|
|
|
// return false;
|
|
|
|
// }
|
|
|
|
if (res) {
|
|
|
|
workerScript.log(
|
|
|
|
"applyToCompany",
|
|
|
|
() => `You were offered a new job at '${companyName}' as a '${player.jobs[companyName]}'`,
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
workerScript.log(
|
|
|
|
"applyToCompany",
|
|
|
|
() => `You failed to get a new job/promotion at '${companyName}' in the '${field}' field.`,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
},
|
|
|
|
getCompanyRep: (_ctx: NetscriptContext) =>
|
|
|
|
function (_companyName: unknown): number {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const companyName = _ctx.helper.string("companyName", _companyName);
|
2022-04-12 08:51:10 +02:00
|
|
|
const company = getCompany(_ctx, companyName);
|
|
|
|
return company.playerReputation;
|
|
|
|
},
|
|
|
|
getCompanyFavor: (_ctx: NetscriptContext) =>
|
|
|
|
function (_companyName: unknown): number {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const companyName = _ctx.helper.string("companyName", _companyName);
|
2022-04-12 08:51:10 +02:00
|
|
|
const company = getCompany(_ctx, companyName);
|
|
|
|
return company.favor;
|
|
|
|
},
|
|
|
|
getCompanyFavorGain: (_ctx: NetscriptContext) =>
|
|
|
|
function (_companyName: unknown): number {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const companyName = _ctx.helper.string("companyName", _companyName);
|
2022-04-12 08:51:10 +02:00
|
|
|
const company = getCompany(_ctx, companyName);
|
|
|
|
return company.getFavorGain();
|
|
|
|
},
|
|
|
|
checkFactionInvitations: (_ctx: NetscriptContext) =>
|
|
|
|
function (): string[] {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
|
|
|
// Make a copy of player.factionInvitations
|
|
|
|
return player.factionInvitations.slice();
|
|
|
|
},
|
|
|
|
joinFaction: (_ctx: NetscriptContext) =>
|
|
|
|
function (_facName: unknown): boolean {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const facName = _ctx.helper.string("facName", _facName);
|
2022-04-12 08:51:10 +02:00
|
|
|
getFaction(_ctx, facName);
|
|
|
|
|
|
|
|
if (!player.factionInvitations.includes(facName)) {
|
|
|
|
workerScript.log("joinFaction", () => `You have not been invited by faction '${facName}'`);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const fac = Factions[facName];
|
|
|
|
joinFaction(fac);
|
|
|
|
|
|
|
|
// Update Faction Invitation list to account for joined + banned factions
|
|
|
|
for (let i = 0; i < player.factionInvitations.length; ++i) {
|
|
|
|
if (player.factionInvitations[i] == facName || Factions[player.factionInvitations[i]].isBanned) {
|
|
|
|
player.factionInvitations.splice(i, 1);
|
|
|
|
i--;
|
2021-11-03 23:16:10 +01:00
|
|
|
}
|
2022-04-12 08:51:10 +02:00
|
|
|
}
|
|
|
|
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 5);
|
|
|
|
workerScript.log("joinFaction", () => `Joined the '${facName}' faction.`);
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
workForFaction: (_ctx: NetscriptContext) =>
|
|
|
|
function (_facName: unknown, _type: unknown, _focus: unknown = true): boolean {
|
2022-04-14 00:13:28 +02:00
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-12 08:51:10 +02:00
|
|
|
const facName = _ctx.helper.string("facName", _facName);
|
|
|
|
const type = _ctx.helper.string("type", _type);
|
|
|
|
const focus = _ctx.helper.boolean(_focus);
|
|
|
|
getFaction(_ctx, facName);
|
|
|
|
|
|
|
|
// if the player is in a gang and the target faction is any of the gang faction, fail
|
|
|
|
if (player.inGang() && AllGangs[facName] !== undefined) {
|
|
|
|
workerScript.log("workForFaction", () => `Faction '${facName}' does not offer work at the moment.`);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!player.factions.includes(facName)) {
|
|
|
|
workerScript.log("workForFaction", () => `You are not a member of '${facName}'`);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const wasFocusing = player.focus;
|
|
|
|
if (player.isWorking) {
|
|
|
|
const txt = player.singularityStopWork();
|
|
|
|
workerScript.log("workForFaction", () => txt);
|
|
|
|
}
|
|
|
|
|
|
|
|
const fac = Factions[facName];
|
|
|
|
// Arrays listing factions that allow each time of work
|
|
|
|
|
|
|
|
switch (type.toLowerCase()) {
|
|
|
|
case "hacking":
|
|
|
|
case "hacking contracts":
|
|
|
|
case "hackingcontracts":
|
|
|
|
if (!FactionInfos[fac.name].offerHackingWork) {
|
|
|
|
workerScript.log(
|
|
|
|
"workForFaction",
|
|
|
|
() => `Faction '${fac.name}' do not need help with hacking contracts.`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
player.startFactionHackWork(fac);
|
|
|
|
if (focus) {
|
|
|
|
player.startFocusing();
|
|
|
|
Router.toWork();
|
|
|
|
} else if (wasFocusing) {
|
|
|
|
player.stopFocusing();
|
|
|
|
Router.toTerminal();
|
|
|
|
}
|
|
|
|
workerScript.log("workForFaction", () => `Started carrying out hacking contracts for '${fac.name}'`);
|
|
|
|
return true;
|
|
|
|
case "field":
|
|
|
|
case "fieldwork":
|
|
|
|
case "field work":
|
|
|
|
if (!FactionInfos[fac.name].offerFieldWork) {
|
|
|
|
workerScript.log("workForFaction", () => `Faction '${fac.name}' do not need help with field missions.`);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
player.startFactionFieldWork(fac);
|
|
|
|
if (focus) {
|
|
|
|
player.startFocusing();
|
|
|
|
Router.toWork();
|
|
|
|
} else if (wasFocusing) {
|
|
|
|
player.stopFocusing();
|
|
|
|
Router.toTerminal();
|
|
|
|
}
|
|
|
|
workerScript.log("workForFaction", () => `Started carrying out field missions for '${fac.name}'`);
|
|
|
|
return true;
|
|
|
|
case "security":
|
|
|
|
case "securitywork":
|
|
|
|
case "security work":
|
|
|
|
if (!FactionInfos[fac.name].offerSecurityWork) {
|
|
|
|
workerScript.log("workForFaction", () => `Faction '${fac.name}' do not need help with security work.`);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
player.startFactionSecurityWork(fac);
|
|
|
|
if (focus) {
|
|
|
|
player.startFocusing();
|
|
|
|
Router.toWork();
|
|
|
|
} else if (wasFocusing) {
|
|
|
|
player.stopFocusing();
|
|
|
|
Router.toTerminal();
|
|
|
|
}
|
|
|
|
workerScript.log("workForFaction", () => `Started carrying out security work for '${fac.name}'`);
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
workerScript.log("workForFaction", () => `Invalid work type: '${type}`);
|
2021-11-03 23:16:10 +01:00
|
|
|
return false;
|
2022-04-12 08:51:10 +02:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
getFactionRep: (_ctx: NetscriptContext) =>
|
|
|
|
function (_facName: unknown): number {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const facName = _ctx.helper.string("facName", _facName);
|
2022-04-12 08:51:10 +02:00
|
|
|
const faction = getFaction(_ctx, facName);
|
|
|
|
return faction.playerReputation;
|
|
|
|
},
|
|
|
|
getFactionFavor: (_ctx: NetscriptContext) =>
|
|
|
|
function (_facName: unknown): number {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const facName = _ctx.helper.string("facName", _facName);
|
2022-04-12 08:51:10 +02:00
|
|
|
const faction = getFaction(_ctx, facName);
|
|
|
|
return faction.favor;
|
|
|
|
},
|
|
|
|
getFactionFavorGain: (_ctx: NetscriptContext) =>
|
|
|
|
function (_facName: unknown): number {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const facName = _ctx.helper.string("facName", _facName);
|
2022-04-12 08:51:10 +02:00
|
|
|
const faction = getFaction(_ctx, facName);
|
|
|
|
return faction.getFavorGain();
|
|
|
|
},
|
|
|
|
donateToFaction: (_ctx: NetscriptContext) =>
|
|
|
|
function (_facName: unknown, _amt: unknown): boolean {
|
2022-04-14 00:13:28 +02:00
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-12 08:51:10 +02:00
|
|
|
const facName = _ctx.helper.string("facName", _facName);
|
|
|
|
const amt = _ctx.helper.number("amt", _amt);
|
|
|
|
const faction = getFaction(_ctx, facName);
|
|
|
|
if (!player.factions.includes(faction.name)) {
|
|
|
|
workerScript.log("donateToFaction", () => `You can't donate to '${facName}' because you aren't a member`);
|
2022-04-05 17:22:02 +02:00
|
|
|
return false;
|
2022-04-12 08:51:10 +02:00
|
|
|
}
|
|
|
|
if (player.inGang() && faction.name === player.getGangFaction().name) {
|
|
|
|
workerScript.log(
|
|
|
|
"donateToFaction",
|
|
|
|
() => `You can't donate to '${facName}' because youre managing a gang for it`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (typeof amt !== "number" || amt <= 0 || isNaN(amt)) {
|
|
|
|
workerScript.log("donateToFaction", () => `Invalid donation amount: '${amt}'.`);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (player.money < amt) {
|
|
|
|
workerScript.log(
|
|
|
|
"donateToFaction",
|
|
|
|
() => `You do not have enough money to donate ${numeralWrapper.formatMoney(amt)} to '${facName}'`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const repNeededToDonate = Math.floor(CONSTANTS.BaseFavorToDonate * BitNodeMultipliers.RepToDonateToFaction);
|
|
|
|
if (faction.favor < repNeededToDonate) {
|
|
|
|
workerScript.log(
|
|
|
|
"donateToFaction",
|
|
|
|
() =>
|
|
|
|
`You do not have enough favor to donate to this faction. Have ${faction.favor}, need ${repNeededToDonate}`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const repGain = (amt / CONSTANTS.DonateMoneyToRepDivisor) * player.faction_rep_mult;
|
|
|
|
faction.playerReputation += repGain;
|
|
|
|
player.loseMoney(amt, "other");
|
2021-11-03 23:16:10 +01:00
|
|
|
workerScript.log(
|
|
|
|
"donateToFaction",
|
2021-11-27 00:30:58 +01:00
|
|
|
() =>
|
2022-04-12 08:51:10 +02:00
|
|
|
`${numeralWrapper.formatMoney(amt)} donated to '${facName}' for ${numeralWrapper.formatReputation(
|
|
|
|
repGain,
|
|
|
|
)} reputation`,
|
2021-11-03 23:16:10 +01:00
|
|
|
);
|
2022-04-12 08:51:10 +02:00
|
|
|
return true;
|
|
|
|
},
|
|
|
|
createProgram: (_ctx: NetscriptContext) =>
|
|
|
|
function (_programName: unknown, _focus: unknown = true): boolean {
|
2022-04-14 00:13:28 +02:00
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-12 08:51:10 +02:00
|
|
|
const programName = _ctx.helper.string("programName", _programName).toLowerCase();
|
|
|
|
const focus = _ctx.helper.boolean(_focus);
|
|
|
|
|
|
|
|
const wasFocusing = player.focus;
|
|
|
|
if (player.isWorking) {
|
|
|
|
const txt = player.singularityStopWork();
|
|
|
|
workerScript.log("createProgram", () => txt);
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
const p = Object.values(Programs).find((p) => p.name.toLowerCase() === programName);
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
if (p == null) {
|
|
|
|
workerScript.log("createProgram", () => `The specified program does not exist: '${programName}`);
|
|
|
|
return false;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
if (player.hasProgram(p.name)) {
|
|
|
|
workerScript.log("createProgram", () => `You already have the '${p.name}' program`);
|
|
|
|
return false;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
const create = p.create;
|
|
|
|
if (create === null) {
|
|
|
|
workerScript.log("createProgram", () => `You cannot create the '${p.name}' program`);
|
|
|
|
return false;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
if (!create.req(player)) {
|
|
|
|
workerScript.log(
|
|
|
|
"createProgram",
|
|
|
|
() => `Hacking level is too low to create '${p.name}' (level ${create.level} req)`,
|
|
|
|
);
|
|
|
|
return false;
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
player.startCreateProgramWork(p.name, create.time, create.level);
|
|
|
|
if (focus) {
|
|
|
|
player.startFocusing();
|
|
|
|
Router.toWork();
|
|
|
|
} else if (wasFocusing) {
|
|
|
|
player.stopFocusing();
|
|
|
|
Router.toTerminal();
|
|
|
|
}
|
|
|
|
workerScript.log("createProgram", () => `Began creating program: '${programName}'`);
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
commitCrime: (_ctx: NetscriptContext) =>
|
|
|
|
function (_crimeRoughName: unknown): number {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const crimeRoughName = _ctx.helper.string("crimeRoughName", _crimeRoughName);
|
2022-04-12 08:51:10 +02:00
|
|
|
|
|
|
|
if (player.isWorking) {
|
|
|
|
const txt = player.singularityStopWork();
|
|
|
|
workerScript.log("commitCrime", () => txt);
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
// Set Location to slums
|
|
|
|
player.gotoLocation(LocationName.Slums);
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
const crime = findCrime(crimeRoughName.toLowerCase());
|
|
|
|
if (crime == null) {
|
|
|
|
// couldn't find crime
|
|
|
|
throw _ctx.helper.makeRuntimeErrorMsg(`Invalid crime: '${crimeRoughName}'`);
|
|
|
|
}
|
|
|
|
workerScript.log("commitCrime", () => `Attempting to commit ${crime.name}...`);
|
|
|
|
return crime.commit(Router, player, 1, workerScript);
|
|
|
|
},
|
|
|
|
getCrimeChance: (_ctx: NetscriptContext) =>
|
|
|
|
function (_crimeRoughName: unknown): number {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const crimeRoughName = _ctx.helper.string("crimeRoughName", _crimeRoughName);
|
2022-04-12 08:51:10 +02:00
|
|
|
|
|
|
|
const crime = findCrime(crimeRoughName.toLowerCase());
|
|
|
|
if (crime == null) {
|
|
|
|
throw _ctx.helper.makeRuntimeErrorMsg(`Invalid crime: ${crimeRoughName}`);
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
return crime.successRate(player);
|
|
|
|
},
|
|
|
|
getCrimeStats: (_ctx: NetscriptContext) =>
|
|
|
|
function (_crimeRoughName: unknown): CrimeStats {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const crimeRoughName = _ctx.helper.string("crimeRoughName", _crimeRoughName);
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
const crime = findCrime(crimeRoughName.toLowerCase());
|
|
|
|
if (crime == null) {
|
|
|
|
throw _ctx.helper.makeRuntimeErrorMsg(`Invalid crime: ${crimeRoughName}`);
|
|
|
|
}
|
2021-11-03 23:16:10 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
return Object.assign({}, crime);
|
|
|
|
},
|
|
|
|
getDarkwebPrograms: (_ctx: NetscriptContext) =>
|
|
|
|
function (): string[] {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-03-21 03:49:46 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
// If we don't have Tor, log it and return [] (empty list)
|
|
|
|
if (!player.hasTorRouter()) {
|
|
|
|
workerScript.log("getDarkwebPrograms", () => "You do not have the TOR router.");
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
return Object.values(DarkWebItems).map((p) => p.program);
|
|
|
|
},
|
|
|
|
getDarkwebProgramCost: (_ctx: NetscriptContext) =>
|
|
|
|
function (_programName: unknown): number {
|
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-14 00:13:28 +02:00
|
|
|
const programName = _ctx.helper.string("programName", _programName).toLowerCase();
|
2022-04-12 08:51:10 +02:00
|
|
|
|
|
|
|
// If we don't have Tor, log it and return -1
|
|
|
|
if (!player.hasTorRouter()) {
|
|
|
|
workerScript.log("getDarkwebProgramCost", () => "You do not have the TOR router.");
|
|
|
|
// returning -1 rather than throwing an error to be consistent with purchaseProgram
|
|
|
|
// which returns false if tor has
|
|
|
|
return -1;
|
|
|
|
}
|
2022-03-21 03:49:46 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
const item = Object.values(DarkWebItems).find((i) => i.program.toLowerCase() === programName);
|
|
|
|
|
|
|
|
// If the program doesn't exist, throw an error. The reasoning here is that the 99% case is that
|
|
|
|
// the player will be using this in automation scripts, and if they're asking for a program that
|
|
|
|
// doesn't exist, it's the first time they've run the script. So throw an error to let them know
|
|
|
|
// that they need to fix it.
|
|
|
|
if (item == null) {
|
|
|
|
throw _ctx.helper.makeRuntimeErrorMsg(
|
|
|
|
`No such exploit ('${programName}') found on the darkweb! ` +
|
|
|
|
`\nThis function is not case-sensitive. Did you perhaps forget .exe at the end?`,
|
|
|
|
);
|
|
|
|
}
|
2022-03-21 03:49:46 +01:00
|
|
|
|
2022-04-12 08:51:10 +02:00
|
|
|
if (player.hasProgram(item.program)) {
|
|
|
|
workerScript.log("getDarkwebProgramCost", () => `You already have the '${item.program}' program`);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return item.price;
|
|
|
|
},
|
2022-04-13 23:34:02 +02:00
|
|
|
b1tflum3:
|
|
|
|
(_ctx: NetscriptContext) =>
|
|
|
|
(_nextBN: unknown, _callbackScript: unknown = ""): void => {
|
2022-04-14 00:13:28 +02:00
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-13 23:34:02 +02:00
|
|
|
const nextBN = _ctx.helper.number("nextBN", _nextBN);
|
|
|
|
const callbackScript = _ctx.helper.string("callbackScript", _callbackScript);
|
2022-04-14 00:08:35 +02:00
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-13 23:34:02 +02:00
|
|
|
enterBitNode(Router, true, player.bitNodeN, nextBN);
|
|
|
|
if (callbackScript)
|
|
|
|
setTimeout(() => {
|
|
|
|
runAfterReset(callbackScript);
|
|
|
|
}, 0);
|
|
|
|
},
|
|
|
|
destroyW0r1dD43m0n:
|
|
|
|
(_ctx: NetscriptContext) =>
|
|
|
|
(_nextBN: unknown, _callbackScript: unknown = ""): void => {
|
2022-04-14 00:13:28 +02:00
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-13 23:34:02 +02:00
|
|
|
const nextBN = _ctx.helper.number("nextBN", _nextBN);
|
|
|
|
const callbackScript = _ctx.helper.string("callbackScript", _callbackScript);
|
2022-04-14 00:08:35 +02:00
|
|
|
_ctx.helper.checkSingularityAccess();
|
2022-04-13 23:34:02 +02:00
|
|
|
|
|
|
|
const hackingRequirements = (): boolean => {
|
|
|
|
const wd = GetServer(SpecialServers.WorldDaemon);
|
|
|
|
if (!(wd instanceof Server))
|
|
|
|
throw new Error("WorldDaemon was not a normal server. This is a bug contact dev.");
|
|
|
|
if (player.hacking < wd.requiredHackingSkill) return false;
|
|
|
|
if (!wd.hasAdminRights) return false;
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
const bladeburnerRequirements = (): boolean => {
|
|
|
|
if (!player.inBladeburner()) return false;
|
|
|
|
if (!player.bladeburner) return false;
|
|
|
|
return player.bladeburner.blackops[BlackOperationNames.OperationDaedalus];
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!hackingRequirements() && !bladeburnerRequirements()) {
|
|
|
|
_ctx.log(() => "Requirements not met to destroy the world daemon");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
enterBitNode(Router, false, player.bitNodeN, nextBN);
|
|
|
|
if (callbackScript)
|
|
|
|
setTimeout(() => {
|
|
|
|
runAfterReset(callbackScript);
|
|
|
|
}, 0);
|
|
|
|
},
|
2021-11-03 23:16:10 +01:00
|
|
|
};
|
|
|
|
}
|