WIP: Crimes streamlining. (#138)

* streamline crimes

* Crimes object is now indexed by CrimeType enum instead of an entirely new set of keys that aren't used for anything else. This eliminated a lot of instances of iterating to find the right crime for a given CrimeType.
* Removed unused `None` CrimeType which allowed typing Crimes as a Record<CrimeType, Crime>.
* Added slums tooltip text as a crime property, to allow streamlining slums.
* Refactor slums location - removed repetitive code, rerenders 1/sec to update chances
* Fix bugged descriptive text when sleeve is committing a crime (was "is attempting to DRUGS", now uses correct text e.g. "to deal drugs").
* Remove unused and now unneeded NewCrimeType enum. Values were identical to existing CrimeType values after removing unused None.

* Add CrimeType enum in NetscriptDefinition.d.ts

* Also update broken ToastVariant type. Better support for enums in player scripts.
* Still todo is modifying some NS functions to expect CrimeType as input (rough crime names will continue to work to avoid breaking scripts)

* Expect enum use for crime functions

Affected functions:
* ns.singularity.commitCrime
* ns.singularity.getCrimeChance
* ns.singularity.getCrimeStats
* ns.sleeve.setToCommitCrime
* formulas.work.crimeGains (param type only)

- Affected functions still will fall back to rough names, except formulas.work.crimeGains which already only accepted the enum members.
- Some documentation changes:
  * examples updated to use uppercase expected form.
  * Note on sleeve.setToCommitCrime that it only accepts exact matches removed. It already, and still does, accept any rough crime name (but the enum is expected input).
  * note about needing to use isBusy to schedule crimes remove - crimes autoloop now.
  * Since expected string inputs are documented directly on the type, removed list of crimes from sleeve.setToCommitCrimes
This commit is contained in:
Snarling
2022-10-21 11:57:37 -04:00
committed by GitHub
parent 06a985bdf8
commit d74c380e42
15 changed files with 412 additions and 512 deletions
+4 -3
View File
@@ -48,6 +48,8 @@ import { calculateFactionExp, calculateFactionRep } from "../Work/formulas/Facti
import { FactionWorkType } from "../Work/data/FactionWorkType";
import { defaultMultipliers } from "../PersonObjects/Multipliers";
import { checkEnum } from "../utils/helpers/checkEnum";
import { CrimeType } from "../utils/WorkType";
export function NetscriptFormulas(): InternalAPI<IFormulas> {
const checkFormulasAccess = function (ctx: NetscriptContext): void {
@@ -362,9 +364,8 @@ export function NetscriptFormulas(): InternalAPI<IFormulas> {
work: {
crimeGains: (ctx) => (_crimeType) => {
const crimeType = helpers.string(ctx, "crimeType", _crimeType);
const crime = Object.values(Crimes).find((c) => String(c.type) === crimeType);
if (!crime) throw new Error(`Invalid crime type: ${crimeType}`);
return calculateCrimeWorkStats(crime);
if (!checkEnum(CrimeType, crimeType)) throw new Error(`Invalid crime type: ${crimeType}`);
return calculateCrimeWorkStats(Crimes[crimeType]);
},
classGains: (ctx) => (_person, _classType, _locationName) => {
const person = helpers.player(ctx, _person);
+36 -42
View File
@@ -50,6 +50,9 @@ import { CompanyWork } from "../Work/CompanyWork";
import { canGetBonus, onExport } from "../ExportBonus";
import { saveObject } from "../SaveObject";
import { calculateCrimeWorkStats } from "../Work/formulas/Crime";
import { checkEnum } from "../utils/helpers/checkEnum";
import { Crimes } from "../Crime/Crimes";
import { CrimeType } from "../utils/WorkType";
export function NetscriptSingularity(): InternalAPI<ISingularity> {
const getAugmentation = function (ctx: NetscriptContext, name: string): Augmentation {
@@ -1115,56 +1118,47 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
helpers.log(ctx, () => `Began creating program: '${programName}'`);
return true;
},
commitCrime:
(ctx) =>
(_crimeRoughName, _focus = true) => {
helpers.checkSingularityAccess(ctx);
const crimeRoughName = helpers.string(ctx, "crimeRoughName", _crimeRoughName);
const focus = !!_focus;
const wasFocusing = Player.focus;
if (Player.currentWork !== null) {
Player.finishWork(true);
}
// Set Location to slums
Player.gotoLocation(LocationName.Slums);
const crime = findCrime(crimeRoughName.toLowerCase());
if (crime == null) {
// couldn't find crime
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid crime: '${crimeRoughName}'`);
}
helpers.log(ctx, () => `Attempting to commit ${crime.name}...`);
const crimeTime = crime.commit(1, ctx.workerScript);
if (focus) {
Player.startFocusing();
Router.toWork();
} else if (wasFocusing) {
Player.stopFocusing();
Router.toTerminal();
}
return crimeTime;
},
getCrimeChance: (ctx) => (_crimeRoughName) => {
commitCrime: (ctx) => (_crimeType, _focus) => {
helpers.checkSingularityAccess(ctx);
const crimeRoughName = helpers.string(ctx, "crimeRoughName", _crimeRoughName);
const crimeType = helpers.string(ctx, "crimeType", _crimeType);
const focus = _focus === undefined ? true : !!_focus;
const wasFocusing = Player.focus;
const crime = findCrime(crimeRoughName.toLowerCase());
if (crime == null) {
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid crime: ${crimeRoughName}`);
if (Player.currentWork !== null) Player.finishWork(true);
Player.gotoLocation(LocationName.Slums);
// If input isn't a crimeType, use search using roughname.
const crime = checkEnum(CrimeType, crimeType) ? Crimes[crimeType] : findCrime(crimeType);
if (crime == null) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid crime: '${crimeType}'`);
helpers.log(ctx, () => `Attempting to commit ${crime.name}...`);
const crimeTime = crime.commit(1, ctx.workerScript);
if (focus) {
Player.startFocusing();
Router.toWork();
} else if (wasFocusing) {
Player.stopFocusing();
Router.toTerminal();
}
return crimeTime;
},
getCrimeChance: (ctx) => (_crimeType) => {
helpers.checkSingularityAccess(ctx);
const crimeType = helpers.string(ctx, "crimeType", _crimeType);
// If input isn't a crimeType, use search using roughname.
const crime = checkEnum(CrimeType, crimeType) ? Crimes[crimeType] : findCrime(crimeType);
if (crime == null) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid crime: '${crimeType}'`);
return crime.successRate(Player);
},
getCrimeStats: (ctx) => (_crimeRoughName) => {
getCrimeStats: (ctx) => (_crimeType) => {
helpers.checkSingularityAccess(ctx);
const crimeRoughName = helpers.string(ctx, "crimeRoughName", _crimeRoughName);
const crimeType = helpers.string(ctx, "crimeType", _crimeType);
const crime = findCrime(crimeRoughName.toLowerCase());
if (crime == null) {
throw helpers.makeRuntimeErrorMsg(ctx, `Invalid crime: ${crimeRoughName}`);
}
// If input isn't a crimeType, use search using roughname.
const crime = checkEnum(CrimeType, crimeType) ? Crimes[crimeType] : findCrime(crimeType);
if (crime == null) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid crime: '${crimeType}'`);
const crimeStatsWithMultipliers = calculateCrimeWorkStats(crime);
+6 -6
View File
@@ -11,6 +11,8 @@ import { isSleeveBladeburnerWork } from "../PersonObjects/Sleeve/Work/SleeveBlad
import { isSleeveFactionWork } from "../PersonObjects/Sleeve/Work/SleeveFactionWork";
import { isSleeveCompanyWork } from "../PersonObjects/Sleeve/Work/SleeveCompanyWork";
import { helpers } from "../Netscript/NetscriptHelpers";
import { Crimes } from "../Crime/Crimes";
import { CrimeType } from "../utils/WorkType";
export function NetscriptSleeve(): InternalAPI<ISleeve> {
const checkSleeveAPIAccess = function (ctx: NetscriptContext) {
@@ -62,15 +64,13 @@ export function NetscriptSleeve(): InternalAPI<ISleeve> {
checkSleeveNumber(ctx, sleeveNumber);
return Player.sleeves[sleeveNumber].synchronize();
},
setToCommitCrime: (ctx) => (_sleeveNumber, _crimeRoughName) => {
setToCommitCrime: (ctx) => (_sleeveNumber, _crimeType) => {
const sleeveNumber = helpers.number(ctx, "sleeveNumber", _sleeveNumber);
const crimeRoughName = helpers.string(ctx, "crimeName", _crimeRoughName);
const crimeType = helpers.string(ctx, "crimeType", _crimeType);
checkSleeveAPIAccess(ctx);
checkSleeveNumber(ctx, sleeveNumber);
const crime = findCrime(crimeRoughName);
if (crime === null) {
return false;
}
const crime = checkEnum(CrimeType, crimeType) ? Crimes[crimeType] : findCrime(crimeType);
if (crime == null) return false;
return Player.sleeves[sleeveNumber].commitCrime(crime.name);
},
setToUniversityCourse: (ctx) => (_sleeveNumber, _universityName, _className) => {