bitburner-src/src/NetscriptFunctions/Singularity.ts

1320 lines
53 KiB
TypeScript
Raw Normal View History

import { INetscriptHelper } from "./INetscriptHelper";
import { WorkerScript } from "../Netscript/WorkerScript";
import { IPlayer } from "../PersonObjects/IPlayer";
import { purchaseAugmentation, joinFaction, getFactionAugmentationsFiltered } from "../Faction/FactionHelpers";
import { startWorkerScript } from "../NetscriptWorker";
import { Augmentation } from "../Augmentation/Augmentation";
import { Augmentations } from "../Augmentation/Augmentations";
import { augmentationExists, installAugmentations } from "../Augmentation/AugmentationHelpers";
import { prestigeAugmentation } from "../Prestige";
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
import { killWorkerScript } from "../Netscript/killWorkerScript";
import { CONSTANTS } from "../Constants";
import { isString } from "../utils/helpers/isString";
import { getRamCost } from "../Netscript/RamCostGenerator";
import { RunningScript } from "../Script/RunningScript";
2022-03-30 01:49:37 +02:00
import {
AugmentationStats,
CharacterInfo,
CrimeStats,
PlayerSkills,
Singularity as ISingularity,
} from "../ScriptEditor/NetscriptDefinitions";
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";
export function NetscriptSingularity(
player: IPlayer,
workerScript: WorkerScript,
helper: INetscriptHelper,
): ISingularity {
2022-03-30 01:49:37 +02:00
const getAugmentation = function (func: string, name: string): Augmentation {
if (!augmentationExists(name)) {
throw helper.makeRuntimeErrorMsg(func, `Invalid augmentation: '${name}'`);
}
return Augmentations[name];
};
2022-03-30 01:49:37 +02:00
const getFaction = function (func: string, name: string): Faction {
if (!factionExists(name)) {
throw helper.makeRuntimeErrorMsg(func, `Invalid faction name: '${name}`);
}
return Factions[name];
};
2022-03-30 01:49:37 +02:00
const getCompany = function (func: string, name: string): Company {
const company = Companies[name];
if (company == null || !(company instanceof Company)) {
throw helper.makeRuntimeErrorMsg(func, `Invalid company name: '${name}'`);
}
return company;
};
2022-03-30 01:49:37 +02:00
const runAfterReset = function (cbScript: string | null = null): void {
//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
}
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);
}
}
};
return {
2022-03-30 01:49:37 +02:00
getOwnedAugmentations: function (_purchased: unknown = false): string[] {
const purchased = helper.boolean(_purchased);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getOwnedAugmentations", getRamCost(player, "getOwnedAugmentations"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getOwnedAugmentations");
const res = [];
for (let i = 0; i < player.augmentations.length; ++i) {
res.push(player.augmentations[i].name);
}
if (purchased) {
for (let i = 0; i < player.queuedAugmentations.length; ++i) {
res.push(player.queuedAugmentations[i].name);
}
}
return res;
},
2022-03-30 01:49:37 +02:00
getAugmentationsFromFaction: function (_facName: unknown): string[] {
const facName = helper.string("getAugmentationsFromFaction", "facName", _facName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getAugmentationsFromFaction", getRamCost(player, "getAugmentationsFromFaction"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getAugmentationsFromFaction");
2022-03-30 01:49:37 +02:00
const faction = getFaction("getAugmentationsFromFaction", facName);
return getFactionAugmentationsFiltered(player, faction);
},
2022-03-30 01:49:37 +02:00
getAugmentationCost: function (_augName: unknown): [number, number] {
const augName = helper.string("getAugmentationCost", "augName", _augName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getAugmentationCost", getRamCost(player, "getAugmentationCost"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getAugmentationCost");
2022-03-30 01:49:37 +02:00
const aug = getAugmentation("getAugmentationCost", augName);
return [aug.baseRepRequirement, aug.baseCost];
},
2022-03-30 01:49:37 +02:00
getAugmentationPrereq: function (_augName: unknown): string[] {
const augName = helper.string("getAugmentationPrereq", "augName", _augName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getAugmentationPrereq", getRamCost(player, "getAugmentationPrereq"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getAugmentationPrereq");
2022-03-30 01:49:37 +02:00
const aug = getAugmentation("getAugmentationPrereq", augName);
return aug.prereqs.slice();
},
2022-03-30 01:49:37 +02:00
getAugmentationPrice: function (_augName: unknown): number {
const augName = helper.string("getAugmentationPrice", "augName", _augName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getAugmentationPrice", getRamCost(player, "getAugmentationPrice"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getAugmentationPrice");
2022-03-30 01:49:37 +02:00
const aug = getAugmentation("getAugmentationPrice", augName);
return aug.baseCost;
},
2022-03-30 01:49:37 +02:00
getAugmentationRepReq: function (_augName: unknown): number {
const augName = helper.string("getAugmentationRepReq", "augName", _augName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getAugmentationRepReq", getRamCost(player, "getAugmentationRepReq"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getAugmentationRepReq");
2022-03-30 01:49:37 +02:00
const aug = getAugmentation("getAugmentationRepReq", augName);
return aug.baseRepRequirement;
},
2022-03-30 01:49:37 +02:00
getAugmentationStats: function (_augName: unknown): AugmentationStats {
const augName = helper.string("getAugmentationStats", "augName", _augName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getAugmentationStats", getRamCost(player, "getAugmentationStats"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getAugmentationStats");
2022-03-30 01:49:37 +02:00
const aug = getAugmentation("getAugmentationStats", augName);
return Object.assign({}, aug.mults);
},
2022-03-30 01:49:37 +02:00
purchaseAugmentation: function (_facName: unknown, _augName: unknown): boolean {
const facName = helper.string("purchaseAugmentation", "facName", _facName);
const augName = helper.string("purchaseAugmentation", "augName", _augName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("purchaseAugmentation", getRamCost(player, "purchaseAugmentation"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("purchaseAugmentation");
2022-03-30 01:49:37 +02:00
const fac = getFaction("purchaseAugmentation", facName);
const aug = getAugmentation("purchaseAugmentation", augName);
const augs = getFactionAugmentationsFiltered(player, fac);
2022-03-30 01:49:37 +02:00
if (!augs.includes(augName)) {
workerScript.log(
"purchaseAugmentation",
2022-03-30 01:49:37 +02:00
() => `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) {
2022-03-30 01:49:37 +02:00
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) {
2022-03-30 01:49:37 +02:00
workerScript.log("purchaseAugmentation", () => `You already have the '${augName}' augmentation.`);
return false;
}
}
}
if (fac.playerReputation < aug.baseRepRequirement) {
workerScript.log("purchaseAugmentation", () => `You do not have enough reputation with '${fac.name}'.`);
return false;
}
const res = purchaseAugmentation(aug, fac, true);
workerScript.log("purchaseAugmentation", () => res);
if (isString(res) && res.startsWith("You purchased")) {
2022-01-09 21:22:23 +01:00
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 10);
return true;
} else {
return false;
}
},
2022-03-30 01:49:37 +02:00
softReset: function (_cbScript: unknown): void {
const cbScript = helper.string("softReset", "cbScript", _cbScript);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("softReset", getRamCost(player, "softReset"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("softReset");
workerScript.log("softReset", () => "Soft resetting. This will cause this script to be killed");
setTimeout(() => {
prestigeAugmentation();
runAfterReset(cbScript);
}, 0);
// Prevent workerScript from "finishing execution naturally"
workerScript.running = false;
killWorkerScript(workerScript);
},
2022-03-30 01:49:37 +02:00
installAugmentations: function (_cbScript: unknown): boolean {
const cbScript = helper.string("installAugmentations", "cbScript", _cbScript);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("installAugmentations", getRamCost(player, "installAugmentations"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("installAugmentations");
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);
workerScript.log(
"installAugmentations",
() => "Installing Augmentations. This will cause this script to be killed",
);
setTimeout(() => {
installAugmentations();
runAfterReset(cbScript);
}, 0);
workerScript.running = false; // Prevent workerScript from "finishing execution naturally"
killWorkerScript(workerScript);
2022-03-30 01:49:37 +02:00
return true;
},
2022-03-30 01:49:37 +02:00
goToLocation: function (_locationName: unknown): boolean {
const locationName = helper.string("goToLocation", "locationName", _locationName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("goToLocation", getRamCost(player, "goToLocation"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("goToLocation");
const location = Object.values(Locations).find((l) => l.name === locationName);
if (!location) {
workerScript.log("goToLocation", () => `No location named ${locationName}`);
return false;
}
if (player.city !== location.city) {
workerScript.log("goToLocation", () => `No location named ${locationName} in ${player.city}`);
return false;
}
Router.toLocation(location);
2022-01-18 20:02:12 +01:00
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 50000);
return true;
},
2022-03-30 01:49:37 +02:00
universityCourse: function (_universityName: unknown, _className: unknown, _focus: unknown = true): boolean {
const universityName = helper.string("universityCourse", "universityName", _universityName);
const className = helper.string("universityCourse", "className", _className);
const focus = helper.boolean(_focus);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("universityCourse", getRamCost(player, "universityCourse"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("universityCourse");
2022-01-12 19:03:49 +01:00
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}'.`);
return false;
}
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}.`);
return false;
}
2022-01-18 15:49:06 +01:00
player.startClass(costMult, expMult, task);
2022-01-12 19:03:49 +01:00
if (focus) {
player.startFocusing();
Router.toWork();
} else if (wasFocusing) {
player.stopFocusing();
Router.toTerminal();
}
workerScript.log("universityCourse", () => `Started ${task} at ${universityName}`);
return true;
},
2022-03-30 01:49:37 +02:00
gymWorkout: function (_gymName: unknown, _stat: unknown, _focus: unknown = true): boolean {
const gymName = helper.string("gymWorkout", "gymName", _gymName);
const stat = helper.string("gymWorkout", "stat", _stat);
const focus = helper.boolean(_focus);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("gymWorkout", getRamCost(player, "gymWorkout"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("gymWorkout");
2022-01-12 19:03:49 +01:00
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",
2022-03-21 03:49:46 +01:00
() =>
`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",
2022-03-21 03:49:46 +01:00
() =>
`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",
2022-03-21 03:49:46 +01:00
() =>
`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",
2022-03-21 03:49:46 +01:00
() =>
`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",
2022-03-21 03:49:46 +01:00
() =>
`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`);
return false;
}
switch (stat.toLowerCase()) {
case "strength".toLowerCase():
case "str".toLowerCase():
2022-01-18 15:49:06 +01:00
player.startClass(costMult, expMult, CONSTANTS.ClassGymStrength);
break;
case "defense".toLowerCase():
case "def".toLowerCase():
2022-01-18 15:49:06 +01:00
player.startClass(costMult, expMult, CONSTANTS.ClassGymDefense);
break;
case "dexterity".toLowerCase():
case "dex".toLowerCase():
2022-01-18 15:49:06 +01:00
player.startClass(costMult, expMult, CONSTANTS.ClassGymDexterity);
break;
case "agility".toLowerCase():
case "agi".toLowerCase():
2022-01-18 15:49:06 +01:00
player.startClass(costMult, expMult, CONSTANTS.ClassGymAgility);
break;
default:
workerScript.log("gymWorkout", () => `Invalid stat: ${stat}.`);
return false;
}
2022-01-12 19:03:49 +01:00
if (focus) {
player.startFocusing();
Router.toWork();
} else if (wasFocusing) {
player.stopFocusing();
Router.toTerminal();
}
workerScript.log("gymWorkout", () => `Started training ${stat} at ${gymName}`);
return true;
},
2022-03-30 01:49:37 +02:00
travelToCity: function (_cityName: unknown): boolean {
const cityName = helper.city("travelToCity", "cityName", _cityName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("travelToCity", getRamCost(player, "travelToCity"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("travelToCity");
2022-03-30 01:49:37 +02:00
switch (cityName) {
case CityName.Aevum:
case CityName.Chongqing:
case CityName.Sector12:
case CityName.NewTokyo:
case CityName.Ishima:
case CityName.Volhaven:
2021-11-12 03:35:26 +01:00
if (player.money < CONSTANTS.TravelCost) {
workerScript.log("travelToCity", () => "Not enough money to travel.");
2022-03-21 03:49:46 +01:00
return false;
}
player.loseMoney(CONSTANTS.TravelCost, "other");
2022-03-30 01:49:37 +02:00
player.city = cityName;
workerScript.log("travelToCity", () => `Traveled to ${cityName}`);
2022-01-18 20:02:12 +01:00
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 50000);
return true;
default:
2022-03-30 01:49:37 +02:00
throw helper.makeRuntimeErrorMsg("travelToCity", `Invalid city name: '${cityName}'.`);
}
},
2022-03-30 01:49:37 +02:00
purchaseTor: function (): boolean {
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("purchaseTor", getRamCost(player, "purchaseTor"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("purchaseTor");
if (player.hasTorRouter()) {
workerScript.log("purchaseTor", () => "You already have a TOR router!");
return true;
}
2021-11-12 03:35:26 +01: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);
2022-01-18 20:02:12 +01:00
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 500);
workerScript.log("purchaseTor", () => "You have purchased a Tor router!");
return true;
},
2022-03-30 01:49:37 +02:00
purchaseProgram: function (_programName: unknown): boolean {
const programName = helper.string("purchaseProgram", "programName", _programName).toLowerCase();
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("purchaseProgram", getRamCost(player, "purchaseProgram"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("purchaseProgram");
if (!player.hasTorRouter()) {
workerScript.log("purchaseProgram", () => "You do not have the TOR router.");
return false;
}
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-12 03:35:26 +01:00
if (player.money < item.price) {
workerScript.log(
"purchaseProgram",
() => `Not enough money to purchase '${item.program}'. Need ${numeralWrapper.formatMoney(item.price)}`,
);
return false;
}
if (player.hasProgram(item.program)) {
workerScript.log("purchaseProgram", () => `You already have the '${item.program}' program`);
return true;
}
player.loseMoney(item.price, "other");
player.getHomeComputer().programs.push(item.program);
workerScript.log(
"purchaseProgram",
() => `You have purchased the '${item.program}' program. The new program can be found on your home computer.`,
);
2022-01-18 20:02:12 +01:00
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain / 5000);
return true;
},
2022-03-30 01:49:37 +02:00
getCurrentServer: function (): string {
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getCurrentServer", getRamCost(player, "getCurrentServer"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getCurrentServer");
return player.getCurrentServer().hostname;
},
2022-03-30 01:49:37 +02:00
connect: function (_hostname: unknown): boolean {
const hostname = helper.string("purchaseProgram", "hostname", _hostname);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("connect", getRamCost(player, "connect"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("connect");
if (!hostname) {
throw helper.makeRuntimeErrorMsg("connect", `Invalid hostname: '${hostname}'`);
}
const target = GetServer(hostname);
if (target == null) {
throw helper.makeRuntimeErrorMsg("connect", `Invalid hostname: '${hostname}'`);
}
if (hostname === "home") {
player.getCurrentServer().isConnectedTo = false;
player.currentServer = player.getHomeComputer().hostname;
player.getCurrentServer().isConnectedTo = true;
Terminal.setcwd("/");
return true;
}
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;
}
}
return false;
},
2022-03-30 01:49:37 +02:00
manualHack: function (): Promise<number> {
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("manualHack", getRamCost(player, "manualHack"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("manualHack");
const server = player.getCurrentServer();
return helper.hack(server.hostname, true);
},
2022-03-30 01:49:37 +02:00
installBackdoor: function (): Promise<void> {
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("installBackdoor", getRamCost(player, "installBackdoor"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("installBackdoor");
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;
// No root access or skill level too low
const canHack = netscriptCanHack(server, player);
if (!canHack.res) {
throw helper.makeRuntimeErrorMsg("installBackdoor", canHack.msg || "");
}
workerScript.log(
"installBackdoor",
() => `Installing backdoor on '${server.hostname}' in ${convertTimeMsToTimeElapsedString(installTime, true)}`,
);
return netscriptDelay(installTime, workerScript).then(function () {
workerScript.log("installBackdoor", () => `Successfully installed backdoor on '${server.hostname}'`);
server.backdoorInstalled = true;
if (SpecialServers.WorldDaemon === server.hostname) {
Router.toBitVerse(false, false);
}
return Promise.resolve();
});
},
2021-12-16 18:02:46 +01:00
isFocused: function (): boolean {
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("isFocused", getRamCost(player, "isFocused"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("isFocused");
return player.focus;
},
2022-03-30 01:49:37 +02:00
setFocus: function (_focus: unknown): boolean {
const focus = helper.boolean(_focus);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("setFocus", getRamCost(player, "setFocus"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("setFocus");
if (!player.isWorking) {
throw helper.makeRuntimeErrorMsg("setFocus", "Not currently working");
}
2021-12-16 18:02:46 +01:00
if (
!(
player.workType == CONSTANTS.WorkTypeFaction ||
player.workType == CONSTANTS.WorkTypeCompany ||
2022-01-18 15:20:58 +01:00
player.workType == CONSTANTS.WorkTypeCompanyPartTime ||
player.workType == CONSTANTS.WorkTypeCreateProgram ||
player.workType == CONSTANTS.WorkTypeStudyClass
2021-12-16 18:02:46 +01:00
)
) {
throw helper.makeRuntimeErrorMsg("setFocus", "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;
}
return false;
},
2022-03-30 01:49:37 +02:00
getStats: function (): PlayerSkills {
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getStats", getRamCost(player, "getStats"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getStats");
workerScript.log("getStats", () => `getStats is deprecated, please use getplayer`);
return {
2021-11-05 22:12:52 +01:00
hacking: player.hacking,
strength: player.strength,
defense: player.defense,
dexterity: player.dexterity,
agility: player.agility,
charisma: player.charisma,
intelligence: player.intelligence,
};
},
2022-03-30 01:49:37 +02:00
getCharacterInformation: function (): CharacterInfo {
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getCharacterInformation", getRamCost(player, "getCharacterInformation"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getCharacterInformation");
workerScript.log("getCharacterInformation", () => `getCharacterInformation is deprecated, please use getplayer`);
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,
2022-03-30 02:05:40 +02:00
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,
};
},
2022-03-30 01:49:37 +02:00
hospitalize: function (): void {
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("hospitalize", getRamCost(player, "hospitalize"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("hospitalize");
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;
}
2022-03-30 01:49:37 +02:00
player.hospitalize();
},
2022-03-30 01:49:37 +02:00
isBusy: function (): boolean {
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("isBusy", getRamCost(player, "isBusy"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("isBusy");
return player.isWorking || Router.page() === Page.Infiltration || Router.page() === Page.BitVerse;
},
2022-03-30 01:49:37 +02:00
stopAction: function (): boolean {
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("stopAction", getRamCost(player, "stopAction"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("stopAction");
if (player.isWorking) {
2021-12-16 02:44:08 +01:00
if (player.focus) {
player.stopFocusing();
2021-12-16 02:44:08 +01:00
Router.toTerminal();
}
const txt = player.singularityStopWork();
workerScript.log("stopAction", () => txt);
return true;
}
return false;
},
2022-03-30 01:49:37 +02:00
upgradeHomeCores: function (): boolean {
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("upgradeHomeCores", getRamCost(player, "upgradeHomeCores"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("upgradeHomeCores");
// 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;
}
const cost = player.getUpgradeHomeCoresCost();
2021-11-12 03:35:26 +01:00
if (player.money < cost) {
workerScript.log(
"upgradeHomeCores",
() => `You don't have enough money. Need ${numeralWrapper.formatMoney(cost)}`,
);
return false;
}
homeComputer.cpuCores += 1;
player.loseMoney(cost, "servers");
2022-01-09 21:22:23 +01:00
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 2);
workerScript.log(
"upgradeHomeCores",
() => `Purchased an additional core for home computer! It now has ${homeComputer.cpuCores} cores.`,
);
return true;
},
2022-03-30 01:49:37 +02:00
getUpgradeHomeCoresCost: function (): number {
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getUpgradeHomeCoresCost", getRamCost(player, "getUpgradeHomeCoresCost"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getUpgradeHomeCoresCost");
return player.getUpgradeHomeCoresCost();
},
2022-03-30 01:49:37 +02:00
upgradeHomeRam: function (): boolean {
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("upgradeHomeRam", getRamCost(player, "upgradeHomeRam"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("upgradeHomeRam");
// 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();
2021-11-12 03:35:26 +01:00
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");
2022-01-09 21:22:23 +01:00
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 2);
workerScript.log(
"upgradeHomeRam",
() =>
`Purchased additional RAM for home computer! It now has ${numeralWrapper.formatRAM(
homeComputer.maxRam,
)} of RAM.`,
);
return true;
},
2022-03-30 01:49:37 +02:00
getUpgradeHomeRamCost: function (): number {
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getUpgradeHomeRamCost", getRamCost(player, "getUpgradeHomeRamCost"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getUpgradeHomeRamCost");
return player.getUpgradeHomeRamCost();
},
2022-03-30 01:49:37 +02:00
workForCompany: function (_companyName: unknown, _focus: unknown = true): boolean {
let companyName = helper.string("workForCompany", "companyName", _companyName);
const focus = helper.boolean(_focus);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("workForCompany", getRamCost(player, "workForCompany"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("workForCompany");
// Sanitize input
if (companyName == null) {
companyName = player.companyName;
}
// Make sure its a valid company
if (companyName == null || companyName === "" || !(Companies[companyName] instanceof Company)) {
workerScript.log("workForCompany", () => `Invalid company: '${companyName}'`);
return false;
}
// 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;
}
// 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;
}
const wasFocused = player.focus;
if (player.isWorking) {
const txt = player.singularityStopWork();
workerScript.log("workForCompany", () => txt);
}
if (companyPosition.isPartTimeJob()) {
player.startWorkPartTime(companyName);
} else {
player.startWork(companyName);
}
2021-12-16 18:02:46 +01:00
if (focus) {
player.startFocusing();
Router.toWork();
2022-01-05 01:09:34 +01:00
} else if (wasFocused) {
player.stopFocusing();
Router.toTerminal();
}
workerScript.log(
"workForCompany",
() => `Began working at '${player.companyName}' as a '${companyPositionName}'`,
);
return true;
},
2022-03-30 01:49:37 +02:00
applyToCompany: function (_companyName: unknown, _field: unknown): boolean {
const companyName = helper.string("applyToCompany", "companyName", _companyName);
const field = helper.string("applyToCompany", "field", _field);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("applyToCompany", getRamCost(player, "applyToCompany"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("applyToCompany");
getCompany("applyToCompany", companyName);
2022-03-30 01:49:37 +02:00
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}'.`);
return false;
}
// 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;
},
2022-03-30 01:49:37 +02:00
getCompanyRep: function (_companyName: unknown): number {
const companyName = helper.string("getCompanyRep", "companyName", _companyName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getCompanyRep", getRamCost(player, "getCompanyRep"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getCompanyRep");
const company = getCompany("getCompanyRep", companyName);
return company.playerReputation;
},
2022-03-30 01:49:37 +02:00
getCompanyFavor: function (_companyName: unknown): number {
const companyName = helper.string("getCompanyFavor", "companyName", _companyName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getCompanyFavor", getRamCost(player, "getCompanyFavor"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getCompanyFavor");
const company = getCompany("getCompanyFavor", companyName);
return company.favor;
},
2022-03-30 01:49:37 +02:00
getCompanyFavorGain: function (_companyName: unknown): number {
const companyName = helper.string("getCompanyFavorGain", "companyName", _companyName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getCompanyFavorGain", getRamCost(player, "getCompanyFavorGain"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getCompanyFavorGain");
const company = getCompany("getCompanyFavorGain", companyName);
2021-11-05 21:09:19 +01:00
return company.getFavorGain();
},
2022-03-30 01:49:37 +02:00
checkFactionInvitations: function (): string[] {
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("checkFactionInvitations", getRamCost(player, "checkFactionInvitations"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("checkFactionInvitations");
// Make a copy of player.factionInvitations
return player.factionInvitations.slice();
},
2022-03-30 01:49:37 +02:00
joinFaction: function (_facName: unknown): boolean {
const facName = helper.string("joinFaction", "facName", _facName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("joinFaction", getRamCost(player, "joinFaction"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("joinFaction");
2022-03-30 01:49:37 +02:00
getFaction("joinFaction", facName);
2022-03-30 01:49:37 +02:00
if (!player.factionInvitations.includes(facName)) {
workerScript.log("joinFaction", () => `You have not been invited by faction '${facName}'`);
return false;
}
2022-03-30 01:49:37 +02:00
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) {
2022-03-30 01:49:37 +02:00
if (player.factionInvitations[i] == facName || Factions[player.factionInvitations[i]].isBanned) {
player.factionInvitations.splice(i, 1);
i--;
}
}
2022-01-09 21:22:23 +01:00
player.gainIntelligenceExp(CONSTANTS.IntelligenceSingFnBaseExpGain * 5);
2022-03-30 01:49:37 +02:00
workerScript.log("joinFaction", () => `Joined the '${facName}' faction.`);
return true;
},
2022-03-30 01:49:37 +02:00
workForFaction: function (_facName: unknown, _type: unknown, _focus: unknown = true): boolean {
const facName = helper.string("workForFaction", "facName", _facName);
const type = helper.string("workForFaction", "type", _type);
const focus = helper.boolean(_focus);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("workForFaction", getRamCost(player, "workForFaction"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("workForFaction");
2022-03-30 01:49:37 +02:00
getFaction("workForFaction", facName);
// if the player is in a gang and the target faction is any of the gang faction, fail
2022-03-30 01:49:37 +02:00
if (player.inGang() && AllGangs[facName] !== undefined) {
workerScript.log("workForFaction", () => `Faction '${facName}' does not offer work at the moment.`);
2021-12-03 20:12:32 +01:00
return false;
}
2022-03-30 01:49:37 +02:00
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);
}
2022-03-30 01:49:37 +02:00
const fac = Factions[facName];
// Arrays listing factions that allow each time of work
switch (type.toLowerCase()) {
case "hacking":
case "hacking contracts":
case "hackingcontracts":
2022-03-21 04:27:53 +01:00
if (!FactionInfos[fac.name].offerHackingWork) {
workerScript.log("workForFaction", () => `Faction '${fac.name}' do not need help with hacking contracts.`);
return false;
}
player.startFactionHackWork(fac);
2022-01-05 01:09:34 +01:00
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":
2022-03-21 04:27:53 +01:00
if (!FactionInfos[fac.name].offerFieldWork) {
workerScript.log("workForFaction", () => `Faction '${fac.name}' do not need help with field missions.`);
return false;
}
player.startFactionFieldWork(fac);
2022-01-05 01:09:34 +01:00
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":
2022-03-21 04:27:53 +01:00
if (!FactionInfos[fac.name].offerSecurityWork) {
workerScript.log("workForFaction", () => `Faction '${fac.name}' do not need help with security work.`);
return false;
}
player.startFactionSecurityWork(fac);
2022-01-05 01:09:34 +01:00
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}`);
}
return true;
},
2022-03-30 01:49:37 +02:00
getFactionRep: function (_facName: unknown): number {
const facName = helper.string("getFactionRep", "facName", _facName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getFactionRep", getRamCost(player, "getFactionRep"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getFactionRep");
2022-03-30 01:49:37 +02:00
const faction = getFaction("getFactionRep", facName);
return faction.playerReputation;
},
2022-03-30 01:49:37 +02:00
getFactionFavor: function (_facName: unknown): number {
const facName = helper.string("getFactionRep", "facName", _facName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getFactionFavor", getRamCost(player, "getFactionFavor"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getFactionFavor");
2022-03-30 01:49:37 +02:00
const faction = getFaction("getFactionFavor", facName);
return faction.favor;
},
2022-03-30 01:49:37 +02:00
getFactionFavorGain: function (_facName: unknown): number {
const facName = helper.string("getFactionFavorGain", "facName", _facName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getFactionFavorGain", getRamCost(player, "getFactionFavorGain"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getFactionFavorGain");
2022-03-30 01:49:37 +02:00
const faction = getFaction("getFactionFavorGain", facName);
2021-11-05 21:09:19 +01:00
return faction.getFavorGain();
},
2022-03-30 01:49:37 +02:00
donateToFaction: function (_facName: unknown, _amt: unknown): boolean {
const facName = helper.string("donateToFaction", "facName", _facName);
const amt = helper.number("donateToFaction", "amt", _amt);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("donateToFaction", getRamCost(player, "donateToFaction"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("donateToFaction");
2022-03-30 01:49:37 +02:00
const faction = getFaction("donateToFaction", facName);
if (!player.factions.includes(faction.name)) {
2022-03-30 01:49:37 +02:00
workerScript.log("donateToFaction", () => `You can't donate to '${facName}' because you aren't a member`);
return false;
}
if (player.inGang() && faction.name === player.getGangFaction().name) {
2022-03-30 01:49:37 +02:00
workerScript.log(
"donateToFaction",
() => `You can't donate to '${facName}' because youre managing a gang for it`,
);
return false;
}
2022-01-05 02:00:10 +01:00
if (typeof amt !== "number" || amt <= 0 || isNaN(amt)) {
workerScript.log("donateToFaction", () => `Invalid donation amount: '${amt}'.`);
return false;
}
2021-11-12 03:35:26 +01:00
if (player.money < amt) {
workerScript.log(
"donateToFaction",
2022-03-30 01:49:37 +02:00
() => `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");
workerScript.log(
"donateToFaction",
() =>
2022-03-30 01:49:37 +02:00
`${numeralWrapper.formatMoney(amt)} donated to '${facName}' for ${numeralWrapper.formatReputation(
repGain,
)} reputation`,
);
return true;
},
2022-03-30 02:05:40 +02:00
createProgram: function (_programName: unknown, _focus: unknown = true): boolean {
2022-03-30 01:49:37 +02:00
const programName = helper.string("createProgram", "programName", _programName).toLowerCase();
const focus = helper.boolean(_focus);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("createProgram", getRamCost(player, "createProgram"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("createProgram");
2022-01-12 19:03:49 +01:00
const wasFocusing = player.focus;
if (player.isWorking) {
const txt = player.singularityStopWork();
workerScript.log("createProgram", () => txt);
}
2022-03-30 01:49:37 +02:00
const p = Object.values(Programs).find((p) => p.name.toLowerCase() === programName);
if (p == null) {
2022-03-30 01:49:37 +02:00
workerScript.log("createProgram", () => `The specified program does not exist: '${programName}`);
return false;
}
if (player.hasProgram(p.name)) {
workerScript.log("createProgram", () => `You already have the '${p.name}' program`);
return false;
}
const create = p.create;
if (create === null) {
workerScript.log("createProgram", () => `You cannot create the '${p.name}' program`);
return false;
}
if (!create.req(player)) {
workerScript.log(
"createProgram",
() => `Hacking level is too low to create '${p.name}' (level ${create.level} req)`,
);
return false;
}
2022-01-18 15:49:06 +01:00
player.startCreateProgramWork(p.name, create.time, create.level);
2022-01-12 19:03:49 +01:00
if (focus) {
player.startFocusing();
Router.toWork();
} else if (wasFocusing) {
player.stopFocusing();
Router.toTerminal();
}
2022-03-30 01:49:37 +02:00
workerScript.log("createProgram", () => `Began creating program: '${programName}'`);
return true;
},
2022-03-30 01:49:37 +02:00
commitCrime: function (_crimeRoughName: unknown): number {
const crimeRoughName = helper.string("commitCrime", "crimeRoughName", _crimeRoughName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("commitCrime", getRamCost(player, "commitCrime"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("commitCrime");
if (player.isWorking) {
const txt = player.singularityStopWork();
workerScript.log("commitCrime", () => txt);
}
// Set Location to slums
player.gotoLocation(LocationName.Slums);
const crime = findCrime(crimeRoughName.toLowerCase());
if (crime == null) {
// couldn't find crime
throw helper.makeRuntimeErrorMsg("commitCrime", `Invalid crime: '${crimeRoughName}'`);
}
workerScript.log("commitCrime", () => `Attempting to commit ${crime.name}...`);
return crime.commit(Router, player, 1, workerScript);
},
2022-03-30 01:49:37 +02:00
getCrimeChance: function (_crimeRoughName: unknown): number {
const crimeRoughName = helper.string("getCrimeChance", "crimeRoughName", _crimeRoughName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getCrimeChance", getRamCost(player, "getCrimeChance"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getCrimeChance");
const crime = findCrime(crimeRoughName.toLowerCase());
if (crime == null) {
throw helper.makeRuntimeErrorMsg("getCrimeChance", `Invalid crime: ${crimeRoughName}`);
}
return crime.successRate(player);
},
2022-03-30 01:49:37 +02:00
getCrimeStats: function (_crimeRoughName: unknown): CrimeStats {
const crimeRoughName = helper.string("getCrimeStats", "crimeRoughName", _crimeRoughName);
2022-01-05 01:09:34 +01:00
helper.updateDynamicRam("getCrimeStats", getRamCost(player, "getCrimeStats"));
2022-01-05 04:21:44 +01:00
helper.checkSingularityAccess("getCrimeStats");
const crime = findCrime(crimeRoughName.toLowerCase());
if (crime == null) {
throw helper.makeRuntimeErrorMsg("getCrimeStats", `Invalid crime: ${crimeRoughName}`);
}
return Object.assign({}, crime);
},
2022-03-21 03:49:46 +01:00
getDarkwebPrograms: function (): string[] {
helper.updateDynamicRam("getDarkwebPrograms", getRamCost(player, "getDarkwebPrograms"));
helper.checkSingularityAccess("getDarkwebPrograms");
// 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);
},
2022-03-30 01:49:37 +02:00
getDarkwebProgramCost: function (_programName: unknown): number {
const programName = helper.string("getDarkwebProgramCost", "programName", _programName).toLowerCase();
2022-03-21 03:49:46 +01:00
helper.updateDynamicRam("getDarkwebProgramCost", getRamCost(player, "getDarkwebProgramCost"));
helper.checkSingularityAccess("getDarkwebProgramCost");
// 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;
}
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 helper.makeRuntimeErrorMsg(
"getDarkwebProgramCost",
`No such exploit ('${programName}') found on the darkweb! ` +
`\nThis function is not case-sensitive. Did you perhaps forget .exe at the end?`,
);
}
if (player.hasProgram(item.program)) {
workerScript.log("getDarkwebProgramCost", () => `You already have the '${item.program}' program`);
return 0;
}
return item.price;
},
};
}