diff --git a/src/Corporation/Actions.ts b/src/Corporation/Actions.ts index acd211467..55c6b646f 100644 --- a/src/Corporation/Actions.ts +++ b/src/Corporation/Actions.ts @@ -13,8 +13,6 @@ import { CorporationUnlockUpgrade } from "./data/CorporationUnlockUpgrades"; import { CorporationUpgrade } from "./data/CorporationUpgrades"; import { Cities } from "../Locations/Cities"; import { EmployeePositions } from "./EmployeePositions"; -import { Employee } from "./Employee"; -import { IndustryUpgrades } from "./IndustryUpgrades"; import { ResearchMap } from "./ResearchMap"; import { isRelevantMaterial } from "./ui/Helpers"; @@ -304,9 +302,19 @@ export function BuyBackShares(corporation: ICorporation, player: IPlayer, numSha return true; } -export function AssignJob(employee: Employee, job: string): void { +export function AssignJob(office: OfficeSpace, employeeName: string, job: string): void { + const employee = office.employees.find((e) => e.name === employeeName); + + if (!employee) throw new Error(`Could not find employee '${name}'.`); if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`); - employee.pos = job; + + office.assignSingleJob(employee, job); +} + +export function AutoAssignJob(office: OfficeSpace, job: string, count: number): boolean { + if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`); + + return office.autoAssignJob(job, count); } export function UpgradeOfficeSize(corp: ICorporation, office: OfficeSpace, size: number): void { @@ -323,15 +331,32 @@ export function UpgradeOfficeSize(corp: ICorporation, office: OfficeSpace, size: corp.funds = corp.funds - cost; } -export function ThrowParty(corp: ICorporation, office: OfficeSpace, costPerEmployee: number): number { - const totalCost = costPerEmployee * office.employees.length; - if (corp.funds < totalCost) return 0; - corp.funds = corp.funds - totalCost; - let mult = 0; - for (let i = 0; i < office.employees.length; ++i) { - mult = office.employees[i].throwParty(costPerEmployee); +export function BuyCoffee(corp: ICorporation, office: OfficeSpace): boolean { + const cost = office.getCoffeeCost(); + if (corp.funds < cost) { + return false; } + if (!office.setCoffee()) { + return false; + } + corp.funds -= cost; + + return true; +} + +export function ThrowParty(corp: ICorporation, office: OfficeSpace, costPerEmployee: number): number { + const mult = 1 + costPerEmployee / 10e6; + const cost = costPerEmployee * office.employees.length; + if (corp.funds < cost) { + return 0; + } + + if (!office.setParty(mult)) { + return 0; + } + corp.funds -= cost; + return mult; } @@ -362,26 +387,11 @@ export function UpgradeWarehouse(corp: ICorporation, division: IIndustry, wareho corp.funds = corp.funds - sizeUpgradeCost; } -export function BuyCoffee(corp: ICorporation, division: IIndustry, office: OfficeSpace): void { - const upgrade = IndustryUpgrades[0]; - const cost = office.employees.length * upgrade[1]; +export function HireAdVert(corp: ICorporation, division: IIndustry): void { + const cost = division.getAdVertCost(); if (corp.funds < cost) return; corp.funds = corp.funds - cost; - division.upgrade(upgrade, { - corporation: corp, - office: office, - }); -} - -export function HireAdVert(corp: ICorporation, division: IIndustry, office: OfficeSpace): void { - const upgrade = IndustryUpgrades[1]; - const cost = upgrade[1] * Math.pow(upgrade[2], division.upgrades[1]); - if (corp.funds < cost) return; - corp.funds = corp.funds - cost; - division.upgrade(upgrade, { - corporation: corp, - office: office, - }); + division.applyAdVert(corp); } export function MakeProduct( diff --git a/src/Corporation/Employee.ts b/src/Corporation/Employee.ts index 60a08f202..bed72a99c 100644 --- a/src/Corporation/Employee.ts +++ b/src/Corporation/Employee.ts @@ -3,7 +3,6 @@ import { getRandomInt } from "../utils/helpers/getRandomInt"; import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver"; import { EmployeePositions } from "./EmployeePositions"; import { ICorporation } from "./ICorporation"; -import { OfficeSpace } from "./OfficeSpace"; import { IIndustry } from "./IIndustry"; interface IParams { @@ -34,6 +33,7 @@ export class Employee { cyclesUntilRaise = CorporationConstants.CyclesPerEmployeeRaise; loc: string; pos: string; + nextPos: string; constructor(params: IParams = {}) { this.name = params.name ? params.name : "Bobby"; @@ -52,12 +52,13 @@ export class Employee { this.loc = params.loc ? params.loc : ""; this.pos = EmployeePositions.Unassigned; + this.nextPos = this.pos; } //Returns the amount the employee needs to be paid - process(marketCycles = 1, office: OfficeSpace): number { - const gain = 0.003 * marketCycles, - det = gain * Math.random(); + process(marketCycles = 1): number { + const gain = 0.003 * marketCycles; + const det = gain * Math.random(); this.exp += gain; //Training @@ -72,12 +73,6 @@ export class Employee { this.ene -= det; this.hap -= det; - if (this.ene < office.minEne) { - this.ene = office.minEne; - } - if (this.hap < office.minHap) { - this.hap = office.minHap; - } const salary = this.sal * marketCycles * CorporationConstants.SecsPerMarketCycle; return salary; } @@ -118,16 +113,6 @@ export class Employee { return prodBase * prodMult; } - //Process benefits from having an office party thrown - throwParty(money: number): number { - const mult = 1 + money / 10e6; - this.mor *= mult; - this.mor = Math.min(100, this.mor); - this.hap *= mult; - this.hap = Math.min(100, this.hap); - return mult; - } - toJSON(): any { return Generic_toJSON("Employee", this); } diff --git a/src/Corporation/IIndustry.ts b/src/Corporation/IIndustry.ts index 1cb5737ea..7b465720d 100644 --- a/src/Corporation/IIndustry.ts +++ b/src/Corporation/IIndustry.ts @@ -3,7 +3,6 @@ import { Warehouse } from "./Warehouse"; import { ICorporation } from "./ICorporation"; import { OfficeSpace } from "./OfficeSpace"; import { Product } from "./Product"; -import { IndustryUpgrade } from "./IndustryUpgrades"; export interface IIndustry { name: string; @@ -36,12 +35,11 @@ export interface IIndustry { thisCycleRevenue: number; thisCycleExpenses: number; - upgrades: number[]; - state: string; newInd: boolean; warehouses: { [key: string]: Warehouse | 0 }; offices: { [key: string]: OfficeSpace | 0 }; + numAdVerts: number; init(): void; getProductDescriptionText(): string; @@ -56,7 +54,8 @@ export interface IIndustry { processProducts(marketCycles: number, corporation: ICorporation): [number, number]; processProduct(marketCycles: number, product: Product, corporation: ICorporation): number; discontinueProduct(product: Product): void; - upgrade(upgrade: IndustryUpgrade, refs: { corporation: ICorporation; office: OfficeSpace }): void; + getAdVertCost(): number; + applyAdVert(corporation: ICorporation): void; getOfficeProductivity(office: OfficeSpace, params?: { forProduct?: boolean }): number; getBusinessFactor(office: OfficeSpace): number; getAdvertisingFactors(): [number, number, number, number]; diff --git a/src/Corporation/Industry.ts b/src/Corporation/Industry.ts index f2a12e129..21dc4d6af 100644 --- a/src/Corporation/Industry.ts +++ b/src/Corporation/Industry.ts @@ -14,7 +14,6 @@ import { MaterialSizes } from "./MaterialSizes"; import { Warehouse } from "./Warehouse"; import { ICorporation } from "./ICorporation"; import { IIndustry } from "./IIndustry"; -import { IndustryUpgrade, IndustryUpgrades } from "./IndustryUpgrades"; interface IParams { name?: string; @@ -59,9 +58,6 @@ export class Industry implements IIndustry { thisCycleRevenue: number; thisCycleExpenses: number; - //Upgrades - upgrades: number[] = Array(Object.keys(IndustryUpgrades).length).fill(0); - state = "START"; newInd = true; @@ -81,6 +77,8 @@ export class Industry implements IIndustry { [CityName.Volhaven]: 0, }; + numAdVerts = 0; + constructor(params: IParams = {}) { this.name = params.name ? params.name : ""; this.type = params.type ? params.type : Industries.Agriculture; @@ -1004,23 +1002,9 @@ export class Industry implements IIndustry { const office = this.offices[city]; if (office === 0) continue; - // Designing/Creating a Product is based mostly off Engineers - const engrProd = office.employeeProd[EmployeePositions.Engineer]; - const mgmtProd = office.employeeProd[EmployeePositions.Management]; - const opProd = office.employeeProd[EmployeePositions.Operations]; - const total = engrProd + mgmtProd + opProd; - if (total <= 0) { - break; - } - - // Management is a multiplier for the production from Engineers - const mgmtFactor = 1 + mgmtProd / (1.2 * total); - - const progress = (Math.pow(engrProd, 0.34) + Math.pow(opProd, 0.2)) * mgmtFactor; - - prod.createProduct(marketCycles, progress); + prod.createProduct(marketCycles, office.employeeProd); if (prod.prog >= 100) { - prod.finishProduct(office.employeeProd, this); + prod.finishProduct(this); } break; } @@ -1262,38 +1246,19 @@ export class Industry implements IIndustry { } } - upgrade(upgrade: IndustryUpgrade, refs: { corporation: ICorporation; office: OfficeSpace }): void { - const corporation = refs.corporation; - const office = refs.office; - const upgN = upgrade[0]; - while (this.upgrades.length <= upgN) { - this.upgrades.push(0); - } - ++this.upgrades[upgN]; + getAdVertCost(): number { + return 1e9 * Math.pow(1.06, this.numAdVerts); + } - switch (upgN) { - case 0: { - //Coffee, 5% energy per employee - for (let i = 0; i < office.employees.length; ++i) { - office.employees[i].ene = Math.min(office.employees[i].ene * 1.05, office.maxEne); - } - break; - } - case 1: { - //AdVert.Inc, - const advMult = corporation.getAdvertisingMultiplier() * this.getAdvertisingMultiplier(); - const awareness = (this.awareness + 3 * advMult) * (1.01 * advMult); - this.awareness = Math.min(awareness, Number.MAX_VALUE); + applyAdVert(corporation: ICorporation): void { + const advMult = corporation.getAdvertisingMultiplier() * this.getAdvertisingMultiplier(); + const awareness = (this.awareness + 3 * advMult) * (1.01 * advMult); + this.awareness = Math.min(awareness, Number.MAX_VALUE); - const popularity = (this.popularity + 1 * advMult) * ((1 + getRandomInt(1, 3) / 100) * advMult); - this.popularity = Math.min(popularity, Number.MAX_VALUE); - break; - } - default: { - console.error(`Un-implemented function index: ${upgN}`); - break; - } - } + const popularity = (this.popularity + 1 * advMult) * ((1 + getRandomInt(1, 3) / 100) * advMult); + this.popularity = Math.min(popularity, Number.MAX_VALUE); + + ++this.numAdVerts; } // Returns how much of a material can be produced based of office productivity (employee stats) diff --git a/src/Corporation/IndustryUpgrades.ts b/src/Corporation/IndustryUpgrades.ts deleted file mode 100644 index 6190fabf4..000000000 --- a/src/Corporation/IndustryUpgrades.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { IMap } from "../types"; - -export type IndustryUpgrade = [number, number, number, number, string, string]; - -// Industry upgrades -// The data structure is an array with the following format: -// [index in array, base price, price mult, benefit mult (if applicable), name, desc] -export const IndustryUpgrades: IMap = { - "0": [0, 500e3, 1, 1.05, "Coffee", "Provide your employees with coffee, increasing their energy by 5%."], - "1": [ - 1, - 1e9, - 1.06, - 1.03, - "AdVert.Inc", - "Hire AdVert.Inc to advertise your company. Each level of " + - "this upgrade grants your company a static increase of 3 and 1 to its awareness and " + - "popularity, respectively. It will then increase your company's awareness by 1%, and its popularity " + - "by a random percentage between 1% and 3%. These effects are increased by other upgrades " + - "that increase the power of your advertising.", - ], -}; diff --git a/src/Corporation/OfficeSpace.ts b/src/Corporation/OfficeSpace.ts index 623b3c5d3..63412ee61 100644 --- a/src/Corporation/OfficeSpace.ts +++ b/src/Corporation/OfficeSpace.ts @@ -15,11 +15,22 @@ interface IParams { export class OfficeSpace { loc: string; size: number; + minEne = 0; - maxEne = 100; minHap = 0; + minMor = 0; + + maxEne = 100; maxHap = 100; maxMor = 100; + + autoCoffee = false; + autoParty = false; + coffeeMult = 0; + partyMult = 0; + coffeeEmployees = 0; + partyEmployees = 0; + employees: Employee[] = []; employeeProd: { [key: string]: number } = { [EmployeePositions.Operations]: 0, @@ -37,7 +48,15 @@ export class OfficeSpace { [EmployeePositions.RandD]: 0, [EmployeePositions.Training]: 0, [EmployeePositions.Unassigned]: 0, - total: 0, + }; + employeeNextJobs: { [key: string]: number } = { + [EmployeePositions.Operations]: 0, + [EmployeePositions.Engineer]: 0, + [EmployeePositions.Business]: 0, + [EmployeePositions.Management]: 0, + [EmployeePositions.RandD]: 0, + [EmployeePositions.Training]: 0, + [EmployeePositions.Unassigned]: 0, }; constructor(params: IParams = {}) { @@ -58,12 +77,18 @@ export class OfficeSpace { } } + // Update employee jobs and job counts + for (const employee of this.employees) { + employee.pos = employee.nextPos; + } this.calculateTotalEmployees(); + this.calculateNextEmployees(); // Process Office properties this.maxEne = 100; this.maxHap = 100; this.maxMor = 100; + if (industry.hasResearch("Go-Juice")) { this.maxEne += 10; } @@ -73,6 +98,12 @@ export class OfficeSpace { if (industry.hasResearch("Sti.mu")) { this.maxMor += 10; } + if (industry.hasResearch("AutoBrew")) { + this.autoCoffee = true; + } + if (industry.hasResearch("AutoPartyManager")) { + this.autoParty = true; + } // Calculate changes in Morale/Happiness/Energy for Employees let perfMult = 1; //Multiplier for employee morale/happiness/energy based on company performance @@ -82,35 +113,56 @@ export class OfficeSpace { perfMult = Math.pow(1.01, marketCycles); } - const hasAutobrew = industry.hasResearch("AutoBrew"); - const hasAutoparty = industry.hasResearch("AutoPartyManager"); + let totalSalary = 0; + for (const employee of this.employees) { + const salary = employee.process(marketCycles); + totalSalary += salary; - 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; + if (this.autoCoffee) { + employee.ene = this.maxEne; + } else if (this.coffeeMult > 1) { + const mult = 1 + ((this.coffeeMult - 1) * this.employees.length) / this.coffeeEmployees; + employee.ene *= mult; } else { - emp.mor *= perfMult; - emp.hap *= perfMult; - emp.mor = Math.min(emp.mor, this.maxMor); - emp.hap = Math.min(emp.hap, this.maxHap); + employee.ene *= perfMult; } - if (hasAutobrew) { - emp.ene = this.maxEne; + if (this.autoParty) { + employee.mor = this.maxMor; + employee.hap = this.maxHap; + } else if (this.partyMult > 1) { + const mult = 1 + ((this.partyMult - 1) * this.employees.length) / this.partyEmployees; + employee.mor *= mult; + employee.hap *= mult; } else { - emp.ene *= perfMult; - emp.ene = Math.min(emp.ene, this.maxEne); + employee.mor *= perfMult; + employee.hap *= perfMult; } - const salary = emp.process(marketCycles, this); - salaryPaid += salary; + employee.ene = Math.max(Math.min(employee.ene, this.maxEne), this.minEne); + employee.mor = Math.max(Math.min(employee.mor, this.maxMor), this.minMor); + employee.hap = Math.max(Math.min(employee.hap, this.maxHap), this.minHap); } + this.coffeeMult = 0; + this.partyMult = 0; + this.coffeeEmployees = 0; + this.partyEmployees = 0; + this.calculateEmployeeProductivity(corporation, industry); - return salaryPaid; + return totalSalary; + } + + calculateNextEmployees(): void { + //Reset + for (const name of Object.keys(this.employeeNextJobs)) { + this.employeeNextJobs[name] = 0; + } + + for (let i = 0; i < this.employees.length; ++i) { + const employee = this.employees[i]; + this.employeeNextJobs[employee.nextPos]++; + } } calculateTotalEmployees(): void { @@ -123,7 +175,6 @@ export class OfficeSpace { const employee = this.employees[i]; this.employeeJobs[employee.pos]++; } - this.employeeJobs.total = this.employees.length; } calculateEmployeeProductivity(corporation: ICorporation, industry: IIndustry): void { @@ -173,45 +224,57 @@ export class OfficeSpace { emp.name = name; this.employees.push(emp); + this.calculateTotalEmployees(); + this.calculateNextEmployees(); return emp; } - //Finds the first unassigned employee and assigns its to the specified job - assignEmployeeToJob(job: string): boolean { - 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; + assignSingleJob(employee: Employee, job: string): void { + employee.nextPos = job; + this.calculateNextEmployees(); } - //Finds the first employee with the given job and unassigns it - unassignEmployeeFromJob(job: string): boolean { - 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; - } - - setEmployeeToJob(job: string, amount: number): boolean { - let jobCount = this.employees.reduce((acc, employee) => (employee.pos === job ? acc + 1 : acc), 0); + autoAssignJob(job: string, target: number): boolean { + let count = this.employeeNextJobs[job]; for (const employee of this.employees) { - if (jobCount == amount) return true; - if (employee.pos === EmployeePositions.Unassigned && jobCount <= amount) { - employee.pos = job; - jobCount++; - } else if (employee.pos === job && jobCount >= amount) { - employee.pos = EmployeePositions.Unassigned; - jobCount--; + if (count === target) { + break; + } else if (employee.nextPos === EmployeePositions.Unassigned && count <= target) { + employee.nextPos = job; + count++; + } else if (employee.nextPos === job && count >= target) { + employee.nextPos = EmployeePositions.Unassigned; + count--; } } - return jobCount === amount; + + this.calculateNextEmployees(); + return count === target; + } + + getCoffeeCost(): number { + return 500e3 * this.employees.length; + } + + setCoffee(mult = 1.05): boolean { + if (mult > 1 && this.coffeeMult === 0 && !this.autoCoffee && this.employees.length > 0) { + this.coffeeMult = mult; + this.coffeeEmployees = this.employees.length; + return true; + } + + return false; + } + + setParty(mult: number): boolean { + if (mult > 1 && this.partyMult === 0 && !this.autoParty && this.employees.length > 0) { + this.partyMult = mult; + this.partyEmployees = this.employees.length; + return true; + } + + return false; } toJSON(): any { diff --git a/src/Corporation/Product.ts b/src/Corporation/Product.ts index cfe15917f..1e30f66bb 100644 --- a/src/Corporation/Product.ts +++ b/src/Corporation/Product.ts @@ -55,6 +55,16 @@ export class Product { designCost = 0; // How much money was invested into designing this Product advCost = 0; // How much money was invested into advertising this Product + // The average employee productivity and scientific research across the creation of the Product + creationProd: { [key: string]: number } = { + [EmployeePositions.Operations]: 0, + [EmployeePositions.Engineer]: 0, + [EmployeePositions.Business]: 0, + [EmployeePositions.Management]: 0, + [EmployeePositions.RandD]: 0, + total: 0, + }; + // Aggregate score for this Product's 'rating' // This is based on the stats/properties below. The weighting of the // stats/properties below differs between different industries @@ -117,25 +127,48 @@ export class Product { this.reqMats = params.req ? params.req : {}; } - // empWorkMult is a multiplier that increases progress rate based on - // productivity of employees - createProduct(marketCycles = 1, empWorkMult = 1): void { + // Make progress on this product based on current employee productivity + createProduct(marketCycles: number, employeeProd: typeof this["creationProd"]): void { if (this.fin) { return; } - this.prog += marketCycles * 0.01 * empWorkMult; + + // Designing/Creating a Product is based mostly off Engineers + const opProd = employeeProd[EmployeePositions.Operations]; + const engrProd = employeeProd[EmployeePositions.Engineer]; + const mgmtProd = employeeProd[EmployeePositions.Management]; + const total = opProd + engrProd + mgmtProd; + if (total <= 0) { + return; + } + + // Management is a multiplier for the production from Engineers + const mgmtFactor = 1 + mgmtProd / (1.2 * total); + const prodMult = (Math.pow(engrProd, 0.34) + Math.pow(opProd, 0.2)) * mgmtFactor; + const progress = Math.min(marketCycles * 0.01 * prodMult, 100 - this.prog); + if (progress <= 0) { + return; + } + + this.prog += progress; + for (const pos of Object.keys(employeeProd)) { + console.log(`${pos} ${this.creationProd[pos]} += ${(employeeProd[pos] * progress) / 100}`); + this.creationProd[pos] += (employeeProd[pos] * progress) / 100; + } } // @param industry - Industry object. Reference to industry that makes this Product - finishProduct(employeeProd: { [key: string]: number }, industry: IIndustry): void { + finishProduct(industry: IIndustry): void { this.fin = true; - //Calculate properties - const engrRatio = employeeProd[EmployeePositions.Engineer] / employeeProd["total"]; - const mgmtRatio = employeeProd[EmployeePositions.Management] / employeeProd["total"]; - const rndRatio = employeeProd[EmployeePositions.RandD] / employeeProd["total"]; - const opsRatio = employeeProd[EmployeePositions.Operations] / employeeProd["total"]; - const busRatio = employeeProd[EmployeePositions.Business] / employeeProd["total"]; + // Calculate properties + const totalProd = this.creationProd.total; + const engrRatio = this.creationProd[EmployeePositions.Engineer] / totalProd; + const mgmtRatio = this.creationProd[EmployeePositions.Management] / totalProd; + const rndRatio = this.creationProd[EmployeePositions.RandD] / totalProd; + const opsRatio = this.creationProd[EmployeePositions.Operations] / totalProd; + const busRatio = this.creationProd[EmployeePositions.Business] / totalProd; + const designMult = 1 + Math.pow(this.designCost, 0.1) / 100; const balanceMult = 1.2 * engrRatio + 0.9 * mgmtRatio + 1.3 * rndRatio + 1.5 * opsRatio + busRatio; const sciMult = 1 + Math.pow(industry.sciResearch.qty, industry.sciFac) / 800; @@ -143,49 +176,49 @@ export class Product { this.qlt = totalMult * - (0.1 * employeeProd[EmployeePositions.Engineer] + - 0.05 * employeeProd[EmployeePositions.Management] + - 0.05 * employeeProd[EmployeePositions.RandD] + - 0.02 * employeeProd[EmployeePositions.Operations] + - 0.02 * employeeProd[EmployeePositions.Business]); + (0.1 * this.creationProd[EmployeePositions.Engineer] + + 0.05 * this.creationProd[EmployeePositions.Management] + + 0.05 * this.creationProd[EmployeePositions.RandD] + + 0.02 * this.creationProd[EmployeePositions.Operations] + + 0.02 * this.creationProd[EmployeePositions.Business]); this.per = totalMult * - (0.15 * employeeProd[EmployeePositions.Engineer] + - 0.02 * employeeProd[EmployeePositions.Management] + - 0.02 * employeeProd[EmployeePositions.RandD] + - 0.02 * employeeProd[EmployeePositions.Operations] + - 0.02 * employeeProd[EmployeePositions.Business]); + (0.15 * this.creationProd[EmployeePositions.Engineer] + + 0.02 * this.creationProd[EmployeePositions.Management] + + 0.02 * this.creationProd[EmployeePositions.RandD] + + 0.02 * this.creationProd[EmployeePositions.Operations] + + 0.02 * this.creationProd[EmployeePositions.Business]); this.dur = totalMult * - (0.05 * employeeProd[EmployeePositions.Engineer] + - 0.02 * employeeProd[EmployeePositions.Management] + - 0.08 * employeeProd[EmployeePositions.RandD] + - 0.05 * employeeProd[EmployeePositions.Operations] + - 0.05 * employeeProd[EmployeePositions.Business]); + (0.05 * this.creationProd[EmployeePositions.Engineer] + + 0.02 * this.creationProd[EmployeePositions.Management] + + 0.08 * this.creationProd[EmployeePositions.RandD] + + 0.05 * this.creationProd[EmployeePositions.Operations] + + 0.05 * this.creationProd[EmployeePositions.Business]); this.rel = totalMult * - (0.02 * employeeProd[EmployeePositions.Engineer] + - 0.08 * employeeProd[EmployeePositions.Management] + - 0.02 * employeeProd[EmployeePositions.RandD] + - 0.05 * employeeProd[EmployeePositions.Operations] + - 0.08 * employeeProd[EmployeePositions.Business]); + (0.02 * this.creationProd[EmployeePositions.Engineer] + + 0.08 * this.creationProd[EmployeePositions.Management] + + 0.02 * this.creationProd[EmployeePositions.RandD] + + 0.05 * this.creationProd[EmployeePositions.Operations] + + 0.08 * this.creationProd[EmployeePositions.Business]); this.aes = totalMult * - (0.0 * employeeProd[EmployeePositions.Engineer] + - 0.08 * employeeProd[EmployeePositions.Management] + - 0.05 * employeeProd[EmployeePositions.RandD] + - 0.02 * employeeProd[EmployeePositions.Operations] + - 0.1 * employeeProd[EmployeePositions.Business]); + (0.0 * this.creationProd[EmployeePositions.Engineer] + + 0.08 * this.creationProd[EmployeePositions.Management] + + 0.05 * this.creationProd[EmployeePositions.RandD] + + 0.02 * this.creationProd[EmployeePositions.Operations] + + 0.1 * this.creationProd[EmployeePositions.Business]); this.fea = totalMult * - (0.08 * employeeProd[EmployeePositions.Engineer] + - 0.05 * employeeProd[EmployeePositions.Management] + - 0.02 * employeeProd[EmployeePositions.RandD] + - 0.05 * employeeProd[EmployeePositions.Operations] + - 0.05 * employeeProd[EmployeePositions.Business]); + (0.08 * this.creationProd[EmployeePositions.Engineer] + + 0.05 * this.creationProd[EmployeePositions.Management] + + 0.02 * this.creationProd[EmployeePositions.RandD] + + 0.05 * this.creationProd[EmployeePositions.Operations] + + 0.05 * this.creationProd[EmployeePositions.Business]); this.calculateRating(industry); const advMult = 1 + Math.pow(this.advCost, 0.1) / 100; - const busmgtgRatio = Math.max(busRatio + mgmtRatio, 1 / employeeProd["total"]); + const busmgtgRatio = Math.max(busRatio + mgmtRatio, 1 / totalProd); this.mku = 100 / (advMult * Math.pow(this.qlt + 0.001, 0.65) * busmgtgRatio); // I actually don't understand well enough to know if this is right. diff --git a/src/Corporation/ui/Industry.tsx b/src/Corporation/ui/Industry.tsx index 9a5f65eb1..9c1fafadf 100644 --- a/src/Corporation/ui/Industry.tsx +++ b/src/Corporation/ui/Industry.tsx @@ -25,7 +25,7 @@ export function Industry(props: IProps): React.ReactElement { return ( - + diff --git a/src/Corporation/ui/IndustryOffice.tsx b/src/Corporation/ui/IndustryOffice.tsx index 10bf65af8..b48031e46 100644 --- a/src/Corporation/ui/IndustryOffice.tsx +++ b/src/Corporation/ui/IndustryOffice.tsx @@ -5,7 +5,9 @@ import React, { useState } from "react"; import { OfficeSpace } from "../OfficeSpace"; import { Employee } from "../Employee"; import { EmployeePositions } from "../EmployeePositions"; +import { BuyCoffee } from "../Actions"; +import { MoneyCost } from "./MoneyCost"; import { numeralWrapper } from "../../ui/numeralFormat"; import { UpgradeOfficeSizeModal } from "./modals/UpgradeOfficeSizeModal"; @@ -17,6 +19,7 @@ import Typography from "@mui/material/Typography"; import Button from "@mui/material/Button"; import IconButton from "@mui/material/IconButton"; import Paper from "@mui/material/Paper"; +import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; import ArrowDropUpIcon from "@mui/icons-material/ArrowDropUp"; import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown"; import Tooltip from "@mui/material/Tooltip"; @@ -33,14 +36,6 @@ interface IProps { rerender: () => void; } -function countEmployee(employees: Employee[], job: string): number { - let n = 0; - for (let i = 0; i < employees.length; ++i) { - if (employees[i].pos === job) n++; - } - return n; -} - interface ISwitchProps { manualMode: boolean; switchMode: (f: (b: boolean) => boolean) => void; @@ -115,14 +110,14 @@ function ManualManagement(props: IProps): React.ReactElement { {positionNames[i]} , ); - if (emp != null && emp.pos === positionNames[i]) { - employeePositionSelectorInitialValue = positionNames[i]; + if (emp != null && emp.nextPos === positionNames[i]) { + employeePositionSelectorInitialValue = emp.nextPos; } } function employeePositionSelectorOnChange(e: SelectChangeEvent): void { if (employee === null) return; - employee.pos = e.target.value; + props.office.assignSingleJob(employee, e.target.value); props.rerender(); } @@ -178,41 +173,53 @@ interface IAutoAssignProps { rerender: () => void; } +function EmployeeCount(props: { num: number; next: number }): React.ReactElement { + return ( + + {props.num === props.next ? null : props.num} + {props.num === props.next ? null : } + {props.next} + + ); +} + function AutoAssignJob(props: IAutoAssignProps): React.ReactElement { - const corp = useCorporation(); - const division = useDivision(); - const numJob = countEmployee(props.office.employees, props.job); - const numUnassigned = countEmployee(props.office.employees, EmployeePositions.Unassigned); + const currJob = props.office.employeeJobs[props.job]; + const nextJob = props.office.employeeNextJobs[props.job]; + const nextUna = props.office.employeeNextJobs[EmployeePositions.Unassigned]; + function assignEmployee(): void { - if (numUnassigned <= 0) { + if (nextUna <= 0) { console.warn("Cannot assign employee. No unassigned employees available"); return; } - props.office.assignEmployeeToJob(props.job); - props.office.calculateEmployeeProductivity(corp, division); + props.office.autoAssignJob(props.job, nextJob + 1); props.rerender(); } function unassignEmployee(): void { - props.office.unassignEmployeeFromJob(props.job); - props.office.calculateEmployeeProductivity(corp, division); + props.office.autoAssignJob(props.job, nextJob - 1); props.rerender(); } + return ( - - {props.job} ({numJob}) - + {props.job} - + + + + - + + + @@ -223,7 +230,6 @@ function AutoAssignJob(props: IAutoAssignProps): React.ReactElement { function AutoManagement(props: IProps): React.ReactElement { const corp = useCorporation(); const division = useDivision(); - const numUnassigned = countEmployee(props.office.employees, EmployeePositions.Unassigned); const vechain = corp.unlockUpgrades[4] === 1; // Has Vechain upgrade // Calculate average morale, happiness, energy, and salary. @@ -247,168 +253,164 @@ function AutoManagement(props: IProps): React.ReactElement { avgEnergy = totalEnergy / props.office.employees.length; } + const currUna = props.office.employeeJobs[EmployeePositions.Unassigned]; + const nextUna = props.office.employeeNextJobs[EmployeePositions.Unassigned]; + return ( - <> - - - - - Unassigned Employees: - - - {numUnassigned} - - - - - Avg Employee Morale: - - - {numeralWrapper.format(avgMorale, "0.000")} - - - - - Avg Employee Happiness: - - - {numeralWrapper.format(avgHappiness, "0.000")} - - - - - Avg Employee Energy: - - - {numeralWrapper.format(avgEnergy, "0.000")} - - - - - Total Employee Salary: - - - - - - - - {vechain && ( - <> - - - - The base amount of material this office can produce. Does not include production multipliers - from upgrades and materials. This value is based off the productivity of your Operations, - Engineering, and Management employees - - } - > - Material Production: - - - - - {numeralWrapper.format(division.getOfficeProductivity(props.office), "0.000")} - - - - - - - The base amount of any given Product this office can produce. Does not include production - multipliers from upgrades and materials. This value is based off the productivity of your - Operations, Engineering, and Management employees - - } - > - Product Production: - - - - - {numeralWrapper.format( - division.getOfficeProductivity(props.office, { - forProduct: true, - }), - "0.000", - )} - - - - - - The effect this office's 'Business' employees has on boosting sales} - > - Business Multiplier: - - - - x{numeralWrapper.format(division.getBusinessFactor(props.office), "0.000")} - - - - )} - -
+ + + + + Unassigned Employees: + + + + + + + + Avg Employee Morale: + + + {numeralWrapper.format(avgMorale, "0.000")} + + + + + Avg Employee Happiness: + + + {numeralWrapper.format(avgHappiness, "0.000")} + + + + + Avg Employee Energy: + + + {numeralWrapper.format(avgEnergy, "0.000")} + + + + + Total Employee Salary: + + + + + + + + {vechain && ( + <> + + + + The base amount of material this office can produce. Does not include production multipliers from + upgrades and materials. This value is based off the productivity of your Operations, Engineering, + and Management employees + + } + > + Material Production: + + + + + {numeralWrapper.format(division.getOfficeProductivity(props.office), "0.000")} + + + + + + + The base amount of any given Product this office can produce. Does not include production + multipliers from upgrades and materials. This value is based off the productivity of your + Operations, Engineering, and Management employees + + } + > + Product Production: + + + + + {numeralWrapper.format( + division.getOfficeProductivity(props.office, { + forProduct: true, + }), + "0.000", + )} + + + + + + The effect this office's 'Business' employees has on boosting sales} + > + Business Multiplier: + + + + x{numeralWrapper.format(division.getBusinessFactor(props.office), "0.000")} + + + + )} + -
- - + - + - + - + - - - - -
- + + + ); } @@ -454,14 +456,40 @@ export function IndustryOffice(props: IProps): React.ReactElement { onClose={() => setUpgradeOfficeSizeOpen(false)} /> + {!division.hasResearch("AutoBrew") && ( + <> + Throw an office party to increase your employee's morale and happiness} + > + + + + + + )} + {!division.hasResearch("AutoPartyManager") && ( <> Throw an office party to increase your employee's morale and happiness} > - diff --git a/src/Corporation/ui/IndustryOverview.tsx b/src/Corporation/ui/IndustryOverview.tsx index 60390e11e..337e52d5b 100644 --- a/src/Corporation/ui/IndustryOverview.tsx +++ b/src/Corporation/ui/IndustryOverview.tsx @@ -2,9 +2,8 @@ // (top-left panel in the Industry UI) import React, { useState } from "react"; -import { OfficeSpace } from "../OfficeSpace"; import { Industries } from "../IndustryData"; -import { IndustryUpgrades } from "../IndustryUpgrades"; +import { HireAdVert } from "../Actions"; import { numeralWrapper } from "../../ui/numeralFormat"; import { createProgressBarText } from "../../utils/helpers/createProgressBarText"; import { MakeProductModal } from "./modals/MakeProductModal"; @@ -87,7 +86,12 @@ function MakeProductButton(): React.ReactElement { ); } -function Text(): React.ReactElement { + +interface IProps { + rerender: () => void; +} + +export function IndustryOverview(props: IProps): React.ReactElement { const corp = useCorporation(); const division = useDivision(); const [helpOpen, setHelpOpen] = useState(false); @@ -113,7 +117,7 @@ function Text(): React.ReactElement { } return ( - <> + Industry: {division.type} (Corp Funds: ) @@ -191,7 +195,6 @@ function Text(): React.ReactElement {
- setResearchOpen(false)} industry={division} /> - - ); -} - -function Upgrades(props: { office: OfficeSpace; rerender: () => void }): React.ReactElement { - const corp = useCorporation(); - const division = useDivision(); - const upgrades = []; - for (const index of Object.keys(IndustryUpgrades)) { - const upgrade = IndustryUpgrades[index]; - - // AutoBrew research disables the Coffee upgrade - if (division.hasResearch("AutoBrew") && upgrade[4] === "Coffee") { - continue; - } - - const i = upgrade[0]; - const baseCost = upgrade[1]; - const priceMult = upgrade[2]; - let cost = 0; - switch (i) { - case 0: //Coffee, cost is static per employee - cost = props.office.employees.length * baseCost; - break; - default: - cost = baseCost * Math.pow(priceMult, division.upgrades[i]); - break; - } - - function onClick(): void { - if (corp.funds < cost) return; - corp.funds = corp.funds - cost; - division.upgrade(upgrade, { - corporation: corp, - office: props.office, - }); - props.rerender(); - } - - upgrades.push( - - - - - , - ); - } - - return <>{upgrades}; -} - -interface IProps { - currentCity: string; - office: OfficeSpace; - rerender: () => void; -} - -export function IndustryOverview(props: IProps): React.ReactElement { - const division = useDivision(); - - return ( - -
- Purchases & Upgrades -
- {division.makesProducts && } + + + Hire AdVert.Inc to advertise your company. Each level of this upgrade grants your company a static + increase of 3 and 1 to its awareness and popularity, respectively. It will then increase your company's + awareness by 1%, and its popularity by a random percentage between 1% and 3%. These effects are increased + by other upgrades that increase the power of your advertising. + + } + > + + + {division.makesProducts && } +
); } diff --git a/src/Corporation/ui/modals/ThrowPartyModal.tsx b/src/Corporation/ui/modals/ThrowPartyModal.tsx index 1df61aac0..8bbd9d3f7 100644 --- a/src/Corporation/ui/modals/ThrowPartyModal.tsx +++ b/src/Corporation/ui/modals/ThrowPartyModal.tsx @@ -38,11 +38,15 @@ export function ThrowPartyModal(props: IProps): React.ReactElement { dialogBoxCreate("You don't have enough company funds to throw a party!"); } else { const mult = ThrowParty(corp, props.office, cost); - dialogBoxCreate( - "You threw a party for the office! The morale and happiness " + - "of each employee increased by " + - numeralWrapper.formatPercentage(mult - 1), - ); + + if (mult > 0) { + dialogBoxCreate( + "You threw a party for the office! The morale and happiness " + + "of each employee increased by " + + numeralWrapper.formatPercentage(mult - 1), + ); + } + props.rerender(); props.onClose(); } diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index 02d3a74ba..e4ced14c8 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -531,7 +531,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS { bladeburner: NetscriptBladeburner(Player, workerScript), codingcontract: NetscriptCodingContract(Player, workerScript), sleeve: NetscriptSleeve(Player), - corporation: NetscriptCorporation(Player, workerScript), + corporation: NetscriptCorporation(Player), stanek: NetscriptStanek(Player, workerScript, helper), infiltration: NetscriptInfiltration(Player), ui: NetscriptUserInterface(), diff --git a/src/NetscriptFunctions/Corporation.ts b/src/NetscriptFunctions/Corporation.ts index 139bf8bfd..038167811 100644 --- a/src/NetscriptFunctions/Corporation.ts +++ b/src/NetscriptFunctions/Corporation.ts @@ -1,6 +1,4 @@ -import { WorkerScript } from "../Netscript/WorkerScript"; import { IPlayer } from "../PersonObjects/IPlayer"; -import { netscriptDelay } from "../NetscriptEvaluator"; import { OfficeSpace } from "../Corporation/OfficeSpace"; import { Employee } from "../Corporation/Employee"; @@ -34,11 +32,12 @@ import { SetSmartSupply, BuyMaterial, AssignJob, + AutoAssignJob, UpgradeOfficeSize, - ThrowParty, PurchaseWarehouse, UpgradeWarehouse, BuyCoffee, + ThrowParty, HireAdVert, MakeProduct, Research, @@ -59,17 +58,15 @@ import { import { CorporationUnlockUpgrades } from "../Corporation/data/CorporationUnlockUpgrades"; import { CorporationUpgrades } from "../Corporation/data/CorporationUpgrades"; import { EmployeePositions } from "../Corporation/EmployeePositions"; -import { calculateIntelligenceBonus } from "../PersonObjects/formulas/intelligence"; import { Industry } from "../Corporation/Industry"; import { IndustryResearchTrees, IndustryStartingCosts } from "../Corporation/IndustryData"; import { CorporationConstants } from "../Corporation/data/Constants"; -import { IndustryUpgrades } from "../Corporation/IndustryUpgrades"; import { ResearchMap } from "../Corporation/ResearchMap"; import { Factions } from "../Faction/Factions"; import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers"; import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper"; -export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript): InternalAPI { +export function NetscriptCorporation(player: IPlayer): InternalAPI { function createCorporation(corporationName: string, selfFund = true): boolean { if (!player.canAccessCorporation() || player.hasCorporation()) return false; if (!corporationName) return false; @@ -302,7 +299,7 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript lastCycleExpenses: division.lastCycleExpenses, thisCycleRevenue: division.thisCycleRevenue, thisCycleExpenses: division.thisCycleExpenses, - upgrades: division.upgrades.slice(), + upgrades: [0, division.numAdVerts], cities: cities, products: division.products === undefined ? [] : Object.keys(division.products), makesProducts: division.makesProducts, @@ -658,8 +655,7 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript checkAccess(ctx, 8); const divisionName = ctx.helper.string("divisionName", _divisionName); const division = getDivision(divisionName); - const upgrade = IndustryUpgrades[1]; - return upgrade[1] * Math.pow(upgrade[2], division.upgrades[1]); + return division.getAdVertCost(); }, getHireAdVertCount: (ctx: NetscriptContext) => @@ -667,7 +663,7 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript checkAccess(ctx, 8); const divisionName = ctx.helper.string("divisionName", _divisionName); const division = getDivision(divisionName); - return division.upgrades[1]; + return division.numAdVerts; }, getResearchCost: (ctx: NetscriptContext) => @@ -685,20 +681,6 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript const researchName = ctx.helper.string("researchName", _researchName); return hasResearched(getDivision(divisionName), researchName); }, - setAutoJobAssignment: - (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown, _job: unknown, _amount: unknown): Promise => { - checkAccess(ctx, 8); - const divisionName = ctx.helper.string("divisionName", _divisionName); - const cityName = ctx.helper.city("cityName", _cityName); - const amount = ctx.helper.number("amount", _amount); - const job = ctx.helper.string("job", _job); - const office = getOffice(divisionName, cityName); - if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`); - return netscriptDelay(1000, workerScript).then(function () { - return Promise.resolve(office.setEmployeeToJob(job, amount)); - }); - }, getOfficeSizeUpgradeCost: (ctx: NetscriptContext) => (_divisionName: unknown, _cityName: unknown, _size: unknown): number => { @@ -718,18 +700,31 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript }, assignJob: (ctx: NetscriptContext) => - (_divisionName: unknown, _cityName: unknown, _employeeName: unknown, _job: unknown): Promise => { + (_divisionName: unknown, _cityName: unknown, _employeeName: unknown, _job: unknown): void => { checkAccess(ctx, 8); const divisionName = ctx.helper.string("divisionName", _divisionName); const cityName = ctx.helper.city("cityName", _cityName); const employeeName = ctx.helper.string("employeeName", _employeeName); const job = ctx.helper.string("job", _job); - const employee = getEmployee(divisionName, cityName, employeeName); - return netscriptDelay(["Training", "Unassigned"].includes(employee.pos) ? 0 : 1000, workerScript).then( - function () { - return Promise.resolve(AssignJob(employee, job)); - }, - ); + + if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`); + const office = getOffice(divisionName, cityName); + + AssignJob(office, employeeName, job); + }, + setAutoJobAssignment: + (ctx: NetscriptContext) => + (_divisionName: unknown, _cityName: unknown, _job: unknown, _amount: unknown): boolean => { + checkAccess(ctx, 8); + const divisionName = ctx.helper.string("divisionName", _divisionName); + const cityName = ctx.helper.city("cityName", _cityName); + const amount = ctx.helper.number("amount", _amount); + const job = ctx.helper.string("job", _job); + + if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`); + const office = getOffice(divisionName, cityName); + + return AutoAssignJob(office, job, amount); }, hireEmployee: (ctx: NetscriptContext) => @@ -769,35 +764,32 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript }, throwParty: (ctx: NetscriptContext) => - async (_divisionName: unknown, _cityName: unknown, _costPerEmployee: unknown): Promise => { + (_divisionName: unknown, _cityName: unknown, _costPerEmployee: unknown): number => { checkAccess(ctx, 8); const divisionName = ctx.helper.string("divisionName", _divisionName); const cityName = ctx.helper.city("cityName", _cityName); const costPerEmployee = ctx.helper.number("costPerEmployee", _costPerEmployee); - if (costPerEmployee < 0) + + if (costPerEmployee < 0) { throw new Error("Invalid value for Cost Per Employee field! Must be numeric and greater than 0"); - const office = getOffice(divisionName, cityName); + } + const corporation = getCorporation(); - return netscriptDelay( - (60 * 1000) / (player.hacking_speed_mult * calculateIntelligenceBonus(player.intelligence, 1)), - workerScript, - ).then(function () { - return Promise.resolve(ThrowParty(corporation, office, costPerEmployee)); - }); + const office = getOffice(divisionName, cityName); + + return ThrowParty(corporation, office, costPerEmployee); }, buyCoffee: (ctx: NetscriptContext) => - async (_divisionName: unknown, _cityName: unknown): Promise => { + (_divisionName: unknown, _cityName: unknown): boolean => { checkAccess(ctx, 8); const divisionName = ctx.helper.string("divisionName", _divisionName); const cityName = ctx.helper.city("cityName", _cityName); + const corporation = getCorporation(); - return netscriptDelay( - (60 * 1000) / (player.hacking_speed_mult * calculateIntelligenceBonus(player.intelligence, 1)), - workerScript, - ).then(function () { - return Promise.resolve(BuyCoffee(corporation, getDivision(divisionName), getOffice(divisionName, cityName))); - }); + const office = getOffice(divisionName, cityName); + + return BuyCoffee(corporation, office); }, hireAdVert: (ctx: NetscriptContext) => @@ -805,7 +797,7 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript checkAccess(ctx, 8); const divisionName = ctx.helper.string("divisionName", _divisionName); const corporation = getCorporation(); - HireAdVert(corporation, getDivision(divisionName), getOffice(divisionName, "Sector-12")); + HireAdVert(corporation, getDivision(divisionName)); }, research: (ctx: NetscriptContext) => @@ -829,6 +821,7 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript maxEne: office.maxEne, minHap: office.minHap, maxHap: office.maxHap, + minMor: office.minMor, maxMor: office.maxMor, employees: office.employees.map((e) => e.name), employeeProd: { diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index 4d35dacef..964a801c7 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -6623,9 +6623,8 @@ export interface OfficeAPI { * @param cityName - Name of the city * @param employeeName - name of the employee * @param job - Name of the job. - * @returns A promise that is fulfilled when the assignment is complete. */ - assignJob(divisionName: string, cityName: string, employeeName: string, job: string): Promise; + assignJob(divisionName: string, cityName: string, employeeName: string, job: string): void; /** * Hire an employee. * @param divisionName - Name of the division @@ -6645,16 +6644,16 @@ export interface OfficeAPI { * @param divisionName - Name of the division * @param cityName - Name of the city * @param costPerEmployee - Amount to spend per employee. - * @returns Amount of happiness increased. + * @returns Multiplier for happiness and morale, or zero on failure */ - throwParty(divisionName: string, cityName: string, costPerEmployee: number): Promise; + throwParty(divisionName: string, cityName: string, costPerEmployee: number): number; /** * Buy coffee for your employees * @param divisionName - Name of the division * @param cityName - Name of the city - * @returns A promise that is fulfilled when the coffee is served. + * @returns true if buying coffee was successful, false otherwise */ - buyCoffee(divisionName: string, cityName: string): Promise; + buyCoffee(divisionName: string, cityName: string): boolean; /** * Hire AdVert. * @param divisionName - Name of the division @@ -6713,9 +6712,9 @@ export interface OfficeAPI { * @param cityName - Name of the city * @param job - Name of the job * @param amount - Number of employees to assign to that job - * @returns A promise that is fulfilled when the assignment is complete. + * @returns true if the employee count reached the target amount, false if not */ - setAutoJobAssignment(divisionName: string, cityName: string, job: string, amount: number): Promise; + setAutoJobAssignment(divisionName: string, cityName: string, job: string, amount: number): boolean; /** * Cost to Upgrade office size. * @param divisionName - Name of the division @@ -7234,6 +7233,8 @@ interface Office { minHap: number; /** Maximum happiness of the employees */ maxHap: number; + /** Minimum morale of the employees */ + minMor: number; /** Maximum morale of the employees */ maxMor: number; /** Name of all the employees */