mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-05-01 21:37:59 +02:00
Merge pull request #3812 from stalefishies/corp-remove-async
CORPORATION: (BREAKING) Remove async
This commit is contained in:
+39
-29
@@ -13,8 +13,6 @@ import { CorporationUnlockUpgrade } from "./data/CorporationUnlockUpgrades";
|
|||||||
import { CorporationUpgrade } from "./data/CorporationUpgrades";
|
import { CorporationUpgrade } from "./data/CorporationUpgrades";
|
||||||
import { Cities } from "../Locations/Cities";
|
import { Cities } from "../Locations/Cities";
|
||||||
import { EmployeePositions } from "./EmployeePositions";
|
import { EmployeePositions } from "./EmployeePositions";
|
||||||
import { Employee } from "./Employee";
|
|
||||||
import { IndustryUpgrades } from "./IndustryUpgrades";
|
|
||||||
import { ResearchMap } from "./ResearchMap";
|
import { ResearchMap } from "./ResearchMap";
|
||||||
import { isRelevantMaterial } from "./ui/Helpers";
|
import { isRelevantMaterial } from "./ui/Helpers";
|
||||||
|
|
||||||
@@ -304,9 +302,19 @@ export function BuyBackShares(corporation: ICorporation, player: IPlayer, numSha
|
|||||||
return true;
|
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.`);
|
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 {
|
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;
|
corp.funds = corp.funds - cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ThrowParty(corp: ICorporation, office: OfficeSpace, costPerEmployee: number): number {
|
export function BuyCoffee(corp: ICorporation, office: OfficeSpace): boolean {
|
||||||
const totalCost = costPerEmployee * office.employees.length;
|
const cost = office.getCoffeeCost();
|
||||||
if (corp.funds < totalCost) return 0;
|
if (corp.funds < cost) {
|
||||||
corp.funds = corp.funds - totalCost;
|
return false;
|
||||||
let mult = 0;
|
|
||||||
for (let i = 0; i < office.employees.length; ++i) {
|
|
||||||
mult = office.employees[i].throwParty(costPerEmployee);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
return mult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,26 +387,11 @@ export function UpgradeWarehouse(corp: ICorporation, division: IIndustry, wareho
|
|||||||
corp.funds = corp.funds - sizeUpgradeCost;
|
corp.funds = corp.funds - sizeUpgradeCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BuyCoffee(corp: ICorporation, division: IIndustry, office: OfficeSpace): void {
|
export function HireAdVert(corp: ICorporation, division: IIndustry): void {
|
||||||
const upgrade = IndustryUpgrades[0];
|
const cost = division.getAdVertCost();
|
||||||
const cost = office.employees.length * upgrade[1];
|
|
||||||
if (corp.funds < cost) return;
|
if (corp.funds < cost) return;
|
||||||
corp.funds = corp.funds - cost;
|
corp.funds = corp.funds - cost;
|
||||||
division.upgrade(upgrade, {
|
division.applyAdVert(corp);
|
||||||
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,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MakeProduct(
|
export function MakeProduct(
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { getRandomInt } from "../utils/helpers/getRandomInt";
|
|||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
||||||
import { EmployeePositions } from "./EmployeePositions";
|
import { EmployeePositions } from "./EmployeePositions";
|
||||||
import { ICorporation } from "./ICorporation";
|
import { ICorporation } from "./ICorporation";
|
||||||
import { OfficeSpace } from "./OfficeSpace";
|
|
||||||
import { IIndustry } from "./IIndustry";
|
import { IIndustry } from "./IIndustry";
|
||||||
|
|
||||||
interface IParams {
|
interface IParams {
|
||||||
@@ -34,6 +33,7 @@ export class Employee {
|
|||||||
cyclesUntilRaise = CorporationConstants.CyclesPerEmployeeRaise;
|
cyclesUntilRaise = CorporationConstants.CyclesPerEmployeeRaise;
|
||||||
loc: string;
|
loc: string;
|
||||||
pos: string;
|
pos: string;
|
||||||
|
nextPos: string;
|
||||||
|
|
||||||
constructor(params: IParams = {}) {
|
constructor(params: IParams = {}) {
|
||||||
this.name = params.name ? params.name : "Bobby";
|
this.name = params.name ? params.name : "Bobby";
|
||||||
@@ -52,12 +52,13 @@ export class Employee {
|
|||||||
|
|
||||||
this.loc = params.loc ? params.loc : "";
|
this.loc = params.loc ? params.loc : "";
|
||||||
this.pos = EmployeePositions.Unassigned;
|
this.pos = EmployeePositions.Unassigned;
|
||||||
|
this.nextPos = this.pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Returns the amount the employee needs to be paid
|
//Returns the amount the employee needs to be paid
|
||||||
process(marketCycles = 1, office: OfficeSpace): number {
|
process(marketCycles = 1): number {
|
||||||
const gain = 0.003 * marketCycles,
|
const gain = 0.003 * marketCycles;
|
||||||
det = gain * Math.random();
|
const det = gain * Math.random();
|
||||||
this.exp += gain;
|
this.exp += gain;
|
||||||
|
|
||||||
//Training
|
//Training
|
||||||
@@ -72,12 +73,6 @@ export class Employee {
|
|||||||
this.ene -= det;
|
this.ene -= det;
|
||||||
this.hap -= 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;
|
const salary = this.sal * marketCycles * CorporationConstants.SecsPerMarketCycle;
|
||||||
return salary;
|
return salary;
|
||||||
}
|
}
|
||||||
@@ -118,16 +113,6 @@ export class Employee {
|
|||||||
return prodBase * prodMult;
|
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 {
|
toJSON(): any {
|
||||||
return Generic_toJSON("Employee", this);
|
return Generic_toJSON("Employee", this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { Warehouse } from "./Warehouse";
|
|||||||
import { ICorporation } from "./ICorporation";
|
import { ICorporation } from "./ICorporation";
|
||||||
import { OfficeSpace } from "./OfficeSpace";
|
import { OfficeSpace } from "./OfficeSpace";
|
||||||
import { Product } from "./Product";
|
import { Product } from "./Product";
|
||||||
import { IndustryUpgrade } from "./IndustryUpgrades";
|
|
||||||
|
|
||||||
export interface IIndustry {
|
export interface IIndustry {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -36,12 +35,11 @@ export interface IIndustry {
|
|||||||
thisCycleRevenue: number;
|
thisCycleRevenue: number;
|
||||||
thisCycleExpenses: number;
|
thisCycleExpenses: number;
|
||||||
|
|
||||||
upgrades: number[];
|
|
||||||
|
|
||||||
state: string;
|
state: string;
|
||||||
newInd: boolean;
|
newInd: boolean;
|
||||||
warehouses: { [key: string]: Warehouse | 0 };
|
warehouses: { [key: string]: Warehouse | 0 };
|
||||||
offices: { [key: string]: OfficeSpace | 0 };
|
offices: { [key: string]: OfficeSpace | 0 };
|
||||||
|
numAdVerts: number;
|
||||||
|
|
||||||
init(): void;
|
init(): void;
|
||||||
getProductDescriptionText(): string;
|
getProductDescriptionText(): string;
|
||||||
@@ -56,7 +54,8 @@ export interface IIndustry {
|
|||||||
processProducts(marketCycles: number, corporation: ICorporation): [number, number];
|
processProducts(marketCycles: number, corporation: ICorporation): [number, number];
|
||||||
processProduct(marketCycles: number, product: Product, corporation: ICorporation): number;
|
processProduct(marketCycles: number, product: Product, corporation: ICorporation): number;
|
||||||
discontinueProduct(product: Product): void;
|
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;
|
getOfficeProductivity(office: OfficeSpace, params?: { forProduct?: boolean }): number;
|
||||||
getBusinessFactor(office: OfficeSpace): number;
|
getBusinessFactor(office: OfficeSpace): number;
|
||||||
getAdvertisingFactors(): [number, number, number, number];
|
getAdvertisingFactors(): [number, number, number, number];
|
||||||
|
|||||||
+15
-50
@@ -14,7 +14,6 @@ import { MaterialSizes } from "./MaterialSizes";
|
|||||||
import { Warehouse } from "./Warehouse";
|
import { Warehouse } from "./Warehouse";
|
||||||
import { ICorporation } from "./ICorporation";
|
import { ICorporation } from "./ICorporation";
|
||||||
import { IIndustry } from "./IIndustry";
|
import { IIndustry } from "./IIndustry";
|
||||||
import { IndustryUpgrade, IndustryUpgrades } from "./IndustryUpgrades";
|
|
||||||
|
|
||||||
interface IParams {
|
interface IParams {
|
||||||
name?: string;
|
name?: string;
|
||||||
@@ -59,9 +58,6 @@ export class Industry implements IIndustry {
|
|||||||
thisCycleRevenue: number;
|
thisCycleRevenue: number;
|
||||||
thisCycleExpenses: number;
|
thisCycleExpenses: number;
|
||||||
|
|
||||||
//Upgrades
|
|
||||||
upgrades: number[] = Array(Object.keys(IndustryUpgrades).length).fill(0);
|
|
||||||
|
|
||||||
state = "START";
|
state = "START";
|
||||||
newInd = true;
|
newInd = true;
|
||||||
|
|
||||||
@@ -81,6 +77,8 @@ export class Industry implements IIndustry {
|
|||||||
[CityName.Volhaven]: 0,
|
[CityName.Volhaven]: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
numAdVerts = 0;
|
||||||
|
|
||||||
constructor(params: IParams = {}) {
|
constructor(params: IParams = {}) {
|
||||||
this.name = params.name ? params.name : "";
|
this.name = params.name ? params.name : "";
|
||||||
this.type = params.type ? params.type : Industries.Agriculture;
|
this.type = params.type ? params.type : Industries.Agriculture;
|
||||||
@@ -1004,23 +1002,9 @@ export class Industry implements IIndustry {
|
|||||||
const office = this.offices[city];
|
const office = this.offices[city];
|
||||||
if (office === 0) continue;
|
if (office === 0) continue;
|
||||||
|
|
||||||
// Designing/Creating a Product is based mostly off Engineers
|
prod.createProduct(marketCycles, office.employeeProd);
|
||||||
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);
|
|
||||||
if (prod.prog >= 100) {
|
if (prod.prog >= 100) {
|
||||||
prod.finishProduct(office.employeeProd, this);
|
prod.finishProduct(this);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1262,38 +1246,19 @@ export class Industry implements IIndustry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
upgrade(upgrade: IndustryUpgrade, refs: { corporation: ICorporation; office: OfficeSpace }): void {
|
getAdVertCost(): number {
|
||||||
const corporation = refs.corporation;
|
return 1e9 * Math.pow(1.06, this.numAdVerts);
|
||||||
const office = refs.office;
|
}
|
||||||
const upgN = upgrade[0];
|
|
||||||
while (this.upgrades.length <= upgN) {
|
|
||||||
this.upgrades.push(0);
|
|
||||||
}
|
|
||||||
++this.upgrades[upgN];
|
|
||||||
|
|
||||||
switch (upgN) {
|
applyAdVert(corporation: ICorporation): void {
|
||||||
case 0: {
|
const advMult = corporation.getAdvertisingMultiplier() * this.getAdvertisingMultiplier();
|
||||||
//Coffee, 5% energy per employee
|
const awareness = (this.awareness + 3 * advMult) * (1.01 * advMult);
|
||||||
for (let i = 0; i < office.employees.length; ++i) {
|
this.awareness = Math.min(awareness, Number.MAX_VALUE);
|
||||||
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);
|
|
||||||
|
|
||||||
const popularity = (this.popularity + 1 * advMult) * ((1 + getRandomInt(1, 3) / 100) * advMult);
|
const popularity = (this.popularity + 1 * advMult) * ((1 + getRandomInt(1, 3) / 100) * advMult);
|
||||||
this.popularity = Math.min(popularity, Number.MAX_VALUE);
|
this.popularity = Math.min(popularity, Number.MAX_VALUE);
|
||||||
break;
|
|
||||||
}
|
++this.numAdVerts;
|
||||||
default: {
|
|
||||||
console.error(`Un-implemented function index: ${upgN}`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns how much of a material can be produced based of office productivity (employee stats)
|
// Returns how much of a material can be produced based of office productivity (employee stats)
|
||||||
|
|||||||
@@ -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<IndustryUpgrade> = {
|
|
||||||
"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.",
|
|
||||||
],
|
|
||||||
};
|
|
||||||
+115
-52
@@ -15,11 +15,22 @@ interface IParams {
|
|||||||
export class OfficeSpace {
|
export class OfficeSpace {
|
||||||
loc: string;
|
loc: string;
|
||||||
size: number;
|
size: number;
|
||||||
|
|
||||||
minEne = 0;
|
minEne = 0;
|
||||||
maxEne = 100;
|
|
||||||
minHap = 0;
|
minHap = 0;
|
||||||
|
minMor = 0;
|
||||||
|
|
||||||
|
maxEne = 100;
|
||||||
maxHap = 100;
|
maxHap = 100;
|
||||||
maxMor = 100;
|
maxMor = 100;
|
||||||
|
|
||||||
|
autoCoffee = false;
|
||||||
|
autoParty = false;
|
||||||
|
coffeeMult = 0;
|
||||||
|
partyMult = 0;
|
||||||
|
coffeeEmployees = 0;
|
||||||
|
partyEmployees = 0;
|
||||||
|
|
||||||
employees: Employee[] = [];
|
employees: Employee[] = [];
|
||||||
employeeProd: { [key: string]: number } = {
|
employeeProd: { [key: string]: number } = {
|
||||||
[EmployeePositions.Operations]: 0,
|
[EmployeePositions.Operations]: 0,
|
||||||
@@ -37,7 +48,15 @@ export class OfficeSpace {
|
|||||||
[EmployeePositions.RandD]: 0,
|
[EmployeePositions.RandD]: 0,
|
||||||
[EmployeePositions.Training]: 0,
|
[EmployeePositions.Training]: 0,
|
||||||
[EmployeePositions.Unassigned]: 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 = {}) {
|
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.calculateTotalEmployees();
|
||||||
|
this.calculateNextEmployees();
|
||||||
|
|
||||||
// Process Office properties
|
// Process Office properties
|
||||||
this.maxEne = 100;
|
this.maxEne = 100;
|
||||||
this.maxHap = 100;
|
this.maxHap = 100;
|
||||||
this.maxMor = 100;
|
this.maxMor = 100;
|
||||||
|
|
||||||
if (industry.hasResearch("Go-Juice")) {
|
if (industry.hasResearch("Go-Juice")) {
|
||||||
this.maxEne += 10;
|
this.maxEne += 10;
|
||||||
}
|
}
|
||||||
@@ -73,6 +98,12 @@ export class OfficeSpace {
|
|||||||
if (industry.hasResearch("Sti.mu")) {
|
if (industry.hasResearch("Sti.mu")) {
|
||||||
this.maxMor += 10;
|
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
|
// Calculate changes in Morale/Happiness/Energy for Employees
|
||||||
let perfMult = 1; //Multiplier for employee morale/happiness/energy based on company performance
|
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);
|
perfMult = Math.pow(1.01, marketCycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasAutobrew = industry.hasResearch("AutoBrew");
|
let totalSalary = 0;
|
||||||
const hasAutoparty = industry.hasResearch("AutoPartyManager");
|
for (const employee of this.employees) {
|
||||||
|
const salary = employee.process(marketCycles);
|
||||||
|
totalSalary += salary;
|
||||||
|
|
||||||
let salaryPaid = 0;
|
if (this.autoCoffee) {
|
||||||
for (let i = 0; i < this.employees.length; ++i) {
|
employee.ene = this.maxEne;
|
||||||
const emp = this.employees[i];
|
} else if (this.coffeeMult > 1) {
|
||||||
if (hasAutoparty) {
|
const mult = 1 + ((this.coffeeMult - 1) * this.employees.length) / this.coffeeEmployees;
|
||||||
emp.mor = this.maxMor;
|
employee.ene *= mult;
|
||||||
emp.hap = this.maxHap;
|
|
||||||
} else {
|
} else {
|
||||||
emp.mor *= perfMult;
|
employee.ene *= perfMult;
|
||||||
emp.hap *= perfMult;
|
|
||||||
emp.mor = Math.min(emp.mor, this.maxMor);
|
|
||||||
emp.hap = Math.min(emp.hap, this.maxHap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasAutobrew) {
|
if (this.autoParty) {
|
||||||
emp.ene = this.maxEne;
|
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 {
|
} else {
|
||||||
emp.ene *= perfMult;
|
employee.mor *= perfMult;
|
||||||
emp.ene = Math.min(emp.ene, this.maxEne);
|
employee.hap *= perfMult;
|
||||||
}
|
}
|
||||||
|
|
||||||
const salary = emp.process(marketCycles, this);
|
employee.ene = Math.max(Math.min(employee.ene, this.maxEne), this.minEne);
|
||||||
salaryPaid += salary;
|
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);
|
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 {
|
calculateTotalEmployees(): void {
|
||||||
@@ -123,7 +175,6 @@ export class OfficeSpace {
|
|||||||
const employee = this.employees[i];
|
const employee = this.employees[i];
|
||||||
this.employeeJobs[employee.pos]++;
|
this.employeeJobs[employee.pos]++;
|
||||||
}
|
}
|
||||||
this.employeeJobs.total = this.employees.length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
calculateEmployeeProductivity(corporation: ICorporation, industry: IIndustry): void {
|
calculateEmployeeProductivity(corporation: ICorporation, industry: IIndustry): void {
|
||||||
@@ -173,45 +224,57 @@ export class OfficeSpace {
|
|||||||
emp.name = name;
|
emp.name = name;
|
||||||
this.employees.push(emp);
|
this.employees.push(emp);
|
||||||
|
|
||||||
|
this.calculateTotalEmployees();
|
||||||
|
this.calculateNextEmployees();
|
||||||
return emp;
|
return emp;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Finds the first unassigned employee and assigns its to the specified job
|
assignSingleJob(employee: Employee, job: string): void {
|
||||||
assignEmployeeToJob(job: string): boolean {
|
employee.nextPos = job;
|
||||||
for (let i = 0; i < this.employees.length; ++i) {
|
this.calculateNextEmployees();
|
||||||
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
|
autoAssignJob(job: string, target: number): boolean {
|
||||||
unassignEmployeeFromJob(job: string): boolean {
|
let count = this.employeeNextJobs[job];
|
||||||
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);
|
|
||||||
|
|
||||||
for (const employee of this.employees) {
|
for (const employee of this.employees) {
|
||||||
if (jobCount == amount) return true;
|
if (count === target) {
|
||||||
if (employee.pos === EmployeePositions.Unassigned && jobCount <= amount) {
|
break;
|
||||||
employee.pos = job;
|
} else if (employee.nextPos === EmployeePositions.Unassigned && count <= target) {
|
||||||
jobCount++;
|
employee.nextPos = job;
|
||||||
} else if (employee.pos === job && jobCount >= amount) {
|
count++;
|
||||||
employee.pos = EmployeePositions.Unassigned;
|
} else if (employee.nextPos === job && count >= target) {
|
||||||
jobCount--;
|
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 {
|
toJSON(): any {
|
||||||
|
|||||||
+75
-42
@@ -55,6 +55,16 @@ export class Product {
|
|||||||
designCost = 0; // How much money was invested into designing this Product
|
designCost = 0; // How much money was invested into designing this Product
|
||||||
advCost = 0; // How much money was invested into advertising 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'
|
// Aggregate score for this Product's 'rating'
|
||||||
// This is based on the stats/properties below. The weighting of the
|
// This is based on the stats/properties below. The weighting of the
|
||||||
// stats/properties below differs between different industries
|
// stats/properties below differs between different industries
|
||||||
@@ -117,25 +127,48 @@ export class Product {
|
|||||||
this.reqMats = params.req ? params.req : {};
|
this.reqMats = params.req ? params.req : {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// empWorkMult is a multiplier that increases progress rate based on
|
// Make progress on this product based on current employee productivity
|
||||||
// productivity of employees
|
createProduct(marketCycles: number, employeeProd: typeof this["creationProd"]): void {
|
||||||
createProduct(marketCycles = 1, empWorkMult = 1): void {
|
|
||||||
if (this.fin) {
|
if (this.fin) {
|
||||||
return;
|
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
|
// @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;
|
this.fin = true;
|
||||||
|
|
||||||
//Calculate properties
|
// Calculate properties
|
||||||
const engrRatio = employeeProd[EmployeePositions.Engineer] / employeeProd["total"];
|
const totalProd = this.creationProd.total;
|
||||||
const mgmtRatio = employeeProd[EmployeePositions.Management] / employeeProd["total"];
|
const engrRatio = this.creationProd[EmployeePositions.Engineer] / totalProd;
|
||||||
const rndRatio = employeeProd[EmployeePositions.RandD] / employeeProd["total"];
|
const mgmtRatio = this.creationProd[EmployeePositions.Management] / totalProd;
|
||||||
const opsRatio = employeeProd[EmployeePositions.Operations] / employeeProd["total"];
|
const rndRatio = this.creationProd[EmployeePositions.RandD] / totalProd;
|
||||||
const busRatio = employeeProd[EmployeePositions.Business] / employeeProd["total"];
|
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 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 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;
|
const sciMult = 1 + Math.pow(industry.sciResearch.qty, industry.sciFac) / 800;
|
||||||
@@ -143,49 +176,49 @@ export class Product {
|
|||||||
|
|
||||||
this.qlt =
|
this.qlt =
|
||||||
totalMult *
|
totalMult *
|
||||||
(0.1 * employeeProd[EmployeePositions.Engineer] +
|
(0.1 * this.creationProd[EmployeePositions.Engineer] +
|
||||||
0.05 * employeeProd[EmployeePositions.Management] +
|
0.05 * this.creationProd[EmployeePositions.Management] +
|
||||||
0.05 * employeeProd[EmployeePositions.RandD] +
|
0.05 * this.creationProd[EmployeePositions.RandD] +
|
||||||
0.02 * employeeProd[EmployeePositions.Operations] +
|
0.02 * this.creationProd[EmployeePositions.Operations] +
|
||||||
0.02 * employeeProd[EmployeePositions.Business]);
|
0.02 * this.creationProd[EmployeePositions.Business]);
|
||||||
this.per =
|
this.per =
|
||||||
totalMult *
|
totalMult *
|
||||||
(0.15 * employeeProd[EmployeePositions.Engineer] +
|
(0.15 * this.creationProd[EmployeePositions.Engineer] +
|
||||||
0.02 * employeeProd[EmployeePositions.Management] +
|
0.02 * this.creationProd[EmployeePositions.Management] +
|
||||||
0.02 * employeeProd[EmployeePositions.RandD] +
|
0.02 * this.creationProd[EmployeePositions.RandD] +
|
||||||
0.02 * employeeProd[EmployeePositions.Operations] +
|
0.02 * this.creationProd[EmployeePositions.Operations] +
|
||||||
0.02 * employeeProd[EmployeePositions.Business]);
|
0.02 * this.creationProd[EmployeePositions.Business]);
|
||||||
this.dur =
|
this.dur =
|
||||||
totalMult *
|
totalMult *
|
||||||
(0.05 * employeeProd[EmployeePositions.Engineer] +
|
(0.05 * this.creationProd[EmployeePositions.Engineer] +
|
||||||
0.02 * employeeProd[EmployeePositions.Management] +
|
0.02 * this.creationProd[EmployeePositions.Management] +
|
||||||
0.08 * employeeProd[EmployeePositions.RandD] +
|
0.08 * this.creationProd[EmployeePositions.RandD] +
|
||||||
0.05 * employeeProd[EmployeePositions.Operations] +
|
0.05 * this.creationProd[EmployeePositions.Operations] +
|
||||||
0.05 * employeeProd[EmployeePositions.Business]);
|
0.05 * this.creationProd[EmployeePositions.Business]);
|
||||||
this.rel =
|
this.rel =
|
||||||
totalMult *
|
totalMult *
|
||||||
(0.02 * employeeProd[EmployeePositions.Engineer] +
|
(0.02 * this.creationProd[EmployeePositions.Engineer] +
|
||||||
0.08 * employeeProd[EmployeePositions.Management] +
|
0.08 * this.creationProd[EmployeePositions.Management] +
|
||||||
0.02 * employeeProd[EmployeePositions.RandD] +
|
0.02 * this.creationProd[EmployeePositions.RandD] +
|
||||||
0.05 * employeeProd[EmployeePositions.Operations] +
|
0.05 * this.creationProd[EmployeePositions.Operations] +
|
||||||
0.08 * employeeProd[EmployeePositions.Business]);
|
0.08 * this.creationProd[EmployeePositions.Business]);
|
||||||
this.aes =
|
this.aes =
|
||||||
totalMult *
|
totalMult *
|
||||||
(0.0 * employeeProd[EmployeePositions.Engineer] +
|
(0.0 * this.creationProd[EmployeePositions.Engineer] +
|
||||||
0.08 * employeeProd[EmployeePositions.Management] +
|
0.08 * this.creationProd[EmployeePositions.Management] +
|
||||||
0.05 * employeeProd[EmployeePositions.RandD] +
|
0.05 * this.creationProd[EmployeePositions.RandD] +
|
||||||
0.02 * employeeProd[EmployeePositions.Operations] +
|
0.02 * this.creationProd[EmployeePositions.Operations] +
|
||||||
0.1 * employeeProd[EmployeePositions.Business]);
|
0.1 * this.creationProd[EmployeePositions.Business]);
|
||||||
this.fea =
|
this.fea =
|
||||||
totalMult *
|
totalMult *
|
||||||
(0.08 * employeeProd[EmployeePositions.Engineer] +
|
(0.08 * this.creationProd[EmployeePositions.Engineer] +
|
||||||
0.05 * employeeProd[EmployeePositions.Management] +
|
0.05 * this.creationProd[EmployeePositions.Management] +
|
||||||
0.02 * employeeProd[EmployeePositions.RandD] +
|
0.02 * this.creationProd[EmployeePositions.RandD] +
|
||||||
0.05 * employeeProd[EmployeePositions.Operations] +
|
0.05 * this.creationProd[EmployeePositions.Operations] +
|
||||||
0.05 * employeeProd[EmployeePositions.Business]);
|
0.05 * this.creationProd[EmployeePositions.Business]);
|
||||||
this.calculateRating(industry);
|
this.calculateRating(industry);
|
||||||
const advMult = 1 + Math.pow(this.advCost, 0.1) / 100;
|
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);
|
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.
|
// I actually don't understand well enough to know if this is right.
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export function Industry(props: IProps): React.ReactElement {
|
|||||||
return (
|
return (
|
||||||
<Box display="flex">
|
<Box display="flex">
|
||||||
<Box sx={{ width: "50%" }}>
|
<Box sx={{ width: "50%" }}>
|
||||||
<IndustryOverview rerender={props.rerender} currentCity={props.city} office={props.office} />
|
<IndustryOverview rerender={props.rerender} />
|
||||||
<IndustryOffice rerender={props.rerender} office={props.office} />
|
<IndustryOffice rerender={props.rerender} office={props.office} />
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ width: "50%" }}>
|
<Box sx={{ width: "50%" }}>
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import React, { useState } from "react";
|
|||||||
import { OfficeSpace } from "../OfficeSpace";
|
import { OfficeSpace } from "../OfficeSpace";
|
||||||
import { Employee } from "../Employee";
|
import { Employee } from "../Employee";
|
||||||
import { EmployeePositions } from "../EmployeePositions";
|
import { EmployeePositions } from "../EmployeePositions";
|
||||||
|
import { BuyCoffee } from "../Actions";
|
||||||
|
|
||||||
|
import { MoneyCost } from "./MoneyCost";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
|
||||||
import { UpgradeOfficeSizeModal } from "./modals/UpgradeOfficeSizeModal";
|
import { UpgradeOfficeSizeModal } from "./modals/UpgradeOfficeSizeModal";
|
||||||
@@ -17,6 +19,7 @@ import Typography from "@mui/material/Typography";
|
|||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import IconButton from "@mui/material/IconButton";
|
import IconButton from "@mui/material/IconButton";
|
||||||
import Paper from "@mui/material/Paper";
|
import Paper from "@mui/material/Paper";
|
||||||
|
import ArrowForwardIcon from "@mui/icons-material/ArrowForward";
|
||||||
import ArrowDropUpIcon from "@mui/icons-material/ArrowDropUp";
|
import ArrowDropUpIcon from "@mui/icons-material/ArrowDropUp";
|
||||||
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
|
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
|
||||||
import Tooltip from "@mui/material/Tooltip";
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
@@ -33,14 +36,6 @@ interface IProps {
|
|||||||
rerender: () => void;
|
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 {
|
interface ISwitchProps {
|
||||||
manualMode: boolean;
|
manualMode: boolean;
|
||||||
switchMode: (f: (b: boolean) => boolean) => void;
|
switchMode: (f: (b: boolean) => boolean) => void;
|
||||||
@@ -115,14 +110,14 @@ function ManualManagement(props: IProps): React.ReactElement {
|
|||||||
{positionNames[i]}
|
{positionNames[i]}
|
||||||
</MenuItem>,
|
</MenuItem>,
|
||||||
);
|
);
|
||||||
if (emp != null && emp.pos === positionNames[i]) {
|
if (emp != null && emp.nextPos === positionNames[i]) {
|
||||||
employeePositionSelectorInitialValue = positionNames[i];
|
employeePositionSelectorInitialValue = emp.nextPos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function employeePositionSelectorOnChange(e: SelectChangeEvent<string>): void {
|
function employeePositionSelectorOnChange(e: SelectChangeEvent<string>): void {
|
||||||
if (employee === null) return;
|
if (employee === null) return;
|
||||||
employee.pos = e.target.value;
|
props.office.assignSingleJob(employee, e.target.value);
|
||||||
props.rerender();
|
props.rerender();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,41 +173,53 @@ interface IAutoAssignProps {
|
|||||||
rerender: () => void;
|
rerender: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function EmployeeCount(props: { num: number; next: number }): React.ReactElement {
|
||||||
|
return (
|
||||||
|
<Typography display="flex" alignItems="center" justifyContent="flex-end">
|
||||||
|
{props.num === props.next ? null : props.num}
|
||||||
|
{props.num === props.next ? null : <ArrowForwardIcon fontSize="inherit"/>}
|
||||||
|
{props.next}
|
||||||
|
</Typography>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function AutoAssignJob(props: IAutoAssignProps): React.ReactElement {
|
function AutoAssignJob(props: IAutoAssignProps): React.ReactElement {
|
||||||
const corp = useCorporation();
|
const currJob = props.office.employeeJobs[props.job];
|
||||||
const division = useDivision();
|
const nextJob = props.office.employeeNextJobs[props.job];
|
||||||
const numJob = countEmployee(props.office.employees, props.job);
|
const nextUna = props.office.employeeNextJobs[EmployeePositions.Unassigned];
|
||||||
const numUnassigned = countEmployee(props.office.employees, EmployeePositions.Unassigned);
|
|
||||||
function assignEmployee(): void {
|
function assignEmployee(): void {
|
||||||
if (numUnassigned <= 0) {
|
if (nextUna <= 0) {
|
||||||
console.warn("Cannot assign employee. No unassigned employees available");
|
console.warn("Cannot assign employee. No unassigned employees available");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
props.office.assignEmployeeToJob(props.job);
|
props.office.autoAssignJob(props.job, nextJob + 1);
|
||||||
props.office.calculateEmployeeProductivity(corp, division);
|
|
||||||
props.rerender();
|
props.rerender();
|
||||||
}
|
}
|
||||||
|
|
||||||
function unassignEmployee(): void {
|
function unassignEmployee(): void {
|
||||||
props.office.unassignEmployeeFromJob(props.job);
|
props.office.autoAssignJob(props.job, nextJob - 1);
|
||||||
props.office.calculateEmployeeProductivity(corp, division);
|
|
||||||
props.rerender();
|
props.rerender();
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<Tooltip title={props.desc}>
|
<Tooltip title={props.desc}>
|
||||||
<Typography>
|
<Typography>{props.job}</Typography>
|
||||||
{props.job} ({numJob})
|
|
||||||
</Typography>
|
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<IconButton disabled={numUnassigned === 0} onClick={assignEmployee}>
|
<EmployeeCount num={currJob} next={nextJob} />
|
||||||
|
</TableCell>
|
||||||
|
<TableCell width="1px">
|
||||||
|
<IconButton disabled={nextUna === 0} onClick={assignEmployee}>
|
||||||
<ArrowDropUpIcon />
|
<ArrowDropUpIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton disabled={numJob === 0} onClick={unassignEmployee}>
|
</TableCell>
|
||||||
|
<TableCell width="1px">
|
||||||
|
<IconButton disabled={nextJob === 0} onClick={unassignEmployee}>
|
||||||
<ArrowDropDownIcon />
|
<ArrowDropDownIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
@@ -223,7 +230,6 @@ function AutoAssignJob(props: IAutoAssignProps): React.ReactElement {
|
|||||||
function AutoManagement(props: IProps): React.ReactElement {
|
function AutoManagement(props: IProps): React.ReactElement {
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const division = useDivision();
|
const division = useDivision();
|
||||||
const numUnassigned = countEmployee(props.office.employees, EmployeePositions.Unassigned);
|
|
||||||
const vechain = corp.unlockUpgrades[4] === 1; // Has Vechain upgrade
|
const vechain = corp.unlockUpgrades[4] === 1; // Has Vechain upgrade
|
||||||
|
|
||||||
// Calculate average morale, happiness, energy, and salary.
|
// Calculate average morale, happiness, energy, and salary.
|
||||||
@@ -247,168 +253,164 @@ function AutoManagement(props: IProps): React.ReactElement {
|
|||||||
avgEnergy = totalEnergy / props.office.employees.length;
|
avgEnergy = totalEnergy / props.office.employees.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const currUna = props.office.employeeJobs[EmployeePositions.Unassigned];
|
||||||
|
const nextUna = props.office.employeeNextJobs[EmployeePositions.Unassigned];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Table padding="none">
|
||||||
<Table padding="none">
|
<TableBody>
|
||||||
<TableBody>
|
<TableRow>
|
||||||
<TableRow>
|
<TableCell>
|
||||||
<TableCell>
|
<Typography>Unassigned Employees:</Typography>
|
||||||
<Typography>Unassigned Employees:</Typography>
|
</TableCell>
|
||||||
</TableCell>
|
<TableCell>
|
||||||
<TableCell>
|
<EmployeeCount num={currUna} next={nextUna} />
|
||||||
<Typography>{numUnassigned}</Typography>
|
</TableCell>
|
||||||
</TableCell>
|
</TableRow>
|
||||||
</TableRow>
|
<TableRow>
|
||||||
<TableRow>
|
<TableCell>
|
||||||
<TableCell>
|
<Typography>Avg Employee Morale:</Typography>
|
||||||
<Typography>Avg Employee Morale:</Typography>
|
</TableCell>
|
||||||
</TableCell>
|
<TableCell align="right">
|
||||||
<TableCell>
|
<Typography>{numeralWrapper.format(avgMorale, "0.000")}</Typography>
|
||||||
<Typography>{numeralWrapper.format(avgMorale, "0.000")}</Typography>
|
</TableCell>
|
||||||
</TableCell>
|
</TableRow>
|
||||||
</TableRow>
|
<TableRow>
|
||||||
<TableRow>
|
<TableCell>
|
||||||
<TableCell>
|
<Typography>Avg Employee Happiness:</Typography>
|
||||||
<Typography>Avg Employee Happiness:</Typography>
|
</TableCell>
|
||||||
</TableCell>
|
<TableCell align="right">
|
||||||
<TableCell>
|
<Typography>{numeralWrapper.format(avgHappiness, "0.000")}</Typography>
|
||||||
<Typography>{numeralWrapper.format(avgHappiness, "0.000")}</Typography>
|
</TableCell>
|
||||||
</TableCell>
|
</TableRow>
|
||||||
</TableRow>
|
<TableRow>
|
||||||
<TableRow>
|
<TableCell>
|
||||||
<TableCell>
|
<Typography>Avg Employee Energy:</Typography>
|
||||||
<Typography>Avg Employee Energy:</Typography>
|
</TableCell>
|
||||||
</TableCell>
|
<TableCell align="right">
|
||||||
<TableCell>
|
<Typography>{numeralWrapper.format(avgEnergy, "0.000")}</Typography>
|
||||||
<Typography>{numeralWrapper.format(avgEnergy, "0.000")}</Typography>
|
</TableCell>
|
||||||
</TableCell>
|
</TableRow>
|
||||||
</TableRow>
|
<TableRow>
|
||||||
<TableRow>
|
<TableCell>
|
||||||
<TableCell>
|
<Typography>Total Employee Salary:</Typography>
|
||||||
<Typography>Total Employee Salary:</Typography>
|
</TableCell>
|
||||||
</TableCell>
|
<TableCell>
|
||||||
<TableCell>
|
<Typography align="right">
|
||||||
<Typography>
|
<Money money={totalSalary} />
|
||||||
<Money money={totalSalary} />
|
</Typography>
|
||||||
</Typography>
|
</TableCell>
|
||||||
</TableCell>
|
</TableRow>
|
||||||
</TableRow>
|
{vechain && (
|
||||||
{vechain && (
|
<>
|
||||||
<>
|
<TableRow>
|
||||||
<TableRow>
|
<TableCell>
|
||||||
<TableCell>
|
<Tooltip
|
||||||
<Tooltip
|
title={
|
||||||
title={
|
<Typography>
|
||||||
<Typography>
|
The base amount of material this office can produce. Does not include production multipliers from
|
||||||
The base amount of material this office can produce. Does not include production multipliers
|
upgrades and materials. This value is based off the productivity of your Operations, Engineering,
|
||||||
from upgrades and materials. This value is based off the productivity of your Operations,
|
and Management employees
|
||||||
Engineering, and Management employees
|
</Typography>
|
||||||
</Typography>
|
}
|
||||||
}
|
>
|
||||||
>
|
<Typography>Material Production:</Typography>
|
||||||
<Typography>Material Production:</Typography>
|
</Tooltip>
|
||||||
</Tooltip>
|
</TableCell>
|
||||||
</TableCell>
|
<TableCell>
|
||||||
<TableCell>
|
<Typography align="right">
|
||||||
<Typography>
|
{numeralWrapper.format(division.getOfficeProductivity(props.office), "0.000")}
|
||||||
{numeralWrapper.format(division.getOfficeProductivity(props.office), "0.000")}
|
</Typography>
|
||||||
</Typography>
|
</TableCell>
|
||||||
</TableCell>
|
</TableRow>
|
||||||
</TableRow>
|
<TableRow>
|
||||||
<TableRow>
|
<TableCell>
|
||||||
<TableCell>
|
<Tooltip
|
||||||
<Tooltip
|
title={
|
||||||
title={
|
<Typography>
|
||||||
<Typography>
|
The base amount of any given Product this office can produce. Does not include production
|
||||||
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
|
||||||
multipliers from upgrades and materials. This value is based off the productivity of your
|
Operations, Engineering, and Management employees
|
||||||
Operations, Engineering, and Management employees
|
</Typography>
|
||||||
</Typography>
|
}
|
||||||
}
|
>
|
||||||
>
|
<Typography>Product Production:</Typography>
|
||||||
<Typography>Product Production:</Typography>
|
</Tooltip>
|
||||||
</Tooltip>
|
</TableCell>
|
||||||
</TableCell>
|
<TableCell>
|
||||||
<TableCell>
|
<Typography align="right">
|
||||||
<Typography>
|
{numeralWrapper.format(
|
||||||
{numeralWrapper.format(
|
division.getOfficeProductivity(props.office, {
|
||||||
division.getOfficeProductivity(props.office, {
|
forProduct: true,
|
||||||
forProduct: true,
|
}),
|
||||||
}),
|
"0.000",
|
||||||
"0.000",
|
)}
|
||||||
)}
|
</Typography>
|
||||||
</Typography>
|
</TableCell>
|
||||||
</TableCell>
|
</TableRow>
|
||||||
</TableRow>
|
<TableRow>
|
||||||
<TableRow>
|
<TableCell>
|
||||||
<TableCell>
|
<Tooltip
|
||||||
<Tooltip
|
title={<Typography>The effect this office's 'Business' employees has on boosting sales</Typography>}
|
||||||
title={<Typography>The effect this office's 'Business' employees has on boosting sales</Typography>}
|
>
|
||||||
>
|
<Typography> Business Multiplier:</Typography>
|
||||||
<Typography> Business Multiplier:</Typography>
|
</Tooltip>
|
||||||
</Tooltip>
|
</TableCell>
|
||||||
</TableCell>
|
<TableCell align="right">
|
||||||
<TableCell>
|
<Typography>x{numeralWrapper.format(division.getBusinessFactor(props.office), "0.000")}</Typography>
|
||||||
<Typography>x{numeralWrapper.format(division.getBusinessFactor(props.office), "0.000")}</Typography>
|
</TableCell>
|
||||||
</TableCell>
|
</TableRow>
|
||||||
</TableRow>
|
</>
|
||||||
</>
|
)}
|
||||||
)}
|
<AutoAssignJob
|
||||||
</TableBody>
|
rerender={props.rerender}
|
||||||
</Table>
|
office={props.office}
|
||||||
|
job={EmployeePositions.Operations}
|
||||||
|
desc={"Manages supply chain operations. Improves the amount of Materials and Products you produce."}
|
||||||
|
/>
|
||||||
|
|
||||||
<Table padding="none">
|
<AutoAssignJob
|
||||||
<TableBody>
|
rerender={props.rerender}
|
||||||
<AutoAssignJob
|
office={props.office}
|
||||||
rerender={props.rerender}
|
job={EmployeePositions.Engineer}
|
||||||
office={props.office}
|
desc={
|
||||||
job={EmployeePositions.Operations}
|
"Develops and maintains products and production systems. Increases the quality of everything you produce. Also increases the amount you produce (not as much as Operations, however)"
|
||||||
desc={"Manages supply chain operations. Improves the amount of Materials and Products you produce."}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<AutoAssignJob
|
<AutoAssignJob
|
||||||
rerender={props.rerender}
|
rerender={props.rerender}
|
||||||
office={props.office}
|
office={props.office}
|
||||||
job={EmployeePositions.Engineer}
|
job={EmployeePositions.Business}
|
||||||
desc={
|
desc={"Handles sales and finances. Improves the amount of Materials and Products you can sell."}
|
||||||
"Develops and maintains products and production systems. Increases the quality of everything you produce. Also increases the amount you produce (not as much as Operations, however)"
|
/>
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AutoAssignJob
|
<AutoAssignJob
|
||||||
rerender={props.rerender}
|
rerender={props.rerender}
|
||||||
office={props.office}
|
office={props.office}
|
||||||
job={EmployeePositions.Business}
|
job={EmployeePositions.Management}
|
||||||
desc={"Handles sales and finances. Improves the amount of Materials and Products you can sell."}
|
desc={
|
||||||
/>
|
"Leads and oversees employees and office operations. Improves the effectiveness of Engineer and Operations employees."
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<AutoAssignJob
|
<AutoAssignJob
|
||||||
rerender={props.rerender}
|
rerender={props.rerender}
|
||||||
office={props.office}
|
office={props.office}
|
||||||
job={EmployeePositions.Management}
|
job={EmployeePositions.RandD}
|
||||||
desc={
|
desc={"Research new innovative ways to improve the company. Generates Scientific Research."}
|
||||||
"Leads and oversees employees and office operations. Improves the effectiveness of Engineer and Operations employees."
|
/>
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<AutoAssignJob
|
<AutoAssignJob
|
||||||
rerender={props.rerender}
|
rerender={props.rerender}
|
||||||
office={props.office}
|
office={props.office}
|
||||||
job={EmployeePositions.RandD}
|
job={EmployeePositions.Training}
|
||||||
desc={"Research new innovative ways to improve the company. Generates Scientific Research."}
|
desc={
|
||||||
/>
|
"Set employee to training, which will increase some of their stats. Employees in training do not affect any company operations."
|
||||||
|
}
|
||||||
<AutoAssignJob
|
/>
|
||||||
rerender={props.rerender}
|
</TableBody>
|
||||||
office={props.office}
|
</Table>
|
||||||
job={EmployeePositions.Training}
|
|
||||||
desc={
|
|
||||||
"Set employee to training, which will increase some of their stats. Employees in training do not affect any company operations."
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,14 +456,40 @@ export function IndustryOffice(props: IProps): React.ReactElement {
|
|||||||
onClose={() => setUpgradeOfficeSizeOpen(false)}
|
onClose={() => setUpgradeOfficeSizeOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{!division.hasResearch("AutoBrew") && (
|
||||||
|
<>
|
||||||
|
<Tooltip
|
||||||
|
title={<Typography>Throw an office party to increase your employee's morale and happiness</Typography>}
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
<Button
|
||||||
|
disabled={corp.funds < props.office.getCoffeeCost() || props.office.coffeeMult > 0}
|
||||||
|
onClick={() => BuyCoffee(corp, props.office)}
|
||||||
|
>
|
||||||
|
{props.office.coffeeMult > 0 ? (
|
||||||
|
"Buying coffee..."
|
||||||
|
) : (
|
||||||
|
<span>
|
||||||
|
Buy Coffee - <MoneyCost money={props.office.getCoffeeCost()} corp={corp} />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
{!division.hasResearch("AutoPartyManager") && (
|
{!division.hasResearch("AutoPartyManager") && (
|
||||||
<>
|
<>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={<Typography>Throw an office party to increase your employee's morale and happiness</Typography>}
|
title={<Typography>Throw an office party to increase your employee's morale and happiness</Typography>}
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
<Button disabled={corp.funds < 0} onClick={() => setThrowPartyOpen(true)}>
|
<Button
|
||||||
Throw Party
|
disabled={corp.funds < 0 || props.office.partyMult > 0}
|
||||||
|
onClick={() => setThrowPartyOpen(true)}
|
||||||
|
>
|
||||||
|
{props.office.partyMult > 0 ? "Throwing Party..." : "Throw Party"}
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|||||||
@@ -2,9 +2,8 @@
|
|||||||
// (top-left panel in the Industry UI)
|
// (top-left panel in the Industry UI)
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import { OfficeSpace } from "../OfficeSpace";
|
|
||||||
import { Industries } from "../IndustryData";
|
import { Industries } from "../IndustryData";
|
||||||
import { IndustryUpgrades } from "../IndustryUpgrades";
|
import { HireAdVert } from "../Actions";
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
|
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
|
||||||
import { MakeProductModal } from "./modals/MakeProductModal";
|
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 corp = useCorporation();
|
||||||
const division = useDivision();
|
const division = useDivision();
|
||||||
const [helpOpen, setHelpOpen] = useState(false);
|
const [helpOpen, setHelpOpen] = useState(false);
|
||||||
@@ -113,7 +117,7 @@ function Text(): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Paper>
|
||||||
<Typography>
|
<Typography>
|
||||||
Industry: {division.type} (Corp Funds: <Money money={corp.funds} />)
|
Industry: {division.type} (Corp Funds: <Money money={corp.funds} />)
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -191,7 +195,6 @@ function Text(): React.ReactElement {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</StaticModal>
|
</StaticModal>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box display="flex" alignItems="center">
|
<Box display="flex" alignItems="center">
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={
|
title={
|
||||||
@@ -207,76 +210,30 @@ function Text(): React.ReactElement {
|
|||||||
</Button>
|
</Button>
|
||||||
<ResearchModal open={researchOpen} onClose={() => setResearchOpen(false)} industry={division} />
|
<ResearchModal open={researchOpen} onClose={() => setResearchOpen(false)} industry={division} />
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
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(
|
|
||||||
<Tooltip key={index} title={upgrade[5]}>
|
|
||||||
<span>
|
|
||||||
<Button disabled={corp.funds < cost} onClick={onClick}>
|
|
||||||
{upgrade[4]} -
|
|
||||||
<MoneyCost money={cost} corp={corp} />
|
|
||||||
</Button>
|
|
||||||
</span>
|
|
||||||
</Tooltip>,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <>{upgrades}</>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IProps {
|
|
||||||
currentCity: string;
|
|
||||||
office: OfficeSpace;
|
|
||||||
rerender: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function IndustryOverview(props: IProps): React.ReactElement {
|
|
||||||
const division = useDivision();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Paper>
|
|
||||||
<Text />
|
|
||||||
<br />
|
<br />
|
||||||
<Typography>Purchases & Upgrades</Typography>
|
<Box display="flex" alignItems="center">
|
||||||
<Upgrades office={props.office} rerender={props.rerender} /> <br />
|
<Tooltip
|
||||||
{division.makesProducts && <MakeProductButton />}
|
title={
|
||||||
|
<Typography>
|
||||||
|
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.
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
disabled={division.getAdVertCost() > corp.funds}
|
||||||
|
onClick={function () {
|
||||||
|
HireAdVert(corp, division);
|
||||||
|
props.rerender();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Hire AdVert - <MoneyCost money={division.getAdVertCost()} corp={corp} />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
{division.makesProducts && <MakeProductButton />}
|
||||||
|
</Box>
|
||||||
</Paper>
|
</Paper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,11 +38,15 @@ export function ThrowPartyModal(props: IProps): React.ReactElement {
|
|||||||
dialogBoxCreate("You don't have enough company funds to throw a party!");
|
dialogBoxCreate("You don't have enough company funds to throw a party!");
|
||||||
} else {
|
} else {
|
||||||
const mult = ThrowParty(corp, props.office, cost);
|
const mult = ThrowParty(corp, props.office, cost);
|
||||||
dialogBoxCreate(
|
|
||||||
"You threw a party for the office! The morale and happiness " +
|
if (mult > 0) {
|
||||||
"of each employee increased by " +
|
dialogBoxCreate(
|
||||||
numeralWrapper.formatPercentage(mult - 1),
|
"You threw a party for the office! The morale and happiness " +
|
||||||
);
|
"of each employee increased by " +
|
||||||
|
numeralWrapper.formatPercentage(mult - 1),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
props.rerender();
|
props.rerender();
|
||||||
props.onClose();
|
props.onClose();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -531,7 +531,7 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS {
|
|||||||
bladeburner: NetscriptBladeburner(Player, workerScript),
|
bladeburner: NetscriptBladeburner(Player, workerScript),
|
||||||
codingcontract: NetscriptCodingContract(Player, workerScript),
|
codingcontract: NetscriptCodingContract(Player, workerScript),
|
||||||
sleeve: NetscriptSleeve(Player),
|
sleeve: NetscriptSleeve(Player),
|
||||||
corporation: NetscriptCorporation(Player, workerScript),
|
corporation: NetscriptCorporation(Player),
|
||||||
stanek: NetscriptStanek(Player, workerScript, helper),
|
stanek: NetscriptStanek(Player, workerScript, helper),
|
||||||
infiltration: NetscriptInfiltration(Player),
|
infiltration: NetscriptInfiltration(Player),
|
||||||
ui: NetscriptUserInterface(),
|
ui: NetscriptUserInterface(),
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
import { WorkerScript } from "../Netscript/WorkerScript";
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { netscriptDelay } from "../NetscriptEvaluator";
|
|
||||||
|
|
||||||
import { OfficeSpace } from "../Corporation/OfficeSpace";
|
import { OfficeSpace } from "../Corporation/OfficeSpace";
|
||||||
import { Employee } from "../Corporation/Employee";
|
import { Employee } from "../Corporation/Employee";
|
||||||
@@ -34,11 +32,12 @@ import {
|
|||||||
SetSmartSupply,
|
SetSmartSupply,
|
||||||
BuyMaterial,
|
BuyMaterial,
|
||||||
AssignJob,
|
AssignJob,
|
||||||
|
AutoAssignJob,
|
||||||
UpgradeOfficeSize,
|
UpgradeOfficeSize,
|
||||||
ThrowParty,
|
|
||||||
PurchaseWarehouse,
|
PurchaseWarehouse,
|
||||||
UpgradeWarehouse,
|
UpgradeWarehouse,
|
||||||
BuyCoffee,
|
BuyCoffee,
|
||||||
|
ThrowParty,
|
||||||
HireAdVert,
|
HireAdVert,
|
||||||
MakeProduct,
|
MakeProduct,
|
||||||
Research,
|
Research,
|
||||||
@@ -59,17 +58,15 @@ import {
|
|||||||
import { CorporationUnlockUpgrades } from "../Corporation/data/CorporationUnlockUpgrades";
|
import { CorporationUnlockUpgrades } from "../Corporation/data/CorporationUnlockUpgrades";
|
||||||
import { CorporationUpgrades } from "../Corporation/data/CorporationUpgrades";
|
import { CorporationUpgrades } from "../Corporation/data/CorporationUpgrades";
|
||||||
import { EmployeePositions } from "../Corporation/EmployeePositions";
|
import { EmployeePositions } from "../Corporation/EmployeePositions";
|
||||||
import { calculateIntelligenceBonus } from "../PersonObjects/formulas/intelligence";
|
|
||||||
import { Industry } from "../Corporation/Industry";
|
import { Industry } from "../Corporation/Industry";
|
||||||
import { IndustryResearchTrees, IndustryStartingCosts } from "../Corporation/IndustryData";
|
import { IndustryResearchTrees, IndustryStartingCosts } from "../Corporation/IndustryData";
|
||||||
import { CorporationConstants } from "../Corporation/data/Constants";
|
import { CorporationConstants } from "../Corporation/data/Constants";
|
||||||
import { IndustryUpgrades } from "../Corporation/IndustryUpgrades";
|
|
||||||
import { ResearchMap } from "../Corporation/ResearchMap";
|
import { ResearchMap } from "../Corporation/ResearchMap";
|
||||||
import { Factions } from "../Faction/Factions";
|
import { Factions } from "../Faction/Factions";
|
||||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
import { InternalAPI, NetscriptContext } from "src/Netscript/APIWrapper";
|
||||||
|
|
||||||
export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript): InternalAPI<NSCorporation> {
|
export function NetscriptCorporation(player: IPlayer): InternalAPI<NSCorporation> {
|
||||||
function createCorporation(corporationName: string, selfFund = true): boolean {
|
function createCorporation(corporationName: string, selfFund = true): boolean {
|
||||||
if (!player.canAccessCorporation() || player.hasCorporation()) return false;
|
if (!player.canAccessCorporation() || player.hasCorporation()) return false;
|
||||||
if (!corporationName) return false;
|
if (!corporationName) return false;
|
||||||
@@ -302,7 +299,7 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript
|
|||||||
lastCycleExpenses: division.lastCycleExpenses,
|
lastCycleExpenses: division.lastCycleExpenses,
|
||||||
thisCycleRevenue: division.thisCycleRevenue,
|
thisCycleRevenue: division.thisCycleRevenue,
|
||||||
thisCycleExpenses: division.thisCycleExpenses,
|
thisCycleExpenses: division.thisCycleExpenses,
|
||||||
upgrades: division.upgrades.slice(),
|
upgrades: [0, division.numAdVerts],
|
||||||
cities: cities,
|
cities: cities,
|
||||||
products: division.products === undefined ? [] : Object.keys(division.products),
|
products: division.products === undefined ? [] : Object.keys(division.products),
|
||||||
makesProducts: division.makesProducts,
|
makesProducts: division.makesProducts,
|
||||||
@@ -658,8 +655,7 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript
|
|||||||
checkAccess(ctx, 8);
|
checkAccess(ctx, 8);
|
||||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||||
const division = getDivision(divisionName);
|
const division = getDivision(divisionName);
|
||||||
const upgrade = IndustryUpgrades[1];
|
return division.getAdVertCost();
|
||||||
return upgrade[1] * Math.pow(upgrade[2], division.upgrades[1]);
|
|
||||||
},
|
},
|
||||||
getHireAdVertCount:
|
getHireAdVertCount:
|
||||||
(ctx: NetscriptContext) =>
|
(ctx: NetscriptContext) =>
|
||||||
@@ -667,7 +663,7 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript
|
|||||||
checkAccess(ctx, 8);
|
checkAccess(ctx, 8);
|
||||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||||
const division = getDivision(divisionName);
|
const division = getDivision(divisionName);
|
||||||
return division.upgrades[1];
|
return division.numAdVerts;
|
||||||
},
|
},
|
||||||
getResearchCost:
|
getResearchCost:
|
||||||
(ctx: NetscriptContext) =>
|
(ctx: NetscriptContext) =>
|
||||||
@@ -685,20 +681,6 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript
|
|||||||
const researchName = ctx.helper.string("researchName", _researchName);
|
const researchName = ctx.helper.string("researchName", _researchName);
|
||||||
return hasResearched(getDivision(divisionName), researchName);
|
return hasResearched(getDivision(divisionName), researchName);
|
||||||
},
|
},
|
||||||
setAutoJobAssignment:
|
|
||||||
(ctx: NetscriptContext) =>
|
|
||||||
(_divisionName: unknown, _cityName: unknown, _job: unknown, _amount: unknown): Promise<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);
|
|
||||||
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:
|
getOfficeSizeUpgradeCost:
|
||||||
(ctx: NetscriptContext) =>
|
(ctx: NetscriptContext) =>
|
||||||
(_divisionName: unknown, _cityName: unknown, _size: unknown): number => {
|
(_divisionName: unknown, _cityName: unknown, _size: unknown): number => {
|
||||||
@@ -718,18 +700,31 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
assignJob:
|
assignJob:
|
||||||
(ctx: NetscriptContext) =>
|
(ctx: NetscriptContext) =>
|
||||||
(_divisionName: unknown, _cityName: unknown, _employeeName: unknown, _job: unknown): Promise<void> => {
|
(_divisionName: unknown, _cityName: unknown, _employeeName: unknown, _job: unknown): void => {
|
||||||
checkAccess(ctx, 8);
|
checkAccess(ctx, 8);
|
||||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||||
const cityName = ctx.helper.city("cityName", _cityName);
|
const cityName = ctx.helper.city("cityName", _cityName);
|
||||||
const employeeName = ctx.helper.string("employeeName", _employeeName);
|
const employeeName = ctx.helper.string("employeeName", _employeeName);
|
||||||
const job = ctx.helper.string("job", _job);
|
const job = ctx.helper.string("job", _job);
|
||||||
const employee = getEmployee(divisionName, cityName, employeeName);
|
|
||||||
return netscriptDelay(["Training", "Unassigned"].includes(employee.pos) ? 0 : 1000, workerScript).then(
|
if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`);
|
||||||
function () {
|
const office = getOffice(divisionName, cityName);
|
||||||
return Promise.resolve(AssignJob(employee, job));
|
|
||||||
},
|
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:
|
hireEmployee:
|
||||||
(ctx: NetscriptContext) =>
|
(ctx: NetscriptContext) =>
|
||||||
@@ -769,35 +764,32 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
throwParty:
|
throwParty:
|
||||||
(ctx: NetscriptContext) =>
|
(ctx: NetscriptContext) =>
|
||||||
async (_divisionName: unknown, _cityName: unknown, _costPerEmployee: unknown): Promise<number> => {
|
(_divisionName: unknown, _cityName: unknown, _costPerEmployee: unknown): number => {
|
||||||
checkAccess(ctx, 8);
|
checkAccess(ctx, 8);
|
||||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||||
const cityName = ctx.helper.city("cityName", _cityName);
|
const cityName = ctx.helper.city("cityName", _cityName);
|
||||||
const costPerEmployee = ctx.helper.number("costPerEmployee", _costPerEmployee);
|
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");
|
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();
|
const corporation = getCorporation();
|
||||||
return netscriptDelay(
|
const office = getOffice(divisionName, cityName);
|
||||||
(60 * 1000) / (player.hacking_speed_mult * calculateIntelligenceBonus(player.intelligence, 1)),
|
|
||||||
workerScript,
|
return ThrowParty(corporation, office, costPerEmployee);
|
||||||
).then(function () {
|
|
||||||
return Promise.resolve(ThrowParty(corporation, office, costPerEmployee));
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
buyCoffee:
|
buyCoffee:
|
||||||
(ctx: NetscriptContext) =>
|
(ctx: NetscriptContext) =>
|
||||||
async (_divisionName: unknown, _cityName: unknown): Promise<void> => {
|
(_divisionName: unknown, _cityName: unknown): boolean => {
|
||||||
checkAccess(ctx, 8);
|
checkAccess(ctx, 8);
|
||||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||||
const cityName = ctx.helper.city("cityName", _cityName);
|
const cityName = ctx.helper.city("cityName", _cityName);
|
||||||
|
|
||||||
const corporation = getCorporation();
|
const corporation = getCorporation();
|
||||||
return netscriptDelay(
|
const office = getOffice(divisionName, cityName);
|
||||||
(60 * 1000) / (player.hacking_speed_mult * calculateIntelligenceBonus(player.intelligence, 1)),
|
|
||||||
workerScript,
|
return BuyCoffee(corporation, office);
|
||||||
).then(function () {
|
|
||||||
return Promise.resolve(BuyCoffee(corporation, getDivision(divisionName), getOffice(divisionName, cityName)));
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
hireAdVert:
|
hireAdVert:
|
||||||
(ctx: NetscriptContext) =>
|
(ctx: NetscriptContext) =>
|
||||||
@@ -805,7 +797,7 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript
|
|||||||
checkAccess(ctx, 8);
|
checkAccess(ctx, 8);
|
||||||
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
const divisionName = ctx.helper.string("divisionName", _divisionName);
|
||||||
const corporation = getCorporation();
|
const corporation = getCorporation();
|
||||||
HireAdVert(corporation, getDivision(divisionName), getOffice(divisionName, "Sector-12"));
|
HireAdVert(corporation, getDivision(divisionName));
|
||||||
},
|
},
|
||||||
research:
|
research:
|
||||||
(ctx: NetscriptContext) =>
|
(ctx: NetscriptContext) =>
|
||||||
@@ -829,6 +821,7 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript
|
|||||||
maxEne: office.maxEne,
|
maxEne: office.maxEne,
|
||||||
minHap: office.minHap,
|
minHap: office.minHap,
|
||||||
maxHap: office.maxHap,
|
maxHap: office.maxHap,
|
||||||
|
minMor: office.minMor,
|
||||||
maxMor: office.maxMor,
|
maxMor: office.maxMor,
|
||||||
employees: office.employees.map((e) => e.name),
|
employees: office.employees.map((e) => e.name),
|
||||||
employeeProd: {
|
employeeProd: {
|
||||||
|
|||||||
+9
-8
@@ -6623,9 +6623,8 @@ export interface OfficeAPI {
|
|||||||
* @param cityName - Name of the city
|
* @param cityName - Name of the city
|
||||||
* @param employeeName - name of the employee
|
* @param employeeName - name of the employee
|
||||||
* @param job - Name of the job.
|
* @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<void>;
|
assignJob(divisionName: string, cityName: string, employeeName: string, job: string): void;
|
||||||
/**
|
/**
|
||||||
* Hire an employee.
|
* Hire an employee.
|
||||||
* @param divisionName - Name of the division
|
* @param divisionName - Name of the division
|
||||||
@@ -6645,16 +6644,16 @@ export interface OfficeAPI {
|
|||||||
* @param divisionName - Name of the division
|
* @param divisionName - Name of the division
|
||||||
* @param cityName - Name of the city
|
* @param cityName - Name of the city
|
||||||
* @param costPerEmployee - Amount to spend per employee.
|
* @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<number>;
|
throwParty(divisionName: string, cityName: string, costPerEmployee: number): number;
|
||||||
/**
|
/**
|
||||||
* Buy coffee for your employees
|
* Buy coffee for your employees
|
||||||
* @param divisionName - Name of the division
|
* @param divisionName - Name of the division
|
||||||
* @param cityName - Name of the city
|
* @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<void>;
|
buyCoffee(divisionName: string, cityName: string): boolean;
|
||||||
/**
|
/**
|
||||||
* Hire AdVert.
|
* Hire AdVert.
|
||||||
* @param divisionName - Name of the division
|
* @param divisionName - Name of the division
|
||||||
@@ -6713,9 +6712,9 @@ export interface OfficeAPI {
|
|||||||
* @param cityName - Name of the city
|
* @param cityName - Name of the city
|
||||||
* @param job - Name of the job
|
* @param job - Name of the job
|
||||||
* @param amount - Number of employees to assign to that 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<boolean>;
|
setAutoJobAssignment(divisionName: string, cityName: string, job: string, amount: number): boolean;
|
||||||
/**
|
/**
|
||||||
* Cost to Upgrade office size.
|
* Cost to Upgrade office size.
|
||||||
* @param divisionName - Name of the division
|
* @param divisionName - Name of the division
|
||||||
@@ -7234,6 +7233,8 @@ interface Office {
|
|||||||
minHap: number;
|
minHap: number;
|
||||||
/** Maximum happiness of the employees */
|
/** Maximum happiness of the employees */
|
||||||
maxHap: number;
|
maxHap: number;
|
||||||
|
/** Minimum morale of the employees */
|
||||||
|
minMor: number;
|
||||||
/** Maximum morale of the employees */
|
/** Maximum morale of the employees */
|
||||||
maxMor: number;
|
maxMor: number;
|
||||||
/** Name of all the employees */
|
/** Name of all the employees */
|
||||||
|
|||||||
Reference in New Issue
Block a user