Merge branch 'dev' of github.com:danielyxie/bitburner into fix/nfg-level-application

This commit is contained in:
nickofolas 2022-05-05 08:34:26 -05:00
commit 6d9dcfe81f
24 changed files with 878 additions and 830 deletions

4
dist/main.bundle.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

42
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -24,6 +24,7 @@ import { IMap } from "../types";
import * as data from "./AchievementData.json"; import * as data from "./AchievementData.json";
import { FactionNames } from "../Faction/data/FactionNames"; import { FactionNames } from "../Faction/data/FactionNames";
import { BlackOperationNames } from "../Bladeburner/data/BlackOperationNames"; import { BlackOperationNames } from "../Bladeburner/data/BlackOperationNames";
import { ClassType } from "../utils/WorkType";
// Unable to correctly cast the JSON data into AchievementDataJson type otherwise... // Unable to correctly cast the JSON data into AchievementDataJson type otherwise...
const achievementData = (<AchievementDataJson>(<unknown>data)).achievements; const achievementData = (<AchievementDataJson>(<unknown>data)).achievements;
@ -391,12 +392,9 @@ export const achievements: IMap<Achievement> = {
...achievementData["WORKOUT"], ...achievementData["WORKOUT"],
Icon: "WORKOUT", Icon: "WORKOUT",
Condition: () => Condition: () =>
[ [ClassType.GymStrength, ClassType.GymDefense, ClassType.GymDexterity, ClassType.GymAgility].includes(
CONSTANTS.ClassGymStrength, Player.className,
CONSTANTS.ClassGymDefense, ),
CONSTANTS.ClassGymDexterity,
CONSTANTS.ClassGymAgility,
].includes(Player.className),
}, },
TOR: { TOR: {
...achievementData["TOR"], ...achievementData["TOR"],

@ -63,26 +63,6 @@ export const CONSTANTS: {
GameCyclesPerQuarterHour: number; GameCyclesPerQuarterHour: number;
MillisecondsPerFiveMinutes: number; MillisecondsPerFiveMinutes: number;
GameCyclesPerFiveMinutes: number; GameCyclesPerFiveMinutes: number;
FactionWorkHacking: string;
FactionWorkField: string;
FactionWorkSecurity: string;
WorkTypeCompany: string;
WorkTypeCompanyPartTime: string;
WorkTypeFaction: string;
WorkTypeCreateProgram: string;
WorkTypeStudyClass: string;
WorkTypeCrime: string;
WorkTypeGraftAugmentation: string;
ClassStudyComputerScience: string;
ClassDataStructures: string;
ClassNetworks: string;
ClassAlgorithms: string;
ClassManagement: string;
ClassLeadership: string;
ClassGymStrength: string;
ClassGymDefense: string;
ClassGymDexterity: string;
ClassGymAgility: string;
ClassDataStructuresBaseCost: number; ClassDataStructuresBaseCost: number;
ClassNetworksBaseCost: number; ClassNetworksBaseCost: number;
ClassAlgorithmsBaseCost: number; ClassAlgorithmsBaseCost: number;
@ -95,18 +75,6 @@ export const CONSTANTS: {
ClassAlgorithmsBaseExp: number; ClassAlgorithmsBaseExp: number;
ClassManagementBaseExp: number; ClassManagementBaseExp: number;
ClassLeadershipBaseExp: number; ClassLeadershipBaseExp: number;
CrimeShoplift: string;
CrimeRobStore: string;
CrimeMug: string;
CrimeLarceny: string;
CrimeDrugs: string;
CrimeBondForgery: string;
CrimeTraffickArms: string;
CrimeHomicide: string;
CrimeGrandTheftAuto: string;
CrimeKidnap: string;
CrimeAssassination: string;
CrimeHeist: string;
CodingContractBaseFactionRepGain: number; CodingContractBaseFactionRepGain: number;
CodingContractBaseCompanyRepGain: number; CodingContractBaseCompanyRepGain: number;
CodingContractBaseMoneyGain: number; CodingContractBaseMoneyGain: number;
@ -223,28 +191,6 @@ export const CONSTANTS: {
// Player Work & Action // Player Work & Action
BaseFocusBonus: 0.8, BaseFocusBonus: 0.8,
FactionWorkHacking: "Faction Hacking Work",
FactionWorkField: "Faction Field Work",
FactionWorkSecurity: "Faction Security Work",
WorkTypeCompany: "Working for Company",
WorkTypeCompanyPartTime: "Working for Company part-time",
WorkTypeFaction: "Working for Faction",
WorkTypeCreateProgram: "Working on Create a Program",
WorkTypeStudyClass: "Studying or Taking a class at university",
WorkTypeCrime: "Committing a crime",
WorkTypeGraftAugmentation: "Grafting an Augmentation",
ClassStudyComputerScience: "studying Computer Science",
ClassDataStructures: "taking a Data Structures course",
ClassNetworks: "taking a Networks course",
ClassAlgorithms: "taking an Algorithms course",
ClassManagement: "taking a Management course",
ClassLeadership: "taking a Leadership course",
ClassGymStrength: "training your strength at a gym",
ClassGymDefense: "training your defense at a gym",
ClassGymDexterity: "training your dexterity at a gym",
ClassGymAgility: "training your agility at a gym",
ClassDataStructuresBaseCost: 40, ClassDataStructuresBaseCost: 40,
ClassNetworksBaseCost: 80, ClassNetworksBaseCost: 80,
@ -260,19 +206,6 @@ export const CONSTANTS: {
ClassManagementBaseExp: 2, ClassManagementBaseExp: 2,
ClassLeadershipBaseExp: 4, ClassLeadershipBaseExp: 4,
CrimeShoplift: "shoplift",
CrimeRobStore: "rob a store",
CrimeMug: "mug someone",
CrimeLarceny: "commit larceny",
CrimeDrugs: "deal drugs",
CrimeBondForgery: "forge corporate bonds",
CrimeTraffickArms: "traffick illegal arms",
CrimeHomicide: "commit homicide",
CrimeGrandTheftAuto: "commit grand theft auto",
CrimeKidnap: "kidnap someone for ransom",
CrimeAssassination: "assassinate a high-profile target",
CrimeHeist: "pull off the ultimate heist",
// Coding Contract // Coding Contract
// TODO: Move this into Coding contract implementation? // TODO: Move this into Coding contract implementation?
CodingContractBaseFactionRepGain: 2500, CodingContractBaseFactionRepGain: 2500,

@ -3,6 +3,7 @@ import { IPlayer } from "../PersonObjects/IPlayer";
import { IPlayerOrSleeve } from "../PersonObjects/IPlayerOrSleeve"; import { IPlayerOrSleeve } from "../PersonObjects/IPlayerOrSleeve";
import { IRouter } from "../ui/Router"; import { IRouter } from "../ui/Router";
import { WorkerScript } from "../Netscript/WorkerScript"; import { WorkerScript } from "../Netscript/WorkerScript";
import { CrimeType } from "../utils/WorkType";
interface IConstructorParams { interface IConstructorParams {
hacking_success_weight?: number; hacking_success_weight?: number;
@ -42,7 +43,7 @@ export class Crime {
time = 0; time = 0;
// Corresponding type in CONSTANTS. Contains a description for the crime activity // Corresponding type in CONSTANTS. Contains a description for the crime activity
type = ""; 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;
@ -61,7 +62,15 @@ export class Crime {
charisma_exp = 0; charisma_exp = 0;
intelligence_exp = 0; intelligence_exp = 0;
constructor(name = "", type = "", time = 0, money = 0, difficulty = 0, karma = 0, params: IConstructorParams = {}) { constructor(
name = "",
type: CrimeType,
time = 0,
money = 0,
difficulty = 0,
karma = 0,
params: IConstructorParams = {},
) {
this.name = name; this.name = name;
this.type = type; this.type = type;
this.time = time; this.time = time;

@ -9,7 +9,7 @@ export function determineCrimeSuccess(p: IPlayer, type: string): boolean {
let found = false; let found = false;
for (const i of Object.keys(Crimes)) { for (const i of Object.keys(Crimes)) {
const crime = Crimes[i]; const crime = Crimes[i];
if (crime.type == type) { if (crime.type === type) {
chance = crime.successRate(p); chance = crime.successRate(p);
found = true; found = true;
break; break;

@ -3,8 +3,10 @@ import { Crime } from "./Crime";
import { CONSTANTS } from "../Constants"; import { CONSTANTS } from "../Constants";
import { IMap } from "../types"; import { IMap } from "../types";
import { CrimeType } from "../utils/WorkType";
export const Crimes: IMap<Crime> = { export const Crimes: IMap<Crime> = {
Shoplift: new Crime("Shoplift", CONSTANTS.CrimeShoplift, 2e3, 15e3, 1 / 20, 0.1, { Shoplift: new Crime("Shoplift", CrimeType.Shoplift, 2e3, 15e3, 1 / 20, 0.1, {
dexterity_success_weight: 1, dexterity_success_weight: 1,
agility_success_weight: 1, agility_success_weight: 1,
@ -12,7 +14,7 @@ export const Crimes: IMap<Crime> = {
agility_exp: 2, agility_exp: 2,
}), }),
RobStore: new Crime("Rob Store", CONSTANTS.CrimeRobStore, 60e3, 400e3, 1 / 5, 0.5, { RobStore: new Crime("Rob Store", CrimeType.RobStore, 60e3, 400e3, 1 / 5, 0.5, {
hacking_exp: 30, hacking_exp: 30,
dexterity_exp: 45, dexterity_exp: 45,
agility_exp: 45, agility_exp: 45,
@ -24,7 +26,7 @@ export const Crimes: IMap<Crime> = {
intelligence_exp: 7.5 * CONSTANTS.IntelligenceCrimeBaseExpGain, intelligence_exp: 7.5 * CONSTANTS.IntelligenceCrimeBaseExpGain,
}), }),
Mug: new Crime("Mug", CONSTANTS.CrimeMug, 4e3, 36e3, 1 / 5, 0.25, { Mug: new Crime("Mug", CrimeType.Mug, 4e3, 36e3, 1 / 5, 0.25, {
strength_exp: 3, strength_exp: 3,
defense_exp: 3, defense_exp: 3,
dexterity_exp: 3, dexterity_exp: 3,
@ -36,7 +38,7 @@ export const Crimes: IMap<Crime> = {
agility_success_weight: 0.5, agility_success_weight: 0.5,
}), }),
Larceny: new Crime("Larceny", CONSTANTS.CrimeLarceny, 90e3, 800e3, 1 / 3, 1.5, { Larceny: new Crime("Larceny", CrimeType.Larceny, 90e3, 800e3, 1 / 3, 1.5, {
hacking_exp: 45, hacking_exp: 45,
dexterity_exp: 60, dexterity_exp: 60,
agility_exp: 60, agility_exp: 60,
@ -48,7 +50,7 @@ export const Crimes: IMap<Crime> = {
intelligence_exp: 15 * CONSTANTS.IntelligenceCrimeBaseExpGain, intelligence_exp: 15 * CONSTANTS.IntelligenceCrimeBaseExpGain,
}), }),
DealDrugs: new Crime("Deal Drugs", CONSTANTS.CrimeDrugs, 10e3, 120e3, 1, 0.5, { DealDrugs: new Crime("Deal Drugs", CrimeType.Drugs, 10e3, 120e3, 1, 0.5, {
dexterity_exp: 5, dexterity_exp: 5,
agility_exp: 5, agility_exp: 5,
charisma_exp: 10, charisma_exp: 10,
@ -58,7 +60,7 @@ export const Crimes: IMap<Crime> = {
agility_success_weight: 1, agility_success_weight: 1,
}), }),
BondForgery: new Crime("Bond Forgery", CONSTANTS.CrimeBondForgery, 300e3, 4.5e6, 1 / 2, 0.1, { BondForgery: new Crime("Bond Forgery", CrimeType.BondForgery, 300e3, 4.5e6, 1 / 2, 0.1, {
hacking_exp: 100, hacking_exp: 100,
dexterity_exp: 150, dexterity_exp: 150,
charisma_exp: 15, charisma_exp: 15,
@ -69,7 +71,7 @@ export const Crimes: IMap<Crime> = {
intelligence_exp: 60 * CONSTANTS.IntelligenceCrimeBaseExpGain, intelligence_exp: 60 * CONSTANTS.IntelligenceCrimeBaseExpGain,
}), }),
TraffickArms: new Crime("Traffick Arms", CONSTANTS.CrimeTraffickArms, 40e3, 600e3, 2, 1, { TraffickArms: new Crime("Traffick Arms", CrimeType.TraffickArms, 40e3, 600e3, 2, 1, {
strength_exp: 20, strength_exp: 20,
defense_exp: 20, defense_exp: 20,
dexterity_exp: 20, dexterity_exp: 20,
@ -83,7 +85,7 @@ export const Crimes: IMap<Crime> = {
agility_success_weight: 1, agility_success_weight: 1,
}), }),
Homicide: new Crime("Homicide", CONSTANTS.CrimeHomicide, 3e3, 45e3, 1, 3, { Homicide: new Crime("Homicide", CrimeType.Homicide, 3e3, 45e3, 1, 3, {
strength_exp: 2, strength_exp: 2,
defense_exp: 2, defense_exp: 2,
dexterity_exp: 2, dexterity_exp: 2,
@ -97,7 +99,7 @@ export const Crimes: IMap<Crime> = {
kills: 1, kills: 1,
}), }),
GrandTheftAuto: new Crime("Grand Theft Auto", CONSTANTS.CrimeGrandTheftAuto, 80e3, 1.6e6, 8, 5, { GrandTheftAuto: new Crime("Grand Theft Auto", CrimeType.GrandTheftAuto, 80e3, 1.6e6, 8, 5, {
strength_exp: 20, strength_exp: 20,
defense_exp: 20, defense_exp: 20,
dexterity_exp: 20, dexterity_exp: 20,
@ -113,7 +115,7 @@ export const Crimes: IMap<Crime> = {
intelligence_exp: 16 * CONSTANTS.IntelligenceCrimeBaseExpGain, intelligence_exp: 16 * CONSTANTS.IntelligenceCrimeBaseExpGain,
}), }),
Kidnap: new Crime("Kidnap", CONSTANTS.CrimeKidnap, 120e3, 3.6e6, 5, 6, { Kidnap: new Crime("Kidnap", CrimeType.Kidnap, 120e3, 3.6e6, 5, 6, {
strength_exp: 80, strength_exp: 80,
defense_exp: 80, defense_exp: 80,
dexterity_exp: 80, dexterity_exp: 80,
@ -128,7 +130,7 @@ export const Crimes: IMap<Crime> = {
intelligence_exp: 26 * CONSTANTS.IntelligenceCrimeBaseExpGain, intelligence_exp: 26 * CONSTANTS.IntelligenceCrimeBaseExpGain,
}), }),
Assassination: new Crime("Assassination", CONSTANTS.CrimeAssassination, 300e3, 12e6, 8, 10, { Assassination: new Crime("Assassination", CrimeType.Assassination, 300e3, 12e6, 8, 10, {
strength_exp: 300, strength_exp: 300,
defense_exp: 300, defense_exp: 300,
dexterity_exp: 300, dexterity_exp: 300,
@ -143,7 +145,7 @@ export const Crimes: IMap<Crime> = {
kills: 1, kills: 1,
}), }),
Heist: new Crime("Heist", CONSTANTS.CrimeHeist, 600e3, 120e6, 18, 15, { Heist: new Crime("Heist", CrimeType.Heist, 600e3, 120e6, 18, 15, {
hacking_exp: 450, hacking_exp: 450,
strength_exp: 450, strength_exp: 450,
defense_exp: 450, defense_exp: 450,

@ -1,19 +1,8 @@
import { LinearProgress, Paper } from "@mui/material"; import { Paper } from "@mui/material";
import { Theme } from "@mui/material/styles";
import withStyles from "@mui/styles/withStyles";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames"; import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { use } from "../../ui/Context"; import { use } from "../../ui/Context";
import { ProgressBar } from "../../ui/React/Progress";
const TimerProgress = withStyles((theme: Theme) => ({
root: {
backgroundColor: theme.palette.background.paper,
},
bar: {
transition: "none",
backgroundColor: theme.palette.primary.main,
},
}))(LinearProgress);
interface IProps { interface IProps {
millis: number; millis: number;
@ -43,10 +32,10 @@ export function GameTimer(props: IProps): React.ReactElement {
// TODO(hydroflame): there's like a bug where it triggers the end before the // TODO(hydroflame): there's like a bug where it triggers the end before the
// bar physically reaches the end // bar physically reaches the end
return props.noPaper ? ( return props.noPaper ? (
<TimerProgress variant="determinate" value={v} color="primary" /> <ProgressBar variant="determinate" value={v} color="primary" />
) : ( ) : (
<Paper sx={{ p: 1, mb: 1 }}> <Paper sx={{ p: 1, mb: 1 }}>
<TimerProgress variant="determinate" value={v} color="primary" /> <ProgressBar variant="determinate" value={v} color="primary" />
</Paper> </Paper>
); );
} }

@ -17,6 +17,7 @@ import { Money } from "../../ui/React/Money";
import { IRouter } from "../../ui/Router"; import { IRouter } from "../../ui/Router";
import { serverMetadata } from "../../Server/data/servers"; import { serverMetadata } from "../../Server/data/servers";
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import { ClassType } from "../../utils/WorkType";
type IProps = { type IProps = {
loc: Location; loc: Location;
@ -33,7 +34,7 @@ export function GymLocation(props: IProps): React.ReactElement {
return props.loc.costMult * discount; return props.loc.costMult * discount;
} }
function train(stat: string): void { function train(stat: ClassType): void {
const loc = props.loc; const loc = props.loc;
props.p.startClass(calculateCost(), loc.expMult, stat); props.p.startClass(calculateCost(), loc.expMult, stat);
props.p.startFocusing(); props.p.startFocusing();
@ -41,19 +42,19 @@ export function GymLocation(props: IProps): React.ReactElement {
} }
function trainStrength(): void { function trainStrength(): void {
train(CONSTANTS.ClassGymStrength); train(ClassType.GymStrength);
} }
function trainDefense(): void { function trainDefense(): void {
train(CONSTANTS.ClassGymDefense); train(ClassType.GymDefense);
} }
function trainDexterity(): void { function trainDexterity(): void {
train(CONSTANTS.ClassGymDexterity); train(ClassType.GymDexterity);
} }
function trainAgility(): void { function trainAgility(): void {
train(CONSTANTS.ClassGymAgility); train(ClassType.GymAgility);
} }
const cost = CONSTANTS.ClassGymBaseCost * calculateCost(); const cost = CONSTANTS.ClassGymBaseCost * calculateCost();

@ -17,6 +17,8 @@ import { Money } from "../../ui/React/Money";
import { use } from "../../ui/Context"; import { use } from "../../ui/Context";
import { Box } from "@mui/material"; import { Box } from "@mui/material";
import { ClassType } from "../../utils/WorkType";
type IProps = { type IProps = {
loc: Location; loc: Location;
}; };
@ -32,7 +34,7 @@ export function UniversityLocation(props: IProps): React.ReactElement {
return props.loc.costMult * discount; return props.loc.costMult * discount;
} }
function take(stat: string): void { function take(stat: ClassType): void {
const loc = props.loc; const loc = props.loc;
player.startClass(calculateCost(), loc.expMult, stat); player.startClass(calculateCost(), loc.expMult, stat);
player.startFocusing(); player.startFocusing();
@ -40,27 +42,27 @@ export function UniversityLocation(props: IProps): React.ReactElement {
} }
function study(): void { function study(): void {
take(CONSTANTS.ClassStudyComputerScience); take(ClassType.StudyComputerScience);
} }
function dataStructures(): void { function dataStructures(): void {
take(CONSTANTS.ClassDataStructures); take(ClassType.DataStructures);
} }
function networks(): void { function networks(): void {
take(CONSTANTS.ClassNetworks); take(ClassType.Networks);
} }
function algorithms(): void { function algorithms(): void {
take(CONSTANTS.ClassAlgorithms); take(ClassType.Algorithms);
} }
function management(): void { function management(): void {
take(CONSTANTS.ClassManagement); take(ClassType.Management);
} }
function leadership(): void { function leadership(): void {
take(CONSTANTS.ClassLeadership); take(ClassType.Leadership);
} }
const costMult: number = calculateCost(); const costMult: number = calculateCost();

@ -49,6 +49,7 @@ 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 { ClassType, WorkType } from "../utils/WorkType";
export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript): InternalAPI<ISingularity> { export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript): InternalAPI<ISingularity> {
const getAugmentation = function (_ctx: NetscriptContext, name: string): Augmentation { const getAugmentation = function (_ctx: NetscriptContext, name: string): Augmentation {
@ -298,25 +299,25 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
return false; return false;
} }
let task = ""; let task: ClassType;
switch (className.toLowerCase()) { switch (className.toLowerCase()) {
case "Study Computer Science".toLowerCase(): case "Study Computer Science".toLowerCase():
task = CONSTANTS.ClassStudyComputerScience; task = ClassType.StudyComputerScience;
break; break;
case "Data Structures".toLowerCase(): case "Data Structures".toLowerCase():
task = CONSTANTS.ClassDataStructures; task = ClassType.DataStructures;
break; break;
case "Networks".toLowerCase(): case "Networks".toLowerCase():
task = CONSTANTS.ClassNetworks; task = ClassType.Networks;
break; break;
case "Algorithms".toLowerCase(): case "Algorithms".toLowerCase():
task = CONSTANTS.ClassAlgorithms; task = ClassType.Algorithms;
break; break;
case "Management".toLowerCase(): case "Management".toLowerCase():
task = CONSTANTS.ClassManagement; task = ClassType.Management;
break; break;
case "Leadership".toLowerCase(): case "Leadership".toLowerCase():
task = CONSTANTS.ClassLeadership; task = ClassType.Leadership;
break; break;
default: default:
_ctx.log(() => `Invalid class name: ${className}.`); _ctx.log(() => `Invalid class name: ${className}.`);
@ -415,19 +416,19 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
switch (stat.toLowerCase()) { switch (stat.toLowerCase()) {
case "strength".toLowerCase(): case "strength".toLowerCase():
case "str".toLowerCase(): case "str".toLowerCase():
player.startClass(costMult, expMult, CONSTANTS.ClassGymStrength); player.startClass(costMult, expMult, ClassType.GymStrength);
break; break;
case "defense".toLowerCase(): case "defense".toLowerCase():
case "def".toLowerCase(): case "def".toLowerCase():
player.startClass(costMult, expMult, CONSTANTS.ClassGymDefense); player.startClass(costMult, expMult, ClassType.GymDefense);
break; break;
case "dexterity".toLowerCase(): case "dexterity".toLowerCase():
case "dex".toLowerCase(): case "dex".toLowerCase():
player.startClass(costMult, expMult, CONSTANTS.ClassGymDexterity); player.startClass(costMult, expMult, ClassType.GymDexterity);
break; break;
case "agility".toLowerCase(): case "agility".toLowerCase():
case "agi".toLowerCase(): case "agi".toLowerCase():
player.startClass(costMult, expMult, CONSTANTS.ClassGymAgility); player.startClass(costMult, expMult, ClassType.GymAgility);
break; break;
default: default:
_ctx.log(() => `Invalid stat: ${stat}.`); _ctx.log(() => `Invalid stat: ${stat}.`);
@ -650,11 +651,11 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
} }
if ( if (
!( !(
player.workType == CONSTANTS.WorkTypeFaction || player.workType === WorkType.Faction ||
player.workType == CONSTANTS.WorkTypeCompany || player.workType === WorkType.Company ||
player.workType == CONSTANTS.WorkTypeCompanyPartTime || player.workType === WorkType.CompanyPartTime ||
player.workType == CONSTANTS.WorkTypeCreateProgram || player.workType === WorkType.CreateProgram ||
player.workType == CONSTANTS.WorkTypeStudyClass player.workType === WorkType.StudyClass
) )
) { ) {
throw _ctx.helper.makeRuntimeErrorMsg("Cannot change focus for current job"); throw _ctx.helper.makeRuntimeErrorMsg("Cannot change focus for current job");

@ -30,6 +30,7 @@ import { WorkerScript } from "../Netscript/WorkerScript";
import { HacknetServer } from "../Hacknet/HacknetServer"; import { HacknetServer } from "../Hacknet/HacknetServer";
import { ISkillProgress } from "./formulas/skill"; import { ISkillProgress } from "./formulas/skill";
import { PlayerAchievement } from "../Achievements/Achievements"; import { PlayerAchievement } from "../Achievements/Achievements";
import { WorkType, ClassType, CrimeType } from "../utils/WorkType";
export interface IPlayer { export interface IPlayer {
// Class members // Class members
@ -130,14 +131,14 @@ export interface IPlayer {
timeWorkedCreateProgram: number; timeWorkedCreateProgram: number;
graftAugmentationName: string; graftAugmentationName: string;
timeWorkedGraftAugmentation: number; timeWorkedGraftAugmentation: number;
crimeType: string; crimeType: CrimeType;
committingCrimeThruSingFn: boolean; committingCrimeThruSingFn: boolean;
singFnCrimeWorkerScript: WorkerScript | null; singFnCrimeWorkerScript: WorkerScript | null;
timeNeededToCompleteWork: number; timeNeededToCompleteWork: number;
focus: boolean; focus: boolean;
className: string; className: ClassType;
currentWorkFactionName: string; currentWorkFactionName: string;
workType: string; workType: WorkType;
workCostMult: number; workCostMult: number;
workExpMult: number; workExpMult: number;
currentWorkFactionDescription: string; currentWorkFactionDescription: string;
@ -219,11 +220,11 @@ export interface IPlayer {
singularityStopWork(): string; singularityStopWork(): string;
startBladeburner(p: any): void; startBladeburner(p: any): void;
startFactionWork(faction: Faction): void; startFactionWork(faction: Faction): void;
startClass(costMult: number, expMult: number, className: string): void; startClass(costMult: number, expMult: number, className: ClassType): void;
startCorporation(corpName: string, additionalShares?: number): void; startCorporation(corpName: string, additionalShares?: number): void;
startCrime( startCrime(
router: IRouter, router: IRouter,
crimeType: string, crimeType: CrimeType,
hackExp: number, hackExp: number,
strExp: number, strExp: number,
defExp: number, defExp: number,
@ -269,7 +270,7 @@ export interface IPlayer {
prestigeSourceFile(): void; prestigeSourceFile(): void;
calculateSkill(exp: number, mult?: number): number; calculateSkill(exp: number, mult?: number): number;
calculateSkillProgress(exp: number, mult?: number): ISkillProgress; calculateSkillProgress(exp: number, mult?: number): ISkillProgress;
resetWorkStatus(generalType?: string, group?: string, workType?: string): void; resetWorkStatus(generalType?: WorkType, group?: string, workType?: string): void;
getWorkHackExpGain(): number; getWorkHackExpGain(): number;
getWorkStrExpGain(): number; getWorkStrExpGain(): number;
getWorkDefExpGain(): number; getWorkDefExpGain(): number;

@ -38,6 +38,7 @@ import { PlayerAchievement } from "../../Achievements/Achievements";
import { cyrb53 } from "../../utils/StringHelperFunctions"; import { cyrb53 } from "../../utils/StringHelperFunctions";
import { getRandomInt } from "../../utils/helpers/getRandomInt"; import { getRandomInt } from "../../utils/helpers/getRandomInt";
import { CONSTANTS } from "../../Constants"; import { CONSTANTS } from "../../Constants";
import { WorkType, ClassType, CrimeType, PlayerFactionWorkType } from "../../utils/WorkType";
export class PlayerObject implements IPlayer { export class PlayerObject implements IPlayer {
// Class members // Class members
@ -135,19 +136,19 @@ export class PlayerObject implements IPlayer {
bladeburner_success_chance_mult: number; bladeburner_success_chance_mult: number;
createProgramReqLvl: number; createProgramReqLvl: number;
factionWorkType: string; factionWorkType: PlayerFactionWorkType;
createProgramName: string; createProgramName: string;
timeWorkedCreateProgram: number; timeWorkedCreateProgram: number;
graftAugmentationName: string; graftAugmentationName: string;
timeWorkedGraftAugmentation: number; timeWorkedGraftAugmentation: number;
crimeType: string; crimeType: CrimeType;
committingCrimeThruSingFn: boolean; committingCrimeThruSingFn: boolean;
singFnCrimeWorkerScript: WorkerScript | null; singFnCrimeWorkerScript: WorkerScript | null;
timeNeededToCompleteWork: number; timeNeededToCompleteWork: number;
focus: boolean; focus: boolean;
className: string; className: ClassType;
currentWorkFactionName: string; currentWorkFactionName: string;
workType: string; workType: WorkType;
workCostMult: number; workCostMult: number;
workExpMult: number; workExpMult: number;
currentWorkFactionDescription: string; currentWorkFactionDescription: string;
@ -229,11 +230,11 @@ export class PlayerObject implements IPlayer {
singularityStopWork: () => string; singularityStopWork: () => string;
startBladeburner: (p: any) => void; startBladeburner: (p: any) => void;
startFactionWork: (faction: Faction) => void; startFactionWork: (faction: Faction) => void;
startClass: (costMult: number, expMult: number, className: string) => void; startClass: (costMult: number, expMult: number, className: ClassType) => void;
startCorporation: (corpName: string, additionalShares?: number) => void; startCorporation: (corpName: string, additionalShares?: number) => void;
startCrime: ( startCrime: (
router: IRouter, router: IRouter,
crimeType: string, crimeType: CrimeType,
hackExp: number, hackExp: number,
strExp: number, strExp: number,
defExp: number, defExp: number,
@ -280,7 +281,7 @@ export class PlayerObject implements IPlayer {
prestigeSourceFile: () => void; prestigeSourceFile: () => void;
calculateSkill: (exp: number, mult?: number) => number; calculateSkill: (exp: number, mult?: number) => number;
calculateSkillProgress: (exp: number, mult?: number) => ISkillProgress; calculateSkillProgress: (exp: number, mult?: number) => ISkillProgress;
resetWorkStatus: (generalType?: string, group?: string, workType?: string) => void; resetWorkStatus: (generalType?: WorkType, group?: string, workType?: string) => void;
getWorkHackExpGain: () => number; getWorkHackExpGain: () => number;
getWorkStrExpGain: () => number; getWorkStrExpGain: () => number;
getWorkDefExpGain: () => number; getWorkDefExpGain: () => number;
@ -398,7 +399,7 @@ export class PlayerObject implements IPlayer {
//Flags/variables for working (Company, Faction, Creating Program, Taking Class) //Flags/variables for working (Company, Faction, Creating Program, Taking Class)
this.isWorking = false; this.isWorking = false;
this.focus = false; this.focus = false;
this.workType = ""; this.workType = WorkType.None;
this.workCostMult = 1; this.workCostMult = 1;
this.workExpMult = 1; this.workExpMult = 1;
@ -430,9 +431,9 @@ export class PlayerObject implements IPlayer {
this.graftAugmentationName = ""; this.graftAugmentationName = "";
this.timeWorkedGraftAugmentation = 0; this.timeWorkedGraftAugmentation = 0;
this.className = ""; this.className = ClassType.None;
this.crimeType = ""; this.crimeType = CrimeType.None;
this.timeWorked = 0; //in m; this.timeWorked = 0; //in m;
this.timeWorkedCreateProgram = 0; this.timeWorkedCreateProgram = 0;
@ -618,7 +619,7 @@ export class PlayerObject implements IPlayer {
this.getUpgradeHomeRamCost = serverMethods.getUpgradeHomeRamCost; this.getUpgradeHomeRamCost = serverMethods.getUpgradeHomeRamCost;
this.getUpgradeHomeCoresCost = serverMethods.getUpgradeHomeCoresCost; this.getUpgradeHomeCoresCost = serverMethods.getUpgradeHomeCoresCost;
this.createHacknetServer = serverMethods.createHacknetServer; this.createHacknetServer = serverMethods.createHacknetServer;
this.factionWorkType = ""; this.factionWorkType = PlayerFactionWorkType.None;
this.committingCrimeThruSingFn = false; this.committingCrimeThruSingFn = false;
this.singFnCrimeWorkerScript = null; this.singFnCrimeWorkerScript = null;

@ -66,6 +66,8 @@ import { achievements } from "../../Achievements/Achievements";
import { FactionNames } from "../../Faction/data/FactionNames"; import { FactionNames } from "../../Faction/data/FactionNames";
import { graftingIntBonus } from "../Grafting/GraftingHelpers"; import { graftingIntBonus } from "../Grafting/GraftingHelpers";
import { WorkType, PlayerFactionWorkType, ClassType, CrimeType } from "../../utils/WorkType";
export function init(this: IPlayer): void { export function init(this: IPlayer): void {
/* Initialize Player's home computer */ /* Initialize Player's home computer */
const t_homeComp = safetlyCreateUniqueServer({ const t_homeComp = safetlyCreateUniqueServer({
@ -140,8 +142,8 @@ export function prestigeAugmentation(this: PlayerObject): void {
this.currentWorkFactionName = ""; this.currentWorkFactionName = "";
this.currentWorkFactionDescription = ""; this.currentWorkFactionDescription = "";
this.createProgramName = ""; this.createProgramName = "";
this.className = ""; this.className = ClassType.None;
this.crimeType = ""; this.crimeType = CrimeType.None;
this.workHackExpGainRate = 0; this.workHackExpGainRate = 0;
this.workStrExpGainRate = 0; this.workStrExpGainRate = 0;
@ -500,9 +502,8 @@ export function queryStatFromString(this: IPlayer, str: string): number {
} }
/******* Working functions *******/ /******* Working functions *******/
export function resetWorkStatus(this: IPlayer, generalType?: string, group?: string, workType?: string): void { export function resetWorkStatus(this: IPlayer, generalType?: WorkType, group?: string, workType?: string): void {
if (this.workType !== CONSTANTS.WorkTypeFaction && generalType === this.workType && group === this.companyName) if (this.workType !== WorkType.Faction && generalType === this.workType && group === this.companyName) return;
return;
if (generalType === this.workType && group === this.currentWorkFactionName && workType === this.factionWorkType) if (generalType === this.workType && group === this.currentWorkFactionName && workType === this.factionWorkType)
return; return;
if (this.isWorking) this.singularityStopWork(); if (this.isWorking) this.singularityStopWork();
@ -533,8 +534,8 @@ export function resetWorkStatus(this: IPlayer, generalType?: string, group?: str
this.currentWorkFactionDescription = ""; this.currentWorkFactionDescription = "";
this.createProgramName = ""; this.createProgramName = "";
this.graftAugmentationName = ""; this.graftAugmentationName = "";
this.className = ""; this.className = ClassType.None;
this.workType = ""; this.workType = WorkType.None;
} }
export function processWorkEarnings(this: IPlayer, numCycles = 1): void { export function processWorkEarnings(this: IPlayer, numCycles = 1): void {
@ -569,10 +570,10 @@ export function processWorkEarnings(this: IPlayer, numCycles = 1): void {
/* Working for Company */ /* Working for Company */
export function startWork(this: IPlayer, companyName: string): void { export function startWork(this: IPlayer, companyName: string): void {
this.resetWorkStatus(CONSTANTS.WorkTypeCompany, companyName); this.resetWorkStatus(WorkType.Company, companyName);
this.isWorking = true; this.isWorking = true;
this.companyName = companyName; this.companyName = companyName;
this.workType = CONSTANTS.WorkTypeCompany; this.workType = WorkType.Company;
this.workHackExpGainRate = this.getWorkHackExpGain(); this.workHackExpGainRate = this.getWorkHackExpGain();
this.workStrExpGainRate = this.getWorkStrExpGain(); this.workStrExpGainRate = this.getWorkStrExpGain();
@ -589,27 +590,27 @@ export function startWork(this: IPlayer, companyName: string): void {
export function process(this: IPlayer, router: IRouter, numCycles = 1): void { export function process(this: IPlayer, router: IRouter, numCycles = 1): void {
// Working // Working
if (this.isWorking) { if (this.isWorking) {
if (this.workType == CONSTANTS.WorkTypeFaction) { if (this.workType === WorkType.Faction) {
if (this.workForFaction(numCycles)) { if (this.workForFaction(numCycles)) {
router.toFaction(Factions[this.currentWorkFactionName]); router.toFaction(Factions[this.currentWorkFactionName]);
} }
} else if (this.workType == CONSTANTS.WorkTypeCreateProgram) { } else if (this.workType === WorkType.CreateProgram) {
if (this.createProgramWork(numCycles)) { if (this.createProgramWork(numCycles)) {
router.toTerminal(); router.toTerminal();
} }
} else if (this.workType == CONSTANTS.WorkTypeStudyClass) { } else if (this.workType === WorkType.StudyClass) {
if (this.takeClass(numCycles)) { if (this.takeClass(numCycles)) {
router.toCity(); router.toCity();
} }
} else if (this.workType == CONSTANTS.WorkTypeCrime) { } else if (this.workType === WorkType.Crime) {
if (this.commitCrime(numCycles)) { if (this.commitCrime(numCycles)) {
router.toLocation(Locations[LocationName.Slums]); router.toLocation(Locations[LocationName.Slums]);
} }
} else if (this.workType == CONSTANTS.WorkTypeCompanyPartTime) { } else if (this.workType === WorkType.CompanyPartTime) {
if (this.workPartTime(numCycles)) { if (this.workPartTime(numCycles)) {
router.toCity(); router.toCity();
} }
} else if (this.workType === CONSTANTS.WorkTypeGraftAugmentation) { } else if (this.workType === WorkType.GraftAugmentation) {
if (this.graftAugmentationWork(numCycles)) { if (this.graftAugmentationWork(numCycles)) {
router.toGrafting(); router.toGrafting();
} }
@ -765,10 +766,10 @@ export function finishWork(this: IPlayer, cancelled: boolean, sing = false): str
} }
export function startWorkPartTime(this: IPlayer, companyName: string): void { export function startWorkPartTime(this: IPlayer, companyName: string): void {
this.resetWorkStatus(CONSTANTS.WorkTypeCompanyPartTime, companyName); this.resetWorkStatus(WorkType.CompanyPartTime, companyName);
this.isWorking = true; this.isWorking = true;
this.companyName = companyName; this.companyName = companyName;
this.workType = CONSTANTS.WorkTypeCompanyPartTime; this.workType = WorkType.CompanyPartTime;
this.workHackExpGainRate = this.getWorkHackExpGain(); this.workHackExpGainRate = this.getWorkHackExpGain();
this.workStrExpGainRate = this.getWorkStrExpGain(); this.workStrExpGainRate = this.getWorkStrExpGain();
@ -881,26 +882,26 @@ export function startFactionWork(this: IPlayer, faction: Faction): void {
this.workRepGainRate *= BitNodeMultipliers.FactionWorkRepGain; this.workRepGainRate *= BitNodeMultipliers.FactionWorkRepGain;
this.isWorking = true; this.isWorking = true;
this.workType = CONSTANTS.WorkTypeFaction; this.workType = WorkType.Faction;
this.currentWorkFactionName = faction.name; this.currentWorkFactionName = faction.name;
this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer20Hours; this.timeNeededToCompleteWork = CONSTANTS.MillisecondsPer20Hours;
} }
export function startFactionHackWork(this: IPlayer, faction: Faction): void { export function startFactionHackWork(this: IPlayer, faction: Faction): void {
this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkHacking); this.resetWorkStatus(WorkType.Faction, faction.name, PlayerFactionWorkType.Hacking);
this.workHackExpGainRate = 0.15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain; this.workHackExpGainRate = 0.15 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.workRepGainRate = getHackingWorkRepGain(this, faction); this.workRepGainRate = getHackingWorkRepGain(this, faction);
this.factionWorkType = CONSTANTS.FactionWorkHacking; this.factionWorkType = PlayerFactionWorkType.Hacking;
this.currentWorkFactionDescription = "carrying out hacking contracts"; this.currentWorkFactionDescription = "carrying out hacking contracts";
this.startFactionWork(faction); this.startFactionWork(faction);
} }
export function startFactionFieldWork(this: IPlayer, faction: Faction): void { export function startFactionFieldWork(this: IPlayer, faction: Faction): void {
this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkField); this.resetWorkStatus(WorkType.Faction, faction.name, PlayerFactionWorkType.Field);
this.workHackExpGainRate = 0.1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain; this.workHackExpGainRate = 0.1 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.workStrExpGainRate = 0.1 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain; this.workStrExpGainRate = 0.1 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
@ -910,14 +911,14 @@ export function startFactionFieldWork(this: IPlayer, faction: Faction): void {
this.workChaExpGainRate = 0.1 * this.charisma_exp_mult * BitNodeMultipliers.FactionWorkExpGain; this.workChaExpGainRate = 0.1 * this.charisma_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.workRepGainRate = getFactionFieldWorkRepGain(this, faction); this.workRepGainRate = getFactionFieldWorkRepGain(this, faction);
this.factionWorkType = CONSTANTS.FactionWorkField; this.factionWorkType = PlayerFactionWorkType.Field;
this.currentWorkFactionDescription = "carrying out field missions"; this.currentWorkFactionDescription = "carrying out field missions";
this.startFactionWork(faction); this.startFactionWork(faction);
} }
export function startFactionSecurityWork(this: IPlayer, faction: Faction): void { export function startFactionSecurityWork(this: IPlayer, faction: Faction): void {
this.resetWorkStatus(CONSTANTS.WorkTypeFaction, faction.name, CONSTANTS.FactionWorkSecurity); this.resetWorkStatus(WorkType.Faction, faction.name, PlayerFactionWorkType.Security);
this.workHackExpGainRate = 0.05 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain; this.workHackExpGainRate = 0.05 * this.hacking_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.workStrExpGainRate = 0.15 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain; this.workStrExpGainRate = 0.15 * this.strength_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
@ -927,7 +928,7 @@ export function startFactionSecurityWork(this: IPlayer, faction: Faction): void
this.workChaExpGainRate = 0.0 * this.charisma_exp_mult * BitNodeMultipliers.FactionWorkExpGain; this.workChaExpGainRate = 0.0 * this.charisma_exp_mult * BitNodeMultipliers.FactionWorkExpGain;
this.workRepGainRate = getFactionSecurityWorkRepGain(this, faction); this.workRepGainRate = getFactionSecurityWorkRepGain(this, faction);
this.factionWorkType = CONSTANTS.FactionWorkSecurity; this.factionWorkType = PlayerFactionWorkType.Security;
this.currentWorkFactionDescription = "performing security detail"; this.currentWorkFactionDescription = "performing security detail";
this.startFactionWork(faction); this.startFactionWork(faction);
@ -942,13 +943,13 @@ export function workForFaction(this: IPlayer, numCycles: number): boolean {
//Constantly update the rep gain rate //Constantly update the rep gain rate
switch (this.factionWorkType) { switch (this.factionWorkType) {
case CONSTANTS.FactionWorkHacking: case PlayerFactionWorkType.Hacking:
this.workRepGainRate = getHackingWorkRepGain(this, faction); this.workRepGainRate = getHackingWorkRepGain(this, faction);
break; break;
case CONSTANTS.FactionWorkField: case PlayerFactionWorkType.Field:
this.workRepGainRate = getFactionFieldWorkRepGain(this, faction); this.workRepGainRate = getFactionFieldWorkRepGain(this, faction);
break; break;
case CONSTANTS.FactionWorkSecurity: case PlayerFactionWorkType.Security:
this.workRepGainRate = getFactionSecurityWorkRepGain(this, faction); this.workRepGainRate = getFactionSecurityWorkRepGain(this, faction);
break; break;
default: default:
@ -1261,7 +1262,7 @@ export function getWorkRepGain(this: IPlayer): number {
export function startCreateProgramWork(this: IPlayer, programName: string, time: number, reqLevel: number): void { export function startCreateProgramWork(this: IPlayer, programName: string, time: number, reqLevel: number): void {
this.resetWorkStatus(); this.resetWorkStatus();
this.isWorking = true; this.isWorking = true;
this.workType = CONSTANTS.WorkTypeCreateProgram; this.workType = WorkType.CreateProgram;
//Time needed to complete work affected by hacking skill (linearly based on //Time needed to complete work affected by hacking skill (linearly based on
//ratio of (your skill - required level) to MAX skill) //ratio of (your skill - required level) to MAX skill)
@ -1338,7 +1339,7 @@ export function finishCreateProgramWork(this: IPlayer, cancelled: boolean): stri
export function startGraftAugmentationWork(this: IPlayer, augmentationName: string, time: number): void { export function startGraftAugmentationWork(this: IPlayer, augmentationName: string, time: number): void {
this.resetWorkStatus(); this.resetWorkStatus();
this.isWorking = true; this.isWorking = true;
this.workType = CONSTANTS.WorkTypeGraftAugmentation; this.workType = WorkType.GraftAugmentation;
this.timeNeededToCompleteWork = time; this.timeNeededToCompleteWork = time;
this.graftAugmentationName = augmentationName; this.graftAugmentationName = augmentationName;
@ -1392,10 +1393,10 @@ export function finishGraftAugmentationWork(this: IPlayer, cancelled: boolean, s
} }
/* Studying/Taking Classes */ /* Studying/Taking Classes */
export function startClass(this: IPlayer, costMult: number, expMult: number, className: string): void { export function startClass(this: IPlayer, costMult: number, expMult: number, className: ClassType): void {
this.resetWorkStatus(); this.resetWorkStatus();
this.isWorking = true; this.isWorking = true;
this.workType = CONSTANTS.WorkTypeStudyClass; this.workType = WorkType.StudyClass;
this.workCostMult = costMult; this.workCostMult = costMult;
this.workExpMult = expMult; this.workExpMult = expMult;
this.className = className; this.className = className;
@ -1487,7 +1488,7 @@ export function finishClass(this: IPlayer, sing = false): string {
export function startCrime( export function startCrime(
this: IPlayer, this: IPlayer,
router: IRouter, router: IRouter,
crimeType: string, crimeType: CrimeType,
hackExp: number, hackExp: number,
strExp: number, strExp: number,
defExp: number, defExp: number,
@ -1503,7 +1504,7 @@ export function startCrime(
this.resetWorkStatus(); this.resetWorkStatus();
this.isWorking = true; this.isWorking = true;
this.focus = true; this.focus = true;
this.workType = CONSTANTS.WorkTypeCrime; this.workType = WorkType.Crime;
if (workerscript !== null) { if (workerscript !== null) {
this.committingCrimeThruSingFn = true; this.committingCrimeThruSingFn = true;
@ -1668,7 +1669,7 @@ export function finishCrime(this: IPlayer, cancelled: boolean): string {
this.committingCrimeThruSingFn = false; this.committingCrimeThruSingFn = false;
this.singFnCrimeWorkerScript = null; this.singFnCrimeWorkerScript = null;
this.isWorking = false; this.isWorking = false;
this.crimeType = ""; this.crimeType = CrimeType.None;
this.resetWorkStatus(); this.resetWorkStatus();
return ""; return "";
} }
@ -1681,25 +1682,25 @@ export function singularityStopWork(this: IPlayer): string {
} }
let res = ""; //Earnings text for work let res = ""; //Earnings text for work
switch (this.workType) { switch (this.workType) {
case CONSTANTS.WorkTypeStudyClass: case WorkType.StudyClass:
res = this.finishClass(true); res = this.finishClass(true);
break; break;
case CONSTANTS.WorkTypeCompany: case WorkType.Company:
res = this.finishWork(true, true); res = this.finishWork(true, true);
break; break;
case CONSTANTS.WorkTypeCompanyPartTime: case WorkType.CompanyPartTime:
res = this.finishWorkPartTime(true); res = this.finishWorkPartTime(true);
break; break;
case CONSTANTS.WorkTypeFaction: case WorkType.Faction:
res = this.finishFactionWork(true, true); res = this.finishFactionWork(true, true);
break; break;
case CONSTANTS.WorkTypeCreateProgram: case WorkType.CreateProgram:
res = this.finishCreateProgramWork(true); res = this.finishCreateProgramWork(true);
break; break;
case CONSTANTS.WorkTypeCrime: case WorkType.Crime:
res = this.finishCrime(true); res = this.finishCrime(true);
break; break;
case CONSTANTS.WorkTypeGraftAugmentation: case WorkType.GraftAugmentation:
res = this.finishGraftAugmentationWork(true, true); res = this.finishGraftAugmentationWork(true, true);
break; break;
default: default:
@ -1793,7 +1794,7 @@ export function applyForJob(this: IPlayer, entryPosType: CompanyPosition, sing =
} }
this.jobs[company.name] = pos.name; this.jobs[company.name] = pos.name;
if (!this.isWorking || !this.workType.includes("Working for Company")) this.companyName = company.name; if (!this.isWorking || this.workType !== WorkType.Company) this.companyName = company.name;
if (!sing) { if (!sing) {
dialogBoxCreate("Congratulations! You were offered a new job at " + company.name + " as a " + pos.name + "!"); dialogBoxCreate("Congratulations! You were offered a new job at " + company.name + " as a " + pos.name + "!");
@ -1842,7 +1843,7 @@ export function getNextCompanyPosition(
} }
export function quitJob(this: IPlayer, company: string, _sing = false): void { export function quitJob(this: IPlayer, company: string, _sing = false): void {
if (this.isWorking == true && this.workType.includes("Working for Company") && this.companyName == company) { if (this.isWorking == true && this.workType !== WorkType.Company && this.companyName == company) {
this.finishWork(true); this.finishWork(true);
} }
delete this.jobs[company]; delete this.jobs[company];

@ -1,23 +1,19 @@
import { Box, Button, Paper, Tooltip, Typography } from "@mui/material";
import React, { useState } from "react"; import React, { useState } from "react";
import { Box, Paper, Typography, Button, Tooltip } from "@mui/material";
import { CONSTANTS } from "../../../Constants"; import { CONSTANTS } from "../../../Constants";
import { Crimes } from "../../../Crime/Crimes"; import { Crimes } from "../../../Crime/Crimes";
import { numeralWrapper } from "../../../ui/numeralFormat";
import { createProgressBarText } from "../../../utils/helpers/createProgressBarText";
import { use } from "../../../ui/Context";
import { FactionWorkType } from "../../../Faction/FactionWorkTypeEnum"; import { FactionWorkType } from "../../../Faction/FactionWorkTypeEnum";
import { use } from "../../../ui/Context";
import { numeralWrapper } from "../../../ui/numeralFormat";
import { ProgressBar } from "../../../ui/React/Progress";
import { Sleeve } from "../Sleeve"; import { Sleeve } from "../Sleeve";
import { SleeveTaskType } from "../SleeveTaskTypesEnum"; import { SleeveTaskType } from "../SleeveTaskTypesEnum";
import { SleeveAugmentationsModal } from "./SleeveAugmentationsModal";
import { TravelModal } from "./TravelModal";
import { StatsElement, EarningsElement } from "./StatsElement";
import { MoreStatsModal } from "./MoreStatsModal";
import { MoreEarningsModal } from "./MoreEarningsModal"; import { MoreEarningsModal } from "./MoreEarningsModal";
import { MoreStatsModal } from "./MoreStatsModal";
import { SleeveAugmentationsModal } from "./SleeveAugmentationsModal";
import { EarningsElement, StatsElement } from "./StatsElement";
import { TaskSelector } from "./TaskSelector"; import { TaskSelector } from "./TaskSelector";
import { TravelModal } from "./TravelModal";
interface IProps { interface IProps {
sleeve: Sleeve; sleeve: Sleeve;
@ -131,74 +127,70 @@ export function SleeveElem(props: IProps): React.ReactElement {
} }
return ( return (
<Box component={Paper} sx={{ width: "auto" }}> <>
<Box sx={{ m: 1 }}> <Paper sx={{ p: 1, display: "grid", gridTemplateColumns: "1fr 1fr", width: "auto", gap: 1 }}>
<Box display="grid" sx={{ gridTemplateColumns: "1fr 1fr", width: "100%", gap: 1 }}> <span>
<Box> <StatsElement sleeve={props.sleeve} />
<StatsElement sleeve={props.sleeve} /> <Box display="grid" sx={{ gridTemplateColumns: "1fr 1fr", width: "100%" }}>
<Box display="grid" sx={{ gridTemplateColumns: "1fr 1fr", width: "100%" }}> <Button onClick={() => setStatsOpen(true)}>More Stats</Button>
<Button onClick={() => setStatsOpen(true)}>More Stats</Button> <Button onClick={() => setEarningsOpen(true)}>More Earnings Info</Button>
<Button onClick={() => setEarningsOpen(true)}>More Earnings Info</Button> <Tooltip title={player.money < CONSTANTS.TravelCost ? <Typography>Insufficient funds</Typography> : ""}>
<Tooltip title={player.money < CONSTANTS.TravelCost ? <Typography>Insufficient funds</Typography> : ""}> <span>
<span> <Button
<Button onClick={() => setTravelOpen(true)}
onClick={() => setTravelOpen(true)} disabled={player.money < CONSTANTS.TravelCost}
disabled={player.money < CONSTANTS.TravelCost} sx={{ width: "100%", height: "100%" }}
sx={{ width: "100%", height: "100%" }} >
> Travel
Travel </Button>
</Button> </span>
</span> </Tooltip>
</Tooltip> <Tooltip
<Tooltip title={props.sleeve.shock < 100 ? <Typography>Unlocked when sleeve has fully recovered</Typography> : ""}
title={ >
props.sleeve.shock < 100 ? <Typography>Unlocked when sleeve has fully recovered</Typography> : "" <span>
} <Button
> onClick={() => setAugmentationsOpen(true)}
<span> disabled={props.sleeve.shock < 100}
<Button sx={{ width: "100%", height: "100%" }}
onClick={() => setAugmentationsOpen(true)} >
disabled={props.sleeve.shock < 100} Manage Augmentations
sx={{ width: "100%", height: "100%" }} </Button>
> </span>
Manage Augmentations </Tooltip>
</Button>
</span>
</Tooltip>
</Box>
</Box> </Box>
<Box> </span>
<EarningsElement sleeve={props.sleeve} /> <span>
<Box> <EarningsElement sleeve={props.sleeve} />
<TaskSelector player={player} sleeve={props.sleeve} setABC={setABC} /> <TaskSelector player={player} sleeve={props.sleeve} setABC={setABC} />
<Button onClick={setTask} sx={{ width: "100%" }}> <Button onClick={setTask} sx={{ width: "100%" }}>
Set Task Set Task
</Button> </Button>
<Typography>{desc}</Typography> <Typography>{desc}</Typography>
<Typography> <Typography>
{props.sleeve.currentTask === SleeveTaskType.Crime && {props.sleeve.currentTask === SleeveTaskType.Crime && (
createProgressBarText({ <ProgressBar
progress: props.sleeve.currentTaskTime / props.sleeve.currentTaskMaxTime, variant="determinate"
totalTicks: 25, value={(props.sleeve.currentTaskTime / props.sleeve.currentTaskMaxTime) * 100}
})} color="primary"
</Typography> />
</Box> )}
</Box> </Typography>
<MoreStatsModal open={statsOpen} onClose={() => setStatsOpen(false)} sleeve={props.sleeve} /> </span>
<MoreEarningsModal open={earningsOpen} onClose={() => setEarningsOpen(false)} sleeve={props.sleeve} /> </Paper>
<TravelModal <MoreStatsModal open={statsOpen} onClose={() => setStatsOpen(false)} sleeve={props.sleeve} />
open={travelOpen} <MoreEarningsModal open={earningsOpen} onClose={() => setEarningsOpen(false)} sleeve={props.sleeve} />
onClose={() => setTravelOpen(false)} <TravelModal
sleeve={props.sleeve} open={travelOpen}
rerender={props.rerender} onClose={() => setTravelOpen(false)}
/> sleeve={props.sleeve}
<SleeveAugmentationsModal rerender={props.rerender}
open={augmentationsOpen} />
onClose={() => setAugmentationsOpen(false)} <SleeveAugmentationsModal
sleeve={props.sleeve} open={augmentationsOpen}
/> onClose={() => setAugmentationsOpen(false)}
</Box> sleeve={props.sleeve}
</Box> />
</Box> </>
); );
} }

@ -1,6 +1,7 @@
import { CONSTANTS } from "../../Constants"; import { CONSTANTS } from "../../Constants";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers"; import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { IPlayer } from "../IPlayer"; import { IPlayer } from "../IPlayer";
import { ClassType } from "../../utils/WorkType";
export interface WorkEarnings { export interface WorkEarnings {
workMoneyLossRate: number; workMoneyLossRate: number;
@ -25,43 +26,43 @@ export function calculateClassEarnings(player: IPlayer): WorkEarnings {
chaExp = 0; chaExp = 0;
const hashManager = player.hashManager; const hashManager = player.hashManager;
switch (player.className) { switch (player.className) {
case CONSTANTS.ClassStudyComputerScience: case ClassType.StudyComputerScience:
hackExp = hackExp =
((CONSTANTS.ClassStudyComputerScienceBaseExp * player.workExpMult) / gameCPS) * hashManager.getStudyMult(); ((CONSTANTS.ClassStudyComputerScienceBaseExp * player.workExpMult) / gameCPS) * hashManager.getStudyMult();
break; break;
case CONSTANTS.ClassDataStructures: case ClassType.DataStructures:
cost = (CONSTANTS.ClassDataStructuresBaseCost * player.workCostMult) / gameCPS; cost = (CONSTANTS.ClassDataStructuresBaseCost * player.workCostMult) / gameCPS;
hackExp = ((CONSTANTS.ClassDataStructuresBaseExp * player.workExpMult) / gameCPS) * hashManager.getStudyMult(); hackExp = ((CONSTANTS.ClassDataStructuresBaseExp * player.workExpMult) / gameCPS) * hashManager.getStudyMult();
break; break;
case CONSTANTS.ClassNetworks: case ClassType.Networks:
cost = (CONSTANTS.ClassNetworksBaseCost * player.workCostMult) / gameCPS; cost = (CONSTANTS.ClassNetworksBaseCost * player.workCostMult) / gameCPS;
hackExp = ((CONSTANTS.ClassNetworksBaseExp * player.workExpMult) / gameCPS) * hashManager.getStudyMult(); hackExp = ((CONSTANTS.ClassNetworksBaseExp * player.workExpMult) / gameCPS) * hashManager.getStudyMult();
break; break;
case CONSTANTS.ClassAlgorithms: case ClassType.Algorithms:
cost = (CONSTANTS.ClassAlgorithmsBaseCost * player.workCostMult) / gameCPS; cost = (CONSTANTS.ClassAlgorithmsBaseCost * player.workCostMult) / gameCPS;
hackExp = ((CONSTANTS.ClassAlgorithmsBaseExp * player.workExpMult) / gameCPS) * hashManager.getStudyMult(); hackExp = ((CONSTANTS.ClassAlgorithmsBaseExp * player.workExpMult) / gameCPS) * hashManager.getStudyMult();
break; break;
case CONSTANTS.ClassManagement: case ClassType.Management:
cost = (CONSTANTS.ClassManagementBaseCost * player.workCostMult) / gameCPS; cost = (CONSTANTS.ClassManagementBaseCost * player.workCostMult) / gameCPS;
chaExp = ((CONSTANTS.ClassManagementBaseExp * player.workExpMult) / gameCPS) * hashManager.getStudyMult(); chaExp = ((CONSTANTS.ClassManagementBaseExp * player.workExpMult) / gameCPS) * hashManager.getStudyMult();
break; break;
case CONSTANTS.ClassLeadership: case ClassType.Leadership:
cost = (CONSTANTS.ClassLeadershipBaseCost * player.workCostMult) / gameCPS; cost = (CONSTANTS.ClassLeadershipBaseCost * player.workCostMult) / gameCPS;
chaExp = ((CONSTANTS.ClassLeadershipBaseExp * player.workExpMult) / gameCPS) * hashManager.getStudyMult(); chaExp = ((CONSTANTS.ClassLeadershipBaseExp * player.workExpMult) / gameCPS) * hashManager.getStudyMult();
break; break;
case CONSTANTS.ClassGymStrength: case ClassType.GymStrength:
cost = (CONSTANTS.ClassGymBaseCost * player.workCostMult) / gameCPS; cost = (CONSTANTS.ClassGymBaseCost * player.workCostMult) / gameCPS;
strExp = (player.workExpMult / gameCPS) * hashManager.getTrainingMult(); strExp = (player.workExpMult / gameCPS) * hashManager.getTrainingMult();
break; break;
case CONSTANTS.ClassGymDefense: case ClassType.GymDefense:
cost = (CONSTANTS.ClassGymBaseCost * player.workCostMult) / gameCPS; cost = (CONSTANTS.ClassGymBaseCost * player.workCostMult) / gameCPS;
defExp = (player.workExpMult / gameCPS) * hashManager.getTrainingMult(); defExp = (player.workExpMult / gameCPS) * hashManager.getTrainingMult();
break; break;
case CONSTANTS.ClassGymDexterity: case ClassType.GymDexterity:
cost = (CONSTANTS.ClassGymBaseCost * player.workCostMult) / gameCPS; cost = (CONSTANTS.ClassGymBaseCost * player.workCostMult) / gameCPS;
dexExp = (player.workExpMult / gameCPS) * hashManager.getTrainingMult(); dexExp = (player.workExpMult / gameCPS) * hashManager.getTrainingMult();
break; break;
case CONSTANTS.ClassGymAgility: case ClassType.GymAgility:
cost = (CONSTANTS.ClassGymBaseCost * player.workCostMult) / gameCPS; cost = (CONSTANTS.ClassGymBaseCost * player.workCostMult) / gameCPS;
agiExp = (player.workExpMult / gameCPS) * hashManager.getTrainingMult(); agiExp = (player.workExpMult / gameCPS) * hashManager.getTrainingMult();
break; break;

@ -50,6 +50,8 @@ import { setupUncaughtPromiseHandler } from "./UncaughtPromiseHandler";
import { Button, Typography } from "@mui/material"; import { Button, Typography } from "@mui/material";
import { SnackbarEvents, ToastVariant } from "./ui/React/Snackbar"; import { SnackbarEvents, ToastVariant } from "./ui/React/Snackbar";
import { WorkType } from "./utils/WorkType";
const Engine: { const Engine: {
_lastUpdate: number; _lastUpdate: number;
updateGame: (numCycles?: number) => void; updateGame: (numCycles?: number) => void;
@ -292,20 +294,27 @@ const Engine: {
loadAllRunningScripts(Player); // This also takes care of offline production for those scripts loadAllRunningScripts(Player); // This also takes care of offline production for those scripts
if (Player.isWorking) { if (Player.isWorking) {
Player.focus = true; Player.focus = true;
if (Player.workType == CONSTANTS.WorkTypeFaction) { switch (Player.workType) {
Player.workForFaction(numCyclesOffline); case WorkType.Faction:
} else if (Player.workType == CONSTANTS.WorkTypeCreateProgram) { Player.workForFaction(numCyclesOffline);
Player.createProgramWork(numCyclesOffline); break;
} else if (Player.workType == CONSTANTS.WorkTypeStudyClass) { case WorkType.CreateProgram:
Player.takeClass(numCyclesOffline); Player.createProgramWork(numCyclesOffline);
} else if (Player.workType == CONSTANTS.WorkTypeCrime) { break;
Player.commitCrime(numCyclesOffline); case WorkType.StudyClass:
} else if (Player.workType == CONSTANTS.WorkTypeCompanyPartTime) { Player.takeClass(numCyclesOffline);
Player.workPartTime(numCyclesOffline); break;
} else if (Player.workType === CONSTANTS.WorkTypeGraftAugmentation) { case WorkType.Crime:
Player.graftAugmentationWork(numCyclesOffline); Player.commitCrime(numCyclesOffline);
} else { break;
Player.work(numCyclesOffline); case WorkType.CompanyPartTime:
Player.workPartTime(numCyclesOffline);
break;
case WorkType.GraftAugmentation:
Player.graftAugmentationWork(numCyclesOffline);
break;
default:
Player.work(numCyclesOffline);
} }
} else { } else {
for (let i = 0; i < Player.factions.length; i++) { for (let i = 0; i < Player.factions.length; i++) {

@ -25,7 +25,8 @@ import { StatsProgressOverviewCell } from "./StatsProgressBar";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers"; import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
import { Box, Tooltip } from "@mui/material"; import { Box, Tooltip } from "@mui/material";
import { CONSTANTS } from "../../Constants";
import { WorkType } from "../../utils/WorkType";
interface IProps { interface IProps {
save: () => void; save: () => void;
@ -144,8 +145,8 @@ function Work(): React.ReactElement {
let header = <></>; let header = <></>;
let innerText = <></>; let innerText = <></>;
switch (player.workType) { switch (player.workType) {
case CONSTANTS.WorkTypeCompanyPartTime: case WorkType.CompanyPartTime:
case CONSTANTS.WorkTypeCompany: case WorkType.Company:
details = ( details = (
<> <>
{player.jobs[player.companyName]} at <strong>{player.companyName}</strong> {player.jobs[player.companyName]} at <strong>{player.companyName}</strong>
@ -162,7 +163,7 @@ function Work(): React.ReactElement {
</> </>
); );
break; break;
case CONSTANTS.WorkTypeFaction: case WorkType.Faction:
details = ( details = (
<> <>
{player.factionWorkType} for <strong>{player.currentWorkFactionName}</strong> {player.factionWorkType} for <strong>{player.currentWorkFactionName}</strong>
@ -179,12 +180,12 @@ function Work(): React.ReactElement {
</> </>
); );
break; break;
case CONSTANTS.WorkTypeStudyClass: case WorkType.StudyClass:
details = <>{player.workType}</>; details = <>{player.workType}</>;
header = <>You are {player.className}</>; header = <>You are {player.className}</>;
innerText = <>{convertTimeMsToTimeElapsedString(player.timeWorked)}</>; innerText = <>{convertTimeMsToTimeElapsedString(player.timeWorked)}</>;
break; break;
case CONSTANTS.WorkTypeCreateProgram: case WorkType.CreateProgram:
details = <>Coding {player.createProgramName}</>; details = <>Coding {player.createProgramName}</>;
header = <>Creating a program</>; header = <>Creating a program</>;
innerText = ( innerText = (
@ -194,7 +195,7 @@ function Work(): React.ReactElement {
</> </>
); );
break; break;
case CONSTANTS.WorkTypeGraftAugmentation: case WorkType.GraftAugmentation:
details = <>Grafting {player.graftAugmentationName}</>; details = <>Grafting {player.graftAugmentationName}</>;
header = <>Grafting an Augmentation</>; header = <>Grafting an Augmentation</>;
innerText = ( innerText = (

13
src/ui/React/Progress.tsx Normal file

@ -0,0 +1,13 @@
import LinearProgress from "@mui/material/LinearProgress";
import { Theme } from "@mui/material/styles";
import withStyles from "@mui/styles/withStyles";
export const ProgressBar = withStyles((theme: Theme) => ({
root: {
backgroundColor: theme.palette.background.paper,
},
bar: {
transition: "none",
backgroundColor: theme.palette.primary.main,
},
}))(LinearProgress);

@ -16,19 +16,21 @@ interface IProps {
name: string; name: string;
color: string; color: string;
classes?: any; classes?: any;
data: ITableRowData; data?: ITableRowData;
children?: React.ReactElement; children?: React.ReactElement;
} }
export const StatsRow = ({ name, color, classes = useStyles(), children, data }: IProps): React.ReactElement => { export const StatsRow = ({ name, color, classes = useStyles(), children, data }: IProps): React.ReactElement => {
let content; let content = "";
if (data.content !== undefined) { if (data) {
content = data.content; if (data.content !== undefined) {
} else if (data.level !== undefined && data.exp !== undefined) { content = data.content;
content = `${formatNumber(data.level, 0)} (${numeralWrapper.formatExp(data.exp)} exp)`; } else if (data.level !== undefined && data.exp !== undefined) {
} else if (data.level !== undefined && data.exp === undefined) { content = `${formatNumber(data.level, 0)} (${numeralWrapper.formatExp(data.exp)} exp)`;
content = `${formatNumber(data.level, 0)}`; } else if (data.level !== undefined && data.exp === undefined) {
content = `${formatNumber(data.level, 0)}`;
}
} }
return ( return (

File diff suppressed because it is too large Load Diff

49
src/utils/WorkType.ts Normal file

@ -0,0 +1,49 @@
export enum WorkType {
None = "",
Company = "Working for Company",
CompanyPartTime = "Working for Company part-time",
Faction = "Working for Faction",
CreateProgram = "Working on Create a Program",
StudyClass = "Studying or Taking a class at university",
Crime = "Committing a crime",
GraftAugmentation = "Grafting an Augmentation",
}
export enum PlayerFactionWorkType {
None = "",
Hacking = "Faction Hacking Work",
Field = "Faction Field Work",
Security = "Faction Security Work",
}
export enum ClassType {
None = "",
StudyComputerScience = "studying Computer Science",
DataStructures = "taking a Data Structures course",
Networks = "taking a Networks course",
Algorithms = "taking an Algorithms course",
Management = "taking a Management course",
Leadership = "taking a Leadership course",
GymStrength = "training your strength at a gym",
GymDefense = "training your defense at a gym",
GymDexterity = "training your dexterity at a gym",
GymAgility = "training your agility at a gym",
}
export enum CrimeType {
None = "",
Shoplift = "shoplift",
RobStore = "rob a store",
Mug = "mug someone",
Larceny = "commit larceny",
Drugs = "deal drugs",
BondForgery = "forge corporate bonds",
TraffickArms = "traffick illegal arms",
Homicide = "commit homicide",
GrandTheftAuto = "commit grand theft auto",
Kidnap = "kidnap someone for ransom",
Assassination = "assassinate a high-profile target",
Heist = "pull off the ultimate heist",
}