MISC: A bunch of enums stuff. (#212)

* Some game enums moved to utils/enums. Others can eventually be moved there as well.
* findEnumMember function for performing fuzzy matching of player input with enum members, without needing separate fuzzy functions for every enum.
* Also used findEnumMember for safely loading save games (allows case changes in enum values)
* Changed capitalization on some enums.
* BREAKING: removed classGains work formulas function
* Split ClassType enum into UniversityClassType and GymType.
* Added universityGains and gymGains work formulas functions
* Provided the new split enums to the player on ns.enums.
This commit is contained in:
Snarling
2022-11-20 08:37:11 -05:00
committed by GitHub
parent 629d610532
commit 88d51e9a7e
34 changed files with 346 additions and 432 deletions

View File

@ -14,7 +14,7 @@ import { Cities } from "../Locations/Cities";
import { EmployeePositions } from "./EmployeePositions"; import { EmployeePositions } from "./EmployeePositions";
import { ResearchMap } from "./ResearchMap"; import { ResearchMap } from "./ResearchMap";
import { isRelevantMaterial } from "./ui/Helpers"; import { isRelevantMaterial } from "./ui/Helpers";
import { checkEnum } from "../utils/helpers/checkEnum"; import { checkEnum } from "../utils/helpers/enum";
import { CityName } from "../Locations/data/CityNames"; import { CityName } from "../Locations/data/CityNames";
export function NewIndustry(corporation: Corporation, industry: IndustryType, name: string): void { export function NewIndustry(corporation: Corporation, industry: IndustryType, name: string): void {

View File

@ -2,7 +2,7 @@ import { CONSTANTS } from "../Constants";
import { Player } from "@player"; import { Player } from "@player";
import { Person as IPerson } from "../ScriptEditor/NetscriptDefinitions"; import { Person as IPerson } from "../ScriptEditor/NetscriptDefinitions";
import { WorkerScript } from "../Netscript/WorkerScript"; import { WorkerScript } from "../Netscript/WorkerScript";
import { CrimeType } from "../utils/WorkType"; import { CrimeType } from "../utils/enums";
import { CrimeWork } from "../Work/CrimeWork"; import { CrimeWork } from "../Work/CrimeWork";
import { calculateIntelligenceBonus } from "../PersonObjects/formulas/intelligence"; import { calculateIntelligenceBonus } from "../PersonObjects/formulas/intelligence";
@ -25,6 +25,9 @@ interface IConstructorParams {
} }
export class Crime { 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 // Number representing the difficulty of the crime. Used for success chance calculations
difficulty: number; difficulty: number;
@ -37,9 +40,6 @@ export class Crime {
// How much money is given by the // How much money is given by the
money: number; money: number;
// Name of crime
name: string;
// Name of crime as it appears on work screen: "You are attempting..." // Name of crime as it appears on work screen: "You are attempting..."
workName: string; workName: string;
@ -49,9 +49,6 @@ export class Crime {
// Milliseconds it takes to attempt the crime // Milliseconds it takes to attempt the crime
time = 0; 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 // Weighting factors that determine how stats affect the success rate of this crime
hacking_success_weight = 0; hacking_success_weight = 0;
strength_success_weight = 0; strength_success_weight = 0;
@ -70,7 +67,6 @@ export class Crime {
intelligence_exp = 0; intelligence_exp = 0;
constructor( constructor(
name: string,
workName: string, workName: string,
tooltipText: string, tooltipText: string,
type: CrimeType, type: CrimeType,
@ -80,7 +76,6 @@ export class Crime {
karma: number, karma: number,
params: IConstructorParams, params: IConstructorParams,
) { ) {
this.name = name;
this.workName = workName; this.workName = workName;
this.tooltipText = tooltipText; this.tooltipText = tooltipText;
this.type = type; this.type = type;

View File

@ -3,8 +3,8 @@ import { Crime } from "./Crime";
import { Player } from "@player"; import { Player } from "@player";
import { dialogBoxCreate } from "../ui/React/DialogBox"; import { dialogBoxCreate } from "../ui/React/DialogBox";
import { checkEnum } from "../utils/helpers/checkEnum"; import { checkEnum } from "../utils/helpers/enum";
import { CrimeType } from "../utils/WorkType"; import { CrimeType } from "../utils/enums";
//This is only used for the player //This is only used for the player
export function determineCrimeSuccess(type: string): boolean { export function determineCrimeSuccess(type: string): boolean {
@ -20,31 +20,18 @@ export function determineCrimeSuccess(type: string): boolean {
export function findCrime(roughName: string): Crime | null { export function findCrime(roughName: string): Crime | null {
if (checkEnum(CrimeType, roughName)) return Crimes[roughName]; if (checkEnum(CrimeType, roughName)) return Crimes[roughName];
roughName = roughName.toLowerCase(); roughName = roughName.toLowerCase();
if (roughName.includes("shoplift")) { if (roughName.includes("shoplift")) return Crimes[CrimeType.shoplift];
return Crimes[CrimeType.SHOPLIFT]; else if (roughName.includes("rob") && roughName.includes("store")) return Crimes[CrimeType.robStore];
} else if (roughName.includes("rob") && roughName.includes("store")) { else if (roughName.includes("mug")) return Crimes[CrimeType.mug];
return Crimes[CrimeType.ROB_STORE]; else if (roughName.includes("larceny")) return Crimes[CrimeType.larceny];
} else if (roughName.includes("mug")) { else if (roughName.includes("drugs")) return Crimes[CrimeType.dealDrugs];
return Crimes[CrimeType.MUG]; else if (roughName.includes("bond") && roughName.includes("forge")) return Crimes[CrimeType.bondForgery];
} else if (roughName.includes("larceny")) { else if ((roughName.includes("traffic") || roughName.includes("illegal")) && roughName.includes("arms")) {
return Crimes[CrimeType.LARCENY]; return Crimes[CrimeType.traffickArms];
} else if (roughName.includes("drugs")) { } else if (roughName.includes("homicide")) return Crimes[CrimeType.homicide];
return Crimes[CrimeType.DRUGS]; else if (roughName.includes("grand") && roughName.includes("auto")) return Crimes[CrimeType.grandTheftAuto];
} else if (roughName.includes("bond") && roughName.includes("forge")) { else if (roughName.includes("kidnap")) return Crimes[CrimeType.kidnap];
return Crimes[CrimeType.BOND_FORGERY]; else if (roughName.includes("assassin")) return Crimes[CrimeType.assassination];
} else if ((roughName.includes("traffic") || roughName.includes("illegal")) && roughName.includes("arms")) { else if (roughName.includes("heist")) return Crimes[CrimeType.heist];
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];
}
return null; return null;
} }

View File

@ -1,15 +1,12 @@
import { Crime } from "./Crime"; import { Crime } from "./Crime";
import { CONSTANTS } from "../Constants"; 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, Crime> = { export const Crimes: Record<CrimeType, Crime> = {
[CrimeType.SHOPLIFT]: new Crime( [CrimeType.shoplift]: new Crime(
"Shoplift",
"to shoplift", "to shoplift",
"Attempt to shoplift from a low-end retailer", "Attempt to shoplift from a low-end retailer",
CrimeType.SHOPLIFT, CrimeType.shoplift,
2e3, 2e3,
15e3, 15e3,
1 / 20, 1 / 20,
@ -23,11 +20,10 @@ export const Crimes: Record<CrimeType, Crime> = {
}, },
), ),
[CrimeType.ROB_STORE]: new Crime( [CrimeType.robStore]: new Crime(
"Rob Store",
"to rob a store", "to rob a store",
"Attempt to commit armed robbery on a high-end store", "Attempt to commit armed robbery on a high-end store",
CrimeType.ROB_STORE, CrimeType.robStore,
60e3, 60e3,
400e3, 400e3,
1 / 5, 1 / 5,
@ -45,11 +41,10 @@ export const Crimes: Record<CrimeType, Crime> = {
}, },
), ),
[CrimeType.MUG]: new Crime( [CrimeType.mug]: new Crime(
"Mug",
"to mug", "to mug",
"Attempt to mug a random person on the street", "Attempt to mug a random person on the street",
CrimeType.MUG, CrimeType.mug,
4e3, 4e3,
36e3, 36e3,
1 / 5, 1 / 5,
@ -67,11 +62,10 @@ export const Crimes: Record<CrimeType, Crime> = {
}, },
), ),
[CrimeType.LARCENY]: new Crime( [CrimeType.larceny]: new Crime(
"Larceny",
"larceny", "larceny",
"Attempt to rob property from someone's house", "Attempt to rob property from someone's house",
CrimeType.LARCENY, CrimeType.larceny,
90e3, 90e3,
800e3, 800e3,
1 / 3, 1 / 3,
@ -89,31 +83,20 @@ export const Crimes: Record<CrimeType, Crime> = {
}, },
), ),
[CrimeType.DRUGS]: new Crime( [CrimeType.dealDrugs]: new Crime("to deal drugs", "Attempt to deal drugs", CrimeType.dealDrugs, 10e3, 120e3, 1, 0.5, {
"Deal Drugs", dexterity_exp: 5,
"to deal drugs", agility_exp: 5,
"Attempt to deal drugs", charisma_exp: 10,
CrimeType.DRUGS,
10e3,
120e3,
1,
0.5,
{
dexterity_exp: 5,
agility_exp: 5,
charisma_exp: 10,
charisma_success_weight: 3, charisma_success_weight: 3,
dexterity_success_weight: 2, dexterity_success_weight: 2,
agility_success_weight: 1, agility_success_weight: 1,
}, }),
),
[CrimeType.BOND_FORGERY]: new Crime( [CrimeType.bondForgery]: new Crime(
"Bond Forgery",
"to forge bonds", "to forge bonds",
"Attempt to forge corporate bonds", "Attempt to forge corporate bonds",
CrimeType.BOND_FORGERY, CrimeType.bondForgery,
300e3, 300e3,
4.5e6, 4.5e6,
1 / 2, 1 / 2,
@ -130,11 +113,10 @@ export const Crimes: Record<CrimeType, Crime> = {
}, },
), ),
[CrimeType.TRAFFIC_ARMS]: new Crime( [CrimeType.traffickArms]: new Crime(
"Traffick Arms",
"to traffic arms", "to traffic arms",
"Attempt to smuggle illegal arms into the city", "Attempt to smuggle illegal arms into the city",
CrimeType.TRAFFIC_ARMS, CrimeType.traffickArms,
40e3, 40e3,
600e3, 600e3,
2, 2,
@ -154,11 +136,10 @@ export const Crimes: Record<CrimeType, Crime> = {
}, },
), ),
[CrimeType.HOMICIDE]: new Crime( [CrimeType.homicide]: new Crime(
"Homicide",
"homicide", "homicide",
"Attempt to murder a random person on the street", "Attempt to murder a random person on the street",
CrimeType.HOMICIDE, CrimeType.homicide,
3e3, 3e3,
45e3, 45e3,
1, 1,
@ -178,11 +159,10 @@ export const Crimes: Record<CrimeType, Crime> = {
}, },
), ),
[CrimeType.GRAND_THEFT_AUTO]: new Crime( [CrimeType.grandTheftAuto]: new Crime(
"Grand Theft Auto",
"grand theft auto", "grand theft auto",
"Attempt to commit grand theft auto", "Attempt to commit grand theft auto",
CrimeType.GRAND_THEFT_AUTO, CrimeType.grandTheftAuto,
80e3, 80e3,
1.6e6, 1.6e6,
8, 8,
@ -204,11 +184,10 @@ export const Crimes: Record<CrimeType, Crime> = {
}, },
), ),
[CrimeType.KIDNAP]: new Crime( [CrimeType.kidnap]: new Crime(
"Kidnap",
"to kidnap", "to kidnap",
"Attempt to kidnap and ransom a high-profile-target", "Attempt to kidnap and ransom a high-profile-target",
CrimeType.KIDNAP, CrimeType.kidnap,
120e3, 120e3,
3.6e6, 3.6e6,
5, 5,
@ -229,11 +208,10 @@ export const Crimes: Record<CrimeType, Crime> = {
}, },
), ),
[CrimeType.ASSASSINATION]: new Crime( [CrimeType.assassination]: new Crime(
"Assassination",
"to assassinate", "to assassinate",
"Attempt to assassinate a high-profile target", "Attempt to assassinate a high-profile target",
CrimeType.ASSASSINATION, CrimeType.assassination,
300e3, 300e3,
12e6, 12e6,
8, 8,
@ -254,11 +232,10 @@ export const Crimes: Record<CrimeType, Crime> = {
}, },
), ),
[CrimeType.HEIST]: new Crime( [CrimeType.heist]: new Crime(
"Heist",
"a heist", "a heist",
"Attempt to pull off the ultimate heist", "Attempt to pull off the ultimate heist",
CrimeType.HEIST, CrimeType.heist,
600e3, 600e3,
120e6, 120e6,
18, 18,

View File

@ -23,7 +23,7 @@ import { CovenantPurchasesRoot } from "../../PersonObjects/Sleeve/ui/CovenantPur
import { FactionNames } from "../data/FactionNames"; import { FactionNames } from "../data/FactionNames";
import { GangButton } from "./GangButton"; import { GangButton } from "./GangButton";
import { FactionWork } from "../../Work/FactionWork"; import { FactionWork } from "../../Work/FactionWork";
import { FactionWorkType } from "../../Work/data/FactionWorkType"; import { FactionWorkType } from "../../utils/enums";
type IProps = { type IProps = {
faction: Faction; faction: Faction;
@ -72,7 +72,7 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea
new FactionWork({ new FactionWork({
singularity: false, singularity: false,
faction: faction.name, faction: faction.name,
factionWorkType: FactionWorkType.FIELD, factionWorkType: FactionWorkType.field,
}), }),
); );
startWork(); startWork();
@ -83,7 +83,7 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea
new FactionWork({ new FactionWork({
singularity: false, singularity: false,
faction: faction.name, faction: faction.name,
factionWorkType: FactionWorkType.HACKING, factionWorkType: FactionWorkType.hacking,
}), }),
); );
startWork(); startWork();
@ -94,7 +94,7 @@ function MainPage({ faction, rerender, onAugmentations }: IMainProps): React.Rea
new FactionWork({ new FactionWork({
singularity: false, singularity: false,
faction: faction.name, faction: faction.name,
factionWorkType: FactionWorkType.SECURITY, factionWorkType: FactionWorkType.security,
}), }),
); );
startWork(); startWork();

View File

@ -13,15 +13,16 @@ import { Player } from "@player";
import { Money } from "../../ui/React/Money"; import { Money } from "../../ui/React/Money";
import { Router } from "../../ui/GameRoot"; import { Router } from "../../ui/GameRoot";
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import { ClassWork, ClassType, Classes } from "../../Work/ClassWork"; import { ClassWork, Classes } from "../../Work/ClassWork";
import { calculateCost } from "../../Work/Formulas"; import { calculateCost } from "../../Work/Formulas";
import { GymType } from "../../utils/enums";
type IProps = { type IProps = {
loc: Location; loc: Location;
}; };
export function GymLocation(props: IProps): React.ReactElement { export function GymLocation(props: IProps): React.ReactElement {
function train(stat: ClassType): void { function train(stat: GymType): void {
Player.startWork( Player.startWork(
new ClassWork({ new ClassWork({
classType: stat, classType: stat,
@ -33,20 +34,20 @@ export function GymLocation(props: IProps): React.ReactElement {
Router.toWork(); Router.toWork();
} }
const cost = calculateCost(Classes[ClassType.GymStrength], props.loc); const cost = calculateCost(Classes[GymType.strength], props.loc);
return ( return (
<Box sx={{ display: "grid", width: "fit-content" }}> <Box sx={{ display: "grid", width: "fit-content" }}>
<Button onClick={() => train(ClassType.GymStrength)}> <Button onClick={() => train(GymType.strength)}>
Train Strength (<Money money={cost} forPurchase={true} /> / sec) Train Strength (<Money money={cost} forPurchase={true} /> / sec)
</Button> </Button>
<Button onClick={() => train(ClassType.GymDefense)}> <Button onClick={() => train(GymType.defense)}>
Train Defense (<Money money={cost} forPurchase={true} /> / sec) Train Defense (<Money money={cost} forPurchase={true} /> / sec)
</Button> </Button>
<Button onClick={() => train(ClassType.GymDexterity)}> <Button onClick={() => train(GymType.dexterity)}>
Train Dexterity (<Money money={cost} forPurchase={true} /> / sec) Train Dexterity (<Money money={cost} forPurchase={true} /> / sec)
</Button> </Button>
<Button onClick={() => train(ClassType.GymAgility)}> <Button onClick={() => train(GymType.agility)}>
Train Agility (<Money money={cost} forPurchase={true} /> / sec) Train Agility (<Money money={cost} forPurchase={true} /> / sec)
</Button> </Button>
</Box> </Box>

View File

@ -36,7 +36,7 @@ export function SlumsLocation(): React.ReactElement {
{crimes.map((crime) => ( {crimes.map((crime) => (
<Tooltip title={crime.tooltipText}> <Tooltip title={crime.tooltipText}>
<Button onClick={(e) => doCrime(e, crime)}> <Button onClick={(e) => doCrime(e, crime)}>
{crime.name} ({numeralWrapper.formatPercentage(crime.successRate(Player))} chance of success) {crime.type} ({numeralWrapper.formatPercentage(crime.successRate(Player))} chance of success)
</Button> </Button>
</Tooltip> </Tooltip>
))} ))}

View File

@ -14,15 +14,16 @@ import { Router } from "../../ui/GameRoot";
import { Player } from "@player"; import { Player } from "@player";
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import { ClassWork, ClassType, Classes } from "../../Work/ClassWork"; import { ClassWork, Classes } from "../../Work/ClassWork";
import { calculateCost } from "../../Work/Formulas"; import { calculateCost } from "../../Work/Formulas";
import { UniversityClassType } from "../../utils/enums";
type IProps = { type IProps = {
loc: Location; loc: Location;
}; };
export function UniversityLocation(props: IProps): React.ReactElement { export function UniversityLocation(props: IProps): React.ReactElement {
function take(classType: ClassType): void { function take(classType: UniversityClassType): void {
Player.startWork( Player.startWork(
new ClassWork({ new ClassWork({
classType: classType, classType: classType,
@ -34,11 +35,11 @@ export function UniversityLocation(props: IProps): React.ReactElement {
Router.toWork(); Router.toWork();
} }
const dataStructuresCost = calculateCost(Classes[ClassType.DataStructures], props.loc); const dataStructuresCost = calculateCost(Classes[UniversityClassType.dataStructures], props.loc);
const networksCost = calculateCost(Classes[ClassType.Networks], props.loc); const networksCost = calculateCost(Classes[UniversityClassType.networks], props.loc);
const algorithmsCost = calculateCost(Classes[ClassType.Algorithms], props.loc); const algorithmsCost = calculateCost(Classes[UniversityClassType.algorithms], props.loc);
const managementCost = calculateCost(Classes[ClassType.Management], props.loc); const managementCost = calculateCost(Classes[UniversityClassType.management], props.loc);
const leadershipCost = calculateCost(Classes[ClassType.Leadership], props.loc); const leadershipCost = calculateCost(Classes[UniversityClassType.leadership], props.loc);
const earnHackingExpTooltip = `Gain hacking experience!`; const earnHackingExpTooltip = `Gain hacking experience!`;
const earnCharismaExpTooltip = `Gain charisma experience!`; const earnCharismaExpTooltip = `Gain charisma experience!`;
@ -46,34 +47,34 @@ export function UniversityLocation(props: IProps): React.ReactElement {
return ( return (
<Box sx={{ display: "grid", width: "fit-content" }}> <Box sx={{ display: "grid", width: "fit-content" }}>
<Tooltip title={earnHackingExpTooltip}> <Tooltip title={earnHackingExpTooltip}>
<Button onClick={() => take(ClassType.StudyComputerScience)}>Study Computer Science (free)</Button> <Button onClick={() => take(UniversityClassType.computerScience)}>Study Computer Science (free)</Button>
</Tooltip> </Tooltip>
<Tooltip title={earnHackingExpTooltip}> <Tooltip title={earnHackingExpTooltip}>
<Button onClick={() => take(ClassType.DataStructures)}> <Button onClick={() => take(UniversityClassType.dataStructures)}>
Take Data Structures course ( Take Data Structures course (
<Money money={dataStructuresCost} forPurchase={true} /> / sec) <Money money={dataStructuresCost} forPurchase={true} /> / sec)
</Button> </Button>
</Tooltip> </Tooltip>
<Tooltip title={earnHackingExpTooltip}> <Tooltip title={earnHackingExpTooltip}>
<Button onClick={() => take(ClassType.Networks)}> <Button onClick={() => take(UniversityClassType.networks)}>
Take Networks course ( Take Networks course (
<Money money={networksCost} forPurchase={true} /> / sec) <Money money={networksCost} forPurchase={true} /> / sec)
</Button> </Button>
</Tooltip> </Tooltip>
<Tooltip title={earnHackingExpTooltip}> <Tooltip title={earnHackingExpTooltip}>
<Button onClick={() => take(ClassType.Algorithms)}> <Button onClick={() => take(UniversityClassType.algorithms)}>
Take Algorithms course ( Take Algorithms course (
<Money money={algorithmsCost} forPurchase={true} /> / sec) <Money money={algorithmsCost} forPurchase={true} /> / sec)
</Button> </Button>
</Tooltip> </Tooltip>
<Tooltip title={earnCharismaExpTooltip}> <Tooltip title={earnCharismaExpTooltip}>
<Button onClick={() => take(ClassType.Management)}> <Button onClick={() => take(UniversityClassType.management)}>
Take Management course ( Take Management course (
<Money money={managementCost} forPurchase={true} /> / sec) <Money money={managementCost} forPurchase={true} /> / sec)
</Button> </Button>
</Tooltip> </Tooltip>
<Tooltip title={earnCharismaExpTooltip}> <Tooltip title={earnCharismaExpTooltip}>
<Button onClick={() => take(ClassType.Leadership)}> <Button onClick={() => take(UniversityClassType.leadership)}>
Take Leadership course ( Take Leadership course (
<Money money={leadershipCost} forPurchase={true} /> / sec) <Money money={leadershipCost} forPurchase={true} /> / sec)
</Button> </Button>

View File

@ -33,7 +33,7 @@ import { arrayToString } from "../utils/helpers/arrayToString";
import { HacknetServer } from "../Hacknet/HacknetServer"; import { HacknetServer } from "../Hacknet/HacknetServer";
import { BaseServer } from "../Server/BaseServer"; import { BaseServer } from "../Server/BaseServer";
import { dialogBoxCreate } from "../ui/React/DialogBox"; import { dialogBoxCreate } from "../ui/React/DialogBox";
import { checkEnum } from "../utils/helpers/checkEnum"; import { checkEnum } from "../utils/helpers/enum";
export const helpers = { export const helpers = {
string, string,

View File

@ -602,7 +602,8 @@ export const RamCosts: RamCostTree<NSFull> = {
work: { work: {
crimeSuccessChance: 0, crimeSuccessChance: 0,
crimeGains: 0, crimeGains: 0,
classGains: 0, gymGains: 0,
universityGains: 0,
factionGains: 0, factionGains: 0,
companyGains: 0, companyGains: 0,
}, },

View File

@ -66,7 +66,7 @@ import { NetscriptSingularity } from "./NetscriptFunctions/Singularity";
import { dialogBoxCreate } from "./ui/React/DialogBox"; import { dialogBoxCreate } from "./ui/React/DialogBox";
import { SnackbarEvents, ToastVariant } from "./ui/React/Snackbar"; 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 { Flags } from "./NetscriptFunctions/Flags";
import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence"; import { calculateIntelligenceBonus } from "./PersonObjects/formulas/intelligence";
@ -77,16 +77,16 @@ import { INetscriptExtra } from "./NetscriptFunctions/Extra";
import { ScriptDeath } from "./Netscript/ScriptDeath"; import { ScriptDeath } from "./Netscript/ScriptDeath";
import { getBitNodeMultipliers } from "./BitNode/BitNode"; import { getBitNodeMultipliers } from "./BitNode/BitNode";
import { assert, arrayAssert, stringAssert, objectAssert } from "./utils/helpers/typeAssertion"; 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 { cloneDeep } from "lodash";
import { FactionWorkType } from "./Work/data/FactionWorkType"; import { FactionWorkType } from "./utils/enums";
import { ClassType } from "./Work/ClassWork";
export const enums: NSEnums = { export const enums: NSEnums = {
toast: ToastVariant, toast: ToastVariant,
CrimeType, CrimeType,
FactionWorkType, FactionWorkType,
ClassType, GymType,
UniversityClassType,
CompanyPosNames, CompanyPosNames,
}; };

View File

@ -58,7 +58,7 @@ import { Factions } from "../Faction/Factions";
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
import { assertEnumMember, helpers } from "../Netscript/NetscriptHelpers"; import { assertEnumMember, helpers } from "../Netscript/NetscriptHelpers";
import { checkEnum } from "../utils/helpers/checkEnum"; import { checkEnum } from "../utils/helpers/enum";
import { CityName } from "../Locations/data/CityNames"; import { CityName } from "../Locations/data/CityNames";
export function NetscriptCorporation(): InternalAPI<NSCorporation> { export function NetscriptCorporation(): InternalAPI<NSCorporation> {

View File

@ -40,19 +40,18 @@ import { repFromDonation } from "../Faction/formulas/donation";
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
import { helpers } from "../Netscript/NetscriptHelpers"; import { helpers } from "../Netscript/NetscriptHelpers";
import { calculateCrimeWorkStats } from "../Work/Formulas"; import { calculateCrimeWorkStats } from "../Work/Formulas";
import { Crimes } from "../Crime/Crimes";
import { calculateCompanyWorkStats } from "../Work/Formulas"; import { calculateCompanyWorkStats } from "../Work/Formulas";
import { Companies } from "../Company/Companies"; import { Companies } from "../Company/Companies";
import { calculateClassEarnings } from "../Work/Formulas"; import { calculateClassEarnings } from "../Work/Formulas";
import { ClassType } from "../Work/ClassWork";
import { LocationName } from "../Locations/data/LocationNames"; import { LocationName } from "../Locations/data/LocationNames";
import { calculateFactionExp, calculateFactionRep } from "../Work/Formulas"; 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 { defaultMultipliers } from "../PersonObjects/Multipliers";
import { checkEnum } from "../utils/helpers/checkEnum"; import { checkEnum, findEnumMember } from "../utils/helpers/enum";
import { CompanyPosNames, CrimeType } from "../utils/WorkType"; import { CompanyPosNames } from "../utils/enums";
import { CompanyPositions } from "../Company/CompanyPositions"; import { CompanyPositions } from "../Company/CompanyPositions";
import { findCrime } from "../Crime/CrimeHelpers";
export function NetscriptFormulas(): InternalAPI<IFormulas> { export function NetscriptFormulas(): InternalAPI<IFormulas> {
const checkFormulasAccess = function (ctx: NetscriptContext): void { const checkFormulasAccess = function (ctx: NetscriptContext): void {
@ -356,22 +355,31 @@ export function NetscriptFormulas(): InternalAPI<IFormulas> {
crimeSuccessChance: (ctx) => (_person, _crimeType) => { crimeSuccessChance: (ctx) => (_person, _crimeType) => {
checkFormulasAccess(ctx); checkFormulasAccess(ctx);
const person = helpers.person(ctx, _person); const person = helpers.person(ctx, _person);
const crimeType = helpers.string(ctx, "crimeType", _crimeType); const crime = findCrime(helpers.string(ctx, "crimeType", _crimeType));
if (!checkEnum(CrimeType, crimeType)) throw new Error(`Invalid crime type: ${crimeType}`); if (!crime) throw new Error(`Invalid crime type: ${_crimeType}`);
return Crimes[crimeType].successRate(person); return crime.successRate(person);
}, },
crimeGains: (ctx) => (_person, _crimeType) => { crimeGains: (ctx) => (_person, _crimeType) => {
checkFormulasAccess(ctx); checkFormulasAccess(ctx);
const person = helpers.person(ctx, _person); const person = helpers.person(ctx, _person);
const crimeType = helpers.string(ctx, "crimeType", _crimeType); const crime = findCrime(helpers.string(ctx, "crimeType", _crimeType));
if (!checkEnum(CrimeType, crimeType)) throw new Error(`Invalid crime type: ${crimeType}`); if (!crime) throw new Error(`Invalid crime type: ${_crimeType}`);
return calculateCrimeWorkStats(person, Crimes[crimeType]); return calculateCrimeWorkStats(person, crime);
}, },
classGains: (ctx) => (_person, _classType, _locationName) => { gymGains: (ctx) => (_person, _classType, _locationName) => {
checkFormulasAccess(ctx); checkFormulasAccess(ctx);
const person = helpers.person(ctx, _person); const person = helpers.person(ctx, _person);
const classType = helpers.string(ctx, "classType", _classType); const classType = findEnumMember(GymType, helpers.string(ctx, "classType", _classType));
if (!checkEnum(ClassType, classType)) throw new Error(`Invalid class type: ${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); const locationName = helpers.string(ctx, "locationName", _locationName);
if (!checkEnum(LocationName, locationName)) throw new Error(`Invalid location name: ${locationName}`); if (!checkEnum(LocationName, locationName)) throw new Error(`Invalid location name: ${locationName}`);
return calculateClassEarnings(person, classType, locationName); return calculateClassEarnings(person, classType, locationName);
@ -379,8 +387,8 @@ export function NetscriptFormulas(): InternalAPI<IFormulas> {
factionGains: (ctx) => (_player, _workType, _favor) => { factionGains: (ctx) => (_player, _workType, _favor) => {
checkFormulasAccess(ctx); checkFormulasAccess(ctx);
const player = helpers.person(ctx, _player); const player = helpers.person(ctx, _player);
const workType = helpers.string(ctx, "_workType", _workType); const workType = findEnumMember(FactionWorkType, helpers.string(ctx, "_workType", _workType));
if (!checkEnum(FactionWorkType, workType)) throw new Error(`Invalid faction work type: ${workType}`); if (!workType) throw new Error(`Invalid faction work type: ${_workType}`);
const favor = helpers.number(ctx, "favor", _favor); const favor = helpers.number(ctx, "favor", _favor);
const exp = calculateFactionExp(player, workType); const exp = calculateFactionExp(player, workType);
const rep = calculateFactionRep(player, workType, favor); const rep = calculateFactionRep(player, workType, favor);
@ -390,8 +398,8 @@ export function NetscriptFormulas(): InternalAPI<IFormulas> {
companyGains: (ctx) => (_person, _companyName, _positionName, _favor) => { companyGains: (ctx) => (_person, _companyName, _positionName, _favor) => {
checkFormulasAccess(ctx); checkFormulasAccess(ctx);
const person = helpers.person(ctx, _person); const person = helpers.person(ctx, _person);
const positionName = helpers.string(ctx, "_positionName", _positionName); const positionName = findEnumMember(CompanyPosNames, helpers.string(ctx, "_positionName", _positionName));
if (!checkEnum(CompanyPosNames, positionName)) throw new Error(`Invalid company position: ${positionName}`); if (!positionName) throw new Error(`Invalid company position: ${_positionName}`);
const position = CompanyPositions[positionName]; const position = CompanyPositions[positionName];
const companyName = helpers.string(ctx, "_companyName", _companyName); const companyName = helpers.string(ctx, "_companyName", _companyName);
const company = Object.values(Companies).find((c) => c.name === companyName); const company = Object.values(Companies).find((c) => c.name === companyName);

View File

@ -10,7 +10,7 @@ import {
import { FactionNames } from "../Faction/data/FactionNames"; import { FactionNames } from "../Faction/data/FactionNames";
import { Factions } from "../Faction/Factions"; import { Factions } from "../Faction/Factions";
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; 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 { LocationName } from "../Locations/data/LocationNames";
import { helpers } from "../Netscript/NetscriptHelpers"; import { helpers } from "../Netscript/NetscriptHelpers";

View File

@ -41,14 +41,15 @@ import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
import { BlackOperationNames } from "../Bladeburner/data/BlackOperationNames"; import { BlackOperationNames } from "../Bladeburner/data/BlackOperationNames";
import { enterBitNode } from "../RedPill"; import { enterBitNode } from "../RedPill";
import { FactionNames } from "../Faction/data/FactionNames"; import { FactionNames } from "../Faction/data/FactionNames";
import { ClassWork, ClassType } from "../Work/ClassWork"; import { ClassWork } from "../Work/ClassWork";
import { CreateProgramWork, isCreateProgramWork } from "../Work/CreateProgramWork"; import { CreateProgramWork, isCreateProgramWork } from "../Work/CreateProgramWork";
import { FactionWork } from "../Work/FactionWork"; import { FactionWork } from "../Work/FactionWork";
import { FactionWorkType } from "../Work/data/FactionWorkType"; import { FactionWorkType, GymType, UniversityClassType } from "../utils/enums";
import { CompanyWork } from "../Work/CompanyWork"; import { CompanyWork } from "../Work/CompanyWork";
import { canGetBonus, onExport } from "../ExportBonus"; import { canGetBonus, onExport } from "../ExportBonus";
import { saveObject } from "../SaveObject"; import { saveObject } from "../SaveObject";
import { calculateCrimeWorkStats } from "../Work/Formulas"; import { calculateCrimeWorkStats } from "../Work/Formulas";
import { findEnumMember } from "../utils/helpers/enum";
export function NetscriptSingularity(): InternalAPI<ISingularity> { export function NetscriptSingularity(): InternalAPI<ISingularity> {
const getAugmentation = function (ctx: NetscriptContext, name: string): Augmentation { const getAugmentation = function (ctx: NetscriptContext, name: string): Augmentation {
@ -253,7 +254,11 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
(_universityName, _className, _focus = true) => { (_universityName, _className, _focus = true) => {
helpers.checkSingularityAccess(ctx); helpers.checkSingularityAccess(ctx);
const universityName = helpers.string(ctx, "universityName", _universityName); 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 focus = !!_focus;
const wasFocusing = Player.focus; const wasFocusing = Player.focus;
@ -293,33 +298,9 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
return false; 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( Player.startWork(
new ClassWork({ new ClassWork({
classType: task, classType,
location: Player.location, location: Player.location,
singularity: true, singularity: true,
}), }),
@ -331,7 +312,7 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
Player.stopFocusing(); Player.stopFocusing();
Router.toTerminal(); Router.toTerminal();
} }
helpers.log(ctx, () => `Started ${task} at ${universityName}`); helpers.log(ctx, () => `Started ${classType} at ${universityName}`);
return true; return true;
}, },
@ -340,7 +321,11 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
(_gymName, _stat, _focus = true) => { (_gymName, _stat, _focus = true) => {
helpers.checkSingularityAccess(ctx); helpers.checkSingularityAccess(ctx);
const gymName = helpers.string(ctx, "gymName", _gymName); 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 focus = !!_focus;
const wasFocusing = Player.focus; const wasFocusing = Player.focus;
@ -405,35 +390,7 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
return false; return false;
} }
switch (stat.toLowerCase()) { Player.startWork(new ClassWork({ classType, location: Player.location, singularity: true }));
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;
}
if (focus) { if (focus) {
Player.startFocusing(); Player.startFocusing();
Router.toWork(); Router.toWork();
@ -441,7 +398,7 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
Player.stopFocusing(); Player.stopFocusing();
Router.toTerminal(); Router.toTerminal();
} }
helpers.log(ctx, () => `Started training ${stat} at ${gymName}`); helpers.log(ctx, () => `Started training ${classType} at ${gymName}`);
return true; return true;
}, },
@ -926,7 +883,7 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
Player.startWork( Player.startWork(
new FactionWork({ new FactionWork({
singularity: true, singularity: true,
factionWorkType: FactionWorkType.HACKING, factionWorkType: FactionWorkType.hacking,
faction: faction.name, faction: faction.name,
}), }),
); );
@ -949,7 +906,7 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
Player.startWork( Player.startWork(
new FactionWork({ new FactionWork({
singularity: true, singularity: true,
factionWorkType: FactionWorkType.FIELD, factionWorkType: FactionWorkType.field,
faction: faction.name, faction: faction.name,
}), }),
); );
@ -972,7 +929,7 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
Player.startWork( Player.startWork(
new FactionWork({ new FactionWork({
singularity: true, singularity: true,
factionWorkType: FactionWorkType.SECURITY, factionWorkType: FactionWorkType.security,
faction: faction.name, faction: faction.name,
}), }),
); );
@ -1118,7 +1075,7 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
const crime = findCrime(crimeType); const crime = findCrime(crimeType);
if (crime == null) throw helpers.makeRuntimeErrorMsg(ctx, `Invalid crime: '${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); const crimeTime = crime.commit(1, ctx.workerScript);
if (focus) { if (focus) {
Player.startFocusing(); Player.startFocusing();

View File

@ -5,7 +5,7 @@ import { findCrime } from "../Crime/CrimeHelpers";
import { Augmentation } from "../Augmentation/Augmentation"; import { Augmentation } from "../Augmentation/Augmentation";
import { sleeve } from "../ScriptEditor/NetscriptDefinitions"; import { sleeve } from "../ScriptEditor/NetscriptDefinitions";
import { checkEnum } from "../utils/helpers/checkEnum"; import { checkEnum } from "../utils/helpers/enum";
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper"; import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
import { isSleeveBladeburnerWork } from "../PersonObjects/Sleeve/Work/SleeveBladeburnerWork"; import { isSleeveBladeburnerWork } from "../PersonObjects/Sleeve/Work/SleeveBladeburnerWork";
import { isSleeveFactionWork } from "../PersonObjects/Sleeve/Work/SleeveFactionWork"; import { isSleeveFactionWork } from "../PersonObjects/Sleeve/Work/SleeveFactionWork";

View File

@ -18,7 +18,7 @@ import { CompanyPosition } from "../../Company/CompanyPosition";
import { CompanyPositions } from "../../Company/CompanyPositions"; import { CompanyPositions } from "../../Company/CompanyPositions";
import { Contracts } from "../../Bladeburner/data/Contracts"; import { Contracts } from "../../Bladeburner/data/Contracts";
import { CONSTANTS } from "../../Constants"; import { CONSTANTS } from "../../Constants";
import { CrimeType } from "../../utils/WorkType"; import { CrimeType, GymType, UniversityClassType } from "../../utils/enums";
import { CityName } from "../../Locations/data/CityNames"; import { CityName } from "../../Locations/data/CityNames";
import { Factions } from "../../Faction/Factions"; 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 { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../utils/JSONReviver";
import { numeralWrapper } from "../../ui/numeralFormat"; import { numeralWrapper } from "../../ui/numeralFormat";
import { FactionWorkType } from "../../Work/data/FactionWorkType"; import { FactionWorkType } from "../../utils/enums";
import { Work } from "./Work/Work"; import { Work } from "./Work/Work";
import { SleeveClassWork } from "./Work/SleeveClassWork"; import { SleeveClassWork } from "./Work/SleeveClassWork";
import { ClassType } from "../../Work/ClassWork"; import { ClassType } from "../../Work/ClassWork";
@ -221,22 +221,22 @@ export class Sleeve extends Person implements ISleeve {
let classType: ClassType | undefined; let classType: ClassType | undefined;
switch (className.toLowerCase()) { switch (className.toLowerCase()) {
case "study computer science": case "study computer science":
classType = ClassType.StudyComputerScience; classType = UniversityClassType.computerScience;
break; break;
case "data structures": case "data structures":
classType = ClassType.DataStructures; classType = UniversityClassType.dataStructures;
break; break;
case "networks": case "networks":
classType = ClassType.Networks; classType = UniversityClassType.networks;
break; break;
case "algorithms": case "algorithms":
classType = ClassType.Algorithms; classType = UniversityClassType.algorithms;
break; break;
case "management": case "management":
classType = ClassType.Management; classType = UniversityClassType.management;
break; break;
case "leadership": case "leadership":
classType = ClassType.Leadership; classType = UniversityClassType.leadership;
break; break;
} }
if (!classType) return false; if (!classType) return false;
@ -311,13 +311,13 @@ export class Sleeve extends Person implements ISleeve {
let factionWorkType: FactionWorkType; let factionWorkType: FactionWorkType;
if (sanitizedWorkType.includes("hack")) { if (sanitizedWorkType.includes("hack")) {
if (!factionInfo.offerHackingWork) return false; if (!factionInfo.offerHackingWork) return false;
factionWorkType = FactionWorkType.HACKING; factionWorkType = FactionWorkType.hacking;
} else if (sanitizedWorkType.includes("field")) { } else if (sanitizedWorkType.includes("field")) {
if (!factionInfo.offerFieldWork) return false; if (!factionInfo.offerFieldWork) return false;
factionWorkType = FactionWorkType.FIELD; factionWorkType = FactionWorkType.field;
} else if (sanitizedWorkType.includes("security")) { } else if (sanitizedWorkType.includes("security")) {
if (!factionInfo.offerSecurityWork) return false; if (!factionInfo.offerSecurityWork) return false;
factionWorkType = FactionWorkType.SECURITY; factionWorkType = FactionWorkType.security;
} else { } else {
return false; return false;
} }
@ -372,16 +372,16 @@ export class Sleeve extends Person implements ISleeve {
// set stat to a default value. // set stat to a default value.
let classType: ClassType | undefined; let classType: ClassType | undefined;
if (sanitizedStat.includes("str")) { if (sanitizedStat.includes("str")) {
classType = ClassType.GymStrength; classType = GymType.strength;
} }
if (sanitizedStat.includes("def")) { if (sanitizedStat.includes("def")) {
classType = ClassType.GymDefense; classType = GymType.defense;
} }
if (sanitizedStat.includes("dex")) { if (sanitizedStat.includes("dex")) {
classType = ClassType.GymDexterity; classType = GymType.dexterity;
} }
if (sanitizedStat.includes("agi")) { if (sanitizedStat.includes("agi")) {
classType = ClassType.GymAgility; classType = GymType.agility;
} }
// if stat is still equals its default value, then validation has failed. // if stat is still equals its default value, then validation has failed.
if (!classType) return false; if (!classType) return false;

View File

@ -5,6 +5,8 @@ import { LocationName } from "../../../Locations/data/LocationNames";
import { calculateClassEarnings } from "../../../Work/Formulas"; import { calculateClassEarnings } from "../../../Work/Formulas";
import { Sleeve } from "../Sleeve"; import { Sleeve } from "../Sleeve";
import { scaleWorkStats, WorkStats } from "../../../Work/WorkStats"; 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; 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) { constructor(params?: ClassWorkParams) {
super(WorkType.CLASS); super(WorkType.CLASS);
this.classType = params?.classType ?? ClassType.StudyComputerScience; this.classType = params?.classType ?? UniversityClassType.computerScience;
this.location = params?.location ?? LocationName.Sector12RothmanUniversity; this.location = params?.location ?? LocationName.Sector12RothmanUniversity;
} }
@ -28,9 +30,7 @@ export class SleeveClassWork extends Work {
} }
isGym(): boolean { isGym(): boolean {
return [ClassType.GymAgility, ClassType.GymDefense, ClassType.GymDexterity, ClassType.GymStrength].includes( return checkEnum(GymType, this.classType);
this.classType,
);
} }
process(sleeve: Sleeve, cycles: number) { process(sleeve: Sleeve, cycles: number) {

View File

@ -2,13 +2,14 @@ import { Player } from "@player";
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver";
import { Sleeve } from "../Sleeve"; import { Sleeve } from "../Sleeve";
import { applySleeveGains, Work, WorkType } from "./Work"; import { applySleeveGains, Work, WorkType } from "./Work";
import { CrimeType } from "../../../utils/WorkType"; import { CrimeType } from "../../../utils/enums";
import { Crimes } from "../../../Crime/Crimes"; import { Crimes } from "../../../Crime/Crimes";
import { Crime } from "../../../Crime/Crime"; import { Crime } from "../../../Crime/Crime";
import { scaleWorkStats, WorkStats } from "../../../Work/WorkStats"; import { scaleWorkStats, WorkStats } from "../../../Work/WorkStats";
import { CONSTANTS } from "../../../Constants"; import { CONSTANTS } from "../../../Constants";
import { checkEnum } from "../../../utils/helpers/checkEnum"; import { checkEnum } from "../../../utils/helpers/enum";
import { calculateCrimeWorkStats } from "../../../Work/Formulas"; 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; 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; cyclesWorked = 0;
constructor(crimeType?: CrimeType) { constructor(crimeType?: CrimeType) {
super(WorkType.CRIME); super(WorkType.CRIME);
this.crimeType = crimeType ?? CrimeType.SHOPLIFT; this.crimeType = crimeType ?? CrimeType.shoplift;
} }
getCrime(): Crime { getCrime(): Crime {
@ -60,7 +61,9 @@ export class SleeveCrimeWork extends Work {
/** Initializes a RecoveryWork object from a JSON save state. */ /** Initializes a RecoveryWork object from a JSON save state. */
static fromJSON(value: IReviverValue): SleeveCrimeWork { 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;
} }
} }

View File

@ -2,7 +2,7 @@ import { Player } from "@player";
import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver"; import { Generic_fromJSON, Generic_toJSON, IReviverValue, Reviver } from "../../../utils/JSONReviver";
import { Sleeve } from "../Sleeve"; import { Sleeve } from "../Sleeve";
import { applySleeveGains, Work, WorkType } from "./Work"; import { applySleeveGains, Work, WorkType } from "./Work";
import { FactionWorkType } from "../../../Work/data/FactionWorkType"; import { FactionWorkType } from "../../../utils/enums";
import { FactionNames } from "../../../Faction/data/FactionNames"; import { FactionNames } from "../../../Faction/data/FactionNames";
import { Factions } from "../../../Faction/Factions"; import { Factions } from "../../../Faction/Factions";
import { calculateFactionExp, calculateFactionRep } from "../../../Work/Formulas"; import { calculateFactionExp, calculateFactionRep } from "../../../Work/Formulas";
@ -23,7 +23,7 @@ export class SleeveFactionWork extends Work {
constructor(params?: SleeveFactionWorkParams) { constructor(params?: SleeveFactionWorkParams) {
super(WorkType.FACTION); super(WorkType.FACTION);
this.factionWorkType = params?.factionWorkType ?? FactionWorkType.HACKING; this.factionWorkType = params?.factionWorkType ?? FactionWorkType.hacking;
this.factionName = params?.factionName ?? FactionNames.Sector12; this.factionName = params?.factionName ?? FactionNames.Sector12;
} }

View File

@ -1,6 +1,6 @@
import { Box, Button, Paper, Tooltip, Typography } from "@mui/material"; import { Box, Button, Paper, Tooltip, Typography } from "@mui/material";
import React, { useState } from "react"; import React, { useState } from "react";
import { FactionWorkType } from "../../../Work/data/FactionWorkType"; import { FactionWorkType } from "../../../utils/enums";
import { CONSTANTS } from "../../../Constants"; import { CONSTANTS } from "../../../Constants";
import { Player } from "@player"; import { Player } from "@player";
import { numeralWrapper } from "../../../ui/numeralFormat"; import { numeralWrapper } from "../../../ui/numeralFormat";
@ -21,7 +21,7 @@ import { isSleeveSupportWork } from "../Work/SleeveSupportWork";
import { isSleeveBladeburnerWork } from "../Work/SleeveBladeburnerWork"; import { isSleeveBladeburnerWork } from "../Work/SleeveBladeburnerWork";
import { isSleeveCrimeWork } from "../Work/SleeveCrimeWork"; import { isSleeveCrimeWork } from "../Work/SleeveCrimeWork";
import { findCrime } from "../../../Crime/CrimeHelpers"; import { findCrime } from "../../../Crime/CrimeHelpers";
import { CrimeType } from "../../../utils/WorkType"; import { CrimeType } from "../../../utils/enums";
interface IProps { interface IProps {
sleeve: Sleeve; sleeve: Sleeve;
@ -46,7 +46,7 @@ export function SleeveElem(props: IProps): React.ReactElement {
props.sleeve.workForFaction(abc[1], abc[2]); props.sleeve.workForFaction(abc[1], abc[2]);
break; break;
case "Commit Crime": case "Commit Crime":
props.sleeve.commitCrime(findCrime(abc[1])?.type ?? CrimeType.SHOPLIFT); props.sleeve.commitCrime(findCrime(abc[1])?.type ?? CrimeType.shoplift);
break; break;
case "Take University Course": case "Take University Course":
props.sleeve.takeUniversityCourse(abc[2], abc[1]); props.sleeve.takeUniversityCourse(abc[2], abc[1]);
@ -106,13 +106,13 @@ export function SleeveElem(props: IProps): React.ReactElement {
if (isSleeveFactionWork(props.sleeve.currentWork)) { if (isSleeveFactionWork(props.sleeve.currentWork)) {
let doing = "nothing"; let doing = "nothing";
switch (props.sleeve.currentWork.factionWorkType) { switch (props.sleeve.currentWork.factionWorkType) {
case FactionWorkType.FIELD: case FactionWorkType.field:
doing = "Field work"; doing = "Field work";
break; break;
case FactionWorkType.HACKING: case FactionWorkType.hacking:
doing = "Hacking contracts"; doing = "Hacking contracts";
break; break;
case FactionWorkType.SECURITY: case FactionWorkType.security:
doing = "Security work"; doing = "Security work";
break; break;
} }

View File

@ -16,11 +16,9 @@ import { isSleeveSynchroWork } from "../Work/SleeveSynchroWork";
import { isSleeveClassWork } from "../Work/SleeveClassWork"; import { isSleeveClassWork } from "../Work/SleeveClassWork";
import { isSleeveInfiltrateWork } from "../Work/SleeveInfiltrateWork"; import { isSleeveInfiltrateWork } from "../Work/SleeveInfiltrateWork";
import { isSleeveSupportWork } from "../Work/SleeveSupportWork"; import { isSleeveSupportWork } from "../Work/SleeveSupportWork";
import { ClassType } from "../../../Work/ClassWork";
import { isSleeveCrimeWork } from "../Work/SleeveCrimeWork"; import { isSleeveCrimeWork } from "../Work/SleeveCrimeWork";
import { FactionWorkType } from "../../../Work/data/FactionWorkType"; import { CrimeType, FactionWorkType, GymType, UniversityClassType } from "../../../utils/enums";
import { checkEnum } from "../../../utils/helpers/checkEnum"; import { checkEnum } from "../../../utils/helpers/enum";
import { CrimeType } from "../../../utils/WorkType";
const universitySelectorOptions: string[] = [ const universitySelectorOptions: string[] = [
"Study Computer Science", "Study Computer Science",
@ -167,7 +165,7 @@ const tasks: {
}; };
}, },
"Commit Crime": (): ITaskDetails => { "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 => { "Take University Course": (sleeve: Sleeve): ITaskDetails => {
let universities: string[] = []; let universities: string[] = [];
@ -263,13 +261,13 @@ function getABC(sleeve: Sleeve): [string, string, string] {
if (isSleeveFactionWork(w)) { if (isSleeveFactionWork(w)) {
let workType = ""; let workType = "";
switch (w.factionWorkType) { switch (w.factionWorkType) {
case FactionWorkType.HACKING: case FactionWorkType.hacking:
workType = "Hacking Contracts"; workType = "Hacking Contracts";
break; break;
case FactionWorkType.FIELD: case FactionWorkType.field:
workType = "Field Work"; workType = "Field Work";
break; break;
case FactionWorkType.SECURITY: case FactionWorkType.security:
workType = "Security Work"; workType = "Security Work";
break; break;
} }
@ -293,30 +291,30 @@ function getABC(sleeve: Sleeve): [string, string, string] {
if (isSleeveClassWork(w)) { if (isSleeveClassWork(w)) {
switch (w.classType) { switch (w.classType) {
case ClassType.StudyComputerScience: case UniversityClassType.computerScience:
return ["Take University Course", "Study Computer Science", w.location]; return ["Take University Course", "Study Computer Science", w.location];
case ClassType.DataStructures: case UniversityClassType.dataStructures:
return ["Take University Course", "Data Structures", w.location]; return ["Take University Course", "Data Structures", w.location];
case ClassType.Networks: case UniversityClassType.networks:
return ["Take University Course", "Networks", w.location]; return ["Take University Course", "Networks", w.location];
case ClassType.Algorithms: case UniversityClassType.algorithms:
return ["Take University Course", "Algorithms", w.location]; return ["Take University Course", "Algorithms", w.location];
case ClassType.Management: case UniversityClassType.management:
return ["Take University Course", "Management", w.location]; return ["Take University Course", "Management", w.location];
case ClassType.Leadership: case UniversityClassType.leadership:
return ["Take University Course", "Leadership", w.location]; return ["Take University Course", "Leadership", w.location];
case ClassType.GymStrength: case GymType.strength:
return ["Workout at Gym", "Train Strength", w.location]; return ["Workout at Gym", "Train Strength", w.location];
case ClassType.GymDefense: case GymType.defense:
return ["Workout at Gym", "Train Defense", w.location]; return ["Workout at Gym", "Train Defense", w.location];
case ClassType.GymDexterity: case GymType.dexterity:
return ["Workout at Gym", "Train Dexterity", w.location]; return ["Workout at Gym", "Train Dexterity", w.location];
case ClassType.GymAgility: case GymType.agility:
return ["Workout at Gym", "Train Agility", w.location]; return ["Workout at Gym", "Train Agility", w.location];
} }
} }
if (isSleeveCrimeWork(w)) { 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)) { if (isSleeveSupportWork(w)) {
return ["Perform Bladeburner Actions", "Support main sleeve", "------"]; return ["Perform Bladeburner Actions", "Support main sleeve", "------"];

View File

@ -211,8 +211,6 @@ export interface CrimeStats {
kills: number; kills: number;
/** How much money is given */ /** How much money is given */
money: number; money: number;
/** Name of crime */
name: string;
/** Milliseconds it takes to attempt the crime */ /** Milliseconds it takes to attempt the crime */
time: number; time: number;
/** Description of the crime activity */ /** Description of the crime activity */
@ -3817,8 +3815,14 @@ interface WorkFormulas {
crimeSuccessChance(person: Person, crimeType: CrimeType | `${CrimeType}`): number; crimeSuccessChance(person: Person, crimeType: CrimeType | `${CrimeType}`): number;
/** @returns The WorkStats gained when completing one instance of the specified crime. */ /** @returns The WorkStats gained when completing one instance of the specified crime. */
crimeGains(person: Person, crimeType: CrimeType | `${CrimeType}`): WorkStats; crimeGains(person: Person, crimeType: CrimeType | `${CrimeType}`): WorkStats;
/** @returns The WorkStats applied every game cycle (200ms) by taking the specified class. */ /** @returns The WorkStats applied every game cycle (200ms) by taking the specified gym class. */
classGains(person: Person, classType: ClassType | `${ClassType}`, locationName: string): WorkStats; 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. */ /** @returns The WorkStats applied every game cycle (200ms) by performing the specified faction work. */
factionGains(person: Person, workType: FactionWorkType | `${FactionWorkType}`, favor: number): WorkStats; factionGains(person: Person, workType: FactionWorkType | `${FactionWorkType}`, favor: number): WorkStats;
/** @returns The WorkStats applied every game cycle (200ms) by performing the specified company work. */ /** @returns The WorkStats applied every game cycle (200ms) by performing the specified company work. */
@ -6815,42 +6819,46 @@ declare enum ToastVariant {
/** @public */ /** @public */
declare enum CrimeType { declare enum CrimeType {
SHOPLIFT = "SHOPLIFT", shoplift = "Shoplift",
ROB_STORE = "ROBSTORE", robStore = "Rob Store",
MUG = "MUG", mug = "Mug",
LARCENY = "LARCENY", larceny = "Larceny",
DRUGS = "DRUGS", dealDrugs = "Deal Drugs",
BOND_FORGERY = "BONDFORGERY", bondForgery = "Bond Forgery",
TRAFFIC_ARMS = "TRAFFICKARMS", traffickArms = "Traffick Arms",
HOMICIDE = "HOMICIDE", homicide = "Homicide",
GRAND_THEFT_AUTO = "GRANDTHEFTAUTO", grandTheftAuto = "Grand Theft Auto",
KIDNAP = "KIDNAP", kidnap = "Kidnap",
ASSASSINATION = "ASSASSINATION", assassination = "Assassination",
HEIST = "HEIST", heist = "Heist",
} }
/** @public */ /** @public */
declare enum FactionWorkType { declare enum FactionWorkType {
HACKING = "HACKING", hacking = "hacking",
FIELD = "FIELD", field = "field",
SECURITY = "SECURITY", security = "security",
} }
// TODO: split ClassType enum into separate enums for gym and uni so they can actually be used for player input.
/** @public */ /** @public */
declare enum ClassType { declare enum UniversityClassType {
StudyComputerScience = "STUDYCOMPUTERSCIENCE", computerScience = "Computer Science",
DataStructures = "DATASTRUCTURES", dataStructures = "Data Structures",
Networks = "NETWORKS", networks = "Networks",
Algorithms = "ALGORITHMS", algorithms = "Algorithms",
Management = "MANAGEMENT", management = "Management",
Leadership = "LEADERSHIP", leadership = "Leadership",
GymStrength = "GYMSTRENGTH",
GymDefense = "GYMDEFENSE",
GymDexterity = "GYMDEXTERITY",
GymAgility = "GYMAGILITY",
} }
/** @public */
declare enum GymType {
strength = "str",
defense = "def",
dexterity = "dex",
agility = "agi",
}
/** @public */
declare enum CompanyPosNames { declare enum CompanyPosNames {
sw0 = "Software Engineering Intern", sw0 = "Software Engineering Intern",
sw1 = "Junior Software Engineer", sw1 = "Junior Software Engineer",
@ -6927,7 +6935,8 @@ export type NSEnums = {
toast: typeof ToastVariant; toast: typeof ToastVariant;
CrimeType: typeof CrimeType; CrimeType: typeof CrimeType;
FactionWorkType: typeof FactionWorkType; FactionWorkType: typeof FactionWorkType;
ClassType: typeof ClassType; GymType: typeof GymType;
UniversityClassType: typeof UniversityClassType;
CompanyPosNames: typeof CompanyPosNames; CompanyPosNames: typeof CompanyPosNames;
}; };

View File

@ -3,7 +3,7 @@ import { BaseServer } from "../../Server/BaseServer";
import { MessageFilenames, showMessage } from "../../Message/MessageHelpers"; import { MessageFilenames, showMessage } from "../../Message/MessageHelpers";
import { showLiterature } from "../../Literature/LiteratureHelpers"; import { showLiterature } from "../../Literature/LiteratureHelpers";
import { dialogBoxCreate } from "../../ui/React/DialogBox"; 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 { export function cat(args: (string | number | boolean)[], server: BaseServer): void {
if (args.length !== 1) { if (args.length !== 1) {

View File

@ -10,110 +10,67 @@ import { Player } from "@player";
import { calculateClassEarnings as calculateClassEarningsRate } from "./Formulas"; import { calculateClassEarnings as calculateClassEarningsRate } from "./Formulas";
import { Work, WorkType } from "./Work"; import { Work, WorkType } from "./Work";
import { applyWorkStats, newWorkStats, sumWorkStats, WorkStats } from "./WorkStats"; import { applyWorkStats, newWorkStats, sumWorkStats, WorkStats } from "./WorkStats";
import { GymType, UniversityClassType } from "../utils/enums";
import { checkEnum, findEnumMember } from "../utils/helpers/enum";
export enum ClassType { export type ClassType = UniversityClassType | GymType;
StudyComputerScience = "STUDYCOMPUTERSCIENCE",
DataStructures = "DATASTRUCTURES",
Networks = "NETWORKS",
Algorithms = "ALGORITHMS",
Management = "MANAGEMENT",
Leadership = "LEADERSHIP",
GymStrength = "GYMSTRENGTH",
GymDefense = "GYMDEFENSE",
GymDexterity = "GYMDEXTERITY",
GymAgility = "GYMAGILITY",
}
export interface Class { export interface Class {
youAreCurrently: string;
type: ClassType; type: ClassType;
youAreCurrently: string;
earnings: WorkStats; earnings: WorkStats;
} }
export const Classes: Record<ClassType, Class> = { export const Classes: Record<ClassType, Class> = {
[ClassType.StudyComputerScience]: { [UniversityClassType.computerScience]: {
youAreCurrently: "studying Computer Science", type: UniversityClassType.computerScience,
type: ClassType.StudyComputerScience, youAreCurrently: `studying Computer Science`,
earnings: newWorkStats({ hackExp: 0.5, intExp: 0.01 }), earnings: newWorkStats({ hackExp: 0.5, intExp: 0.01 }),
}, },
[ClassType.DataStructures]: { [UniversityClassType.dataStructures]: {
type: UniversityClassType.dataStructures,
youAreCurrently: "taking a Data Structures course", 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", 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", 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", 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", 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", 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", 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", 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", 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) { constructor(params?: ClassWorkParams) {
super(WorkType.CLASS, params?.singularity ?? true); super(WorkType.CLASS, params?.singularity ?? true);
this.classType = params?.classType ?? ClassType.StudyComputerScience; this.classType = params?.classType ?? UniversityClassType.computerScience;
this.location = params?.location ?? LocationName.Sector12RothmanUniversity; this.location = params?.location ?? LocationName.Sector12RothmanUniversity;
} }
isGym(): boolean { isGym(): boolean {
return [ClassType.GymAgility, ClassType.GymDefense, ClassType.GymDexterity, ClassType.GymStrength].includes( return checkEnum(GymType, this.classType);
this.classType,
);
} }
getClass(): Class { getClass(): Class {
@ -195,7 +150,12 @@ export class ClassWork extends Work {
/** Initializes a ClassWork object from a JSON save state. */ /** Initializes a ClassWork object from a JSON save state. */
static fromJSON(value: IReviverValue): ClassWork { 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;
} }
} }

View File

@ -5,11 +5,11 @@ import { determineCrimeSuccess } from "../Crime/CrimeHelpers";
import { Crimes } from "../Crime/Crimes"; import { Crimes } from "../Crime/Crimes";
import { Player } from "@player"; import { Player } from "@player";
import { dialogBoxCreate } from "../ui/React/DialogBox"; import { dialogBoxCreate } from "../ui/React/DialogBox";
import { CrimeType } from "../utils/WorkType"; import { CrimeType } from "../utils/enums";
import { Work, WorkType } from "./Work"; import { Work, WorkType } from "./Work";
import { scaleWorkStats, WorkStats } from "./WorkStats"; import { scaleWorkStats, WorkStats } from "./WorkStats";
import { calculateCrimeWorkStats } from "./Formulas"; import { calculateCrimeWorkStats } from "./Formulas";
import { checkEnum } from "../utils/helpers/checkEnum"; import { checkEnum } from "../utils/helpers/enum";
interface CrimeWorkParams { interface CrimeWorkParams {
crimeType: CrimeType; crimeType: CrimeType;
@ -24,7 +24,7 @@ export class CrimeWork extends Work {
constructor(params?: CrimeWorkParams) { constructor(params?: CrimeWorkParams) {
super(WorkType.CRIME, params?.singularity ?? true); super(WorkType.CRIME, params?.singularity ?? true);
this.crimeType = params?.crimeType ?? CrimeType.SHOPLIFT; this.crimeType = params?.crimeType ?? CrimeType.shoplift;
this.unitCompleted = 0; this.unitCompleted = 0;
} }
@ -89,7 +89,7 @@ export class CrimeWork extends Work {
return { return {
type: this.type, type: this.type,
cyclesWorked: this.cyclesWorked, cyclesWorked: this.cyclesWorked,
crimeType: checkEnum(CrimeType, this.crimeType) ? this.crimeType : CrimeType.SHOPLIFT, crimeType: checkEnum(CrimeType, this.crimeType) ? this.crimeType : CrimeType.shoplift,
}; };
} }

View File

@ -11,7 +11,7 @@ import { Reputation } from "../ui/React/Reputation";
import { CONSTANTS } from "../Constants"; import { CONSTANTS } from "../Constants";
import { AugmentationNames } from "../Augmentation/data/AugmentationNames"; import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
import { calculateFactionExp, calculateFactionRep } from "./Formulas"; import { calculateFactionExp, calculateFactionRep } from "./Formulas";
import { FactionWorkType } from "./data/FactionWorkType"; import { FactionWorkType } from "../utils/enums";
interface FactionWorkParams { interface FactionWorkParams {
singularity: boolean; singularity: boolean;
@ -27,7 +27,7 @@ export class FactionWork extends Work {
constructor(params?: FactionWorkParams) { constructor(params?: FactionWorkParams) {
super(WorkType.FACTION, params?.singularity ?? true); super(WorkType.FACTION, params?.singularity ?? true);
this.factionWorkType = params?.factionWorkType ?? FactionWorkType.HACKING; this.factionWorkType = params?.factionWorkType ?? FactionWorkType.hacking;
this.factionName = params?.faction ?? FactionNames.Sector12; this.factionName = params?.faction ?? FactionNames.Sector12;
} }
@ -92,7 +92,9 @@ export class FactionWork extends Work {
/** Initializes a FactionWork object from a JSON save state. */ /** Initializes a FactionWork object from a JSON save state. */
static fromJSON(value: IReviverValue): FactionWork { 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;
} }
} }

View File

@ -3,7 +3,7 @@ import { Crime } from "../Crime/Crime";
import { newWorkStats, scaleWorkStats, WorkStats, multWorkStats } from "./WorkStats"; import { newWorkStats, scaleWorkStats, WorkStats, multWorkStats } from "./WorkStats";
import { Person as IPerson } from "../ScriptEditor/NetscriptDefinitions"; import { Person as IPerson } from "../ScriptEditor/NetscriptDefinitions";
import { CONSTANTS } from "../Constants"; import { CONSTANTS } from "../Constants";
import { FactionWorkType } from "./data/FactionWorkType"; import { FactionWorkType, GymType } from "../utils/enums";
import { import {
getFactionFieldWorkRepGain, getFactionFieldWorkRepGain,
getFactionSecurityWorkRepGain, getFactionSecurityWorkRepGain,
@ -19,11 +19,12 @@ import { serverMetadata } from "../Server/data/servers";
import { LocationName } from "../Locations/data/LocationNames"; import { LocationName } from "../Locations/data/LocationNames";
import { Company } from "../Company/Company"; import { Company } from "../Company/Company";
import { CompanyPosition } from "../Company/CompanyPosition"; import { CompanyPosition } from "../Company/CompanyPosition";
import { checkEnum } from "../utils/helpers/enum";
const gameCPS = 1000 / CONSTANTS._idleSpeed; // 5 cycles per second const gameCPS = 1000 / CONSTANTS._idleSpeed; // 5 cycles per second
export const FactionWorkStats: Record<FactionWorkType, WorkStats> = { export const FactionWorkStats: Record<FactionWorkType, WorkStats> = {
[FactionWorkType.HACKING]: newWorkStats({ hackExp: 15 }), [FactionWorkType.hacking]: newWorkStats({ hackExp: 15 }),
[FactionWorkType.FIELD]: newWorkStats({ [FactionWorkType.field]: newWorkStats({
hackExp: 10, hackExp: 10,
strExp: 10, strExp: 10,
defExp: 10, defExp: 10,
@ -31,7 +32,7 @@ export const FactionWorkStats: Record<FactionWorkType, WorkStats> = {
agiExp: 10, agiExp: 10,
chaExp: 10, chaExp: 10,
}), }),
[FactionWorkType.SECURITY]: newWorkStats({ [FactionWorkType.security]: newWorkStats({
hackExp: 5, hackExp: 5,
strExp: 15, strExp: 15,
defExp: 15, defExp: 15,
@ -66,9 +67,9 @@ export function calculateCrimeWorkStats(person: IPerson, crime: Crime): WorkStat
/** @returns faction rep rate per cycle */ /** @returns faction rep rate per cycle */
export const calculateFactionRep = (person: IPerson, type: FactionWorkType, favor: number): number => { export const calculateFactionRep = (person: IPerson, type: FactionWorkType, favor: number): number => {
const repFormulas = { const repFormulas = {
[FactionWorkType.HACKING]: getHackingWorkRepGain, [FactionWorkType.hacking]: getHackingWorkRepGain,
[FactionWorkType.FIELD]: getFactionFieldWorkRepGain, [FactionWorkType.field]: getFactionFieldWorkRepGain,
[FactionWorkType.SECURITY]: getFactionSecurityWorkRepGain, [FactionWorkType.security]: getFactionSecurityWorkRepGain,
}; };
return repFormulas[type](person, favor); return repFormulas[type](person, favor);
}; };
@ -95,11 +96,7 @@ export function calculateClassEarnings(person: IPerson, type: ClassType, locatio
const classs = Classes[type]; const classs = Classes[type];
const location = Locations[locationName]; const location = Locations[locationName];
const hashMult = [ClassType.GymAgility, ClassType.GymDefense, ClassType.GymStrength, ClassType.GymDexterity].includes( const hashMult = checkEnum(GymType, type) ? hashManager.getTrainingMult() : hashManager.getStudyMult();
type,
)
? hashManager.getTrainingMult()
: hashManager.getStudyMult();
const earnings = multWorkStats( const earnings = multWorkStats(
scaleWorkStats(classs.earnings, (location.expMult / gameCPS) * hashMult, false), scaleWorkStats(classs.earnings, (location.expMult / gameCPS) * hashMult, false),

View File

@ -1,5 +0,0 @@
export enum FactionWorkType {
HACKING = "HACKING",
FIELD = "FIELD",
SECURITY = "SECURITY",
}

View File

@ -1,20 +1,13 @@
/** Construct a type using the values from an object. Requires object to be defined "as const" */ /** Status object for functions that return a boolean indicating success/failure
export type ValuesFrom<T> = T[keyof T]; * and an optional message */
/**
* Status object for functions that return a boolean indicating success/failure
* and an optional message
*/
export interface IReturnStatus { export interface IReturnStatus {
res: boolean; res: boolean;
msg?: string; 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 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 { export interface IMinMaxRange {
/** Value by which the bounds are to be divided for the final range */ /** Value by which the bounds are to be divided for the final range */
divisor?: number; divisor?: number;

View File

@ -24,7 +24,7 @@ import { WorkStats } from "../Work/WorkStats";
import { isCreateProgramWork } from "../Work/CreateProgramWork"; import { isCreateProgramWork } from "../Work/CreateProgramWork";
import { isGraftingWork } from "../Work/GraftingWork"; import { isGraftingWork } from "../Work/GraftingWork";
import { isFactionWork } from "../Work/FactionWork"; import { isFactionWork } from "../Work/FactionWork";
import { FactionWorkType } from "../Work/data/FactionWorkType"; import { FactionWorkType } from "../utils/enums";
import { isCompanyWork } from "../Work/CompanyWork"; import { isCompanyWork } from "../Work/CompanyWork";
const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle; const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle;
@ -394,9 +394,9 @@ export function WorkInProgressRoot(): React.ReactElement {
} }
const description = { const description = {
[FactionWorkType.HACKING]: "carrying out hacking contracts", [FactionWorkType.hacking]: "carrying out hacking contracts",
[FactionWorkType.FIELD]: "carrying out field missions", [FactionWorkType.field]: "carrying out field missions",
[FactionWorkType.SECURITY]: "performing security detail", [FactionWorkType.security]: "performing security detail",
}; };
const exp = Player.currentWork.getExpRates(); const exp = Player.currentWork.getExpRates();

View File

@ -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 { export enum CompanyPosNames {
sw0 = "Software Engineering Intern", sw0 = "Software Engineering Intern",
sw1 = "Junior Software Engineer", sw1 = "Junior Software Engineer",
@ -53,3 +38,41 @@ export enum CompanyPosNames {
waiterPT = "Part-time Waiter", waiterPT = "Part-time Waiter",
employeePT = "Part-time Employee", 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",
}

View File

@ -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<T extends Record<string, unknown>>(obj: T, value: unknown): value is T[keyof T] {
return Object.values(obj).includes(value);
}

11
src/utils/helpers/enum.ts Normal file
View File

@ -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<T extends Record<string, unknown>>(obj: T, value: unknown): value is T[keyof T] {
return Object.values(obj).includes(value);
}
export function findEnumMember<T extends Record<string, string>>(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;
}
}