mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-26 09:33:49 +01:00
COMPANY: Much better job location interface (#927)
This commit is contained in:
parent
97d679bdac
commit
28ef5df880
@ -56,42 +56,6 @@ export class Company {
|
||||
return this.companyPositions.has(typeof pos === "string" ? pos : pos.name);
|
||||
}
|
||||
|
||||
hasAgentPositions(): boolean {
|
||||
return this.companyPositions.has(JobName.agent0);
|
||||
}
|
||||
|
||||
hasBusinessConsultantPositions(): boolean {
|
||||
return this.companyPositions.has(JobName.businessConsult0);
|
||||
}
|
||||
|
||||
hasBusinessPositions(): boolean {
|
||||
return this.companyPositions.has(JobName.business0);
|
||||
}
|
||||
|
||||
hasEmployeePositions(): boolean {
|
||||
return this.companyPositions.has(JobName.employee);
|
||||
}
|
||||
|
||||
hasITPositions(): boolean {
|
||||
return this.companyPositions.has(JobName.IT0);
|
||||
}
|
||||
|
||||
hasSecurityPositions(): boolean {
|
||||
return this.companyPositions.has(JobName.security0);
|
||||
}
|
||||
|
||||
hasSoftwareConsultantPositions(): boolean {
|
||||
return this.companyPositions.has(JobName.softwareConsult0);
|
||||
}
|
||||
|
||||
hasSoftwarePositions(): boolean {
|
||||
return this.companyPositions.has(JobName.software0);
|
||||
}
|
||||
|
||||
hasWaiterPositions(): boolean {
|
||||
return this.companyPositions.has(JobName.waiter);
|
||||
}
|
||||
|
||||
prestigeAugmentation(): void {
|
||||
if (this.favor == null) this.favor = 0;
|
||||
this.favor += this.getFavorGain();
|
||||
@ -121,7 +85,7 @@ export class Company {
|
||||
return Generic_fromJSON(Company, value.data, Company.includedKeys);
|
||||
}
|
||||
|
||||
// Only these 3 keys are relevant to the save file
|
||||
// Only these 2 keys are relevant to the save file
|
||||
static includedKeys = ["favor", "playerReputation"] as const;
|
||||
}
|
||||
|
||||
|
@ -1,22 +1,16 @@
|
||||
import { Person as IPerson } from "@nsdefs";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { JobName, JobField } from "@enums";
|
||||
import {
|
||||
agentJobs,
|
||||
businessConsultJobs,
|
||||
businessJobs,
|
||||
itJobs,
|
||||
netEngJobs,
|
||||
securityJobs,
|
||||
softwareConsultJobs,
|
||||
softwareJobs,
|
||||
} from "./data/JobTracks";
|
||||
import type { Skills } from "../PersonObjects/Skills";
|
||||
|
||||
export interface CompanyPositionCtorParams {
|
||||
nextPosition: JobName | null;
|
||||
field: JobField;
|
||||
baseSalary: number;
|
||||
repMultiplier: number;
|
||||
applyText?: string;
|
||||
hiredText?: string;
|
||||
isPartTime?: boolean;
|
||||
|
||||
reqdHacking?: number;
|
||||
reqdStrength?: number;
|
||||
@ -60,6 +54,15 @@ export class CompanyPosition {
|
||||
/** Reputation multiplier */
|
||||
repMultiplier: number;
|
||||
|
||||
/** Text to display when applying for this job */
|
||||
applyText: string;
|
||||
|
||||
/** Text to display when receiving this job */
|
||||
hiredText: string;
|
||||
|
||||
/** Whether this position is part-time */
|
||||
isPartTime: boolean;
|
||||
|
||||
/** Required stats to earn this position */
|
||||
requiredAgility: number;
|
||||
requiredCharisma: number;
|
||||
@ -93,6 +96,9 @@ export class CompanyPosition {
|
||||
this.nextPosition = p.nextPosition;
|
||||
this.baseSalary = p.baseSalary;
|
||||
this.repMultiplier = p.repMultiplier;
|
||||
this.isPartTime = p.isPartTime ?? false;
|
||||
this.applyText = p.applyText ?? `Apply for ${this.name} Job`;
|
||||
this.hiredText = p.hiredText ?? `Congratulations, you are now employed as a ${this.name}`;
|
||||
|
||||
this.requiredHacking = p.reqdHacking != null ? p.reqdHacking : 0;
|
||||
this.requiredStrength = p.reqdStrength != null ? p.reqdStrength : 0;
|
||||
@ -130,6 +136,18 @@ export class CompanyPosition {
|
||||
this.charismaExpGain = p.charismaExpGain != null ? p.charismaExpGain : 0;
|
||||
}
|
||||
|
||||
requiredSkills(jobStatReqOffset: number): Skills {
|
||||
return {
|
||||
hacking: this.requiredHacking > 0 ? this.requiredHacking + jobStatReqOffset : 0,
|
||||
strength: this.requiredStrength > 0 ? this.requiredStrength + jobStatReqOffset : 0,
|
||||
defense: this.requiredDefense > 0 ? this.requiredDefense + jobStatReqOffset : 0,
|
||||
dexterity: this.requiredDexterity > 0 ? this.requiredDexterity + jobStatReqOffset : 0,
|
||||
agility: this.requiredAgility > 0 ? this.requiredAgility + jobStatReqOffset : 0,
|
||||
charisma: this.requiredCharisma > 0 ? this.requiredCharisma + jobStatReqOffset : 0,
|
||||
intelligence: 0,
|
||||
};
|
||||
}
|
||||
|
||||
calculateJobPerformance(worker: IPerson): number {
|
||||
const hackRatio: number = (this.hackingEffectiveness * worker.skills.hacking) / CONSTANTS.MaxSkillLevel;
|
||||
const strRatio: number = (this.strengthEffectiveness * worker.skills.strength) / CONSTANTS.MaxSkillLevel;
|
||||
@ -147,44 +165,4 @@ export class CompanyPosition {
|
||||
reputationGain += worker.skills.intelligence / CONSTANTS.MaxSkillLevel;
|
||||
return reputationGain;
|
||||
}
|
||||
|
||||
isSoftwareJob(): boolean {
|
||||
return softwareJobs.includes(this.name);
|
||||
}
|
||||
|
||||
isITJob(): boolean {
|
||||
return itJobs.includes(this.name);
|
||||
}
|
||||
|
||||
isSecurityEngineerJob(): boolean {
|
||||
return this.name === JobName.securityEng;
|
||||
}
|
||||
|
||||
isNetworkEngineerJob(): boolean {
|
||||
return netEngJobs.includes(this.name);
|
||||
}
|
||||
|
||||
isBusinessJob(): boolean {
|
||||
return businessJobs.includes(this.name);
|
||||
}
|
||||
|
||||
isSecurityJob(): boolean {
|
||||
return securityJobs.includes(this.name);
|
||||
}
|
||||
|
||||
isAgentJob(): boolean {
|
||||
return agentJobs.includes(this.name);
|
||||
}
|
||||
|
||||
isSoftwareConsultantJob(): boolean {
|
||||
return softwareConsultJobs.includes(this.name);
|
||||
}
|
||||
|
||||
isBusinessConsultantJob(): boolean {
|
||||
return businessConsultJobs.includes(this.name);
|
||||
}
|
||||
|
||||
isPartTimeJob(): boolean {
|
||||
return [JobName.employeePT, JobName.waiterPT].includes(this.name);
|
||||
}
|
||||
}
|
||||
|
@ -1,51 +0,0 @@
|
||||
import { Company } from "./Company";
|
||||
import { CompanyPosition } from "./CompanyPosition";
|
||||
|
||||
/** Returns a string with the given CompanyPosition's stat requirements */
|
||||
export function getJobRequirementText(company: Company, pos: CompanyPosition, tooltiptext = false): string {
|
||||
let reqText = "";
|
||||
const offset: number = company.jobStatReqOffset;
|
||||
const reqHacking: number = pos.requiredHacking > 0 ? pos.requiredHacking + offset : 0;
|
||||
const reqStrength: number = pos.requiredStrength > 0 ? pos.requiredStrength + offset : 0;
|
||||
const reqDefense: number = pos.requiredDefense > 0 ? pos.requiredDefense + offset : 0;
|
||||
const reqDexterity: number = pos.requiredDexterity > 0 ? pos.requiredDexterity + offset : 0;
|
||||
const reqAgility: number = pos.requiredDexterity > 0 ? pos.requiredDexterity + offset : 0;
|
||||
const reqCharisma: number = pos.requiredCharisma > 0 ? pos.requiredCharisma + offset : 0;
|
||||
const reqRep: number = pos.requiredReputation;
|
||||
if (tooltiptext) {
|
||||
reqText = "Requires:<br>";
|
||||
reqText += reqHacking.toString() + " hacking<br>";
|
||||
reqText += reqStrength.toString() + " strength<br>";
|
||||
reqText += reqDefense.toString() + " defense<br>";
|
||||
reqText += reqDexterity.toString() + " dexterity<br>";
|
||||
reqText += reqAgility.toString() + " agility<br>";
|
||||
reqText += reqCharisma.toString() + " charisma<br>";
|
||||
reqText += reqRep.toString() + " reputation";
|
||||
} else {
|
||||
reqText = "(Requires ";
|
||||
if (reqHacking > 0) {
|
||||
reqText += reqHacking + " hacking, ";
|
||||
}
|
||||
if (reqStrength > 0) {
|
||||
reqText += reqStrength + " strength, ";
|
||||
}
|
||||
if (reqDefense > 0) {
|
||||
reqText += reqDefense + " defense, ";
|
||||
}
|
||||
if (reqDexterity > 0) {
|
||||
reqText += reqDexterity + " dexterity, ";
|
||||
}
|
||||
if (reqAgility > 0) {
|
||||
reqText += reqAgility + " agility, ";
|
||||
}
|
||||
if (reqCharisma > 0) {
|
||||
reqText += reqCharisma + " charisma, ";
|
||||
}
|
||||
if (reqRep > 1) {
|
||||
reqText += reqRep + " reputation, ";
|
||||
}
|
||||
reqText = reqText.substring(0, reqText.length - 2);
|
||||
reqText += ")";
|
||||
}
|
||||
return reqText;
|
||||
}
|
23
src/Company/GetJobRequirements.ts
Normal file
23
src/Company/GetJobRequirements.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { Company } from "./Company";
|
||||
import { CompanyPosition } from "./CompanyPosition";
|
||||
|
||||
import { PlayerCondition, haveSkill, haveCompanyRep } from "../Faction/FactionJoinCondition";
|
||||
import type { Skills } from "../PersonObjects/Skills";
|
||||
|
||||
export function getJobRequirements(company: Company, pos: CompanyPosition): PlayerCondition[] {
|
||||
const reqSkills = pos.requiredSkills(company.jobStatReqOffset);
|
||||
const reqs = [];
|
||||
for (const [skillName, value] of Object.entries(reqSkills)) {
|
||||
if (value > 0) reqs.push(haveSkill(skillName as keyof Skills, value));
|
||||
}
|
||||
if (pos.requiredReputation > 0) {
|
||||
reqs.push(haveCompanyRep(company.name, pos.requiredReputation));
|
||||
}
|
||||
return reqs;
|
||||
}
|
||||
|
||||
/** Returns a string with the given CompanyPosition's stat requirements */
|
||||
export function getJobRequirementText(company: Company, pos: CompanyPosition): string {
|
||||
const reqs = getJobRequirements(company, pos);
|
||||
return `(${pos.name} requires: ${reqs.map((s) => s.toString()).join(", ")})`;
|
||||
}
|
@ -1,14 +1,15 @@
|
||||
import { CompanyCtorParams } from "../Company";
|
||||
|
||||
import { CompanyName, JobName, FactionName } from "@enums";
|
||||
import { CompanyName, FactionName, JobName } from "@enums";
|
||||
import {
|
||||
agentJobs,
|
||||
softwareJobs,
|
||||
businessJobs,
|
||||
itJobs,
|
||||
netEngJobs,
|
||||
securityJobs,
|
||||
softwareConsultJobs,
|
||||
softwareJobs,
|
||||
netEngJobs,
|
||||
itJobs,
|
||||
agentJobs,
|
||||
businessConsultJobs,
|
||||
} from "./JobTracks";
|
||||
|
||||
export function getCompaniesMetadata(): Record<CompanyName, CompanyCtorParams> {
|
||||
@ -107,14 +108,14 @@ export function getCompaniesMetadata(): Record<CompanyName, CompanyCtorParams> {
|
||||
},
|
||||
[CompanyName.DefComm]: {
|
||||
name: CompanyName.DefComm,
|
||||
companyPositions: [JobName.business5, ...allTechJobs, ...softwareConsultJobs],
|
||||
companyPositions: [JobName.business5, ...allTechJobs, ...softwareConsultJobs, ...businessConsultJobs],
|
||||
expMultiplier: 1.75,
|
||||
salaryMultiplier: 1.75,
|
||||
jobStatReqOffset: 199,
|
||||
},
|
||||
[CompanyName.HeliosLabs]: {
|
||||
name: CompanyName.HeliosLabs,
|
||||
companyPositions: [JobName.business5, ...allTechJobs, ...softwareConsultJobs],
|
||||
companyPositions: [JobName.business5, ...allTechJobs, ...softwareConsultJobs, ...businessConsultJobs],
|
||||
expMultiplier: 1.8,
|
||||
salaryMultiplier: 1.8,
|
||||
jobStatReqOffset: 199,
|
||||
@ -149,28 +150,28 @@ export function getCompaniesMetadata(): Record<CompanyName, CompanyCtorParams> {
|
||||
},
|
||||
[CompanyName.AeroCorp]: {
|
||||
name: CompanyName.AeroCorp,
|
||||
companyPositions: [JobName.business3, JobName.business5, ...allTechJobs, ...securityJobs],
|
||||
companyPositions: [JobName.business3, JobName.business5, ...allTechJobs, ...securityJobs, ...businessConsultJobs],
|
||||
expMultiplier: 1.7,
|
||||
salaryMultiplier: 1.7,
|
||||
jobStatReqOffset: 199,
|
||||
},
|
||||
[CompanyName.OmniaCybersystems]: {
|
||||
name: CompanyName.OmniaCybersystems,
|
||||
companyPositions: [JobName.business3, JobName.business5, ...allTechJobs, ...securityJobs],
|
||||
companyPositions: [JobName.business3, JobName.business5, ...allTechJobs, ...securityJobs, ...businessConsultJobs],
|
||||
expMultiplier: 1.7,
|
||||
salaryMultiplier: 1.7,
|
||||
jobStatReqOffset: 199,
|
||||
},
|
||||
[CompanyName.SolarisSpaceSystems]: {
|
||||
name: CompanyName.SolarisSpaceSystems,
|
||||
companyPositions: [JobName.business3, JobName.business5, ...allTechJobs, ...securityJobs],
|
||||
companyPositions: [JobName.business3, JobName.business5, ...allTechJobs, ...securityJobs, ...businessConsultJobs],
|
||||
expMultiplier: 1.7,
|
||||
salaryMultiplier: 1.7,
|
||||
jobStatReqOffset: 199,
|
||||
},
|
||||
[CompanyName.DeltaOne]: {
|
||||
name: CompanyName.DeltaOne,
|
||||
companyPositions: [JobName.business3, JobName.business5, ...allTechJobs, ...securityJobs],
|
||||
companyPositions: [JobName.business3, JobName.business5, ...allTechJobs, ...securityJobs, ...businessConsultJobs],
|
||||
expMultiplier: 1.6,
|
||||
salaryMultiplier: 1.6,
|
||||
jobStatReqOffset: 199,
|
||||
|
@ -65,6 +65,7 @@ export function getCompanyPositionMetadata(): Record<JobName, CompanyPositionCto
|
||||
reqdHacking: 501,
|
||||
reqdReputation: 400e3,
|
||||
repMultiplier: 1.6,
|
||||
hiredText: `Congratulations, you are now ${JobName.software4}`,
|
||||
},
|
||||
[JobName.software5]: {
|
||||
nextPosition: JobName.software6, // Vice President of Technology
|
||||
@ -78,6 +79,7 @@ export function getCompanyPositionMetadata(): Record<JobName, CompanyPositionCto
|
||||
reqdHacking: 501,
|
||||
reqdReputation: 800e3,
|
||||
repMultiplier: 1.6,
|
||||
hiredText: `Congratulations, you are now ${JobName.software5}`,
|
||||
},
|
||||
[JobName.software6]: {
|
||||
nextPosition: JobName.software7, // Chief Technology Officer
|
||||
@ -91,6 +93,7 @@ export function getCompanyPositionMetadata(): Record<JobName, CompanyPositionCto
|
||||
reqdHacking: 601,
|
||||
reqdReputation: 1.6e6,
|
||||
repMultiplier: 1.75,
|
||||
hiredText: `Congratulations, you are now ${JobName.software6}`,
|
||||
},
|
||||
[JobName.software7]: {
|
||||
nextPosition: null,
|
||||
@ -104,6 +107,7 @@ export function getCompanyPositionMetadata(): Record<JobName, CompanyPositionCto
|
||||
reqdHacking: 751,
|
||||
reqdReputation: 3.2e6,
|
||||
repMultiplier: 2,
|
||||
hiredText: `Congratulations, you are now ${JobName.software7}`,
|
||||
},
|
||||
[JobName.IT0]: {
|
||||
nextPosition: JobName.IT1, // IT Analyst
|
||||
@ -256,6 +260,7 @@ export function getCompanyPositionMetadata(): Record<JobName, CompanyPositionCto
|
||||
reqdHacking: 76,
|
||||
reqdReputation: 800e3,
|
||||
repMultiplier: 1.6,
|
||||
hiredText: `Congratulations, you are now ${JobName.business4}`,
|
||||
},
|
||||
[JobName.business5]: {
|
||||
nextPosition: null,
|
||||
@ -269,6 +274,7 @@ export function getCompanyPositionMetadata(): Record<JobName, CompanyPositionCto
|
||||
reqdHacking: 101,
|
||||
reqdReputation: 3.2e6,
|
||||
repMultiplier: 1.75,
|
||||
hiredText: `Congratulations, you are now ${JobName.business5}`,
|
||||
},
|
||||
[JobName.security0]: {
|
||||
nextPosition: JobName.security1, // Security Officer
|
||||
@ -457,6 +463,8 @@ export function getCompanyPositionMetadata(): Record<JobName, CompanyPositionCto
|
||||
agilityExpGain: 0.02,
|
||||
charismaExpGain: 0.05,
|
||||
repMultiplier: 1,
|
||||
applyText: `Apply to be a ${JobName.waiter}`,
|
||||
hiredText: `Congratulations, you are now employed as a ${JobName.waiter}`,
|
||||
},
|
||||
[JobName.employee]: {
|
||||
nextPosition: null,
|
||||
@ -472,6 +480,8 @@ export function getCompanyPositionMetadata(): Record<JobName, CompanyPositionCto
|
||||
agilityExpGain: 0.02,
|
||||
charismaExpGain: 0.04,
|
||||
repMultiplier: 1,
|
||||
applyText: `Apply to be an ${JobName.employee}`,
|
||||
hiredText: "Congratulations, you are now employed",
|
||||
},
|
||||
[JobName.softwareConsult0]: {
|
||||
nextPosition: JobName.softwareConsult1, // Senior Software Consultant
|
||||
@ -483,6 +493,8 @@ export function getCompanyPositionMetadata(): Record<JobName, CompanyPositionCto
|
||||
charismaExpGain: 0.03,
|
||||
reqdHacking: 51,
|
||||
repMultiplier: 1,
|
||||
applyText: `Pitch a Software Consulting contract`,
|
||||
hiredText: `Congratulations, you got a contract as a ${JobName.softwareConsult0}`,
|
||||
},
|
||||
[JobName.softwareConsult1]: {
|
||||
nextPosition: null,
|
||||
@ -495,6 +507,8 @@ export function getCompanyPositionMetadata(): Record<JobName, CompanyPositionCto
|
||||
reqdHacking: 251,
|
||||
reqdCharisma: 51,
|
||||
repMultiplier: 1.2,
|
||||
applyText: `Pitch a Software Consulting contract`,
|
||||
hiredText: `Congratulations, you got a contract as a ${JobName.softwareConsult1}`,
|
||||
},
|
||||
[JobName.businessConsult0]: {
|
||||
nextPosition: JobName.businessConsult1, // Senior Business Consultant
|
||||
@ -507,6 +521,8 @@ export function getCompanyPositionMetadata(): Record<JobName, CompanyPositionCto
|
||||
reqdHacking: 6,
|
||||
reqdCharisma: 51,
|
||||
repMultiplier: 1,
|
||||
applyText: `Pitch a Business Consulting contract`,
|
||||
hiredText: `Congratulations, you got a contract as a ${JobName.businessConsult0}`,
|
||||
},
|
||||
[JobName.businessConsult1]: {
|
||||
nextPosition: null,
|
||||
@ -519,10 +535,12 @@ export function getCompanyPositionMetadata(): Record<JobName, CompanyPositionCto
|
||||
reqdHacking: 51,
|
||||
reqdCharisma: 226,
|
||||
repMultiplier: 1.2,
|
||||
applyText: `Pitch a Business Consulting contract`,
|
||||
hiredText: `Congratulations, you got a contract as a ${JobName.businessConsult1}`,
|
||||
},
|
||||
[JobName.waiterPT]: {
|
||||
nextPosition: null,
|
||||
field: JobField.partTimeWaiter,
|
||||
field: JobField.waiter,
|
||||
baseSalary: 20,
|
||||
strengthEffectiveness: 10,
|
||||
dexterityEffectiveness: 10,
|
||||
@ -534,10 +552,13 @@ export function getCompanyPositionMetadata(): Record<JobName, CompanyPositionCto
|
||||
agilityExpGain: 0.0075,
|
||||
charismaExpGain: 0.04,
|
||||
repMultiplier: 1,
|
||||
isPartTime: true,
|
||||
applyText: `Apply to be a ${JobName.waiterPT}`,
|
||||
hiredText: `Congratulations, you are now employed as a ${JobName.waiterPT}`,
|
||||
},
|
||||
[JobName.employeePT]: {
|
||||
nextPosition: null,
|
||||
field: JobField.partTimeEmployee,
|
||||
field: JobField.employee,
|
||||
baseSalary: 20,
|
||||
strengthEffectiveness: 10,
|
||||
dexterityEffectiveness: 10,
|
||||
@ -549,6 +570,9 @@ export function getCompanyPositionMetadata(): Record<JobName, CompanyPositionCto
|
||||
agilityExpGain: 0.0075,
|
||||
charismaExpGain: 0.03,
|
||||
repMultiplier: 1,
|
||||
isPartTime: true,
|
||||
applyText: `Apply to be a ${JobName.employeePT}`,
|
||||
hiredText: "Congratulations, you are now employed part-time",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { JobName } from "@enums";
|
||||
export const softwareJobs = [
|
||||
import { JobName, JobField } from "@enums";
|
||||
|
||||
export const JobTracks: Record<JobField, readonly JobName[]> = {
|
||||
[JobField.software]: [
|
||||
JobName.software0,
|
||||
JobName.software1,
|
||||
JobName.software2,
|
||||
@ -8,18 +10,33 @@ export const softwareJobs = [
|
||||
JobName.software5,
|
||||
JobName.software6,
|
||||
JobName.software7,
|
||||
];
|
||||
export const itJobs = [JobName.IT0, JobName.IT1, JobName.IT2, JobName.IT3];
|
||||
export const netEngJobs = [JobName.networkEng0, JobName.networkEng1];
|
||||
export const businessJobs = [
|
||||
],
|
||||
[JobField.softwareConsultant]: [JobName.softwareConsult0, JobName.softwareConsult1],
|
||||
[JobField.it]: [JobName.IT0, JobName.IT1, JobName.IT2, JobName.IT3],
|
||||
[JobField.securityEngineer]: [JobName.securityEng],
|
||||
[JobField.networkEngineer]: [JobName.networkEng0, JobName.networkEng1],
|
||||
[JobField.business]: [
|
||||
JobName.business0,
|
||||
JobName.business1,
|
||||
JobName.business2,
|
||||
JobName.business3,
|
||||
JobName.business4,
|
||||
JobName.business5,
|
||||
];
|
||||
export const securityJobs = [JobName.security0, JobName.security1, JobName.security2, JobName.security3];
|
||||
export const agentJobs = [JobName.agent0, JobName.agent1, JobName.agent2];
|
||||
export const softwareConsultJobs = [JobName.softwareConsult0, JobName.softwareConsult1];
|
||||
export const businessConsultJobs = [JobName.businessConsult0, JobName.businessConsult1];
|
||||
],
|
||||
[JobField.businessConsultant]: [JobName.businessConsult0, JobName.businessConsult1],
|
||||
[JobField.security]: [JobName.security0, JobName.security1, JobName.security2, JobName.security3],
|
||||
[JobField.agent]: [JobName.agent0, JobName.agent1, JobName.agent2],
|
||||
[JobField.employee]: [JobName.employee],
|
||||
[JobField.partTimeEmployee]: [JobName.employeePT],
|
||||
[JobField.waiter]: [JobName.waiter],
|
||||
[JobField.partTimeWaiter]: [JobName.waiterPT],
|
||||
} as const;
|
||||
|
||||
export const softwareJobs = JobTracks[JobField.software];
|
||||
export const itJobs = JobTracks[JobField.it];
|
||||
export const netEngJobs = JobTracks[JobField.networkEngineer];
|
||||
export const businessJobs = JobTracks[JobField.business];
|
||||
export const securityJobs = JobTracks[JobField.security];
|
||||
export const agentJobs = JobTracks[JobField.agent];
|
||||
export const softwareConsultJobs = JobTracks[JobField.softwareConsultant];
|
||||
export const businessConsultJobs = JobTracks[JobField.businessConsultant];
|
||||
|
74
src/Company/ui/ApplyToJobButton.tsx
Normal file
74
src/Company/ui/ApplyToJobButton.tsx
Normal file
@ -0,0 +1,74 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { Company } from "../Company";
|
||||
import { CompanyPosition } from "../CompanyPosition";
|
||||
|
||||
import { Player } from "@player";
|
||||
import { Typography } from "@mui/material";
|
||||
import { ButtonWithTooltip } from "../../ui/Components/ButtonWithTooltip";
|
||||
import { CompanyPositions } from "../CompanyPositions";
|
||||
import { JobSummary } from "./JobSummary";
|
||||
import { Requirement } from "../../ui/Components/Requirement";
|
||||
import { getJobRequirements } from "../GetJobRequirements";
|
||||
|
||||
interface IProps {
|
||||
company: Company;
|
||||
position: CompanyPosition;
|
||||
currentPosition: CompanyPosition | null;
|
||||
}
|
||||
|
||||
/** React Component for a button that's used to apply for a job */
|
||||
export function ApplyToJobButton(props: IProps): React.ReactElement {
|
||||
const underqualified = !Player.isQualified(props.company, props.position);
|
||||
const nextPos = props.position.nextPosition && CompanyPositions[props.position.nextPosition];
|
||||
const overqualified = nextPos != null && Player.isQualified(props.company, nextPos);
|
||||
|
||||
const reqs = getJobRequirements(props.company, props.position);
|
||||
const positionRequirements =
|
||||
reqs.length == 0 ? (
|
||||
<Typography>Accepting all applicants</Typography>
|
||||
) : (
|
||||
<>
|
||||
<Typography>Requirements:</Typography>
|
||||
{reqs.map((req, i) => (
|
||||
<Requirement key={i} fulfilled={req.isSatisfied(Player)} value={req.toString()} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
|
||||
const positionDetails = (
|
||||
<>
|
||||
<JobSummary company={props.company} position={props.position} overqualified={overqualified} />
|
||||
{props.position.isPartTime && (
|
||||
<Typography>
|
||||
<br />
|
||||
Part-time jobs have no penalty for
|
||||
<br /> doing something else simultaneously.
|
||||
</Typography>
|
||||
)}
|
||||
<br />
|
||||
{positionRequirements}
|
||||
{overqualified && (
|
||||
<Typography>
|
||||
<br />
|
||||
You are overqualified for this position.
|
||||
</Typography>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
function applyForJob(): void {
|
||||
Player.applyForJob(props.company, props.position);
|
||||
}
|
||||
|
||||
return (
|
||||
<ButtonWithTooltip
|
||||
disabledTooltip={underqualified && positionDetails}
|
||||
normalTooltip={positionDetails}
|
||||
onClick={applyForJob}
|
||||
tooltipProps={{ style: { display: "grid" } }}
|
||||
>
|
||||
{props.position.applyText}
|
||||
</ButtonWithTooltip>
|
||||
);
|
||||
}
|
40
src/Company/ui/JobListings.tsx
Normal file
40
src/Company/ui/JobListings.tsx
Normal file
@ -0,0 +1,40 @@
|
||||
import type { Company } from "../Company";
|
||||
import type { CompanyPosition } from "../CompanyPosition";
|
||||
|
||||
import React from "react";
|
||||
|
||||
import { CompanyPositions } from "../CompanyPositions";
|
||||
import { ApplyToJobButton } from "./ApplyToJobButton";
|
||||
import { Player } from "@player";
|
||||
|
||||
interface IJobListingsProps {
|
||||
company: Company;
|
||||
currentPosition: CompanyPosition | null;
|
||||
}
|
||||
|
||||
export function JobListings(props: IJobListingsProps): React.ReactElement {
|
||||
const { company, currentPosition } = props;
|
||||
|
||||
const jobsToShow = [];
|
||||
for (const jobName of company.companyPositions) {
|
||||
const offeredPos = CompanyPositions[jobName];
|
||||
const underqualified = !Player.isQualified(props.company, offeredPos);
|
||||
const isCurrentPosition = jobName == props.currentPosition?.name;
|
||||
const nextPos = offeredPos.nextPosition && CompanyPositions[offeredPos.nextPosition];
|
||||
const overqualified = nextPos != null && Player.isQualified(props.company, nextPos);
|
||||
const shouldShowApplyButton =
|
||||
!isCurrentPosition && !overqualified && (!underqualified || offeredPos.requiredReputation == 0);
|
||||
|
||||
if (shouldShowApplyButton) {
|
||||
jobsToShow.push(offeredPos);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{jobsToShow.map((position) => (
|
||||
<ApplyToJobButton key={position.name} company={company} position={position} currentPosition={currentPosition} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
35
src/Company/ui/JobSummary.tsx
Normal file
35
src/Company/ui/JobSummary.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import { Typography } from "@mui/material";
|
||||
import { Player } from "@player";
|
||||
import * as React from "react";
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { calculateCompanyWorkStats } from "../../Work/Formulas";
|
||||
import { MoneyRate } from "../../ui/React/MoneyRate";
|
||||
import { ReputationRate } from "../../ui/React/ReputationRate";
|
||||
import { StatsTable } from "../../ui/React/StatsTable";
|
||||
import type { Company } from "../Company";
|
||||
import type { CompanyPosition } from "../CompanyPosition";
|
||||
|
||||
const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle;
|
||||
interface IJobSummaryProps {
|
||||
company: Company;
|
||||
position: CompanyPosition;
|
||||
overqualified?: boolean;
|
||||
}
|
||||
|
||||
export function JobSummary(props: IJobSummaryProps): React.ReactElement {
|
||||
const workStats = calculateCompanyWorkStats(Player, props.company, props.position, props.company.favor);
|
||||
return (
|
||||
<>
|
||||
<Typography>
|
||||
<u>{props.position.name}</u>
|
||||
</Typography>
|
||||
<StatsTable
|
||||
wide
|
||||
rows={[
|
||||
["Wages:", <MoneyRate key="money" money={workStats.money * CYCLES_PER_SEC} />],
|
||||
["Reputation:", <ReputationRate key="rep" reputation={workStats.reputation * CYCLES_PER_SEC} />],
|
||||
]}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
@ -43,6 +43,20 @@ export function ServersDev(): React.ReactElement {
|
||||
}
|
||||
}
|
||||
|
||||
function backdoorServer(): void {
|
||||
const s = GetServer(server);
|
||||
if (s === null) return;
|
||||
if (!(s instanceof Server)) return;
|
||||
s.backdoorInstalled = true;
|
||||
}
|
||||
|
||||
function backdoorAllServers(): void {
|
||||
for (const s of GetAllServers()) {
|
||||
if (!(s instanceof Server)) return;
|
||||
s.backdoorInstalled = true;
|
||||
}
|
||||
}
|
||||
|
||||
function minSecurity(): void {
|
||||
const s = GetServer(server);
|
||||
if (s === null) return;
|
||||
@ -118,6 +132,17 @@ export function ServersDev(): React.ReactElement {
|
||||
<Button onClick={rootAllServers}>Root all</Button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Typography>Backdoor:</Typography>
|
||||
</td>
|
||||
<td>
|
||||
<Button onClick={backdoorServer}>Backdoor one</Button>
|
||||
</td>
|
||||
<td>
|
||||
<Button onClick={backdoorAllServers}>Backdoor all</Button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<Typography>Security:</Typography>
|
||||
|
@ -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<HTMLElement>) => 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 (
|
||||
<>
|
||||
<Tooltip title={<span dangerouslySetInnerHTML={{ __html: getJobRequirementTooltip() }}></span>}>
|
||||
<Button onClick={props.onClick}>{props.text}</Button>
|
||||
</Tooltip>
|
||||
</>
|
||||
);
|
||||
}
|
@ -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<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Player.applyForAgentJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
function applyForBusinessConsultantJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Player.applyForBusinessConsultantJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
function applyForBusinessJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Player.applyForBusinessJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
function applyForEmployeeJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Player.applyForEmployeeJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
function applyForItJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Player.applyForItJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
function applyForPartTimeEmployeeJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Player.applyForPartTimeEmployeeJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
function applyForPartTimeWaiterJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Player.applyForPartTimeWaiterJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
function applyForSecurityJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Player.applyForSecurityJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
function applyForSoftwareConsultantJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Player.applyForSoftwareConsultantJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
function applyForSoftwareJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Player.applyForSoftwareJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
function applyForWaiterJob(e: React.MouseEvent<HTMLElement>): void {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
Player.applyForWaiterJob();
|
||||
rerender();
|
||||
}
|
||||
|
||||
function startInfiltration(e: React.MouseEvent<HTMLElement>): 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,26 +97,27 @@ 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 (
|
||||
<>
|
||||
<Box sx={{ display: "grid", width: "fit-content", minWidth: "25em" }}>
|
||||
{isEmployedHere && hasMoreJobs && (
|
||||
<>
|
||||
<Box>
|
||||
<Button onClick={() => switchLoc(-1)}>Previous</Button>
|
||||
<Button onClick={() => switchLoc(1)}>Next</Button>
|
||||
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
|
||||
<Button onClick={() => switchLoc(-1)}>Previous Job</Button>
|
||||
<Button onClick={() => switchLoc(1)}>Next Job</Button>
|
||||
</Box>
|
||||
<br />
|
||||
</>
|
||||
)}
|
||||
{isEmployedHere && (
|
||||
<>
|
||||
<Typography>Job Title: {jobTitle}</Typography>
|
||||
<Typography>-------------------------</Typography>
|
||||
<Box display="flex">
|
||||
<Paper sx={{ p: "0.5em 1em", mt: 2, mb: 2 }}>
|
||||
<JobSummary company={company} position={currentPosition} />
|
||||
<StatsTable
|
||||
wide
|
||||
rows={[
|
||||
[
|
||||
<Tooltip
|
||||
key="repLabel"
|
||||
title={
|
||||
<>
|
||||
You will have <Favor favor={company.favor + favorGain} /> company favor upon resetting after
|
||||
@ -216,32 +125,30 @@ export function CompanyLocation(props: IProps): React.ReactElement {
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Typography>
|
||||
Company reputation: <Reputation reputation={company.playerReputation} />
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
<Typography>-------------------------</Typography>
|
||||
<Box display="flex">
|
||||
<Typography>Total reputation:</Typography>
|
||||
</Tooltip>,
|
||||
<Reputation key="rep" reputation={company.playerReputation} />,
|
||||
],
|
||||
[
|
||||
<Tooltip
|
||||
key="favorLabel"
|
||||
title={
|
||||
<>
|
||||
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 is gained whenever you reset after installing Augmentations. The amount of favor
|
||||
you gain depends on how much reputation you have with the company.
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Typography>
|
||||
Company Favor: <Favor favor={company.favor} />
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
<Typography>-------------------------</Typography>
|
||||
<br />
|
||||
</>
|
||||
<Typography>Company favor:</Typography>
|
||||
</Tooltip>,
|
||||
<Favor key="favor" favor={company.favor} />,
|
||||
],
|
||||
]}
|
||||
/>
|
||||
</Paper>
|
||||
)}
|
||||
<Box sx={{ display: "grid", width: "fit-content" }}>
|
||||
|
||||
{isEmployedHere && (
|
||||
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 1fr" }}>
|
||||
<Button onClick={work}>Work</Button>
|
||||
@ -255,94 +162,9 @@ export function CompanyLocation(props: IProps): React.ReactElement {
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
{company.hasAgentPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[JobName.agent0]}
|
||||
onClick={applyForAgentJob}
|
||||
text={"Apply for " + JobField.agent + " Job"}
|
||||
/>
|
||||
)}
|
||||
{company.hasBusinessConsultantPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[JobName.businessConsult0]}
|
||||
onClick={applyForBusinessConsultantJob}
|
||||
text={"Apply for " + JobField.businessConsultant + " Job"}
|
||||
/>
|
||||
)}
|
||||
{company.hasBusinessPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[JobName.business0]}
|
||||
onClick={applyForBusinessJob}
|
||||
text={"Apply for " + JobField.business + " Job"}
|
||||
/>
|
||||
)}
|
||||
{company.hasEmployeePositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[JobName.employee]}
|
||||
onClick={applyForEmployeeJob}
|
||||
text={"Apply to be an " + JobField.employee}
|
||||
/>
|
||||
)}
|
||||
{company.hasEmployeePositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[JobName.employeePT]}
|
||||
onClick={applyForPartTimeEmployeeJob}
|
||||
text={"Apply to be a " + JobField.partTimeEmployee}
|
||||
/>
|
||||
)}
|
||||
{company.hasITPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[JobName.IT0]}
|
||||
onClick={applyForItJob}
|
||||
text={"Apply for " + JobField.it + " Job"}
|
||||
/>
|
||||
)}
|
||||
{company.hasSecurityPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[JobName.security0]}
|
||||
onClick={applyForSecurityJob}
|
||||
text={"Apply for " + JobField.security + " Job"}
|
||||
/>
|
||||
)}
|
||||
{company.hasSoftwareConsultantPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[JobName.softwareConsult0]}
|
||||
onClick={applyForSoftwareConsultantJob}
|
||||
text={"Apply for " + JobField.softwareConsultant + " Job"}
|
||||
/>
|
||||
)}
|
||||
{company.hasSoftwarePositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[JobName.software0]}
|
||||
onClick={applyForSoftwareJob}
|
||||
text={"Apply for " + JobField.software + " Job"}
|
||||
/>
|
||||
)}
|
||||
{company.hasWaiterPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[JobName.waiter]}
|
||||
onClick={applyForWaiterJob}
|
||||
text={"Apply to be a " + JobField.waiter}
|
||||
/>
|
||||
)}
|
||||
{company.hasWaiterPositions() && (
|
||||
<ApplyToJobButton
|
||||
company={company}
|
||||
entryPosType={CompanyPositions[JobName.waiterPT]}
|
||||
onClick={applyForPartTimeWaiterJob}
|
||||
text={"Apply to be a " + JobField.partTimeWaiter}
|
||||
/>
|
||||
)}
|
||||
|
||||
{company.companyPositions.size > 0 && <JobListings company={company} currentPosition={currentPosition} />}
|
||||
|
||||
{location.infiltrationData != null && <Button onClick={startInfiltration}>Infiltrate Company</Button>}
|
||||
</Box>
|
||||
</>
|
||||
|
@ -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<ISingularity> {
|
||||
const runAfterReset = function (cbScript: ScriptFilePath) {
|
||||
@ -687,20 +686,12 @@ export function NetscriptSingularity(): InternalAPI<ISingularity> {
|
||||
|
||||
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<ISingularity> {
|
||||
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);
|
||||
|
@ -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;
|
||||
|
@ -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 ***********/
|
||||
|
2
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
2
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user