Security:
diff --git a/src/Locations/ui/ApplyToJobButton.tsx b/src/Locations/ui/ApplyToJobButton.tsx
deleted file mode 100644
index 5b5c80255..000000000
--- a/src/Locations/ui/ApplyToJobButton.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import * as React from "react";
-
-import { Company } from "../../Company/Company";
-import { CompanyPosition } from "../../Company/CompanyPosition";
-import { getJobRequirementText } from "../../Company/GetJobRequirementText";
-
-import { Player } from "@player";
-import Button from "@mui/material/Button";
-import Tooltip from "@mui/material/Tooltip";
-
-interface IProps {
- company: Company;
- entryPosType: CompanyPosition;
- onClick: (e: React.MouseEvent) => void;
- text: string;
-}
-
-/** React Component for a button that's used to apply for a job */
-export function ApplyToJobButton(props: IProps): React.ReactElement {
- function getJobRequirementTooltip(): string {
- const pos = Player.getNextCompanyPosition(props.company, props.entryPosType);
- if (pos == null) {
- return "";
- }
-
- if (!props.company.hasPosition(pos)) {
- return "";
- }
-
- return getJobRequirementText(props.company, pos, true);
- }
-
- return (
- <>
- }>
-
-
- >
- );
-}
diff --git a/src/Locations/ui/CompanyLocation.tsx b/src/Locations/ui/CompanyLocation.tsx
index 9c30afc33..bcfe303b9 100644
--- a/src/Locations/ui/CompanyLocation.tsx
+++ b/src/Locations/ui/CompanyLocation.tsx
@@ -4,15 +4,10 @@
* This subcomponent renders all of the buttons for applying to jobs at a company
*/
import React, { useState } from "react";
-import Typography from "@mui/material/Typography";
-import Button from "@mui/material/Button";
-import Tooltip from "@mui/material/Tooltip";
-import Box from "@mui/material/Box";
-
-import { ApplyToJobButton } from "./ApplyToJobButton";
+import { Paper, Box, Tooltip, Button, Typography } from "@mui/material";
import { Locations } from "../Locations";
-import { CompanyName, JobName, JobField } from "@enums";
+import { CompanyName } from "@enums";
import { Companies } from "../../Company/Companies";
import { CompanyPositions } from "../../Company/CompanyPositions";
@@ -26,6 +21,9 @@ import { QuitJobModal } from "../../Company/ui/QuitJobModal";
import { CompanyWork } from "../../Work/CompanyWork";
import { useRerender } from "../../ui/React/hooks";
import { companyNameAsLocationName } from "../../Company/utils";
+import { JobSummary } from "../../Company/ui/JobSummary";
+import { StatsTable } from "../../ui/React/StatsTable";
+import { JobListings } from "../../Company/ui/JobListings";
interface IProps {
companyName: CompanyName;
@@ -54,101 +52,12 @@ export function CompanyLocation(props: IProps): React.ReactElement {
const hasMoreJobs = Object.keys(Player.jobs).length > 1;
/**
- * CompanyPosition object for the job that the player holds at this company
- * (if he has one)
+ * CompanyPosition object for the job that the player holds at this company, if applicable
*/
- const companyPosition = jobTitle ? CompanyPositions[jobTitle] : null;
+ const currentPosition = jobTitle ? CompanyPositions[jobTitle] : null;
Player.location = companyNameAsLocationName(props.companyName);
- function applyForAgentJob(e: React.MouseEvent): void {
- if (!e.isTrusted) {
- return;
- }
- Player.applyForAgentJob();
- rerender();
- }
-
- function applyForBusinessConsultantJob(e: React.MouseEvent): void {
- if (!e.isTrusted) {
- return;
- }
- Player.applyForBusinessConsultantJob();
- rerender();
- }
-
- function applyForBusinessJob(e: React.MouseEvent): void {
- if (!e.isTrusted) {
- return;
- }
- Player.applyForBusinessJob();
- rerender();
- }
-
- function applyForEmployeeJob(e: React.MouseEvent): void {
- if (!e.isTrusted) {
- return;
- }
- Player.applyForEmployeeJob();
- rerender();
- }
-
- function applyForItJob(e: React.MouseEvent): void {
- if (!e.isTrusted) {
- return;
- }
- Player.applyForItJob();
- rerender();
- }
-
- function applyForPartTimeEmployeeJob(e: React.MouseEvent): void {
- if (!e.isTrusted) {
- return;
- }
- Player.applyForPartTimeEmployeeJob();
- rerender();
- }
-
- function applyForPartTimeWaiterJob(e: React.MouseEvent): void {
- if (!e.isTrusted) {
- return;
- }
- Player.applyForPartTimeWaiterJob();
- rerender();
- }
-
- function applyForSecurityJob(e: React.MouseEvent): void {
- if (!e.isTrusted) {
- return;
- }
- Player.applyForSecurityJob();
- rerender();
- }
-
- function applyForSoftwareConsultantJob(e: React.MouseEvent): void {
- if (!e.isTrusted) {
- return;
- }
- Player.applyForSoftwareConsultantJob();
- rerender();
- }
-
- function applyForSoftwareJob(e: React.MouseEvent): void {
- if (!e.isTrusted) {
- return;
- }
- Player.applyForSoftwareJob();
- rerender();
- }
-
- function applyForWaiterJob(e: React.MouseEvent): void {
- if (!e.isTrusted) {
- return;
- }
- Player.applyForWaiterJob();
- rerender();
- }
-
function startInfiltration(e: React.MouseEvent): void {
if (!e.isTrusted) {
return;
@@ -164,8 +73,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
return;
}
- const pos = companyPosition;
- if (pos) {
+ if (currentPosition) {
Player.startWork(
new CompanyWork({
singularity: false,
@@ -189,59 +97,58 @@ export function CompanyLocation(props: IProps): React.ReactElement {
Router.toPage(Page.Job, { location: Locations[Object.keys(Player.jobs)[targetNum]] });
}
- const isEmployedHere = jobTitle != null;
+ const isEmployedHere = currentPosition != null;
const favorGain = company.getFavorGain();
return (
<>
- {isEmployedHere && hasMoreJobs && (
- <>
-
-
-
+
+ {isEmployedHere && hasMoreJobs && (
+
+
+
-
- >
- )}
- {isEmployedHere && (
- <>
- Job Title: {jobTitle}
- -------------------------
-
-
- You will have company favor upon resetting after
- installing Augmentations
- >
- }
- >
-
- Company reputation:
-
-
-
- -------------------------
-
-
- Company favor increases the rate at which you earn reputation for this company by 1% per favor.
- Company favor is gained whenever you reset after installing Augmentations. The amount of favor you
- gain depends on how much reputation you have with the company.
- >
- }
- >
-
- Company Favor:
-
-
-
- -------------------------
-
- >
- )}
-
+ )}
+ {isEmployedHere && (
+
+
+
+ You will have company favor upon resetting after
+ installing Augmentations
+ >
+ }
+ >
+ Total reputation:
+ ,
+ ,
+ ],
+ [
+
+ Company favor increases the rate at which you earn reputation for this company by 1% per favor.
+ Company favor is gained whenever you reset after installing Augmentations. The amount of favor
+ you gain depends on how much reputation you have with the company.
+ >
+ }
+ >
+ Company favor:
+ ,
+ ,
+ ],
+ ]}
+ />
+
+ )}
+
{isEmployedHere && (
@@ -255,94 +162,9 @@ export function CompanyLocation(props: IProps): React.ReactElement {
/>
)}
- {company.hasAgentPositions() && (
-
- )}
- {company.hasBusinessConsultantPositions() && (
-
- )}
- {company.hasBusinessPositions() && (
-
- )}
- {company.hasEmployeePositions() && (
-
- )}
- {company.hasEmployeePositions() && (
-
- )}
- {company.hasITPositions() && (
-
- )}
- {company.hasSecurityPositions() && (
-
- )}
- {company.hasSoftwareConsultantPositions() && (
-
- )}
- {company.hasSoftwarePositions() && (
-
- )}
- {company.hasWaiterPositions() && (
-
- )}
- {company.hasWaiterPositions() && (
-
- )}
+
+ {company.companyPositions.size > 0 && }
+
{location.infiltrationData != null && }
>
diff --git a/src/NetscriptFunctions/Singularity.ts b/src/NetscriptFunctions/Singularity.ts
index faedfb2fe..c0a89863d 100644
--- a/src/NetscriptFunctions/Singularity.ts
+++ b/src/NetscriptFunctions/Singularity.ts
@@ -8,7 +8,6 @@ import {
FactionName,
FactionWorkType,
GymType,
- JobField,
LocationName,
UniversityClassType,
} from "@enums";
@@ -55,8 +54,8 @@ import { Engine } from "../engine";
import { getEnumHelper } from "../utils/EnumHelper";
import { ScriptFilePath, resolveScriptFilePath } from "../Paths/ScriptFilePath";
import { root } from "../Paths/Directory";
-import { companyNameAsLocationName } from "../Company/utils";
import { getRecordEntries } from "../Types/Record";
+import { JobTracks } from "../Company/data/JobTracks";
export function NetscriptSingularity(): InternalAPI {
const runAfterReset = function (cbScript: ScriptFilePath) {
@@ -687,20 +686,12 @@ export function NetscriptSingularity(): InternalAPI {
const job = CompanyPositions[positionName];
const res = {
- name: CompanyPositions[positionName].name,
- field: CompanyPositions[positionName].field,
- nextPosition: CompanyPositions[positionName].nextPosition,
- salary: CompanyPositions[positionName].baseSalary * company.salaryMultiplier,
- requiredReputation: CompanyPositions[positionName].requiredReputation,
- requiredSkills: {
- hacking: job.requiredHacking > 0 ? job.requiredHacking + company.jobStatReqOffset : 0,
- strength: job.requiredStrength > 0 ? job.requiredStrength + company.jobStatReqOffset : 0,
- defense: job.requiredDefense > 0 ? job.requiredDefense + company.jobStatReqOffset : 0,
- dexterity: job.requiredDexterity > 0 ? job.requiredDexterity + company.jobStatReqOffset : 0,
- agility: job.requiredAgility > 0 ? job.requiredAgility + company.jobStatReqOffset : 0,
- charisma: job.requiredCharisma > 0 ? job.requiredCharisma + company.jobStatReqOffset : 0,
- intelligence: 0,
- },
+ name: job.name,
+ field: job.field,
+ nextPosition: job.nextPosition,
+ salary: job.baseSalary * company.salaryMultiplier,
+ requiredReputation: job.requiredReputation,
+ requiredSkills: job.requiredSkills(company.jobStatReqOffset),
};
return res;
},
@@ -739,62 +730,16 @@ export function NetscriptSingularity(): InternalAPI {
helpers.checkSingularityAccess(ctx);
const companyName = getEnumHelper("CompanyName").nsGetMember(ctx, _companyName);
const field = getEnumHelper("JobField").nsGetMember(ctx, _field, "field", { fuzzy: true });
+ const company = Companies[companyName];
+ const entryPos = CompanyPositions[JobTracks[field][0]];
- Player.location = companyNameAsLocationName(companyName);
- let res;
- switch (field) {
- case JobField.software:
- res = Player.applyForSoftwareJob(true);
- break;
- case JobField.softwareConsultant:
- res = Player.applyForSoftwareConsultantJob(true);
- break;
- case JobField.it:
- res = Player.applyForItJob(true);
- break;
- case JobField.securityEngineer:
- res = Player.applyForSecurityEngineerJob(true);
- break;
- case JobField.networkEngineer:
- res = Player.applyForNetworkEngineerJob(true);
- break;
- case JobField.business:
- res = Player.applyForBusinessJob(true);
- break;
- case JobField.businessConsultant:
- res = Player.applyForBusinessConsultantJob(true);
- break;
- case JobField.security:
- res = Player.applyForSecurityJob(true);
- break;
- case JobField.agent:
- res = Player.applyForAgentJob(true);
- break;
- case JobField.employee:
- res = Player.applyForEmployeeJob(true);
- break;
- case JobField.partTimeEmployee:
- res = Player.applyForPartTimeEmployeeJob(true);
- break;
- case JobField.waiter:
- res = Player.applyForWaiterJob(true);
- break;
- case JobField.partTimeWaiter:
- res = Player.applyForPartTimeWaiterJob(true);
- break;
- default:
- helpers.log(ctx, () => `Invalid job: '${field}'.`);
- return false;
- }
- if (res) {
- helpers.log(
- ctx,
- () => `You were offered a new job at '${companyName}' with position '${Player.jobs[companyName]}'`,
- );
+ const jobName = Player.applyForJob(company, entryPos, true);
+ if (jobName) {
+ helpers.log(ctx, () => `You were offered a new job at '${companyName}' with position '${jobName}'`);
} else {
helpers.log(ctx, () => `You failed to get a new job/promotion at '${companyName}' in the '${field}' field.`);
}
- return res;
+ return jobName;
},
quitJob: (ctx) => (_companyName) => {
helpers.checkSingularityAccess(ctx);
diff --git a/src/PersonObjects/Player/PlayerObject.ts b/src/PersonObjects/Player/PlayerObject.ts
index 526e92c9f..1d6ca7ff8 100644
--- a/src/PersonObjects/Player/PlayerObject.ts
+++ b/src/PersonObjects/Player/PlayerObject.ts
@@ -79,19 +79,6 @@ export class PlayerObject extends Person implements IPlayer {
startWork = workMethods.startWork;
processWork = workMethods.processWork;
finishWork = workMethods.finishWork;
- applyForSoftwareJob = generalMethods.applyForSoftwareJob;
- applyForSoftwareConsultantJob = generalMethods.applyForSoftwareConsultantJob;
- applyForItJob = generalMethods.applyForItJob;
- applyForSecurityEngineerJob = generalMethods.applyForSecurityEngineerJob;
- applyForNetworkEngineerJob = generalMethods.applyForNetworkEngineerJob;
- applyForBusinessJob = generalMethods.applyForBusinessJob;
- applyForBusinessConsultantJob = generalMethods.applyForBusinessConsultantJob;
- applyForSecurityJob = generalMethods.applyForSecurityJob;
- applyForAgentJob = generalMethods.applyForAgentJob;
- applyForEmployeeJob = generalMethods.applyForEmployeeJob;
- applyForPartTimeEmployeeJob = generalMethods.applyForPartTimeEmployeeJob;
- applyForWaiterJob = generalMethods.applyForWaiterJob;
- applyForPartTimeWaiterJob = generalMethods.applyForPartTimeWaiterJob;
applyForJob = generalMethods.applyForJob;
canAccessBladeburner = bladeburnerMethods.canAccessBladeburner;
canAccessCorporation = corporationMethods.canAccessCorporation;
diff --git a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts
index 44288622a..90cc159bd 100644
--- a/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts
+++ b/src/PersonObjects/Player/PlayerObjectGeneralMethods.ts
@@ -20,8 +20,7 @@ import { CodingContractRewardType, ICodingContractReward } from "../../CodingCon
import { Company } from "../../Company/Company";
import { Companies } from "../../Company/Companies";
import { getNextCompanyPositionHelper } from "../../Company/GetNextCompanyPosition";
-import { getJobRequirementText } from "../../Company/GetJobRequirementText";
-import { CompanyPositions } from "../../Company/CompanyPositions";
+import { getJobRequirements, getJobRequirementText } from "../../Company/GetJobRequirements";
import { CompanyPosition } from "../../Company/CompanyPosition";
import { CONSTANTS } from "../../Constants";
import { Exploit } from "../../Exploits/Exploit";
@@ -51,7 +50,7 @@ import { SnackbarEvents } from "../../ui/React/Snackbar";
import { achievements } from "../../Achievements/Achievements";
import { isCompanyWork } from "../../Work/CompanyWork";
-import { getEnumHelper, isMember } from "../../utils/EnumHelper";
+import { isMember } from "../../utils/EnumHelper";
export function init(this: PlayerObject): void {
/* Initialize Player's home computer */
@@ -273,26 +272,34 @@ export function hospitalize(this: PlayerObject): number {
return cost;
}
-/********* Company job application **********/
-//Determines the job that the Player should get (if any) at the current company
-//The 'sing' argument designates whether or not this is being called from
-//the applyToCompany() Netscript Singularity function
-export function applyForJob(this: PlayerObject, entryPosType: CompanyPosition, sing = false): boolean {
- const companyName = getEnumHelper("CompanyName").getMember(this.location);
- if (!companyName) return false;
- const company = Companies[companyName]; //Company being applied to
- let pos = entryPosType;
+/**
+ * Company job application. Determines the job that the Player should get (if any) at the given company.
+ * @param this The player instance
+ * @param company The company being applied to
+ * @param position A specific position
+ * @param sing Whether this is being called from the applyToCompany() Netscript Singularity function
+ * @returns The name of the Job received (if any). May be higher or lower than the job applied to.
+ */
+export function applyForJob(
+ this: PlayerObject,
+ company: Company,
+ position: CompanyPosition,
+ sing = false,
+): JobName | null {
+ if (!company) return null;
+ // Start searching the job track from the provided point (which may not be the entry position)
+ let pos = position;
if (!this.isQualified(company, pos)) {
if (!sing) {
- dialogBoxCreate("Unfortunately, you do not qualify for this position\n" + getJobRequirementText(company, pos));
+ dialogBoxCreate(`Unfortunately, you do not qualify for this position.\n${getJobRequirementText(company, pos)}`);
}
- return false;
+ return null;
}
if (!company.hasPosition(pos)) {
- console.error(`Company ${company.name} does not have position ${pos}. Player.applyToCompany() failed`);
- return false;
+ console.error(`Company ${company.name} does not have position ${pos}. Player.applyToCompany() failed.`);
+ return null;
}
let nextPos = getNextCompanyPositionHelper(pos);
@@ -305,59 +312,53 @@ export function applyForJob(this: PlayerObject, entryPosType: CompanyPosition, s
if (this.jobs[company.name] === pos.name) {
if (!sing) {
const nextPos = getNextCompanyPositionHelper(pos);
- if (nextPos == null || !company.hasPosition(nextPos)) {
- dialogBoxCreate("You are already at the highest position for your field! No promotion available");
+ if (nextPos == null) {
+ dialogBoxCreate(`You are already ${pos.name}! No promotion available`);
+ } else if (!company.hasPosition(nextPos)) {
+ dialogBoxCreate(
+ `You already have the highest ${pos.field} position available at ${company.name}! No promotion available`,
+ );
} else {
- const reqText = getJobRequirementText(company, nextPos);
- dialogBoxCreate("Unfortunately, you do not qualify for a promotion\n" + reqText);
+ dialogBoxCreate(
+ `Unfortunately, you do not qualify for a promotion.\n${getJobRequirementText(company, nextPos)}`,
+ );
}
}
- return false;
+ return null;
}
this.jobs[company.name] = pos.name;
if (!sing) {
- dialogBoxCreate(`Congratulations! You were offered a new job at ${company.name} for position ${pos.name}!`);
+ dialogBoxCreate(`${pos.hiredText} at ${company.name}!`);
}
- return true;
+ return pos.name;
}
-//Returns your next position at a company given the field (software, business, etc.)
+/**
+ * Get a job position that the player can apply for.
+ * @param this The player instance
+ * @param company The Company being applied to
+ * @param entryPosType Job field (Software, Business, etc)
+ * @returns The highest job the player can apply for at this company, if any
+ */
export function getNextCompanyPosition(
this: PlayerObject,
company: Company,
entryPosType: CompanyPosition,
): CompanyPosition | null {
- const currCompany = Companies[company.name];
-
- //Not employed at this company, so return the entry position
- if (currCompany == null || currCompany.name != company.name) {
- return entryPosType;
+ let pos: CompanyPosition | null = entryPosType;
+ let nextPos = getNextCompanyPositionHelper(pos);
+ // Find the highest-level job in this category that the player is currently able to apply for.
+ while (nextPos && company.hasPosition(nextPos) && this.isQualified(company, nextPos)) {
+ pos = nextPos;
+ nextPos = getNextCompanyPositionHelper(pos);
}
-
- //If the entry pos type and the player's current position have the same type,
- //return the player's "nextCompanyPosition". Otherwise return the entryposType
- //Employed at this company, so just return the next position if it exists.
- const currentPositionName = this.jobs[company.name];
- if (!currentPositionName) return entryPosType;
- const currentPosition = CompanyPositions[currentPositionName];
- if (
- (currentPosition.isSoftwareJob() && entryPosType.isSoftwareJob()) ||
- (currentPosition.isITJob() && entryPosType.isITJob()) ||
- (currentPosition.isBusinessJob() && entryPosType.isBusinessJob()) ||
- (currentPosition.isSecurityEngineerJob() && entryPosType.isSecurityEngineerJob()) ||
- (currentPosition.isNetworkEngineerJob() && entryPosType.isNetworkEngineerJob()) ||
- (currentPosition.isSecurityJob() && entryPosType.isSecurityJob()) ||
- (currentPosition.isAgentJob() && entryPosType.isAgentJob()) ||
- (currentPosition.isSoftwareConsultantJob() && entryPosType.isSoftwareConsultantJob()) ||
- (currentPosition.isBusinessConsultantJob() && entryPosType.isBusinessConsultantJob()) ||
- (currentPosition.isPartTimeJob() && entryPosType.isPartTimeJob())
- ) {
- return getNextCompanyPositionHelper(currentPosition);
+ // If the player already has this position, return the one after that (if any).
+ if (this.jobs[company.name] == pos.name) {
+ pos = nextPos;
}
-
- return entryPosType;
+ return pos;
}
export function quitJob(this: PlayerObject, company: CompanyName): void {
@@ -382,192 +383,10 @@ export function hasJob(this: PlayerObject): boolean {
return Boolean(Object.keys(this.jobs).length);
}
-export function applyForSoftwareJob(this: PlayerObject, sing = false): boolean {
- return this.applyForJob(CompanyPositions[JobName.software0], sing);
-}
-
-export function applyForSoftwareConsultantJob(this: PlayerObject, sing = false): boolean {
- return this.applyForJob(CompanyPositions[JobName.softwareConsult0], sing);
-}
-
-export function applyForItJob(this: PlayerObject, sing = false): boolean {
- return this.applyForJob(CompanyPositions[JobName.IT0], sing);
-}
-
-export function applyForSecurityEngineerJob(this: PlayerObject, sing = false): boolean {
- const companyName = getEnumHelper("CompanyName").getMember(this.location);
- if (!companyName) return false;
- const company = Companies[companyName];
- if (this.isQualified(company, CompanyPositions[JobName.securityEng])) {
- return this.applyForJob(CompanyPositions[JobName.securityEng], sing);
- } else {
- if (!sing) {
- dialogBoxCreate("Unfortunately, you do not qualify for this position");
- }
- return false;
- }
-}
-
-export function applyForNetworkEngineerJob(this: PlayerObject, sing = false): boolean {
- const companyName = getEnumHelper("CompanyName").getMember(this.location);
- if (!companyName) return false;
- const company = Companies[companyName];
- if (this.isQualified(company, CompanyPositions[JobName.networkEng0])) {
- const pos = CompanyPositions[JobName.networkEng0];
- return this.applyForJob(pos, sing);
- } else {
- if (!sing) {
- dialogBoxCreate("Unfortunately, you do not qualify for this position");
- }
- return false;
- }
-}
-
-export function applyForBusinessJob(this: PlayerObject, sing = false): boolean {
- return this.applyForJob(CompanyPositions[JobName.business0], sing);
-}
-
-export function applyForBusinessConsultantJob(this: PlayerObject, sing = false): boolean {
- return this.applyForJob(CompanyPositions[JobName.businessConsult0], sing);
-}
-
-export function applyForSecurityJob(this: PlayerObject, sing = false): boolean {
- // TODO Police Jobs
- // Indexing starts at 2 because 0 is for police officer
- return this.applyForJob(CompanyPositions[JobName.security0], sing);
-}
-
-export function applyForAgentJob(this: PlayerObject, sing = false): boolean {
- const companyName = getEnumHelper("CompanyName").getMember(this.location);
- if (!companyName) return false;
- const company = Companies[companyName];
- if (this.isQualified(company, CompanyPositions[JobName.agent0])) {
- const pos = CompanyPositions[JobName.agent0];
- return this.applyForJob(pos, sing);
- } else {
- if (!sing) {
- dialogBoxCreate("Unfortunately, you do not qualify for this position");
- }
- return false;
- }
-}
-
-export function applyForEmployeeJob(this: PlayerObject, sing = false): boolean {
- const companyName = getEnumHelper("CompanyName").getMember(this.location);
- if (!companyName) return false;
- const company = Companies[companyName];
- const position = JobName.employee;
- // Check if this company has the position
- if (!company.hasPosition(position)) {
- return false;
- }
- if (this.isQualified(company, CompanyPositions[position])) {
- this.jobs[company.name] = position;
-
- if (!sing) {
- dialogBoxCreate("Congratulations, you are now employed at " + this.location);
- }
-
- return true;
- } else {
- if (!sing) {
- dialogBoxCreate("Unfortunately, you do not qualify for this position");
- }
-
- return false;
- }
-}
-
-export function applyForPartTimeEmployeeJob(this: PlayerObject, sing = false): boolean {
- const companyName = getEnumHelper("CompanyName").getMember(this.location);
- if (!companyName) return false;
- const company = Companies[companyName];
- const position = JobName.employeePT;
- // Check if this company has the position
- if (!company.hasPosition(position)) {
- return false;
- }
- if (this.isQualified(company, CompanyPositions[position])) {
- this.jobs[company.name] = position;
- if (!sing) {
- dialogBoxCreate("Congratulations, you are now employed part-time at " + this.location);
- }
-
- return true;
- } else {
- if (!sing) {
- dialogBoxCreate("Unfortunately, you do not qualify for this position");
- }
-
- return false;
- }
-}
-
-export function applyForWaiterJob(this: PlayerObject, sing = false): boolean {
- const companyName = getEnumHelper("CompanyName").getMember(this.location);
- if (!companyName) return false;
- const company = Companies[companyName];
- const position = JobName.waiter;
- // Check if this company has the position
- if (!company.hasPosition(position)) {
- return false;
- }
- if (this.isQualified(company, CompanyPositions[position])) {
- this.jobs[company.name] = position;
- if (!sing) {
- dialogBoxCreate("Congratulations, you are now employed as a waiter at " + this.location);
- }
- return true;
- } else {
- if (!sing) {
- dialogBoxCreate("Unfortunately, you do not qualify for this position");
- }
- return false;
- }
-}
-
-export function applyForPartTimeWaiterJob(this: PlayerObject, sing = false): boolean {
- const companyName = getEnumHelper("CompanyName").getMember(this.location);
- if (!companyName) return false;
- const company = Companies[companyName];
- const position = JobName.waiterPT;
- // Check if this company has the position
- if (!company.hasPosition(position)) {
- return false;
- }
- if (this.isQualified(company, CompanyPositions[position])) {
- this.jobs[company.name] = position;
- if (!sing) {
- dialogBoxCreate("Congratulations, you are now employed as a part-time waiter at " + this.location);
- }
- return true;
- } else {
- if (!sing) {
- dialogBoxCreate("Unfortunately, you do not qualify for this position");
- }
- return false;
- }
-}
-
//Checks if the Player is qualified for a certain position
export function isQualified(this: PlayerObject, company: Company, position: CompanyPosition): boolean {
- const offset = company.jobStatReqOffset;
- const reqHacking = position.requiredHacking > 0 ? position.requiredHacking + offset : 0;
- const reqStrength = position.requiredStrength > 0 ? position.requiredStrength + offset : 0;
- const reqDefense = position.requiredDefense > 0 ? position.requiredDefense + offset : 0;
- const reqDexterity = position.requiredDexterity > 0 ? position.requiredDexterity + offset : 0;
- const reqAgility = position.requiredDexterity > 0 ? position.requiredDexterity + offset : 0;
- const reqCharisma = position.requiredCharisma > 0 ? position.requiredCharisma + offset : 0;
-
- return (
- this.skills.hacking >= reqHacking &&
- this.skills.strength >= reqStrength &&
- this.skills.defense >= reqDefense &&
- this.skills.dexterity >= reqDexterity &&
- this.skills.agility >= reqAgility &&
- this.skills.charisma >= reqCharisma &&
- company.playerReputation >= position.requiredReputation
- );
+ const reqs = getJobRequirements(company, position);
+ return reqs.every((req) => req.isSatisfied(this));
}
/********** Reapplying Augmentations and Source File ***********/
diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts
index c83a6d913..930235af1 100644
--- a/src/ScriptEditor/NetscriptDefinitions.d.ts
+++ b/src/ScriptEditor/NetscriptDefinitions.d.ts
@@ -1893,7 +1893,7 @@ export interface Singularity {
* @param field - Field to which you want to apply.
* @returns True if the player successfully get a job/promotion, and false otherwise.
*/
- applyToCompany(companyName: CompanyName | `${CompanyName}`, field: JobField | `${JobField}`): boolean;
+ applyToCompany(companyName: CompanyName | `${CompanyName}`, field: JobField | `${JobField}`): JobName | null;
/**
* Get company reputation.
diff --git a/src/Work/CompanyWork.tsx b/src/Work/CompanyWork.tsx
index 1dde82400..3e8679e38 100644
--- a/src/Work/CompanyWork.tsx
+++ b/src/Work/CompanyWork.tsx
@@ -3,14 +3,13 @@ import { constructorsForReviver, Generic_toJSON, Generic_fromJSON, IReviverValue
import { Player } from "@player";
import { Work, WorkType } from "./Work";
import { influenceStockThroughCompanyWork } from "../StockMarket/PlayerInfluencing";
-import { AugmentationName, CompanyName, JobName } from "@enums";
+import { CompanyName, JobName } from "@enums";
import { calculateCompanyWorkStats } from "./Formulas";
import { Companies } from "../Company/Companies";
import { applyWorkStats, scaleWorkStats, WorkStats } from "./WorkStats";
import { Company } from "../Company/Company";
import { dialogBoxCreate } from "../ui/React/DialogBox";
import { Reputation } from "../ui/React/Reputation";
-import { CONSTANTS } from "../Constants";
import { CompanyPositions } from "../Company/CompanyPositions";
import { isMember } from "../utils/EnumHelper";
import { invalidWork } from "./InvalidWork";
@@ -34,10 +33,7 @@ export class CompanyWork extends Work {
}
getGainRates(job: JobName): WorkStats {
- let focusBonus = 1;
- if (!Player.hasAugmentation(AugmentationName.NeuroreceptorManager, true)) {
- focusBonus = Player.focus ? 1 : CONSTANTS.BaseFocusBonus;
- }
+ const focusBonus = CompanyPositions[job].isPartTime ? 1 : Player.focusPenalty();
const company = this.getCompany();
return scaleWorkStats(calculateCompanyWorkStats(Player, company, CompanyPositions[job], company.favor), focusBonus);
}
diff --git a/src/Work/CreateProgramWork.ts b/src/Work/CreateProgramWork.ts
index 8039306fd..cf8c6d18e 100644
--- a/src/Work/CreateProgramWork.ts
+++ b/src/Work/CreateProgramWork.ts
@@ -1,6 +1,6 @@
import { dialogBoxCreate } from "../ui/React/DialogBox";
import { constructorsForReviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
-import { AugmentationName, CompletedProgramName } from "@enums";
+import { CompletedProgramName } from "@enums";
import { CONSTANTS } from "../Constants";
import { Player } from "@player";
import { Programs } from "../Programs/Programs";
@@ -55,10 +55,7 @@ export class CreateProgramWork extends Work {
}
process(cycles: number): boolean {
- let focusBonus = 1;
- if (!Player.hasAugmentation(AugmentationName.NeuroreceptorManager, true)) {
- focusBonus = Player.focus ? 1 : CONSTANTS.BaseFocusBonus;
- }
+ const focusBonus = Player.focusPenalty();
//Higher hacking skill will allow you to create programs faster
const reqLvl = this.getProgram().create?.level ?? 0;
let skillMult = (Player.skills.hacking / reqLvl) * calculateIntelligenceBonus(Player.skills.intelligence, 3); //This should always be greater than 1;
diff --git a/src/Work/CrimeWork.ts b/src/Work/CrimeWork.ts
index a64fae7cc..1c6cbcf8f 100644
--- a/src/Work/CrimeWork.ts
+++ b/src/Work/CrimeWork.ts
@@ -55,10 +55,10 @@ export class CrimeWork extends Work {
);
return;
}
- const focusPenalty = Player.focusPenalty();
+ const focusBonus = Player.focusPenalty();
// exp times 2 because were trying to maintain the same numbers as before the conversion
// Technically the definition of Crimes should have the success numbers and failure should divide by 4
- let gains = scaleWorkStats(this.earnings(), focusPenalty, false);
+ let gains = scaleWorkStats(this.earnings(), focusBonus, false);
let karma = crime.karma;
const success = determineCrimeSuccess(crime.type);
if (success) {
@@ -75,7 +75,7 @@ export class CrimeWork extends Work {
Player.gainDexterityExp(gains.dexExp);
Player.gainAgilityExp(gains.agiExp);
Player.gainCharismaExp(gains.chaExp);
- Player.karma -= karma * focusPenalty;
+ Player.karma -= karma * focusBonus;
}
finish(): void {
diff --git a/src/Work/FactionWork.tsx b/src/Work/FactionWork.tsx
index 26c17530c..1e1bdafc6 100644
--- a/src/Work/FactionWork.tsx
+++ b/src/Work/FactionWork.tsx
@@ -4,12 +4,11 @@ import React from "react";
import { Work, WorkType } from "./Work";
import { constructorsForReviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
import { Player } from "@player";
-import { AugmentationName, FactionName, FactionWorkType } from "@enums";
+import { FactionName, FactionWorkType } from "@enums";
import { Factions } from "../Faction/Factions";
import { applyWorkStats, scaleWorkStats, WorkStats } from "./WorkStats";
import { dialogBoxCreate } from "../ui/React/DialogBox";
import { Reputation } from "../ui/React/Reputation";
-import { CONSTANTS } from "../Constants";
import { calculateFactionExp, calculateFactionRep } from "./Formulas";
import { getEnumHelper } from "../utils/EnumHelper";
@@ -36,18 +35,12 @@ export class FactionWork extends Work {
}
getReputationRate(): number {
- let focusBonus = 1;
- if (!Player.hasAugmentation(AugmentationName.NeuroreceptorManager, true)) {
- focusBonus = Player.focus ? 1 : CONSTANTS.BaseFocusBonus;
- }
+ const focusBonus = Player.focusPenalty();
return calculateFactionRep(Player, this.factionWorkType, this.getFaction().favor) * focusBonus;
}
getExpRates(): WorkStats {
- let focusBonus = 1;
- if (!Player.hasAugmentation(AugmentationName.NeuroreceptorManager, true)) {
- focusBonus = Player.focus ? 1 : CONSTANTS.BaseFocusBonus;
- }
+ const focusBonus = Player.focusPenalty();
const rate = calculateFactionExp(Player, this.factionWorkType);
return scaleWorkStats(rate, focusBonus, false);
}
diff --git a/src/Work/GraftingWork.tsx b/src/Work/GraftingWork.tsx
index 2bf8145bd..87fa8a902 100644
--- a/src/Work/GraftingWork.tsx
+++ b/src/Work/GraftingWork.tsx
@@ -35,11 +35,7 @@ export class GraftingWork extends Work {
}
process(cycles: number): boolean {
- let focusBonus = 1;
- if (!Player.hasAugmentation(AugmentationName.NeuroreceptorManager, true)) {
- focusBonus = Player.focus ? 1 : CONSTANTS.BaseFocusBonus;
- }
-
+ const focusBonus = Player.focusPenalty();
this.cyclesWorked += cycles;
this.unitCompleted += CONSTANTS.MilliPerCycle * cycles * graftingIntBonus() * focusBonus;
|