diff --git a/src/Corporation/Actions.ts b/src/Corporation/Actions.ts index ec1ab1538..a29bebd40 100644 --- a/src/Corporation/Actions.ts +++ b/src/Corporation/Actions.ts @@ -14,7 +14,7 @@ import { Cities } from "../Locations/Cities"; import { EmployeePositions } from "./EmployeePositions"; import { ResearchMap } from "./ResearchMap"; import { isRelevantMaterial } from "./ui/Helpers"; -import { checkEnum } from "../utils/helpers/checkEnum"; +import { checkEnum } from "../utils/helpers/enum"; import { CityName } from "../Locations/data/CityNames"; export function NewIndustry(corporation: Corporation, industry: IndustryType, name: string): void { diff --git a/src/Crime/Crime.ts b/src/Crime/Crime.ts index c1387252b..0e5841cb9 100644 --- a/src/Crime/Crime.ts +++ b/src/Crime/Crime.ts @@ -2,7 +2,7 @@ import { CONSTANTS } from "../Constants"; import { Player } from "@player"; import { Person as IPerson } from "../ScriptEditor/NetscriptDefinitions"; import { WorkerScript } from "../Netscript/WorkerScript"; -import { CrimeType } from "../utils/WorkType"; +import { CrimeType } from "../utils/enums"; import { CrimeWork } from "../Work/CrimeWork"; import { calculateIntelligenceBonus } from "../PersonObjects/formulas/intelligence"; @@ -25,6 +25,9 @@ interface IConstructorParams { } export class Crime { + // Corresponding type, also the name of the crime. + type: CrimeType; + // Number representing the difficulty of the crime. Used for success chance calculations difficulty: number; @@ -37,9 +40,6 @@ export class Crime { // How much money is given by the money: number; - // Name of crime - name: string; - // Name of crime as it appears on work screen: "You are attempting..." workName: string; @@ -49,9 +49,6 @@ export class Crime { // Milliseconds it takes to attempt the crime time = 0; - // Corresponding type in CONSTANTS. Contains a description for the crime activity - type: CrimeType; - // Weighting factors that determine how stats affect the success rate of this crime hacking_success_weight = 0; strength_success_weight = 0; @@ -70,7 +67,6 @@ export class Crime { intelligence_exp = 0; constructor( - name: string, workName: string, tooltipText: string, type: CrimeType, @@ -80,7 +76,6 @@ export class Crime { karma: number, params: IConstructorParams, ) { - this.name = name; this.workName = workName; this.tooltipText = tooltipText; this.type = type; diff --git a/src/Crime/CrimeHelpers.ts b/src/Crime/CrimeHelpers.ts index aeb3f1380..b89f6a23f 100644 --- a/src/Crime/CrimeHelpers.ts +++ b/src/Crime/CrimeHelpers.ts @@ -3,8 +3,8 @@ import { Crime } from "./Crime"; import { Player } from "@player"; import { dialogBoxCreate } from "../ui/React/DialogBox"; -import { checkEnum } from "../utils/helpers/checkEnum"; -import { CrimeType } from "../utils/WorkType"; +import { checkEnum } from "../utils/helpers/enum"; +import { CrimeType } from "../utils/enums"; //This is only used for the player export function determineCrimeSuccess(type: string): boolean { @@ -20,31 +20,18 @@ export function determineCrimeSuccess(type: string): boolean { export function findCrime(roughName: string): Crime | null { if (checkEnum(CrimeType, roughName)) return Crimes[roughName]; roughName = roughName.toLowerCase(); - if (roughName.includes("shoplift")) { - return Crimes[CrimeType.SHOPLIFT]; - } else if (roughName.includes("rob") && roughName.includes("store")) { - return Crimes[CrimeType.ROB_STORE]; - } else if (roughName.includes("mug")) { - return Crimes[CrimeType.MUG]; - } else if (roughName.includes("larceny")) { - return Crimes[CrimeType.LARCENY]; - } else if (roughName.includes("drugs")) { - return Crimes[CrimeType.DRUGS]; - } else if (roughName.includes("bond") && roughName.includes("forge")) { - return Crimes[CrimeType.BOND_FORGERY]; - } else if ((roughName.includes("traffic") || roughName.includes("illegal")) && roughName.includes("arms")) { - return Crimes[CrimeType.TRAFFIC_ARMS]; - } else if (roughName.includes("homicide")) { - return Crimes[CrimeType.HOMICIDE]; - } else if (roughName.includes("grand") && roughName.includes("auto")) { - return Crimes[CrimeType.GRAND_THEFT_AUTO]; - } else if (roughName.includes("kidnap")) { - return Crimes[CrimeType.KIDNAP]; - } else if (roughName.includes("assassin")) { - return Crimes[CrimeType.ASSASSINATION]; - } else if (roughName.includes("heist")) { - return Crimes[CrimeType.HEIST]; - } - + if (roughName.includes("shoplift")) return Crimes[CrimeType.shoplift]; + else if (roughName.includes("rob") && roughName.includes("store")) return Crimes[CrimeType.robStore]; + else if (roughName.includes("mug")) return Crimes[CrimeType.mug]; + else if (roughName.includes("larceny")) return Crimes[CrimeType.larceny]; + else if (roughName.includes("drugs")) return Crimes[CrimeType.dealDrugs]; + else if (roughName.includes("bond") && roughName.includes("forge")) return Crimes[CrimeType.bondForgery]; + else if ((roughName.includes("traffic") || roughName.includes("illegal")) && roughName.includes("arms")) { + return Crimes[CrimeType.traffickArms]; + } else if (roughName.includes("homicide")) return Crimes[CrimeType.homicide]; + else if (roughName.includes("grand") && roughName.includes("auto")) return Crimes[CrimeType.grandTheftAuto]; + else if (roughName.includes("kidnap")) return Crimes[CrimeType.kidnap]; + else if (roughName.includes("assassin")) return Crimes[CrimeType.assassination]; + else if (roughName.includes("heist")) return Crimes[CrimeType.heist]; return null; } diff --git a/src/Crime/Crimes.ts b/src/Crime/Crimes.ts index f41b161b8..bbfba4c9c 100644 --- a/src/Crime/Crimes.ts +++ b/src/Crime/Crimes.ts @@ -1,15 +1,12 @@ import { Crime } from "./Crime"; - import { CONSTANTS } from "../Constants"; +import { CrimeType } from "../utils/enums"; -import { CrimeType } from "../utils/WorkType"; -// TODO: What is the point of CrimeType using totally different strings than export const Crimes: Record = { - [CrimeType.SHOPLIFT]: new Crime( - "Shoplift", + [CrimeType.shoplift]: new Crime( "to shoplift", "Attempt to shoplift from a low-end retailer", - CrimeType.SHOPLIFT, + CrimeType.shoplift, 2e3, 15e3, 1 / 20, @@ -23,11 +20,10 @@ export const Crimes: Record = { }, ), - [CrimeType.ROB_STORE]: new Crime( - "Rob Store", + [CrimeType.robStore]: new Crime( "to rob a store", "Attempt to commit armed robbery on a high-end store", - CrimeType.ROB_STORE, + CrimeType.robStore, 60e3, 400e3, 1 / 5, @@ -45,11 +41,10 @@ export const Crimes: Record = { }, ), - [CrimeType.MUG]: new Crime( - "Mug", + [CrimeType.mug]: new Crime( "to mug", "Attempt to mug a random person on the street", - CrimeType.MUG, + CrimeType.mug, 4e3, 36e3, 1 / 5, @@ -67,11 +62,10 @@ export const Crimes: Record = { }, ), - [CrimeType.LARCENY]: new Crime( - "Larceny", + [CrimeType.larceny]: new Crime( "larceny", "Attempt to rob property from someone's house", - CrimeType.LARCENY, + CrimeType.larceny, 90e3, 800e3, 1 / 3, @@ -89,31 +83,20 @@ export const Crimes: Record = { }, ), - [CrimeType.DRUGS]: new Crime( - "Deal Drugs", - "to deal drugs", - "Attempt to deal drugs", - CrimeType.DRUGS, - 10e3, - 120e3, - 1, - 0.5, - { - dexterity_exp: 5, - agility_exp: 5, - charisma_exp: 10, + [CrimeType.dealDrugs]: new Crime("to deal drugs", "Attempt to deal drugs", CrimeType.dealDrugs, 10e3, 120e3, 1, 0.5, { + dexterity_exp: 5, + agility_exp: 5, + charisma_exp: 10, - charisma_success_weight: 3, - dexterity_success_weight: 2, - agility_success_weight: 1, - }, - ), + charisma_success_weight: 3, + dexterity_success_weight: 2, + agility_success_weight: 1, + }), - [CrimeType.BOND_FORGERY]: new Crime( - "Bond Forgery", + [CrimeType.bondForgery]: new Crime( "to forge bonds", "Attempt to forge corporate bonds", - CrimeType.BOND_FORGERY, + CrimeType.bondForgery, 300e3, 4.5e6, 1 / 2, @@ -130,11 +113,10 @@ export const Crimes: Record = { }, ), - [CrimeType.TRAFFIC_ARMS]: new Crime( - "Traffick Arms", + [CrimeType.traffickArms]: new Crime( "to traffic arms", "Attempt to smuggle illegal arms into the city", - CrimeType.TRAFFIC_ARMS, + CrimeType.traffickArms, 40e3, 600e3, 2, @@ -154,11 +136,10 @@ export const Crimes: Record = { }, ), - [CrimeType.HOMICIDE]: new Crime( - "Homicide", + [CrimeType.homicide]: new Crime( "homicide", "Attempt to murder a random person on the street", - CrimeType.HOMICIDE, + CrimeType.homicide, 3e3, 45e3, 1, @@ -178,11 +159,10 @@ export const Crimes: Record = { }, ), - [CrimeType.GRAND_THEFT_AUTO]: new Crime( - "Grand Theft Auto", + [CrimeType.grandTheftAuto]: new Crime( "grand theft auto", "Attempt to commit grand theft auto", - CrimeType.GRAND_THEFT_AUTO, + CrimeType.grandTheftAuto, 80e3, 1.6e6, 8, @@ -204,11 +184,10 @@ export const Crimes: Record = { }, ), - [CrimeType.KIDNAP]: new Crime( - "Kidnap", + [CrimeType.kidnap]: new Crime( "to kidnap", "Attempt to kidnap and ransom a high-profile-target", - CrimeType.KIDNAP, + CrimeType.kidnap, 120e3, 3.6e6, 5, @@ -229,11 +208,10 @@ export const Crimes: Record = { }, ), - [CrimeType.ASSASSINATION]: new Crime( - "Assassination", + [CrimeType.assassination]: new Crime( "to assassinate", "Attempt to assassinate a high-profile target", - CrimeType.ASSASSINATION, + CrimeType.assassination, 300e3, 12e6, 8, @@ -254,11 +232,10 @@ export const Crimes: Record = { }, ), - [CrimeType.HEIST]: new Crime( - "Heist", + [CrimeType.heist]: new Crime( "a heist", "Attempt to pull off the ultimate heist", - CrimeType.HEIST, + CrimeType.heist, 600e3, 120e6, 18, diff --git a/src/Faction/ui/FactionRoot.tsx b/src/Faction/ui/FactionRoot.tsx index 3cbacc6d2..b2ea437ae 100644 --- a/src/Faction/ui/FactionRoot.tsx +++ b/src/Faction/ui/FactionRoot.tsx @@ -23,7 +23,7 @@ import { CovenantPurchasesRoot } from "../../PersonObjects/Sleeve/ui/CovenantPur import { FactionNames } from "../data/FactionNames"; import { GangButton } from "./GangButton"; import { FactionWork } from "../../Work/FactionWork"; -import { FactionWorkType } from "../../Work/data/FactionWorkType"; +import { FactionWorkType } from "../../utils/enums"; type IProps = { faction: Faction; @@ -72,7 +72,7 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea new FactionWork({ singularity: false, faction: faction.name, - factionWorkType: FactionWorkType.FIELD, + factionWorkType: FactionWorkType.field, }), ); startWork(); @@ -83,7 +83,7 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea new FactionWork({ singularity: false, faction: faction.name, - factionWorkType: FactionWorkType.HACKING, + factionWorkType: FactionWorkType.hacking, }), ); startWork(); @@ -94,7 +94,7 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea new FactionWork({ singularity: false, faction: faction.name, - factionWorkType: FactionWorkType.SECURITY, + factionWorkType: FactionWorkType.security, }), ); startWork(); diff --git a/src/Locations/ui/GymLocation.tsx b/src/Locations/ui/GymLocation.tsx index 9e931df7d..2e570d55e 100644 --- a/src/Locations/ui/GymLocation.tsx +++ b/src/Locations/ui/GymLocation.tsx @@ -13,15 +13,16 @@ import { Player } from "@player"; import { Money } from "../../ui/React/Money"; import { Router } from "../../ui/GameRoot"; import { Box } from "@mui/material"; -import { ClassWork, ClassType, Classes } from "../../Work/ClassWork"; +import { ClassWork, Classes } from "../../Work/ClassWork"; import { calculateCost } from "../../Work/Formulas"; +import { GymType } from "../../utils/enums"; type IProps = { loc: Location; }; export function GymLocation(props: IProps): React.ReactElement { - function train(stat: ClassType): void { + function train(stat: GymType): void { Player.startWork( new ClassWork({ classType: stat, @@ -33,20 +34,20 @@ export function GymLocation(props: IProps): React.ReactElement { Router.toWork(); } - const cost = calculateCost(Classes[ClassType.GymStrength], props.loc); + const cost = calculateCost(Classes[GymType.strength], props.loc); return ( - - - - diff --git a/src/Locations/ui/SlumsLocation.tsx b/src/Locations/ui/SlumsLocation.tsx index fad038f5a..5e5912ab6 100644 --- a/src/Locations/ui/SlumsLocation.tsx +++ b/src/Locations/ui/SlumsLocation.tsx @@ -36,7 +36,7 @@ export function SlumsLocation(): React.ReactElement { {crimes.map((crime) => ( ))} diff --git a/src/Locations/ui/UniversityLocation.tsx b/src/Locations/ui/UniversityLocation.tsx index 7b8528ca9..7e2bb27f0 100644 --- a/src/Locations/ui/UniversityLocation.tsx +++ b/src/Locations/ui/UniversityLocation.tsx @@ -14,15 +14,16 @@ import { Router } from "../../ui/GameRoot"; import { Player } from "@player"; import { Box } from "@mui/material"; -import { ClassWork, ClassType, Classes } from "../../Work/ClassWork"; +import { ClassWork, Classes } from "../../Work/ClassWork"; import { calculateCost } from "../../Work/Formulas"; +import { UniversityClassType } from "../../utils/enums"; type IProps = { loc: Location; }; export function UniversityLocation(props: IProps): React.ReactElement { - function take(classType: ClassType): void { + function take(classType: UniversityClassType): void { Player.startWork( new ClassWork({ classType: classType, @@ -34,11 +35,11 @@ export function UniversityLocation(props: IProps): React.ReactElement { Router.toWork(); } - const dataStructuresCost = calculateCost(Classes[ClassType.DataStructures], props.loc); - const networksCost = calculateCost(Classes[ClassType.Networks], props.loc); - const algorithmsCost = calculateCost(Classes[ClassType.Algorithms], props.loc); - const managementCost = calculateCost(Classes[ClassType.Management], props.loc); - const leadershipCost = calculateCost(Classes[ClassType.Leadership], props.loc); + const dataStructuresCost = calculateCost(Classes[UniversityClassType.dataStructures], props.loc); + const networksCost = calculateCost(Classes[UniversityClassType.networks], props.loc); + const algorithmsCost = calculateCost(Classes[UniversityClassType.algorithms], props.loc); + const managementCost = calculateCost(Classes[UniversityClassType.management], props.loc); + const leadershipCost = calculateCost(Classes[UniversityClassType.leadership], props.loc); const earnHackingExpTooltip = `Gain hacking experience!`; const earnCharismaExpTooltip = `Gain charisma experience!`; @@ -46,34 +47,34 @@ export function UniversityLocation(props: IProps): React.ReactElement { return ( - + - - - - - diff --git a/src/Netscript/NetscriptHelpers.ts b/src/Netscript/NetscriptHelpers.ts index dc918fe47..69f31fc20 100644 --- a/src/Netscript/NetscriptHelpers.ts +++ b/src/Netscript/NetscriptHelpers.ts @@ -33,7 +33,7 @@ import { arrayToString } from "../utils/helpers/arrayToString"; import { HacknetServer } from "../Hacknet/HacknetServer"; import { BaseServer } from "../Server/BaseServer"; import { dialogBoxCreate } from "../ui/React/DialogBox"; -import { checkEnum } from "../utils/helpers/checkEnum"; +import { checkEnum } from "../utils/helpers/enum"; export const helpers = { string, diff --git a/src/Netscript/RamCostGenerator.ts b/src/Netscript/RamCostGenerator.ts index 862cdcfc5..a50a0ef75 100644 --- a/src/Netscript/RamCostGenerator.ts +++ b/src/Netscript/RamCostGenerator.ts @@ -602,7 +602,8 @@ export const RamCosts: RamCostTree = { work: { crimeSuccessChance: 0, crimeGains: 0, - classGains: 0, + gymGains: 0, + universityGains: 0, factionGains: 0, companyGains: 0, }, diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index 7d45e2824..54644e430 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -66,7 +66,7 @@ import { NetscriptSingularity } from "./NetscriptFunctions/Singularity"; import { dialogBoxCreate } from "./ui/React/DialogBox"; import { SnackbarEvents, ToastVariant } from "./ui/React/Snackbar"; -import { checkEnum } from "./utils/helpers/checkEnum"; +import { checkEnum } from "./utils/helpers/enum"; import { Flags } from "./NetscriptFunctions/Flags"; import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence"; @@ -77,16 +77,16 @@ import { INetscriptExtra } from "./NetscriptFunctions/Extra"; import { ScriptDeath } from "./Netscript/ScriptDeath"; import { getBitNodeMultipliers } from "./BitNode/BitNode"; import { assert, arrayAssert, stringAssert, objectAssert } from "./utils/helpers/typeAssertion"; -import { CompanyPosNames, CrimeType } from "./utils/WorkType"; +import { CompanyPosNames, CrimeType, GymType, UniversityClassType } from "./utils/enums"; import { cloneDeep } from "lodash"; -import { FactionWorkType } from "./Work/data/FactionWorkType"; -import { ClassType } from "./Work/ClassWork"; +import { FactionWorkType } from "./utils/enums"; export const enums: NSEnums = { toast: ToastVariant, CrimeType, FactionWorkType, - ClassType, + GymType, + UniversityClassType, CompanyPosNames, }; diff --git a/src/NetscriptFunctions/Corporation.ts b/src/NetscriptFunctions/Corporation.ts index 9c33e54ca..d10aee45c 100644 --- a/src/NetscriptFunctions/Corporation.ts +++ b/src/NetscriptFunctions/Corporation.ts @@ -58,7 +58,7 @@ import { Factions } from "../Faction/Factions"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import { assertEnumMember, helpers } from "../Netscript/NetscriptHelpers"; -import { checkEnum } from "../utils/helpers/checkEnum"; +import { checkEnum } from "../utils/helpers/enum"; import { CityName } from "../Locations/data/CityNames"; export function NetscriptCorporation(): InternalAPI { diff --git a/src/NetscriptFunctions/Formulas.ts b/src/NetscriptFunctions/Formulas.ts index 796cd016e..2961a640d 100644 --- a/src/NetscriptFunctions/Formulas.ts +++ b/src/NetscriptFunctions/Formulas.ts @@ -40,19 +40,18 @@ import { repFromDonation } from "../Faction/formulas/donation"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import { helpers } from "../Netscript/NetscriptHelpers"; import { calculateCrimeWorkStats } from "../Work/Formulas"; -import { Crimes } from "../Crime/Crimes"; import { calculateCompanyWorkStats } from "../Work/Formulas"; import { Companies } from "../Company/Companies"; import { calculateClassEarnings } from "../Work/Formulas"; -import { ClassType } from "../Work/ClassWork"; import { LocationName } from "../Locations/data/LocationNames"; import { calculateFactionExp, calculateFactionRep } from "../Work/Formulas"; -import { FactionWorkType } from "../Work/data/FactionWorkType"; +import { FactionWorkType, GymType, UniversityClassType } from "../utils/enums"; import { defaultMultipliers } from "../PersonObjects/Multipliers"; -import { checkEnum } from "../utils/helpers/checkEnum"; -import { CompanyPosNames, CrimeType } from "../utils/WorkType"; +import { checkEnum, findEnumMember } from "../utils/helpers/enum"; +import { CompanyPosNames } from "../utils/enums"; import { CompanyPositions } from "../Company/CompanyPositions"; +import { findCrime } from "../Crime/CrimeHelpers"; export function NetscriptFormulas(): InternalAPI { const checkFormulasAccess = function (ctx: NetscriptContext): void { @@ -356,22 +355,31 @@ export function NetscriptFormulas(): InternalAPI { crimeSuccessChance: (ctx) => (_person, _crimeType) => { checkFormulasAccess(ctx); const person = helpers.person(ctx, _person); - const crimeType = helpers.string(ctx, "crimeType", _crimeType); - if (!checkEnum(CrimeType, crimeType)) throw new Error(`Invalid crime type: ${crimeType}`); - return Crimes[crimeType].successRate(person); + const crime = findCrime(helpers.string(ctx, "crimeType", _crimeType)); + if (!crime) throw new Error(`Invalid crime type: ${_crimeType}`); + return crime.successRate(person); }, crimeGains: (ctx) => (_person, _crimeType) => { checkFormulasAccess(ctx); const person = helpers.person(ctx, _person); - const crimeType = helpers.string(ctx, "crimeType", _crimeType); - if (!checkEnum(CrimeType, crimeType)) throw new Error(`Invalid crime type: ${crimeType}`); - return calculateCrimeWorkStats(person, Crimes[crimeType]); + const crime = findCrime(helpers.string(ctx, "crimeType", _crimeType)); + if (!crime) throw new Error(`Invalid crime type: ${_crimeType}`); + return calculateCrimeWorkStats(person, crime); }, - classGains: (ctx) => (_person, _classType, _locationName) => { + gymGains: (ctx) => (_person, _classType, _locationName) => { checkFormulasAccess(ctx); const person = helpers.person(ctx, _person); - const classType = helpers.string(ctx, "classType", _classType); - if (!checkEnum(ClassType, classType)) throw new Error(`Invalid class type: ${classType}`); + const classType = findEnumMember(GymType, helpers.string(ctx, "classType", _classType)); + if (!classType) throw new Error(`Invalid gym training type: ${_classType}`); + const locationName = helpers.string(ctx, "locationName", _locationName); + if (!checkEnum(LocationName, locationName)) throw new Error(`Invalid location name: ${locationName}`); + return calculateClassEarnings(person, classType, locationName); + }, + universityGains: (ctx) => (_person, _classType, _locationName) => { + checkFormulasAccess(ctx); + const person = helpers.person(ctx, _person); + const classType = findEnumMember(UniversityClassType, helpers.string(ctx, "classType", _classType)); + if (!classType) throw new Error(`Invalid university class type: ${_classType}`); const locationName = helpers.string(ctx, "locationName", _locationName); if (!checkEnum(LocationName, locationName)) throw new Error(`Invalid location name: ${locationName}`); return calculateClassEarnings(person, classType, locationName); @@ -379,8 +387,8 @@ export function NetscriptFormulas(): InternalAPI { factionGains: (ctx) => (_player, _workType, _favor) => { checkFormulasAccess(ctx); const player = helpers.person(ctx, _player); - const workType = helpers.string(ctx, "_workType", _workType); - if (!checkEnum(FactionWorkType, workType)) throw new Error(`Invalid faction work type: ${workType}`); + const workType = findEnumMember(FactionWorkType, helpers.string(ctx, "_workType", _workType)); + if (!workType) throw new Error(`Invalid faction work type: ${_workType}`); const favor = helpers.number(ctx, "favor", _favor); const exp = calculateFactionExp(player, workType); const rep = calculateFactionRep(player, workType, favor); @@ -390,8 +398,8 @@ export function NetscriptFormulas(): InternalAPI { companyGains: (ctx) => (_person, _companyName, _positionName, _favor) => { checkFormulasAccess(ctx); const person = helpers.person(ctx, _person); - const positionName = helpers.string(ctx, "_positionName", _positionName); - if (!checkEnum(CompanyPosNames, positionName)) throw new Error(`Invalid company position: ${positionName}`); + const positionName = findEnumMember(CompanyPosNames, helpers.string(ctx, "_positionName", _positionName)); + if (!positionName) throw new Error(`Invalid company position: ${_positionName}`); const position = CompanyPositions[positionName]; const companyName = helpers.string(ctx, "_companyName", _companyName); const company = Object.values(Companies).find((c) => c.name === companyName); diff --git a/src/NetscriptFunctions/Infiltration.ts b/src/NetscriptFunctions/Infiltration.ts index dcd3f0f73..70bf12fcd 100644 --- a/src/NetscriptFunctions/Infiltration.ts +++ b/src/NetscriptFunctions/Infiltration.ts @@ -10,7 +10,7 @@ import { import { FactionNames } from "../Faction/data/FactionNames"; import { Factions } from "../Faction/Factions"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; -import { checkEnum } from "../utils/helpers/checkEnum"; +import { checkEnum } from "../utils/helpers/enum"; import { LocationName } from "../Locations/data/LocationNames"; import { helpers } from "../Netscript/NetscriptHelpers"; diff --git a/src/NetscriptFunctions/Singularity.ts b/src/NetscriptFunctions/Singularity.ts index 1731db42f..211e17ea9 100644 --- a/src/NetscriptFunctions/Singularity.ts +++ b/src/NetscriptFunctions/Singularity.ts @@ -41,14 +41,15 @@ import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper"; import { BlackOperationNames } from "../Bladeburner/data/BlackOperationNames"; import { enterBitNode } from "../RedPill"; import { FactionNames } from "../Faction/data/FactionNames"; -import { ClassWork, ClassType } from "../Work/ClassWork"; +import { ClassWork } from "../Work/ClassWork"; import { CreateProgramWork, isCreateProgramWork } from "../Work/CreateProgramWork"; import { FactionWork } from "../Work/FactionWork"; -import { FactionWorkType } from "../Work/data/FactionWorkType"; +import { FactionWorkType, GymType, UniversityClassType } from "../utils/enums"; import { CompanyWork } from "../Work/CompanyWork"; import { canGetBonus, onExport } from "../ExportBonus"; import { saveObject } from "../SaveObject"; import { calculateCrimeWorkStats } from "../Work/Formulas"; +import { findEnumMember } from "../utils/helpers/enum"; export function NetscriptSingularity(): InternalAPI { const getAugmentation = function (ctx: NetscriptContext, name: string): Augmentation { @@ -253,7 +254,11 @@ export function NetscriptSingularity(): InternalAPI { (_universityName, _className, _focus = true) => { helpers.checkSingularityAccess(ctx); const universityName = helpers.string(ctx, "universityName", _universityName); - const className = helpers.string(ctx, "className", _className); + const classType = findEnumMember(UniversityClassType, helpers.string(ctx, "className", _className)); + if (!classType) { + helpers.log(ctx, () => `Invalid class name: ${_className}.`); + return false; + } const focus = !!_focus; const wasFocusing = Player.focus; @@ -293,33 +298,9 @@ export function NetscriptSingularity(): InternalAPI { return false; } - let task: ClassType; - switch (className.toLowerCase()) { - case "Study Computer Science".toLowerCase(): - task = ClassType.StudyComputerScience; - break; - case "Data Structures".toLowerCase(): - task = ClassType.DataStructures; - break; - case "Networks".toLowerCase(): - task = ClassType.Networks; - break; - case "Algorithms".toLowerCase(): - task = ClassType.Algorithms; - break; - case "Management".toLowerCase(): - task = ClassType.Management; - break; - case "Leadership".toLowerCase(): - task = ClassType.Leadership; - break; - default: - helpers.log(ctx, () => `Invalid class name: ${className}.`); - return false; - } Player.startWork( new ClassWork({ - classType: task, + classType, location: Player.location, singularity: true, }), @@ -331,7 +312,7 @@ export function NetscriptSingularity(): InternalAPI { Player.stopFocusing(); Router.toTerminal(); } - helpers.log(ctx, () => `Started ${task} at ${universityName}`); + helpers.log(ctx, () => `Started ${classType} at ${universityName}`); return true; }, @@ -340,7 +321,11 @@ export function NetscriptSingularity(): InternalAPI { (_gymName, _stat, _focus = true) => { helpers.checkSingularityAccess(ctx); const gymName = helpers.string(ctx, "gymName", _gymName); - const stat = helpers.string(ctx, "stat", _stat); + const classType = findEnumMember(GymType, helpers.string(ctx, "stat", _stat)); + if (!classType) { + helpers.log(ctx, () => `Invalid stat: ${_stat}.`); + return false; + } const focus = !!_focus; const wasFocusing = Player.focus; @@ -405,35 +390,7 @@ export function NetscriptSingularity(): InternalAPI { return false; } - switch (stat.toLowerCase()) { - case "strength".toLowerCase(): - case "str".toLowerCase(): - Player.startWork( - new ClassWork({ classType: ClassType.GymStrength, location: Player.location, singularity: true }), - ); - break; - case "defense".toLowerCase(): - case "def".toLowerCase(): - Player.startWork( - new ClassWork({ classType: ClassType.GymDefense, location: Player.location, singularity: true }), - ); - break; - case "dexterity".toLowerCase(): - case "dex".toLowerCase(): - Player.startWork( - new ClassWork({ classType: ClassType.GymDexterity, location: Player.location, singularity: true }), - ); - break; - case "agility".toLowerCase(): - case "agi".toLowerCase(): - Player.startWork( - new ClassWork({ classType: ClassType.GymAgility, location: Player.location, singularity: true }), - ); - break; - default: - helpers.log(ctx, () => `Invalid stat: ${stat}.`); - return false; - } + Player.startWork(new ClassWork({ classType, location: Player.location, singularity: true })); if (focus) { Player.startFocusing(); Router.toWork(); @@ -441,7 +398,7 @@ export function NetscriptSingularity(): InternalAPI { Player.stopFocusing(); Router.toTerminal(); } - helpers.log(ctx, () => `Started training ${stat} at ${gymName}`); + helpers.log(ctx, () => `Started training ${classType} at ${gymName}`); return true; }, @@ -926,7 +883,7 @@ export function NetscriptSingularity(): InternalAPI { Player.startWork( new FactionWork({ singularity: true, - factionWorkType: FactionWorkType.HACKING, + factionWorkType: FactionWorkType.hacking, faction: faction.name, }), ); @@ -949,7 +906,7 @@ export function NetscriptSingularity(): InternalAPI { Player.startWork( new FactionWork({ singularity: true, - factionWorkType: FactionWorkType.FIELD, + factionWorkType: FactionWorkType.field, faction: faction.name, }), ); @@ -972,7 +929,7 @@ export function NetscriptSingularity(): InternalAPI { Player.startWork( new FactionWork({ singularity: true, - factionWorkType: FactionWorkType.SECURITY, + factionWorkType: FactionWorkType.security, faction: faction.name, }), ); @@ -1118,7 +1075,7 @@ export function NetscriptSingularity(): InternalAPI { const crime = findCrime(crimeType); if (crime == null) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid crime: '${crimeType}'`); - helpers.log(ctx, () => `Attempting to commit ${crime.name}...`); + helpers.log(ctx, () => `Attempting to commit ${crime.type}...`); const crimeTime = crime.commit(1, ctx.workerScript); if (focus) { Player.startFocusing(); diff --git a/src/NetscriptFunctions/Sleeve.ts b/src/NetscriptFunctions/Sleeve.ts index bb8f9b97f..9908c8e0b 100644 --- a/src/NetscriptFunctions/Sleeve.ts +++ b/src/NetscriptFunctions/Sleeve.ts @@ -5,7 +5,7 @@ import { findCrime } from "../Crime/CrimeHelpers"; import { Augmentation } from "../Augmentation/Augmentation"; import { sleeve } from "../ScriptEditor/NetscriptDefinitions"; -import { checkEnum } from "../utils/helpers/checkEnum"; +import { checkEnum } from "../utils/helpers/enum"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import { isSleeveBladeburnerWork } from "../PersonObjects/Sleeve/Work/SleeveBladeburnerWork"; import { isSleeveFactionWork } from "../PersonObjects/Sleeve/Work/SleeveFactionWork"; diff --git a/src/PersonObjects/Sleeve/Sleeve.ts b/src/PersonObjects/Sleeve/Sleeve.ts index c20d74617..027c997b7 100644 --- a/src/PersonObjects/Sleeve/Sleeve.ts +++ b/src/PersonObjects/Sleeve/Sleeve.ts @@ -18,7 +18,7 @@ import { CompanyPosition } from "../../Company/CompanyPosition"; import { CompanyPositions } from "../../Company/CompanyPositions"; import { Contracts } from "../../Bladeburner/data/Contracts"; import { CONSTANTS } from "../../Constants"; -import { CrimeType } from "../../utils/WorkType"; +import { CrimeType, GymType, UniversityClassType } from "../../utils/enums"; import { CityName } from "../../Locations/data/CityNames"; import { Factions } from "../../Faction/Factions"; @@ -27,7 +27,7 @@ import { LocationName } from "../../Locations/data/LocationNames"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../utils/JSONReviver"; import { numeralWrapper } from "../../ui/numeralFormat"; -import { FactionWorkType } from "../../Work/data/FactionWorkType"; +import { FactionWorkType } from "../../utils/enums"; import { Work } from "./Work/Work"; import { SleeveClassWork } from "./Work/SleeveClassWork"; import { ClassType } from "../../Work/ClassWork"; @@ -221,22 +221,22 @@ export class Sleeve extends Person implements ISleeve { let classType: ClassType | undefined; switch (className.toLowerCase()) { case "study computer science": - classType = ClassType.StudyComputerScience; + classType = UniversityClassType.computerScience; break; case "data structures": - classType = ClassType.DataStructures; + classType = UniversityClassType.dataStructures; break; case "networks": - classType = ClassType.Networks; + classType = UniversityClassType.networks; break; case "algorithms": - classType = ClassType.Algorithms; + classType = UniversityClassType.algorithms; break; case "management": - classType = ClassType.Management; + classType = UniversityClassType.management; break; case "leadership": - classType = ClassType.Leadership; + classType = UniversityClassType.leadership; break; } if (!classType) return false; @@ -311,13 +311,13 @@ export class Sleeve extends Person implements ISleeve { let factionWorkType: FactionWorkType; if (sanitizedWorkType.includes("hack")) { if (!factionInfo.offerHackingWork) return false; - factionWorkType = FactionWorkType.HACKING; + factionWorkType = FactionWorkType.hacking; } else if (sanitizedWorkType.includes("field")) { if (!factionInfo.offerFieldWork) return false; - factionWorkType = FactionWorkType.FIELD; + factionWorkType = FactionWorkType.field; } else if (sanitizedWorkType.includes("security")) { if (!factionInfo.offerSecurityWork) return false; - factionWorkType = FactionWorkType.SECURITY; + factionWorkType = FactionWorkType.security; } else { return false; } @@ -372,16 +372,16 @@ export class Sleeve extends Person implements ISleeve { // set stat to a default value. let classType: ClassType | undefined; if (sanitizedStat.includes("str")) { - classType = ClassType.GymStrength; + classType = GymType.strength; } if (sanitizedStat.includes("def")) { - classType = ClassType.GymDefense; + classType = GymType.defense; } if (sanitizedStat.includes("dex")) { - classType = ClassType.GymDexterity; + classType = GymType.dexterity; } if (sanitizedStat.includes("agi")) { - classType = ClassType.GymAgility; + classType = GymType.agility; } // if stat is still equals its default value, then validation has failed. if (!classType) return false; diff --git a/src/PersonObjects/Sleeve/Work/SleeveClassWork.ts b/src/PersonObjects/Sleeve/Work/SleeveClassWork.ts index 74ff09862..245bd935f 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveClassWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveClassWork.ts @@ -5,6 +5,8 @@ import { LocationName } from "../../../Locations/data/LocationNames"; import { calculateClassEarnings } from "../../../Work/Formulas"; import { Sleeve } from "../Sleeve"; import { scaleWorkStats, WorkStats } from "../../../Work/WorkStats"; +import { GymType, UniversityClassType } from "../../../utils/enums"; +import { checkEnum } from "../../../utils/helpers/enum"; export const isSleeveClassWork = (w: Work | null): w is SleeveClassWork => w !== null && w.type === WorkType.CLASS; @@ -19,7 +21,7 @@ export class SleeveClassWork extends Work { constructor(params?: ClassWorkParams) { super(WorkType.CLASS); - this.classType = params?.classType ?? ClassType.StudyComputerScience; + this.classType = params?.classType ?? UniversityClassType.computerScience; this.location = params?.location ?? LocationName.Sector12RothmanUniversity; } @@ -28,9 +30,7 @@ export class SleeveClassWork extends Work { } isGym(): boolean { - return [ClassType.GymAgility, ClassType.GymDefense, ClassType.GymDexterity, ClassType.GymStrength].includes( - this.classType, - ); + return checkEnum(GymType, this.classType); } process(sleeve: Sleeve, cycles: number) { diff --git a/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts b/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts index 0cd91016d..ba83536b9 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveCrimeWork.ts @@ -2,13 +2,14 @@ import { Player } from "@player"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver"; import { Sleeve } from "../Sleeve"; import { applySleeveGains, Work, WorkType } from "./Work"; -import { CrimeType } from "../../../utils/WorkType"; +import { CrimeType } from "../../../utils/enums"; import { Crimes } from "../../../Crime/Crimes"; import { Crime } from "../../../Crime/Crime"; import { scaleWorkStats, WorkStats } from "../../../Work/WorkStats"; import { CONSTANTS } from "../../../Constants"; -import { checkEnum } from "../../../utils/helpers/checkEnum"; +import { checkEnum } from "../../../utils/helpers/enum"; import { calculateCrimeWorkStats } from "../../../Work/Formulas"; +import { findCrime } from "../../../Crime/CrimeHelpers"; export const isSleeveCrimeWork = (w: Work | null): w is SleeveCrimeWork => w !== null && w.type === WorkType.CRIME; @@ -17,7 +18,7 @@ export class SleeveCrimeWork extends Work { cyclesWorked = 0; constructor(crimeType?: CrimeType) { super(WorkType.CRIME); - this.crimeType = crimeType ?? CrimeType.SHOPLIFT; + this.crimeType = crimeType ?? CrimeType.shoplift; } getCrime(): Crime { @@ -60,7 +61,9 @@ export class SleeveCrimeWork extends Work { /** Initializes a RecoveryWork object from a JSON save state. */ static fromJSON(value: IReviverValue): SleeveCrimeWork { - return Generic_fromJSON(SleeveCrimeWork, value.data); + const crimeWork = Generic_fromJSON(SleeveCrimeWork, value.data); + crimeWork.crimeType = findCrime(crimeWork.crimeType)?.type ?? CrimeType.shoplift; + return crimeWork; } } diff --git a/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts b/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts index b3bc29f9e..5e052dbb4 100644 --- a/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts +++ b/src/PersonObjects/Sleeve/Work/SleeveFactionWork.ts @@ -2,7 +2,7 @@ import { Player } from "@player"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver"; import { Sleeve } from "../Sleeve"; import { applySleeveGains, Work, WorkType } from "./Work"; -import { FactionWorkType } from "../../../Work/data/FactionWorkType"; +import { FactionWorkType } from "../../../utils/enums"; import { FactionNames } from "../../../Faction/data/FactionNames"; import { Factions } from "../../../Faction/Factions"; import { calculateFactionExp, calculateFactionRep } from "../../../Work/Formulas"; @@ -23,7 +23,7 @@ export class SleeveFactionWork extends Work { constructor(params?: SleeveFactionWorkParams) { super(WorkType.FACTION); - this.factionWorkType = params?.factionWorkType ?? FactionWorkType.HACKING; + this.factionWorkType = params?.factionWorkType ?? FactionWorkType.hacking; this.factionName = params?.factionName ?? FactionNames.Sector12; } diff --git a/src/PersonObjects/Sleeve/ui/SleeveElem.tsx b/src/PersonObjects/Sleeve/ui/SleeveElem.tsx index 230b7d3a9..02e8b6f2e 100644 --- a/src/PersonObjects/Sleeve/ui/SleeveElem.tsx +++ b/src/PersonObjects/Sleeve/ui/SleeveElem.tsx @@ -1,6 +1,6 @@ import { Box, Button, Paper, Tooltip, Typography } from "@mui/material"; import React, { useState } from "react"; -import { FactionWorkType } from "../../../Work/data/FactionWorkType"; +import { FactionWorkType } from "../../../utils/enums"; import { CONSTANTS } from "../../../Constants"; import { Player } from "@player"; import { numeralWrapper } from "../../../ui/numeralFormat"; @@ -21,7 +21,7 @@ import { isSleeveSupportWork } from "../Work/SleeveSupportWork"; import { isSleeveBladeburnerWork } from "../Work/SleeveBladeburnerWork"; import { isSleeveCrimeWork } from "../Work/SleeveCrimeWork"; import { findCrime } from "../../../Crime/CrimeHelpers"; -import { CrimeType } from "../../../utils/WorkType"; +import { CrimeType } from "../../../utils/enums"; interface IProps { sleeve: Sleeve; @@ -46,7 +46,7 @@ export function SleeveElem(props: IProps): React.ReactElement { props.sleeve.workForFaction(abc[1], abc[2]); break; case "Commit Crime": - props.sleeve.commitCrime(findCrime(abc[1])?.type ?? CrimeType.SHOPLIFT); + props.sleeve.commitCrime(findCrime(abc[1])?.type ?? CrimeType.shoplift); break; case "Take University Course": props.sleeve.takeUniversityCourse(abc[2], abc[1]); @@ -106,13 +106,13 @@ export function SleeveElem(props: IProps): React.ReactElement { if (isSleeveFactionWork(props.sleeve.currentWork)) { let doing = "nothing"; switch (props.sleeve.currentWork.factionWorkType) { - case FactionWorkType.FIELD: + case FactionWorkType.field: doing = "Field work"; break; - case FactionWorkType.HACKING: + case FactionWorkType.hacking: doing = "Hacking contracts"; break; - case FactionWorkType.SECURITY: + case FactionWorkType.security: doing = "Security work"; break; } diff --git a/src/PersonObjects/Sleeve/ui/TaskSelector.tsx b/src/PersonObjects/Sleeve/ui/TaskSelector.tsx index 9575c989a..4608b5999 100644 --- a/src/PersonObjects/Sleeve/ui/TaskSelector.tsx +++ b/src/PersonObjects/Sleeve/ui/TaskSelector.tsx @@ -16,11 +16,9 @@ import { isSleeveSynchroWork } from "../Work/SleeveSynchroWork"; import { isSleeveClassWork } from "../Work/SleeveClassWork"; import { isSleeveInfiltrateWork } from "../Work/SleeveInfiltrateWork"; import { isSleeveSupportWork } from "../Work/SleeveSupportWork"; -import { ClassType } from "../../../Work/ClassWork"; import { isSleeveCrimeWork } from "../Work/SleeveCrimeWork"; -import { FactionWorkType } from "../../../Work/data/FactionWorkType"; -import { checkEnum } from "../../../utils/helpers/checkEnum"; -import { CrimeType } from "../../../utils/WorkType"; +import { CrimeType, FactionWorkType, GymType, UniversityClassType } from "../../../utils/enums"; +import { checkEnum } from "../../../utils/helpers/enum"; const universitySelectorOptions: string[] = [ "Study Computer Science", @@ -167,7 +165,7 @@ const tasks: { }; }, "Commit Crime": (): ITaskDetails => { - return { first: Object.values(Crimes).map((crime) => crime.name), second: () => ["------"] }; + return { first: Object.keys(Crimes), second: () => ["------"] }; }, "Take University Course": (sleeve: Sleeve): ITaskDetails => { let universities: string[] = []; @@ -263,13 +261,13 @@ function getABC(sleeve: Sleeve): [string, string, string] { if (isSleeveFactionWork(w)) { let workType = ""; switch (w.factionWorkType) { - case FactionWorkType.HACKING: + case FactionWorkType.hacking: workType = "Hacking Contracts"; break; - case FactionWorkType.FIELD: + case FactionWorkType.field: workType = "Field Work"; break; - case FactionWorkType.SECURITY: + case FactionWorkType.security: workType = "Security Work"; break; } @@ -293,30 +291,30 @@ function getABC(sleeve: Sleeve): [string, string, string] { if (isSleeveClassWork(w)) { switch (w.classType) { - case ClassType.StudyComputerScience: + case UniversityClassType.computerScience: return ["Take University Course", "Study Computer Science", w.location]; - case ClassType.DataStructures: + case UniversityClassType.dataStructures: return ["Take University Course", "Data Structures", w.location]; - case ClassType.Networks: + case UniversityClassType.networks: return ["Take University Course", "Networks", w.location]; - case ClassType.Algorithms: + case UniversityClassType.algorithms: return ["Take University Course", "Algorithms", w.location]; - case ClassType.Management: + case UniversityClassType.management: return ["Take University Course", "Management", w.location]; - case ClassType.Leadership: + case UniversityClassType.leadership: return ["Take University Course", "Leadership", w.location]; - case ClassType.GymStrength: + case GymType.strength: return ["Workout at Gym", "Train Strength", w.location]; - case ClassType.GymDefense: + case GymType.defense: return ["Workout at Gym", "Train Defense", w.location]; - case ClassType.GymDexterity: + case GymType.dexterity: return ["Workout at Gym", "Train Dexterity", w.location]; - case ClassType.GymAgility: + case GymType.agility: return ["Workout at Gym", "Train Agility", w.location]; } } if (isSleeveCrimeWork(w)) { - return ["Commit Crime", checkEnum(CrimeType, w.crimeType) ? Crimes[w.crimeType].name : "Shoplift", "------"]; + return ["Commit Crime", checkEnum(CrimeType, w.crimeType) ? w.crimeType : "Shoplift", "------"]; } if (isSleeveSupportWork(w)) { return ["Perform Bladeburner Actions", "Support main sleeve", "------"]; diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index 30ced172e..ee051beaa 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -211,8 +211,6 @@ export interface CrimeStats { kills: number; /** How much money is given */ money: number; - /** Name of crime */ - name: string; /** Milliseconds it takes to attempt the crime */ time: number; /** Description of the crime activity */ @@ -3817,8 +3815,14 @@ interface WorkFormulas { crimeSuccessChance(person: Person, crimeType: CrimeType | `${CrimeType}`): number; /** @returns The WorkStats gained when completing one instance of the specified crime. */ crimeGains(person: Person, crimeType: CrimeType | `${CrimeType}`): WorkStats; - /** @returns The WorkStats applied every game cycle (200ms) by taking the specified class. */ - classGains(person: Person, classType: ClassType | `${ClassType}`, locationName: string): WorkStats; + /** @returns The WorkStats applied every game cycle (200ms) by taking the specified gym class. */ + gymGains(person: Person, gymType: GymType | `${GymType}`, locationName: string): WorkStats; + /** @returns The WorkStats applied every game cycle (200ms) by taking the specified university class. */ + universityGains( + person: Person, + classType: UniversityClassType | `${UniversityClassType}`, + locationName: string, + ): WorkStats; /** @returns The WorkStats applied every game cycle (200ms) by performing the specified faction work. */ factionGains(person: Person, workType: FactionWorkType | `${FactionWorkType}`, favor: number): WorkStats; /** @returns The WorkStats applied every game cycle (200ms) by performing the specified company work. */ @@ -6815,42 +6819,46 @@ declare enum ToastVariant { /** @public */ declare enum CrimeType { - SHOPLIFT = "SHOPLIFT", - ROB_STORE = "ROBSTORE", - MUG = "MUG", - LARCENY = "LARCENY", - DRUGS = "DRUGS", - BOND_FORGERY = "BONDFORGERY", - TRAFFIC_ARMS = "TRAFFICKARMS", - HOMICIDE = "HOMICIDE", - GRAND_THEFT_AUTO = "GRANDTHEFTAUTO", - KIDNAP = "KIDNAP", - ASSASSINATION = "ASSASSINATION", - HEIST = "HEIST", + shoplift = "Shoplift", + robStore = "Rob Store", + mug = "Mug", + larceny = "Larceny", + dealDrugs = "Deal Drugs", + bondForgery = "Bond Forgery", + traffickArms = "Traffick Arms", + homicide = "Homicide", + grandTheftAuto = "Grand Theft Auto", + kidnap = "Kidnap", + assassination = "Assassination", + heist = "Heist", } /** @public */ declare enum FactionWorkType { - HACKING = "HACKING", - FIELD = "FIELD", - SECURITY = "SECURITY", + hacking = "hacking", + field = "field", + security = "security", } -// TODO: split ClassType enum into separate enums for gym and uni so they can actually be used for player input. /** @public */ -declare enum ClassType { - StudyComputerScience = "STUDYCOMPUTERSCIENCE", - DataStructures = "DATASTRUCTURES", - Networks = "NETWORKS", - Algorithms = "ALGORITHMS", - Management = "MANAGEMENT", - Leadership = "LEADERSHIP", - GymStrength = "GYMSTRENGTH", - GymDefense = "GYMDEFENSE", - GymDexterity = "GYMDEXTERITY", - GymAgility = "GYMAGILITY", +declare enum UniversityClassType { + computerScience = "Computer Science", + dataStructures = "Data Structures", + networks = "Networks", + algorithms = "Algorithms", + management = "Management", + leadership = "Leadership", } +/** @public */ +declare enum GymType { + strength = "str", + defense = "def", + dexterity = "dex", + agility = "agi", +} + +/** @public */ declare enum CompanyPosNames { sw0 = "Software Engineering Intern", sw1 = "Junior Software Engineer", @@ -6927,7 +6935,8 @@ export type NSEnums = { toast: typeof ToastVariant; CrimeType: typeof CrimeType; FactionWorkType: typeof FactionWorkType; - ClassType: typeof ClassType; + GymType: typeof GymType; + UniversityClassType: typeof UniversityClassType; CompanyPosNames: typeof CompanyPosNames; }; diff --git a/src/Terminal/commands/cat.ts b/src/Terminal/commands/cat.ts index a108662f0..962a134bf 100644 --- a/src/Terminal/commands/cat.ts +++ b/src/Terminal/commands/cat.ts @@ -3,7 +3,7 @@ import { BaseServer } from "../../Server/BaseServer"; import { MessageFilenames, showMessage } from "../../Message/MessageHelpers"; import { showLiterature } from "../../Literature/LiteratureHelpers"; import { dialogBoxCreate } from "../../ui/React/DialogBox"; -import { checkEnum } from "../../utils/helpers/checkEnum"; +import { checkEnum } from "../../utils/helpers/enum"; export function cat(args: (string | number | boolean)[], server: BaseServer): void { if (args.length !== 1) { diff --git a/src/Work/ClassWork.tsx b/src/Work/ClassWork.tsx index c3daa6ed3..8ae518d3f 100644 --- a/src/Work/ClassWork.tsx +++ b/src/Work/ClassWork.tsx @@ -10,110 +10,67 @@ import { Player } from "@player"; import { calculateClassEarnings as calculateClassEarningsRate } from "./Formulas"; import { Work, WorkType } from "./Work"; import { applyWorkStats, newWorkStats, sumWorkStats, WorkStats } from "./WorkStats"; +import { GymType, UniversityClassType } from "../utils/enums"; +import { checkEnum, findEnumMember } from "../utils/helpers/enum"; -export enum ClassType { - StudyComputerScience = "STUDYCOMPUTERSCIENCE", - DataStructures = "DATASTRUCTURES", - Networks = "NETWORKS", - Algorithms = "ALGORITHMS", - - Management = "MANAGEMENT", - Leadership = "LEADERSHIP", - - GymStrength = "GYMSTRENGTH", - GymDefense = "GYMDEFENSE", - GymDexterity = "GYMDEXTERITY", - GymAgility = "GYMAGILITY", -} +export type ClassType = UniversityClassType | GymType; export interface Class { - youAreCurrently: string; type: ClassType; + youAreCurrently: string; earnings: WorkStats; } export const Classes: Record = { - [ClassType.StudyComputerScience]: { - youAreCurrently: "studying Computer Science", - type: ClassType.StudyComputerScience, + [UniversityClassType.computerScience]: { + type: UniversityClassType.computerScience, + youAreCurrently: `studying Computer Science`, earnings: newWorkStats({ hackExp: 0.5, intExp: 0.01 }), }, - [ClassType.DataStructures]: { + [UniversityClassType.dataStructures]: { + type: UniversityClassType.dataStructures, youAreCurrently: "taking a Data Structures course", - type: ClassType.DataStructures, - earnings: newWorkStats({ - money: -40, - hackExp: 1, - intExp: 0.01, - }), + earnings: newWorkStats({ money: -40, hackExp: 1, intExp: 0.01 }), }, - [ClassType.Networks]: { + [UniversityClassType.networks]: { + type: UniversityClassType.networks, youAreCurrently: "taking a Networks course", - type: ClassType.Networks, - earnings: newWorkStats({ - money: -80, - hackExp: 2, - intExp: 0.01, - }), + earnings: newWorkStats({ money: -80, hackExp: 2, intExp: 0.01 }), }, - [ClassType.Algorithms]: { + [UniversityClassType.algorithms]: { + type: UniversityClassType.algorithms, youAreCurrently: "taking an Algorithms course", - type: ClassType.Algorithms, - earnings: newWorkStats({ - money: -320, - hackExp: 4, - intExp: 0.01, - }), + earnings: newWorkStats({ money: -320, hackExp: 4, intExp: 0.01 }), }, - [ClassType.Management]: { + [UniversityClassType.management]: { + type: UniversityClassType.management, youAreCurrently: "taking a Management course", - type: ClassType.Management, - earnings: newWorkStats({ - money: -160, - chaExp: 2, - intExp: 0.01, - }), + earnings: newWorkStats({ money: -160, chaExp: 2, intExp: 0.01 }), }, - [ClassType.Leadership]: { + [UniversityClassType.leadership]: { + type: UniversityClassType.leadership, youAreCurrently: "taking a Leadership course", - type: ClassType.Leadership, - earnings: newWorkStats({ - money: -320, - chaExp: 4, - intExp: 0.01, - }), + earnings: newWorkStats({ money: -320, chaExp: 4, intExp: 0.01 }), }, - [ClassType.GymStrength]: { + [GymType.strength]: { + type: GymType.strength, youAreCurrently: "training your strength at a gym", - type: ClassType.GymStrength, - earnings: newWorkStats({ - money: -120, - strExp: 1, - }), + earnings: newWorkStats({ money: -120, strExp: 1 }), }, - [ClassType.GymDefense]: { + [GymType.defense]: { + type: GymType.defense, youAreCurrently: "training your defense at a gym", - type: ClassType.GymDefense, - earnings: newWorkStats({ - money: -120, - defExp: 1, - }), + earnings: newWorkStats({ money: -120, defExp: 1 }), }, - [ClassType.GymDexterity]: { + [GymType.dexterity]: { + type: GymType.dexterity, youAreCurrently: "training your dexterity at a gym", - type: ClassType.GymDexterity, - earnings: newWorkStats({ - money: -120, - dexExp: 1, - }), + earnings: newWorkStats({ money: -120, dexExp: 1 }), }, - [ClassType.GymAgility]: { + [GymType.agility]: { + type: GymType.agility, youAreCurrently: "training your agility at a gym", - type: ClassType.GymAgility, - earnings: newWorkStats({ - money: -120, - agiExp: 1, - }), + earnings: newWorkStats({ money: -120, agiExp: 1 }), }, }; @@ -132,14 +89,12 @@ export class ClassWork extends Work { constructor(params?: ClassWorkParams) { super(WorkType.CLASS, params?.singularity ?? true); - this.classType = params?.classType ?? ClassType.StudyComputerScience; + this.classType = params?.classType ?? UniversityClassType.computerScience; this.location = params?.location ?? LocationName.Sector12RothmanUniversity; } isGym(): boolean { - return [ClassType.GymAgility, ClassType.GymDefense, ClassType.GymDexterity, ClassType.GymStrength].includes( - this.classType, - ); + return checkEnum(GymType, this.classType); } getClass(): Class { @@ -195,7 +150,12 @@ export class ClassWork extends Work { /** Initializes a ClassWork object from a JSON save state. */ static fromJSON(value: IReviverValue): ClassWork { - return Generic_fromJSON(ClassWork, value.data); + const classWork = Generic_fromJSON(ClassWork, value.data); + classWork.classType = + findEnumMember(UniversityClassType, classWork.classType) ?? + findEnumMember(GymType, classWork.classType) ?? + UniversityClassType.computerScience; + return classWork; } } diff --git a/src/Work/CrimeWork.ts b/src/Work/CrimeWork.ts index 52d387886..3bc26bcfa 100644 --- a/src/Work/CrimeWork.ts +++ b/src/Work/CrimeWork.ts @@ -5,11 +5,11 @@ import { determineCrimeSuccess } from "../Crime/CrimeHelpers"; import { Crimes } from "../Crime/Crimes"; import { Player } from "@player"; import { dialogBoxCreate } from "../ui/React/DialogBox"; -import { CrimeType } from "../utils/WorkType"; +import { CrimeType } from "../utils/enums"; import { Work, WorkType } from "./Work"; import { scaleWorkStats, WorkStats } from "./WorkStats"; import { calculateCrimeWorkStats } from "./Formulas"; -import { checkEnum } from "../utils/helpers/checkEnum"; +import { checkEnum } from "../utils/helpers/enum"; interface CrimeWorkParams { crimeType: CrimeType; @@ -24,7 +24,7 @@ export class CrimeWork extends Work { constructor(params?: CrimeWorkParams) { super(WorkType.CRIME, params?.singularity ?? true); - this.crimeType = params?.crimeType ?? CrimeType.SHOPLIFT; + this.crimeType = params?.crimeType ?? CrimeType.shoplift; this.unitCompleted = 0; } @@ -89,7 +89,7 @@ export class CrimeWork extends Work { return { type: this.type, cyclesWorked: this.cyclesWorked, - crimeType: checkEnum(CrimeType, this.crimeType) ? this.crimeType : CrimeType.SHOPLIFT, + crimeType: checkEnum(CrimeType, this.crimeType) ? this.crimeType : CrimeType.shoplift, }; } diff --git a/src/Work/FactionWork.tsx b/src/Work/FactionWork.tsx index 0c6fb8267..5d0eaf201 100644 --- a/src/Work/FactionWork.tsx +++ b/src/Work/FactionWork.tsx @@ -11,7 +11,7 @@ import { Reputation } from "../ui/React/Reputation"; import { CONSTANTS } from "../Constants"; import { AugmentationNames } from "../Augmentation/data/AugmentationNames"; import { calculateFactionExp, calculateFactionRep } from "./Formulas"; -import { FactionWorkType } from "./data/FactionWorkType"; +import { FactionWorkType } from "../utils/enums"; interface FactionWorkParams { singularity: boolean; @@ -27,7 +27,7 @@ export class FactionWork extends Work { constructor(params?: FactionWorkParams) { super(WorkType.FACTION, params?.singularity ?? true); - this.factionWorkType = params?.factionWorkType ?? FactionWorkType.HACKING; + this.factionWorkType = params?.factionWorkType ?? FactionWorkType.hacking; this.factionName = params?.faction ?? FactionNames.Sector12; } @@ -92,7 +92,9 @@ export class FactionWork extends Work { /** Initializes a FactionWork object from a JSON save state. */ static fromJSON(value: IReviverValue): FactionWork { - return Generic_fromJSON(FactionWork, value.data); + const factionWork = Generic_fromJSON(FactionWork, value.data); + factionWork.factionWorkType = factionWork.factionWorkType.toLowerCase() as FactionWorkType; + return factionWork; } } diff --git a/src/Work/Formulas.ts b/src/Work/Formulas.ts index 0f421f308..cbbd992ea 100644 --- a/src/Work/Formulas.ts +++ b/src/Work/Formulas.ts @@ -3,7 +3,7 @@ import { Crime } from "../Crime/Crime"; import { newWorkStats, scaleWorkStats, WorkStats, multWorkStats } from "./WorkStats"; import { Person as IPerson } from "../ScriptEditor/NetscriptDefinitions"; import { CONSTANTS } from "../Constants"; -import { FactionWorkType } from "./data/FactionWorkType"; +import { FactionWorkType, GymType } from "../utils/enums"; import { getFactionFieldWorkRepGain, getFactionSecurityWorkRepGain, @@ -19,11 +19,12 @@ import { serverMetadata } from "../Server/data/servers"; import { LocationName } from "../Locations/data/LocationNames"; import { Company } from "../Company/Company"; import { CompanyPosition } from "../Company/CompanyPosition"; +import { checkEnum } from "../utils/helpers/enum"; const gameCPS = 1000 / CONSTANTS._idleSpeed; // 5 cycles per second export const FactionWorkStats: Record = { - [FactionWorkType.HACKING]: newWorkStats({ hackExp: 15 }), - [FactionWorkType.FIELD]: newWorkStats({ + [FactionWorkType.hacking]: newWorkStats({ hackExp: 15 }), + [FactionWorkType.field]: newWorkStats({ hackExp: 10, strExp: 10, defExp: 10, @@ -31,7 +32,7 @@ export const FactionWorkStats: Record = { agiExp: 10, chaExp: 10, }), - [FactionWorkType.SECURITY]: newWorkStats({ + [FactionWorkType.security]: newWorkStats({ hackExp: 5, strExp: 15, defExp: 15, @@ -66,9 +67,9 @@ export function calculateCrimeWorkStats(person: IPerson, crime: Crime): WorkStat /** @returns faction rep rate per cycle */ export const calculateFactionRep = (person: IPerson, type: FactionWorkType, favor: number): number => { const repFormulas = { - [FactionWorkType.HACKING]: getHackingWorkRepGain, - [FactionWorkType.FIELD]: getFactionFieldWorkRepGain, - [FactionWorkType.SECURITY]: getFactionSecurityWorkRepGain, + [FactionWorkType.hacking]: getHackingWorkRepGain, + [FactionWorkType.field]: getFactionFieldWorkRepGain, + [FactionWorkType.security]: getFactionSecurityWorkRepGain, }; return repFormulas[type](person, favor); }; @@ -95,11 +96,7 @@ export function calculateClassEarnings(person: IPerson, type: ClassType, locatio const classs = Classes[type]; const location = Locations[locationName]; - const hashMult = [ClassType.GymAgility, ClassType.GymDefense, ClassType.GymStrength, ClassType.GymDexterity].includes( - type, - ) - ? hashManager.getTrainingMult() - : hashManager.getStudyMult(); + const hashMult = checkEnum(GymType, type) ? hashManager.getTrainingMult() : hashManager.getStudyMult(); const earnings = multWorkStats( scaleWorkStats(classs.earnings, (location.expMult / gameCPS) * hashMult, false), diff --git a/src/Work/data/FactionWorkType.ts b/src/Work/data/FactionWorkType.ts deleted file mode 100644 index 336ead4b1..000000000 --- a/src/Work/data/FactionWorkType.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum FactionWorkType { - HACKING = "HACKING", - FIELD = "FIELD", - SECURITY = "SECURITY", -} diff --git a/src/types.ts b/src/types.ts index 054accfc4..1ea113c97 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,20 +1,13 @@ -/** Construct a type using the values from an object. Requires object to be defined "as const" */ -export type ValuesFrom = T[keyof T]; - -/** - * Status object for functions that return a boolean indicating success/failure - * and an optional message - */ +/** Status object for functions that return a boolean indicating success/failure + * and an optional message */ export interface IReturnStatus { res: boolean; msg?: string; } -/** - * Defines the minimum and maximum values for a range. +/** Defines the minimum and maximum values for a range. * It is up to the consumer if these values are inclusive or exclusive. - * It is up to the implementor to ensure max > min. - */ + * It is up to the implementor to ensure max > min. */ export interface IMinMaxRange { /** Value by which the bounds are to be divided for the final range */ divisor?: number; diff --git a/src/ui/WorkInProgressRoot.tsx b/src/ui/WorkInProgressRoot.tsx index 37ede863d..fbf49510e 100644 --- a/src/ui/WorkInProgressRoot.tsx +++ b/src/ui/WorkInProgressRoot.tsx @@ -24,7 +24,7 @@ import { WorkStats } from "../Work/WorkStats"; import { isCreateProgramWork } from "../Work/CreateProgramWork"; import { isGraftingWork } from "../Work/GraftingWork"; import { isFactionWork } from "../Work/FactionWork"; -import { FactionWorkType } from "../Work/data/FactionWorkType"; +import { FactionWorkType } from "../utils/enums"; import { isCompanyWork } from "../Work/CompanyWork"; const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle; @@ -394,9 +394,9 @@ export function WorkInProgressRoot(): React.ReactElement { } const description = { - [FactionWorkType.HACKING]: "carrying out hacking contracts", - [FactionWorkType.FIELD]: "carrying out field missions", - [FactionWorkType.SECURITY]: "performing security detail", + [FactionWorkType.hacking]: "carrying out hacking contracts", + [FactionWorkType.field]: "carrying out field missions", + [FactionWorkType.security]: "performing security detail", }; const exp = Player.currentWork.getExpRates(); diff --git a/src/utils/WorkType.ts b/src/utils/enums.ts similarity index 60% rename from src/utils/WorkType.ts rename to src/utils/enums.ts index 79b741360..f81df1207 100644 --- a/src/utils/WorkType.ts +++ b/src/utils/enums.ts @@ -1,18 +1,3 @@ -export enum CrimeType { - SHOPLIFT = "SHOPLIFT", //"shoplift", - ROB_STORE = "ROBSTORE", //"rob a store", - MUG = "MUG", //"mug someone", - LARCENY = "LARCENY", //"commit larceny", - DRUGS = "DRUGS", //"deal drugs", - BOND_FORGERY = "BONDFORGERY", //"forge corporate bonds", - TRAFFIC_ARMS = "TRAFFICKARMS", //"traffick illegal arms", - HOMICIDE = "HOMICIDE", //"commit homicide", - GRAND_THEFT_AUTO = "GRANDTHEFTAUTO", //"commit grand theft auto", - KIDNAP = "KIDNAP", //"kidnap someone for ransom", - ASSASSINATION = "ASSASSINATION", //"assassinate a high-profile target", - HEIST = "HEIST", //"pull off the ultimate heist", -} - export enum CompanyPosNames { sw0 = "Software Engineering Intern", sw1 = "Junior Software Engineer", @@ -53,3 +38,41 @@ export enum CompanyPosNames { waiterPT = "Part-time Waiter", employeePT = "Part-time Employee", } + +export enum CrimeType { + shoplift = "Shoplift", + robStore = "Rob Store", + mug = "Mug", + larceny = "Larceny", + dealDrugs = "Deal Drugs", + bondForgery = "Bond Forgery", + traffickArms = "Traffick Arms", + homicide = "Homicide", + grandTheftAuto = "Grand Theft Auto", + kidnap = "Kidnap", + assassination = "Assassination", + heist = "Heist", +} + +export enum FactionWorkType { + hacking = "hacking", + field = "field", + security = "security", +} + +export enum UniversityClassType { + computerScience = "Computer Science", + dataStructures = "Data Structures", + networks = "Networks", + algorithms = "Algorithms", + management = "Management", + leadership = "Leadership", +} + +//Uses skill short codes to allow easier fuzzy matching with player input +export enum GymType { + strength = "str", + defense = "def", + dexterity = "dex", + agility = "agi", +} diff --git a/src/utils/helpers/checkEnum.ts b/src/utils/helpers/checkEnum.ts deleted file mode 100644 index 46354a52f..000000000 --- a/src/utils/helpers/checkEnum.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** Verifies that a supplied value is a member of the provided object/enum. Works for enums as well as enum-like objects (const {} as const). */ -export function checkEnum>(obj: T, value: unknown): value is T[keyof T] { - return Object.values(obj).includes(value); -} diff --git a/src/utils/helpers/enum.ts b/src/utils/helpers/enum.ts new file mode 100644 index 000000000..752f9ee83 --- /dev/null +++ b/src/utils/helpers/enum.ts @@ -0,0 +1,11 @@ +/** Verifies that a supplied value is a member of the provided object/enum. Works for enums as well as enum-like objects (const {} as const). */ +export function checkEnum>(obj: T, value: unknown): value is T[keyof T] { + return Object.values(obj).includes(value); +} + +export function findEnumMember>(obj: T, value: string): T[keyof T] | undefined { + const lowerValue = value.toLowerCase().replace(/ /g, ""); + for (const member of Object.values(obj) as T[keyof T][]) { + if (lowerValue.includes(member.toLowerCase().replace(/ /g, ""))) return member; + } +}