bitburner-src/src/Corporation/OfficeSpace.ts

317 lines
11 KiB
TypeScript
Raw Normal View History

2021-08-28 08:50:06 +02:00
import { EmployeePositions } from "./EmployeePositions";
import { CorporationConstants } from "./data/Constants";
import { getRandomInt } from "../../utils/helpers/getRandomInt";
import { formatNumber, generateRandomString } from "../../utils/StringHelperFunctions";
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../../utils/JSONReviver";
2021-08-28 20:45:55 +02:00
import { yesNoTxtInpBoxCreate,
2021-08-28 08:50:06 +02:00
yesNoTxtInpBoxGetYesButton,
yesNoTxtInpBoxGetNoButton,
yesNoTxtInpBoxGetInput,
yesNoTxtInpBoxClose } from "../../utils/YesNoBox";
import { dialogBoxCreate } from "../../utils/DialogBox";
import { createPopup } from "../../utils/uiHelpers/createPopup";
import { removeElementById } from "../../utils/uiHelpers/removeElementById";
import { createElement } from "../../utils/uiHelpers/createElement";
import { numeralWrapper } from "../ui/numeralFormat";
import { Employee } from "./Employee";
2021-08-31 19:04:33 +02:00
import { IIndustry } from "./IIndustry";
import { ICorporation } from './ICorporation';
import { IPlayer } from "../PersonObjects/IPlayer";
2021-08-28 08:50:06 +02:00
interface IParams {
loc?: string;
cost?: number;
size?: number;
comfort?: number;
beauty?: number;
}
export class OfficeSpace {
loc: string;
cost: number;
size: number;
comf: number;
beau: number;
tier = "Basic";
minEne = 0;
maxEne = 100;
minHap = 0;
maxHap = 100;
maxMor = 100;
2021-08-31 21:51:27 +02:00
employees: Employee[] = [];
2021-08-28 08:50:06 +02:00
employeeProd: {[key: string]: number} = {
[EmployeePositions.Operations]: 0,
[EmployeePositions.Engineer]: 0,
[EmployeePositions.Business]: 0,
[EmployeePositions.Management]: 0,
[EmployeePositions.RandD]: 0,
total: 0,
};
constructor(params: IParams = {}) {
this.loc = params.loc ? params.loc : "";
this.cost = params.cost ? params.cost : 1;
this.size = params.size ? params.size : 1;
this.comf = params.comfort ? params.comfort : 1;
this.beau = params.beauty ? params.beauty : 1;
}
atCapacity(): boolean {
return (this.employees.length) >= this.size;
}
2021-08-31 20:47:07 +02:00
process(marketCycles = 1, corporation: ICorporation, industry: IIndustry): number {
2021-08-28 08:50:06 +02:00
// HRBuddy AutoRecruitment and training
if (industry.hasResearch("HRBuddy-Recruitment") && !this.atCapacity()) {
const emp = this.hireRandomEmployee();
if (industry.hasResearch("HRBuddy-Training") && emp !== undefined) {
emp.pos = EmployeePositions.Training;
}
}
// Process Office properties
this.maxEne = 100;
this.maxHap = 100;
this.maxMor = 100;
if (industry.hasResearch("Go-Juice")) {
this.maxEne += 10;
}
if (industry.hasResearch("JoyWire")) {
this.maxHap += 10;
}
if (industry.hasResearch("Sti.mu")) {
this.maxMor += 10;
}
// Calculate changes in Morale/Happiness/Energy for Employees
let perfMult=1; //Multiplier for employee morale/happiness/energy based on company performance
2021-08-31 20:47:07 +02:00
if (corporation.funds < 0 && industry.lastCycleRevenue < 0) {
2021-08-28 08:50:06 +02:00
perfMult = Math.pow(0.99, marketCycles);
2021-08-31 20:47:07 +02:00
} else if (corporation.funds > 0 && industry.lastCycleRevenue > 0) {
2021-08-28 08:50:06 +02:00
perfMult = Math.pow(1.01, marketCycles);
}
const hasAutobrew = industry.hasResearch("AutoBrew");
const hasAutoparty = industry.hasResearch("AutoPartyManager");
let salaryPaid = 0;
for (let i = 0; i < this.employees.length; ++i) {
const emp = this.employees[i];
if (hasAutoparty) {
emp.mor = this.maxMor;
emp.hap = this.maxHap;
} else {
emp.mor *= perfMult;
emp.hap *= perfMult;
emp.mor = Math.min(emp.mor, this.maxMor);
emp.hap = Math.min(emp.hap, this.maxHap);
}
if (hasAutobrew) {
emp.ene = this.maxEne;
} else {
emp.ene *= perfMult;
emp.ene = Math.min(emp.ene, this.maxEne);
}
const salary = emp.process(marketCycles, this);
salaryPaid += salary;
}
2021-08-31 20:47:07 +02:00
this.calculateEmployeeProductivity(corporation, industry);
2021-08-28 08:50:06 +02:00
return salaryPaid;
}
2021-08-31 20:47:07 +02:00
calculateEmployeeProductivity(corporation: ICorporation, industry: IIndustry): void {
2021-08-28 08:50:06 +02:00
//Reset
for (const name in this.employeeProd) {
this.employeeProd[name] = 0;
}
let total = 0;
for (let i = 0; i < this.employees.length; ++i) {
const employee = this.employees[i];
2021-08-31 20:47:07 +02:00
const prod = employee.calculateProductivity(corporation, industry);
2021-08-28 08:50:06 +02:00
this.employeeProd[employee.pos] += prod;
total += prod;
}
this.employeeProd.total = total;
}
//Takes care of UI as well
2021-08-31 20:47:07 +02:00
findEmployees(player: IPlayer, corporation: ICorporation): void {
2021-08-28 08:50:06 +02:00
if (this.atCapacity()) { return; }
if (document.getElementById("cmpy-mgmt-hire-employee-popup") != null) {return;}
//Generate three random employees (meh, decent, amazing)
const mult1 = getRandomInt(25, 50)/100,
mult2 = getRandomInt(51, 75)/100,
mult3 = getRandomInt(76, 100)/100;
const int = getRandomInt(50, 100),
cha = getRandomInt(50, 100),
exp = getRandomInt(50, 100),
cre = getRandomInt(50, 100),
eff = getRandomInt(50, 100),
sal = CorporationConstants.EmployeeSalaryMultiplier * (int + cha + exp + cre + eff);
const emp1 = new Employee({
intelligence: int * mult1,
charisma: cha * mult1,
experience: exp * mult1,
creativity: cre * mult1,
efficiency: eff * mult1,
salary: sal * mult1,
});
const emp2 = new Employee({
intelligence: int * mult2,
charisma: cha * mult2,
experience: exp * mult2,
creativity: cre * mult2,
efficiency: eff * mult2,
salary: sal * mult2,
});
const emp3 = new Employee({
intelligence: int * mult3,
charisma: cha * mult3,
experience: exp * mult3,
creativity: cre * mult3,
efficiency: eff * mult3,
salary: sal * mult3,
});
const text = createElement("h1", {
innerHTML: "Select one of the following candidates for hire:",
});
2021-08-31 21:51:27 +02:00
function createEmpDiv(employee: Employee, office: OfficeSpace): HTMLElement {
2021-08-28 08:50:06 +02:00
const div = createElement("div", {
class:"cmpy-mgmt-find-employee-option",
innerHTML: "Intelligence: " + formatNumber(employee.int, 1) + "<br>" +
"Charisma: " + formatNumber(employee.cha, 1) + "<br>" +
"Experience: " + formatNumber(employee.exp, 1) + "<br>" +
"Creativity: " + formatNumber(employee.cre, 1) + "<br>" +
"Efficiency: " + formatNumber(employee.eff, 1) + "<br>" +
"Salary: " + numeralWrapper.format(employee.sal, '$0.000a') + " \ s<br>",
clickListener: () => {
2021-08-31 20:47:07 +02:00
office.hireEmployee(player, employee, corporation);
2021-08-28 08:50:06 +02:00
removeElementById("cmpy-mgmt-hire-employee-popup");
return false;
},
});
return div;
2021-08-28 20:45:55 +02:00
}
2021-08-28 08:50:06 +02:00
const cancelBtn = createElement("a", {
class:"a-link-button",
innerText:"Cancel",
float:"right",
clickListener:() => {
removeElementById("cmpy-mgmt-hire-employee-popup");
return false;
},
});
const elems = [text,
createEmpDiv(emp1, this),
createEmpDiv(emp2, this),
createEmpDiv(emp3, this),
cancelBtn];
createPopup("cmpy-mgmt-hire-employee-popup", elems);
}
2021-08-31 20:47:07 +02:00
hireEmployee(player: IPlayer, employee: Employee, corporation: ICorporation): void {
2021-08-28 08:50:06 +02:00
const yesBtn = yesNoTxtInpBoxGetYesButton(),
noBtn = yesNoTxtInpBoxGetNoButton();
yesBtn.innerHTML = "Hire";
noBtn.innerHTML = "Cancel";
yesBtn.addEventListener("click", () => {
const name = yesNoTxtInpBoxGetInput();
for (let i = 0; i < this.employees.length; ++i) {
if (this.employees[i].name === name) {
dialogBoxCreate("You already have an employee with this nickname! Please give every employee a unique nickname.");
return false;
}
}
employee.name = name;
this.employees.push(employee);
2021-08-31 19:04:33 +02:00
corporation.rerender(player);
2021-08-28 08:50:06 +02:00
return yesNoTxtInpBoxClose();
});
noBtn.addEventListener("click", () => {
return yesNoTxtInpBoxClose();
});
yesNoTxtInpBoxCreate("Give your employee a nickname!");
}
hireRandomEmployee(): Employee | undefined {
if (this.atCapacity()) return;
if (document.getElementById("cmpy-mgmt-hire-employee-popup") != null) return;
//Generate three random employees (meh, decent, amazing)
const mult = getRandomInt(76, 100)/100;
const int = getRandomInt(50, 100),
cha = getRandomInt(50, 100),
exp = getRandomInt(50, 100),
cre = getRandomInt(50, 100),
eff = getRandomInt(50, 100),
sal = CorporationConstants.EmployeeSalaryMultiplier * (int + cha + exp + cre + eff);
const emp = new Employee({
intelligence: int * mult,
charisma: cha * mult,
experience: exp * mult,
creativity: cre * mult,
efficiency: eff * mult,
salary: sal * mult,
});
const name = generateRandomString(7);
for (let i = 0; i < this.employees.length; ++i) {
if (this.employees[i].name === name) {
return this.hireRandomEmployee();
}
}
emp.name = name;
this.employees.push(emp);
return emp;
}
//Finds the first unassigned employee and assigns its to the specified job
2021-08-31 19:04:33 +02:00
assignEmployeeToJob(job: string): boolean {
2021-08-28 08:50:06 +02:00
for (let i = 0; i < this.employees.length; ++i) {
if (this.employees[i].pos === EmployeePositions.Unassigned) {
this.employees[i].pos = job;
return true;
}
}
return false;
}
//Finds the first employee with the given job and unassigns it
2021-08-31 19:04:33 +02:00
unassignEmployeeFromJob(job: string): boolean {
2021-08-28 08:50:06 +02:00
for (let i = 0; i < this.employees.length; ++i) {
if (this.employees[i].pos === job) {
this.employees[i].pos = EmployeePositions.Unassigned;
return true;
}
}
return false;
}
toJSON(): any {
return Generic_toJSON("OfficeSpace", this);
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
static fromJSON(value: any): OfficeSpace {
return Generic_fromJSON(OfficeSpace, value.data);
}
}
Reviver.constructors.OfficeSpace = OfficeSpace;