mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-26 17:43:48 +01:00
Fixed numerous bugs with the recent Corporation UI rewrite. Rebalanced Corporation mechanic to give employees better and more interesting effects
This commit is contained in:
parent
8470f307ac
commit
c3ecc189fd
@ -5,7 +5,7 @@ played at https://danielyxie.github.io/bitburner.
|
||||
# Documentation
|
||||
The game's official documentation can be found on [Read The
|
||||
Docs](http://bitburner.readthedocs.io/). Please note that this is still a
|
||||
work-in-progress and is in its early stages.
|
||||
work-in-progress.
|
||||
|
||||
The documentation is created using [Sphinx](http://www.sphinx-doc.org).
|
||||
|
||||
@ -14,11 +14,6 @@ files](/doc/source) and then making a pull request with your contributions.
|
||||
For further guidance, please refer to the "As A Documentor" section of
|
||||
[CONTRIBUTING](CONTRIBUTING.md).
|
||||
|
||||
# Wiki
|
||||
The game's wiki can be found on [Wikia](http://bitburner.wikia.com/). Please
|
||||
note that the wiki is in the process of being deprecated. Eventually all of
|
||||
the wiki content will be moved into the Read The Docs documentation.
|
||||
|
||||
# Contribution
|
||||
There are many ways to contribute to the game. It can be as simple as fixing
|
||||
a typo, correcting a bug, or improving the UI. For guidance on doing so,
|
||||
@ -32,4 +27,4 @@ publish, and distribute your contributions to the project. A formal
|
||||
Contributor's License Agreement will be drawn up in the future.
|
||||
|
||||
If you would like to make significant contributions to the project as a
|
||||
collaborator, please reach out to @danielyxie to help coordinate the effort.
|
||||
collaborator, please reach out to @danielyxie to help coordinate the effort.
|
||||
|
@ -159,5 +159,6 @@
|
||||
|
||||
/* Research */
|
||||
#corporation-research-popup-box-content {
|
||||
overflow-x: visible !important;
|
||||
overflow-x: auto !important;
|
||||
overflow-y: auto !important;
|
||||
}
|
||||
|
@ -258,6 +258,7 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.FactionPassiveRepGain = 0;
|
||||
break;
|
||||
case 3: //Corporatocracy
|
||||
BitNodeMultipliers.HackingLevelMultiplier = 0.8;
|
||||
BitNodeMultipliers.RepToDonateToFaction = 0.5;
|
||||
BitNodeMultipliers.AugmentationRepCost = 3;
|
||||
BitNodeMultipliers.AugmentationMoneyCost = 3;
|
||||
@ -268,6 +269,8 @@ export function initBitNodeMultipliers(p: IPlayer) {
|
||||
BitNodeMultipliers.CompanyWorkMoney = 0.25;
|
||||
BitNodeMultipliers.CrimeMoney = 0.25;
|
||||
BitNodeMultipliers.HacknetNodeMoney = 0.25;
|
||||
BitNodeMultipliers.HomeComputerRamCost = 1.5;
|
||||
BitNodeMultipliers.PurchasedServerCost = 2;
|
||||
break;
|
||||
case 4: //The Singularity
|
||||
BitNodeMultipliers.ServerMaxMoney = 0.15;
|
||||
|
@ -1417,7 +1417,7 @@ Bladeburner.prototype.completeAction = function() {
|
||||
break;
|
||||
case ActionTypes["Hyperbolic Regeneration Chamber"]:
|
||||
Player.regenerateHp(HrcHpGain);
|
||||
this.stamina = Math.max(this.maxStamina, this.stamina + HrcStaminaGain); // TODO Turn this into a const and adjust value
|
||||
this.stamina = Math.min(this.maxStamina, this.stamina + HrcStaminaGain);
|
||||
this.startAction(this.action);
|
||||
if (this.logging.general) {
|
||||
this.log(`Rested in Hyperbolic Regeneration Chamber. Restored ${HrcHpGain} HP and gained ${HrcStaminaGain} stamina`);
|
||||
|
@ -291,7 +291,15 @@ export let CONSTANTS: IMap<any> = {
|
||||
** Added several new Research upgrades
|
||||
** Reduced the amount of Scientific Research needed to unlock the Hi-Tech R&D Laboratory from 10k to 5k
|
||||
** Energy Material requirement of the Software industry reduced from 1 to 0.5
|
||||
** It is now slightly easier to increase the Software industry's production multiplier
|
||||
** Industries now have a maximum number of allowed products, starting at 3. This can be increased through research.
|
||||
** You can now see an approximation of how each material affects an industry's production multiplier by clicking the "?" help tip next to it
|
||||
** Significantly changed the effects of the different employee positions. See updated descriptions
|
||||
** Reduced the amount of money you gain from private investors
|
||||
** Training employees is now 3x more effective
|
||||
|
||||
* Rebalanced BitNode-3 to make it slightly harder
|
||||
* Bug Fix: Bladeburner's Hyperbolic Regeneration Chamber should no longer instantly refill all stamina
|
||||
`
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ import { Player } from "../Player";
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
import { Page, routing } from "../ui/navigationTracking";
|
||||
|
||||
import { calculateEffectWithFactors } from "../utils/calculateEffectWithFactors";
|
||||
|
||||
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||
import { clearSelector } from "../../utils/uiHelpers/clearSelector";
|
||||
import { Reviver,
|
||||
@ -37,7 +39,6 @@ import { formatNumber, generateRandomString } from "../../utils/String
|
||||
import { getRandomInt } from "../../utils/helpers/getRandomInt";
|
||||
import { isString } from "../../utils/helpers/isString";
|
||||
import { KEY } from "../../utils/helpers/keyCodes";
|
||||
import { removeChildrenFromElement } from "../../utils/uiHelpers/removeChildrenFromElement";
|
||||
import { removeElement } from "../../utils/uiHelpers/removeElement";
|
||||
import { removeElementById } from "../../utils/uiHelpers/removeElementById";
|
||||
import { yesNoBoxCreate,
|
||||
@ -48,8 +49,7 @@ import { yesNoBoxCreate,
|
||||
yesNoTxtInpBoxGetNoButton,
|
||||
yesNoTxtInpBoxGetInput,
|
||||
yesNoBoxClose,
|
||||
yesNoTxtInpBoxClose,
|
||||
yesNoBoxOpen } from "../../utils/YesNoBox";
|
||||
yesNoTxtInpBoxClose } from "../../utils/YesNoBox";
|
||||
|
||||
// UI Related Imports
|
||||
import React from "react";
|
||||
@ -124,18 +124,6 @@ function Industry(params={}) {
|
||||
[Locations.Volhaven]: 0
|
||||
};
|
||||
|
||||
this.warehouses = { //Maps locations to warehouses. 0 if no warehouse at that location
|
||||
[Locations.Aevum]: 0,
|
||||
[Locations.Chonqing]: 0,
|
||||
[Locations.Sector12]: new Warehouse({
|
||||
loc:Locations.Sector12,
|
||||
size: WarehouseInitialSize,
|
||||
}),
|
||||
[Locations.NewTokyo]: 0,
|
||||
[Locations.Ishima]: 0,
|
||||
[Locations.Volhaven]: 0
|
||||
};
|
||||
|
||||
this.name = params.name ? params.name : 0;
|
||||
this.type = params.type ? params.type : 0;
|
||||
|
||||
@ -183,6 +171,20 @@ function Industry(params={}) {
|
||||
this.state = "START";
|
||||
this.newInd = true;
|
||||
|
||||
this.warehouses = { //Maps locations to warehouses. 0 if no warehouse at that location
|
||||
[Locations.Aevum]: 0,
|
||||
[Locations.Chonqing]: 0,
|
||||
[Locations.Sector12]: new Warehouse({
|
||||
corp: params.corp,
|
||||
industry: this,
|
||||
loc: Locations.Sector12,
|
||||
size: WarehouseInitialSize,
|
||||
}),
|
||||
[Locations.NewTokyo]: 0,
|
||||
[Locations.Ishima]: 0,
|
||||
[Locations.Volhaven]: 0
|
||||
};
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
@ -340,8 +342,8 @@ Industry.prototype.init = function() {
|
||||
this.sciFac = 0.62;
|
||||
this.advFac = 0.16;
|
||||
this.hwFac = 0.25;
|
||||
this.reFac = 0.1;
|
||||
this.aiFac = 0.15;
|
||||
this.reFac = 0.15;
|
||||
this.aiFac = 0.18;
|
||||
this.robFac = 0.05;
|
||||
this.reqMats = {
|
||||
"Hardware": 0.5,
|
||||
@ -711,7 +713,7 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
|
||||
for (var j = 0; j < this.prodMats.length; ++j) {
|
||||
warehouse.materials[this.prodMats[j]].qty += (prod * producableFrac);
|
||||
warehouse.materials[this.prodMats[j]].qlt =
|
||||
(office.employeeProd[EmployeePositions.Engineer] / 100 +
|
||||
(office.employeeProd[EmployeePositions.Engineer] / 90 +
|
||||
Math.pow(this.sciResearch.qty, this.sciFac) +
|
||||
Math.pow(warehouse.materials["AICores"].qty, this.aiFac) / 10e3);
|
||||
}
|
||||
@ -918,27 +920,30 @@ Industry.prototype.processProducts = function(marketCycles=1, corporation) {
|
||||
|
||||
//Create products
|
||||
if (this.state === "PRODUCTION") {
|
||||
for (var prodName in this.products) {
|
||||
if (this.products.hasOwnProperty(prodName)) {
|
||||
var prod = this.products[prodName];
|
||||
if (!prod.fin) {
|
||||
var city = prod.createCity, office = this.offices[city];
|
||||
var total = office.employeeProd[EmployeePositions.Operations] +
|
||||
office.employeeProd[EmployeePositions.Engineer] +
|
||||
office.employeeProd[EmployeePositions.Management], ratio;
|
||||
if (total === 0) {
|
||||
ratio = 0;
|
||||
} else {
|
||||
ratio = office.employeeProd[EmployeePositions.Engineer] / total +
|
||||
office.employeeProd[EmployeePositions.Operations] / total +
|
||||
office.employeeProd[EmployeePositions.Management] / total;
|
||||
}
|
||||
prod.createProduct(marketCycles, ratio * Math.pow(total, 0.35));
|
||||
if (prod.prog >= 100) {
|
||||
prod.finishProduct(office.employeeProd, this);
|
||||
}
|
||||
break;
|
||||
for (const prodName in this.products) {
|
||||
const prod = this.products[prodName];
|
||||
if (!prod.fin) {
|
||||
const city = prod.createCity;
|
||||
const office = this.offices[city];
|
||||
|
||||
// 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);
|
||||
if (prod.prog >= 100) {
|
||||
prod.finishProduct(office.employeeProd, this);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1147,33 +1152,38 @@ Industry.prototype.upgrade = function(upgrade, refs) {
|
||||
}
|
||||
}
|
||||
|
||||
//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)
|
||||
Industry.prototype.getOfficeProductivity = function(office, params) {
|
||||
var total = office.employeeProd[EmployeePositions.Operations] +
|
||||
office.employeeProd[EmployeePositions.Engineer] +
|
||||
office.employeeProd[EmployeePositions.Management], ratio;
|
||||
if (total === 0) {
|
||||
ratio = 0;
|
||||
} else {
|
||||
ratio = (office.employeeProd[EmployeePositions.Operations] / total) *
|
||||
(office.employeeProd[EmployeePositions.Engineer] / total) *
|
||||
(office.employeeProd[EmployeePositions.Management] / total);
|
||||
ratio = Math.max(0.01, ratio); //Minimum ratio value if you have employees
|
||||
}
|
||||
const opProd = office.employeeProd[EmployeePositions.Operations];
|
||||
const engrProd = office.employeeProd[EmployeePositions.Engineer];
|
||||
const mgmtProd = office.employeeProd[EmployeePositions.Management]
|
||||
const total = opProd + engrProd + mgmtProd;
|
||||
|
||||
if (total <= 0) { return 0; }
|
||||
|
||||
// Management is a multiplier for the production from Operations and Engineers
|
||||
const mgmtFactor = 1 + (mgmtProd / (1.2 * total));
|
||||
|
||||
// For production, Operations is slightly more important than engineering
|
||||
// Both Engineering and Operations have diminishing returns
|
||||
const prod = (Math.pow(opProd, 0.4) + Math.pow(engrProd, 0.3)) * mgmtFactor;
|
||||
|
||||
// Generic multiplier for the production. Used for game-balancing purposes
|
||||
const balancingMult = 0.05;
|
||||
|
||||
if (params && params.forProduct) {
|
||||
return ratio * Math.pow(total, 0.25);
|
||||
// Products are harder to create and therefore have less production
|
||||
return 0.5 * balancingMult * prod;
|
||||
} else {
|
||||
return 2 * ratio * Math.pow(total, 0.35);
|
||||
return balancingMult * prod;
|
||||
}
|
||||
}
|
||||
|
||||
//Returns a multiplier based on the office' 'Business' employees that affects sales
|
||||
// Returns a multiplier based on the office' 'Business' employees that affects sales
|
||||
Industry.prototype.getBusinessFactor = function(office) {
|
||||
var ratioMult = 1;
|
||||
if (office.employeeProd["total"] > 0) {
|
||||
ratioMult = 1 + (office.employeeProd[EmployeePositions.Business] / office.employeeProd["total"]);
|
||||
}
|
||||
return ratioMult * Math.pow(1 + office.employeeProd[EmployeePositions.Business], 0.25);
|
||||
const businessProd = 1 + office.employeeProd[EmployeePositions.Business];
|
||||
|
||||
return calculateEffectWithFactors(businessProd, 0.26, 10e3);
|
||||
}
|
||||
|
||||
//Returns a set of multipliers based on the Industry's awareness, popularity, and advFac. This
|
||||
@ -1399,7 +1409,7 @@ function Employee(params={}) {
|
||||
|
||||
//Returns the amount the employee needs to be paid
|
||||
Employee.prototype.process = function(marketCycles=1, office) {
|
||||
var gain = 0.001 * marketCycles,
|
||||
var gain = 0.003 * marketCycles,
|
||||
det = gain * Math.random();
|
||||
this.age += gain;
|
||||
this.exp += gain;
|
||||
@ -1425,16 +1435,9 @@ Employee.prototype.process = function(marketCycles=1, office) {
|
||||
this.eff += trainingEff;
|
||||
}
|
||||
|
||||
//Weight based on how full office is
|
||||
//Too many employees = more likely to decrease energy and happiness
|
||||
var officeCapacityWeight = 0.5 * (office.employees.length / office.size - 0.5);
|
||||
if (Math.random() < 0.5 - officeCapacityWeight) {
|
||||
this.ene += det;
|
||||
this.hap += det;
|
||||
} else {
|
||||
this.ene -= det;
|
||||
this.hap -= det;
|
||||
}
|
||||
this.ene -= det;
|
||||
this.hap -= det;
|
||||
|
||||
if (this.ene < office.minEne) {this.ene = office.minEne;}
|
||||
if (this.hap < office.minHap) {this.hap = office.minHap;}
|
||||
var salary = this.sal * marketCycles * SecsPerMarketCycle;
|
||||
@ -1640,18 +1643,16 @@ OfficeSpace.prototype.process = function(marketCycles=1, parentRefs) {
|
||||
salaryPaid += salary;
|
||||
}
|
||||
|
||||
this.calculateEmployeeProductivity(marketCycles, parentRefs);
|
||||
this.calculateEmployeeProductivity(parentRefs);
|
||||
return salaryPaid;
|
||||
}
|
||||
|
||||
OfficeSpace.prototype.calculateEmployeeProductivity = function(marketCycles=1, parentRefs) {
|
||||
OfficeSpace.prototype.calculateEmployeeProductivity = function(parentRefs) {
|
||||
var company = parentRefs.corporation, industry = parentRefs.industry;
|
||||
|
||||
//Reset
|
||||
for (const name in this.employeeProd) {
|
||||
if (this.employeeProd.hasOwnProperty(name)) {
|
||||
this.employeeProd[name] = 0;
|
||||
}
|
||||
this.employeeProd[name] = 0;
|
||||
}
|
||||
|
||||
var total = 0;
|
||||
@ -1977,19 +1978,19 @@ Corporation.prototype.getInvestment = function() {
|
||||
switch (this.fundingRound) {
|
||||
case 0: //Seed
|
||||
percShares = 0.10;
|
||||
roundMultiplier = 5;
|
||||
roundMultiplier = 4;
|
||||
break;
|
||||
case 1: //Series A
|
||||
percShares = 0.35;
|
||||
roundMultiplier = 4;
|
||||
roundMultiplier = 3;
|
||||
break;
|
||||
case 2: //Series B
|
||||
percShares = 0.25;
|
||||
roundMultiplier = 4;
|
||||
roundMultiplier = 3;
|
||||
break;
|
||||
case 3: //Series C
|
||||
percShares = 0.20;
|
||||
roundMultiplier = 3.5;
|
||||
roundMultiplier = 2.5;
|
||||
break;
|
||||
case 4:
|
||||
return;
|
||||
|
@ -164,11 +164,11 @@ export class Product {
|
||||
//Calculate properties
|
||||
var progrMult = this.prog / 100;
|
||||
|
||||
var engrRatio = employeeProd[EmployeePositions.Engineer] / employeeProd["total"],
|
||||
mgmtRatio = employeeProd[EmployeePositions.Management] / employeeProd["total"],
|
||||
rndRatio = employeeProd[EmployeePositions.RandD] / employeeProd["total"],
|
||||
opsRatio = employeeProd[EmployeePositions.Operations] / employeeProd["total"],
|
||||
busRatio = employeeProd[EmployeePositions.Business] / employeeProd["total"];
|
||||
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"];
|
||||
var designMult = 1 + (Math.pow(this.designCost, 0.1) / 100);
|
||||
console.log("designMult: " + designMult);
|
||||
var balanceMult = (1.2 * engrRatio) + (0.9 * mgmtRatio) + (1.3 * rndRatio) +
|
||||
|
@ -8,6 +8,8 @@ import { ResearchMap } from "./ResearchMap";
|
||||
|
||||
import { IMap } from "../types";
|
||||
|
||||
import { numeralWrapper } from "../ui/numeralFormat";
|
||||
|
||||
interface IConstructorParams {
|
||||
children?: Node[];
|
||||
cost: number;
|
||||
@ -83,7 +85,7 @@ export class Node {
|
||||
children: childrenArray,
|
||||
HTMLclass: htmlClass,
|
||||
innerHTML: `<div id="${sanitizedName}-corp-research-click-listener" class="tooltip">` +
|
||||
`${this.text}<br>${this.cost} Scientific Research` +
|
||||
`${this.text}<br>${numeralWrapper.format(this.cost, "0,0")} Scientific Research` +
|
||||
`<span class="tooltiptext">` +
|
||||
`${research.desc}` +
|
||||
`</span>` +
|
||||
|
@ -5,16 +5,19 @@ import { numeralWrapper } from "../ui/numeralFormat";
|
||||
import { Generic_fromJSON,
|
||||
Generic_toJSON,
|
||||
Reviver } from "../../utils/JSONReviver";
|
||||
|
||||
interface IConstructorParams {
|
||||
loc?: string;
|
||||
size?: number;
|
||||
}
|
||||
import { exceptionAlert } from "../../utils/helpers/exceptionAlert";
|
||||
|
||||
interface IParent {
|
||||
getStorageMultiplier(): number;
|
||||
}
|
||||
|
||||
interface IConstructorParams {
|
||||
corp?: IParent;
|
||||
industry?: IParent;
|
||||
loc?: string;
|
||||
size?: number;
|
||||
}
|
||||
|
||||
export class Warehouse {
|
||||
// Initiatizes a Warehouse object from a JSON save state.
|
||||
static fromJSON(value: any): Warehouse {
|
||||
@ -65,6 +68,10 @@ export class Warehouse {
|
||||
AICores: new Material({name: "AI Cores"}),
|
||||
RealEstate: new Material({name: "Real Estate"})
|
||||
}
|
||||
|
||||
if (params.corp && params.industry) {
|
||||
this.updateSize(params.corp, params.industry);
|
||||
}
|
||||
}
|
||||
|
||||
// Re-calculate how much space is being used by this Warehouse
|
||||
@ -76,7 +83,7 @@ export class Warehouse {
|
||||
if (MaterialSizes.hasOwnProperty(matName)) {
|
||||
this.sizeUsed += (mat.qty * MaterialSizes[matName]);
|
||||
if (mat.qty > 0) {
|
||||
this.breakdown += (matName + ": " + numeralWrapper.format(mat.qty * MaterialSizes[matName], "0,0") + "<br>");
|
||||
this.breakdown += (matName + ": " + numeralWrapper.format(mat.qty * MaterialSizes[matName], "0,0.0") + "<br>");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,9 +93,13 @@ export class Warehouse {
|
||||
}
|
||||
|
||||
updateSize(corporation: IParent, industry: IParent) {
|
||||
this.size = (this.level * 100)
|
||||
* corporation.getStorageMultiplier()
|
||||
* industry.getStorageMultiplier();
|
||||
try {
|
||||
this.size = (this.level * 100)
|
||||
* corporation.getStorageMultiplier()
|
||||
* industry.getStorageMultiplier();
|
||||
} catch(e) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
}
|
||||
|
||||
// Serialize the current object to a JSON save state.
|
||||
|
@ -14,6 +14,9 @@ export class CityTabs extends BaseReactComponent {
|
||||
if (props.city == null) {
|
||||
throw new Error(`CityTabs component constructed without 'city' property`)
|
||||
}
|
||||
if (props.cityStateSetter == null) {
|
||||
throw new Error(`CityTabs component constructed without 'cityStateSetter' property`)
|
||||
}
|
||||
|
||||
super(props);
|
||||
}
|
||||
@ -46,7 +49,8 @@ export class CityTabs extends BaseReactComponent {
|
||||
}
|
||||
|
||||
// Tab to "Expand into new City"
|
||||
const newCityOnClick = this.eventHandler().createNewCityPopup.bind(this.eventHandler(), division);
|
||||
const newCityOnClick = this.eventHandler().createNewCityPopup.bind(this.eventHandler(), division, this.props.cityStateSetter);
|
||||
|
||||
tabs.push(this.renderTab({
|
||||
current: false,
|
||||
key: "Expand into new City",
|
||||
|
@ -17,6 +17,8 @@ import { Industries,
|
||||
IndustryDescriptions,
|
||||
IndustryResearchTrees } from "../IndustryData";
|
||||
|
||||
import { Product } from "../Product";
|
||||
|
||||
import { Player } from "../../Player";
|
||||
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
@ -109,7 +111,7 @@ export class CorporationEventHandler {
|
||||
}
|
||||
}
|
||||
});
|
||||
var confirmButton = createElement("a", {
|
||||
var confirmButton = createElement("button", {
|
||||
class:"a-link-button", innerText:"Bribe", display:"inline-block",
|
||||
clickListener:()=>{
|
||||
var money = moneyInput.value == null || moneyInput.value == "" ? 0 : parseFloat(moneyInput.value);
|
||||
@ -181,7 +183,7 @@ export class CorporationEventHandler {
|
||||
}
|
||||
}
|
||||
});
|
||||
var confirmBtn = createElement("a", {
|
||||
var confirmBtn = createElement("button", {
|
||||
class:"a-link-button", innerText:"Buy shares", display:"inline-block",
|
||||
clickListener: () => {
|
||||
var shares = Math.round(input.value);
|
||||
@ -234,12 +236,12 @@ export class CorporationEventHandler {
|
||||
"produce this product and all of its existing stock will be " +
|
||||
"removed and left unsold",
|
||||
});
|
||||
const confirmBtn = createElement("a", {
|
||||
const confirmBtn = createElement("button", {
|
||||
class:"a-link-button",innerText:"Discontinue",
|
||||
clickListener:()=>{
|
||||
clickListener: () => {
|
||||
industry.discontinueProduct(product, parentRefs);
|
||||
removeElementById(popupId);
|
||||
this.corp.rerender();
|
||||
this.rerender();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
@ -294,7 +296,7 @@ export class CorporationEventHandler {
|
||||
placeholder:"Export amount / s"
|
||||
});
|
||||
|
||||
const exportBtn = createElement("a", {
|
||||
const exportBtn = createElement("button", {
|
||||
class: "std-button", display:"inline-block", innerText:"Export",
|
||||
clickListener: () => {
|
||||
const industryName = getSelectText(industrySelector);
|
||||
@ -473,7 +475,7 @@ export class CorporationEventHandler {
|
||||
}
|
||||
});
|
||||
|
||||
issueBtn = createElement("a", {
|
||||
issueBtn = createElement("button", {
|
||||
class: "std-button",
|
||||
display: "inline-block",
|
||||
innerText: "Issue New Shares",
|
||||
@ -529,7 +531,7 @@ export class CorporationEventHandler {
|
||||
}
|
||||
|
||||
// Create a popup that lets the player limit the production of a product
|
||||
createLimitProductProdutionPopup(product) {
|
||||
createLimitProductProdutionPopup(product, city) {
|
||||
const popupId = "cmpy-mgmt-limit-product-production-popup";
|
||||
const txt = createElement("p", {
|
||||
innerText:"Enter a limit to the amount of this product you would " +
|
||||
@ -543,7 +545,7 @@ export class CorporationEventHandler {
|
||||
if (e.keyCode === KEY.ENTER) { confirmBtn.click(); }
|
||||
}
|
||||
});
|
||||
confirmBtn = createElement("a", {
|
||||
confirmBtn = createElement("button", {
|
||||
class: "std-button",
|
||||
display:"inline-block",
|
||||
innerText:"Limit production",
|
||||
@ -585,7 +587,7 @@ export class CorporationEventHandler {
|
||||
const txt = createElement("p", {
|
||||
innerHTML: popupText,
|
||||
});
|
||||
const designCity = createElement("select");
|
||||
const designCity = createElement("select", { margin: "5px" });
|
||||
for (const cityName in division.offices) {
|
||||
if (division.offices[cityName] instanceof OfficeSpace) {
|
||||
designCity.add(createElement("option", {
|
||||
@ -603,18 +605,26 @@ export class CorporationEventHandler {
|
||||
productNamePlaceholder = "Property Name";
|
||||
}
|
||||
var productNameInput = createElement("input", {
|
||||
margin: "5px",
|
||||
placeholder: productNamePlaceholder,
|
||||
});
|
||||
var lineBreak1 = createElement("br");
|
||||
var designInvestInput = createElement("input", {
|
||||
margin: "5px",
|
||||
placeholder: "Design investment",
|
||||
type: "number",
|
||||
placeholder: "Design investment"
|
||||
});
|
||||
let confirmBtn;
|
||||
var marketingInvestInput = createElement("input", {
|
||||
margin: "5px",
|
||||
placeholder: "Marketing investment",
|
||||
type: "number",
|
||||
placeholder: "Marketing investment"
|
||||
onkeyup: (e) => {
|
||||
e.preventDefault();
|
||||
if (e.keyCode === KEY.ENTER) { confirmBtn.click(); }
|
||||
}
|
||||
});
|
||||
const confirmBtn = createElement("a", {
|
||||
confirmBtn = createElement("button", {
|
||||
class: "std-button",
|
||||
innerText: "Develop Product",
|
||||
clickListener: () => {
|
||||
@ -637,17 +647,19 @@ export class CorporationEventHandler {
|
||||
designCost: designInvest,
|
||||
advCost: marketingInvest,
|
||||
});
|
||||
if (division.products[product.name] instanceof Product) {
|
||||
dialogBoxCreate(`You already have a product with this name!`);
|
||||
return;
|
||||
}
|
||||
this.corp.funds = this.corp.funds.minus(designInvest + marketingInvest);
|
||||
division.products[product.name] = product;
|
||||
removeElementById(popupId);
|
||||
}
|
||||
this.rerender();
|
||||
//this.updateUIContent();
|
||||
//this.displayDivisionContent(division, city);
|
||||
return false;
|
||||
}
|
||||
})
|
||||
const cancelBtn = createPopupCloseButton(popupid, {
|
||||
const cancelBtn = createPopupCloseButton(popupId, {
|
||||
class: "std-button",
|
||||
innerText: "Cancel",
|
||||
});
|
||||
@ -741,7 +753,8 @@ export class CorporationEventHandler {
|
||||
}
|
||||
|
||||
// Create a popup that lets the player expand into a new city (for the current industry)
|
||||
createNewCityPopup(division) {
|
||||
// The 'cityStateSetter' arg is a function that sets the UI's 'city' state property
|
||||
createNewCityPopup(division, cityStateSetter) {
|
||||
const popupId = "cmpy-mgmt-expand-city-popup";
|
||||
const text = createElement("p", {
|
||||
innerText: "Would you like to expand into a new city by opening an office? " +
|
||||
@ -757,7 +770,7 @@ export class CorporationEventHandler {
|
||||
}
|
||||
}
|
||||
|
||||
const confirmBtn = createElement("a", {
|
||||
const confirmBtn = createElement("button", {
|
||||
class:"std-button",
|
||||
display:"inline-block",
|
||||
innerText: "Confirm",
|
||||
@ -772,9 +785,11 @@ export class CorporationEventHandler {
|
||||
loc: city,
|
||||
size: OfficeInitialSize,
|
||||
});
|
||||
this.corp.displayDivisionContent(division, city);
|
||||
}
|
||||
|
||||
cityStateSetter(city);
|
||||
removeElementById(popupId);
|
||||
this.rerender();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
@ -836,15 +851,17 @@ export class CorporationEventHandler {
|
||||
} else {
|
||||
this.corp.funds = this.corp.funds.minus(IndustryStartingCosts[ind]);
|
||||
var newInd = new Industry({
|
||||
name:newDivisionName,
|
||||
type:ind,
|
||||
corp: this.corp,
|
||||
name: newDivisionName,
|
||||
type: ind,
|
||||
});
|
||||
this.corp.divisions.push(newInd);
|
||||
// this.corp.updateUIHeaderTabs();
|
||||
// this.corp.selectHeaderTab(headerTabs[headerTabs.length-2]);
|
||||
|
||||
// Set routing to the new division so that the UI automatically switches to it
|
||||
this.routing.routeTo(newDivisionName);
|
||||
|
||||
removeElementById("cmpy-mgmt-expand-industry-popup");
|
||||
this.rerender();
|
||||
// this.corp.displayDivisionContent(newInd, Locations.Sector12);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -855,14 +872,14 @@ export class CorporationEventHandler {
|
||||
innerText: "Cancel",
|
||||
});
|
||||
|
||||
//Make an object to keep track of what industries you're already in
|
||||
// Make an object to keep track of what industries you're already in
|
||||
const ownedIndustries = {};
|
||||
for (let i = 0; i < this.corp.divisions.length; ++i) {
|
||||
ownedIndustries[this.corp.divisions[i].type] = true;
|
||||
}
|
||||
|
||||
//Add industry types to selector
|
||||
//Have Agriculture be first as recommended option
|
||||
// Add industry types to selector
|
||||
// Have Agriculture be first as recommended option
|
||||
if (!ownedIndustries["Agriculture"]) {
|
||||
selector.add(createElement("option", {
|
||||
text:Industries["Agriculture"], value:"Agriculture"
|
||||
@ -933,6 +950,7 @@ export class CorporationEventHandler {
|
||||
mat.buy = parseFloat(input.value);
|
||||
if (isNaN(mat.buy)) {mat.buy = 0;}
|
||||
removeElementById(purchasePopupId);
|
||||
this.rerender();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -942,6 +960,7 @@ export class CorporationEventHandler {
|
||||
clickListener: () => {
|
||||
mat.buy = 0;
|
||||
removeElementById(purchasePopupId);
|
||||
this.rerender();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
@ -979,7 +998,7 @@ export class CorporationEventHandler {
|
||||
type: "number",
|
||||
onkeyup: (e) => {
|
||||
e.preventDefault();
|
||||
bulkPurchaseUpdateCostTxt();
|
||||
updateBulkPurchaseText();
|
||||
if (e.keyCode === KEY.ENTER) {bulkPurchaseConfirmBtn.click();}
|
||||
}
|
||||
});
|
||||
@ -1010,6 +1029,7 @@ export class CorporationEventHandler {
|
||||
elems.push(bulkPurchaseInfo);
|
||||
elems.push(bulkPurchaseCostTxt);
|
||||
elems.push(bulkPurchaseInput);
|
||||
elems.push(bulkPurchaseConfirmBtn);
|
||||
}
|
||||
|
||||
createPopup(purchasePopupId, elems);
|
||||
@ -1129,7 +1149,7 @@ export class CorporationEventHandler {
|
||||
}
|
||||
|
||||
// Create a popup that lets the player manage sales of the product
|
||||
createSellProductPopup(product) {
|
||||
createSellProductPopup(product, city) {
|
||||
const popupId = "cmpy-mgmt-sell-product-popup";
|
||||
const txt = createElement("p", {
|
||||
innerHTML:"Enter the maximum amount of " + product.name + " you would like " +
|
||||
@ -1150,15 +1170,17 @@ export class CorporationEventHandler {
|
||||
});
|
||||
let confirmBtn;
|
||||
const inputQty = createElement("input", {
|
||||
margin: "5px 0px 5px 0px",
|
||||
placeholder: "Sell amount",
|
||||
type: "text",
|
||||
value:product.sllman[city][1] ? product.sllman[city][1] : null,
|
||||
value: product.sllman[city][1] ? product.sllman[city][1] : null,
|
||||
onkeyup: (e) => {
|
||||
e.preventDefault();
|
||||
if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
|
||||
}
|
||||
});
|
||||
const inputPx = createElement("input", {
|
||||
margin: "5px 0px 5px 0px",
|
||||
placeholder: "Sell price",
|
||||
type: "text",
|
||||
value: product.sCost ? product.sCost : null,
|
||||
@ -1167,7 +1189,7 @@ export class CorporationEventHandler {
|
||||
if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
|
||||
}
|
||||
});
|
||||
confirmBtn = createElement("a", {
|
||||
confirmBtn = createElement("button", {
|
||||
class: "std-button",
|
||||
innerText: "Confirm",
|
||||
clickListener: () => {
|
||||
@ -1276,7 +1298,7 @@ export class CorporationEventHandler {
|
||||
}
|
||||
}
|
||||
});
|
||||
const confirmBtn = createElement("a", {
|
||||
const confirmBtn = createElement("button", {
|
||||
class:"a-link-button", innerText:"Sell shares", display:"inline-block",
|
||||
clickListener:()=>{
|
||||
var shares = Math.round(input.value);
|
||||
@ -1355,7 +1377,7 @@ export class CorporationEventHandler {
|
||||
if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
|
||||
}
|
||||
});
|
||||
confirmBtn = createElement("a", {
|
||||
confirmBtn = createElement("button", {
|
||||
class: "std-button",
|
||||
innerText: "Throw Party",
|
||||
clickListener:()=>{
|
||||
@ -1366,20 +1388,20 @@ export class CorporationEventHandler {
|
||||
if (this.corp.funds.lt(totalCost)) {
|
||||
dialogBoxCreate("You don't have enough company funds to throw this.corp party!");
|
||||
} else {
|
||||
this.corp.funds = this.funds.minus(totalCost);
|
||||
this.corp.funds = this.corp.funds.minus(totalCost);
|
||||
var mult;
|
||||
for (let fooit = 0; fooit < office.employees.length; ++fooit) {
|
||||
mult = office.employees[fooit].throwParty(input.value);
|
||||
}
|
||||
dialogBoxCreate("You threw a party for the office! The morale and happiness " +
|
||||
"of each employee increased by " + formatNumber((mult-1) * 100, 2) + "%.");
|
||||
"of each employee increased by " + numeralWrapper.formatPercentage((mult-1)));
|
||||
removeElementById(popupId);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" });
|
||||
const cancelBtn = createPopupCloseButton(popupId, { class: "std-button", innerText: "Cancel" });
|
||||
|
||||
createPopup(popupId, [txt, totalCostTxt, input, confirmBtn, cancelBtn]);
|
||||
input.focus();
|
||||
@ -1420,7 +1442,7 @@ export class CorporationEventHandler {
|
||||
});
|
||||
const text2 = createElement("p", { innerText: "Upgrade size: " });
|
||||
|
||||
const confirmBtn = createElement("a", {
|
||||
const confirmBtn = createElement("button", {
|
||||
class: this.corp.funds.lt(upgradeCost) ? "a-link-button-inactive" : "a-link-button",
|
||||
display:"inline-block", margin:"4px", innerText:"by 3",
|
||||
tooltip:numeralWrapper.format(upgradeCost, "$0.000a"),
|
||||
@ -1437,7 +1459,7 @@ export class CorporationEventHandler {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
const confirmBtn15 = createElement("a", {
|
||||
const confirmBtn15 = createElement("button", {
|
||||
class: this.corp.funds.lt(upgradeCost15) ? "a-link-button-inactive" : "a-link-button",
|
||||
display:"inline-block", margin:"4px", innerText:"by 15",
|
||||
tooltip:numeralWrapper.format(upgradeCost15, "$0.000a"),
|
||||
@ -1454,7 +1476,7 @@ export class CorporationEventHandler {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
const confirmBtnMax = createElement("a", {
|
||||
const confirmBtnMax = createElement("button", {
|
||||
class:this.corp.funds.lt(upgradeCostMax) ? "a-link-button-inactive" : "a-link-button",
|
||||
display:"inline-block", margin:"4px", innerText:"by MAX (" + maxNum*OfficeInitialSize + ")",
|
||||
tooltip:numeralWrapper.format(upgradeCostMax, "$0.000a"),
|
||||
@ -1484,6 +1506,8 @@ export class CorporationEventHandler {
|
||||
dialogBoxCreate("You do not have enough funds to do this!");
|
||||
} else {
|
||||
division.warehouses[city] = new Warehouse({
|
||||
corp: corp,
|
||||
industry: division,
|
||||
loc: city,
|
||||
size: WarehouseInitialSize,
|
||||
});
|
||||
|
@ -15,6 +15,8 @@ export class IndustryOffice extends BaseReactComponent {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
city: "",
|
||||
division: "",
|
||||
employeeManualAssignMode: false,
|
||||
employee: null, // Reference to employee being referenced if in Manual Mode
|
||||
numEmployees: 0,
|
||||
@ -30,6 +32,17 @@ export class IndustryOffice extends BaseReactComponent {
|
||||
this.updateEmployeeCount(); // This function validates division and office refs
|
||||
}
|
||||
|
||||
resetEmployeeCount() {
|
||||
this.state.numEmployees = 0;
|
||||
this.state.numOperations = 0;
|
||||
this.state.numEngineers = 0;
|
||||
this.state.numBusiness = 0;
|
||||
this.state.numManagement = 0;
|
||||
this.state.numResearch = 0;
|
||||
this.state.numUnassigned = 0;
|
||||
this.state.numTraining = 0;
|
||||
}
|
||||
|
||||
updateEmployeeCount() {
|
||||
const division = this.routing().currentDivision;
|
||||
if (division == null) {
|
||||
@ -40,6 +53,13 @@ export class IndustryOffice extends BaseReactComponent {
|
||||
throw new Error(`Current City (${this.props.currentCity}) for UI does not have an OfficeSpace object`);
|
||||
}
|
||||
|
||||
// If we're in a new city, we have to reset the state
|
||||
if (division.name !== this.state.division || this.props.currentCity !== this.state.city) {
|
||||
this.resetEmployeeCount();
|
||||
this.state.division = division.name;
|
||||
this.state.city = this.props.currentCity;
|
||||
}
|
||||
|
||||
// Calculate how many NEW emplyoees we need to account for
|
||||
const currentNumEmployees = office.employees.length;
|
||||
const newEmployees = currentNumEmployees - this.state.numEmployees;
|
||||
@ -151,6 +171,7 @@ export class IndustryOffice extends BaseReactComponent {
|
||||
--this.state.numUnassigned;
|
||||
|
||||
office.assignEmployeeToJob(to);
|
||||
office.calculateEmployeeProductivity({ corporation: this.corp(), industry:division });
|
||||
this.corp().rerender();
|
||||
}
|
||||
|
||||
@ -194,6 +215,7 @@ export class IndustryOffice extends BaseReactComponent {
|
||||
++this.state.numUnassigned;
|
||||
|
||||
office.unassignEmployeeFromJob(from);
|
||||
office.calculateEmployeeProductivity({ corporation: this.corp(), industry:division });
|
||||
this.corp().rerender();
|
||||
}
|
||||
|
||||
@ -283,36 +305,40 @@ export class IndustryOffice extends BaseReactComponent {
|
||||
<p>Total Employee Salary: {numeralWrapper.formatMoney(totalSalary)}</p>
|
||||
{
|
||||
vechain &&
|
||||
<div>
|
||||
<p className={"tooltip"}>
|
||||
<p className={"tooltip"} style={{display: "block"}}>
|
||||
Material Production: {numeralWrapper.format(division.getOfficeProductivity(office), "0.000")}
|
||||
<span className={"tooltiptext"}>
|
||||
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
|
||||
</span>
|
||||
</p><br />
|
||||
<p className={"tooltip"}>
|
||||
</p>
|
||||
}
|
||||
{
|
||||
vechain &&
|
||||
<p className={"tooltip"} style={{display: "block"}}>
|
||||
Product Production: {numeralWrapper.format(division.getOfficeProductivity(office, {forProduct:true}), "0.000")}
|
||||
<span className={"tooltiptext"}>
|
||||
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
|
||||
</span>
|
||||
</p><br />
|
||||
<p className={"tooltip"}>
|
||||
Business Multiplier: x" ${numeralWrapper.format(division.getBusinessFactor(office), "0.000")}
|
||||
</p>
|
||||
}
|
||||
{
|
||||
vechain &&
|
||||
<p className={"tooltip"} style={{display: "block"}}>
|
||||
Business Multiplier: x{numeralWrapper.format(division.getBusinessFactor(office), "0.000")}
|
||||
<span className={"tooltiptext"}>
|
||||
The effect this office's 'Business' employees has on boosting sales
|
||||
</span>
|
||||
</p><br />
|
||||
</div>
|
||||
</p>
|
||||
}
|
||||
|
||||
<h2 className={"tooltip"} style={positionHeaderStyle}>
|
||||
{EmployeePositions.Operations} ({this.state.numOperations})
|
||||
<span className={"tooltiptext"}>
|
||||
Manages supply chain operations. Improves production.
|
||||
Manages supply chain operations. Improves the amount of Materials and Products you produce.
|
||||
</span>
|
||||
</h2>
|
||||
<button className={assignButtonClass} onClick={operationAssignButtonOnClick}>+</button>
|
||||
@ -322,7 +348,9 @@ export class IndustryOffice extends BaseReactComponent {
|
||||
<h2 className={"tooltip"} style={positionHeaderStyle}>
|
||||
{EmployeePositions.Engineer} ({this.state.numEngineers})
|
||||
<span className={"tooltiptext"}>
|
||||
Develops and maintains products and production systems. Improves production.
|
||||
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)
|
||||
</span>
|
||||
</h2>
|
||||
<button className={assignButtonClass} onClick={engineerAssignButtonOnClick}>+</button>
|
||||
@ -332,7 +360,7 @@ export class IndustryOffice extends BaseReactComponent {
|
||||
<h2 className={"tooltip"} style={positionHeaderStyle}>
|
||||
{EmployeePositions.Business} ({this.state.numBusiness})
|
||||
<span className={"tooltiptext"}>
|
||||
Handles sales and finances. Improves sales.
|
||||
Handles sales and finances. Improves the amount of Materials and Products you can sell.
|
||||
</span>
|
||||
</h2>
|
||||
<button className={assignButtonClass} onClick={businessAssignButtonOnClick}>+</button>
|
||||
@ -342,7 +370,8 @@ export class IndustryOffice extends BaseReactComponent {
|
||||
<h2 className={"tooltip"} style={positionHeaderStyle}>
|
||||
{EmployeePositions.Management} ({this.state.numManagement})
|
||||
<span className={"tooltiptext"}>
|
||||
Leads and oversees employees and office operations. Improves production.
|
||||
Leads and oversees employees and office operations. Improves the effectiveness of
|
||||
Engineer and Operations employees
|
||||
</span>
|
||||
</h2>
|
||||
<button className={assignButtonClass} onClick={managementAssignButtonOnClick}>+</button>
|
||||
@ -398,27 +427,36 @@ export class IndustryOffice extends BaseReactComponent {
|
||||
for (let i = 0; i < office.employees.length; ++i) {
|
||||
if (name === office.employees[i].name) {
|
||||
this.state.employee = office.employees[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
corp.rerender();
|
||||
}
|
||||
|
||||
// Employee Positions Selector
|
||||
const emp = this.state.employee;
|
||||
let employeePositionSelectorInitialValue = null;
|
||||
const employeePositions = [];
|
||||
const positionNames = Object.values(EmployeePositions);
|
||||
for (let i = 0; i < positionNames.length; ++i) {
|
||||
employeePositions.push(<option key={positionNames[i]}>{positionNames[i]}</option>);
|
||||
employeePositions.push(<option key={positionNames[i]} value={positionNames[i]}>{positionNames[i]}</option>);
|
||||
if (emp != null && emp.pos === positionNames[i]) {
|
||||
employeePositionSelectorInitialValue = positionNames[i];
|
||||
}
|
||||
}
|
||||
|
||||
const employeePositionSelectorOnChange = (e) => {
|
||||
const pos = getSelectText(e.target);
|
||||
this.state.employee.pos = pos;
|
||||
this.resetEmployeeCount();
|
||||
corp.rerender();
|
||||
}
|
||||
|
||||
// Numeraljs formatter
|
||||
const nf = "0.000";
|
||||
|
||||
// Employee stats (after applying multipliers)
|
||||
const emp = this.state.employee;
|
||||
const effCre = emp ? emp.cre * corp.getEmployeeCreMultiplier() * division.getEmployeeCreMultiplier() : 0;
|
||||
const effCha = emp ? emp.cha * corp.getEmployeeChaMultiplier() * division.getEmployeeChaMultiplier() : 0;
|
||||
const effInt = emp ? emp.int * corp.getEmployeeIntMultiplier() * division.getEmployeeIntMultiplier() : 0;
|
||||
@ -436,6 +474,9 @@ export class IndustryOffice extends BaseReactComponent {
|
||||
</button>
|
||||
|
||||
<div style={employeeInfoDivStyle}>
|
||||
<select onChange={employeeSelectorOnChange}>
|
||||
{employees}
|
||||
</select>
|
||||
{
|
||||
this.state.employee != null &&
|
||||
<p>
|
||||
@ -462,15 +503,11 @@ export class IndustryOffice extends BaseReactComponent {
|
||||
}
|
||||
{
|
||||
this.state.employee != null &&
|
||||
<select onChange={employeePositionSelectorOnChange}>
|
||||
<select onChange={employeePositionSelectorOnChange} value={employeePositionSelectorInitialValue}>
|
||||
{employeePositions}
|
||||
</select>
|
||||
}
|
||||
</div>
|
||||
|
||||
<select onChange={employeeSelectorOnChange}>
|
||||
{employees}
|
||||
</select>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -495,7 +532,6 @@ export class IndustryOffice extends BaseReactComponent {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const hireEmployeeButtonOnClick = () => {
|
||||
office.findEmployees({ corporation: corp, industry: division });
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import { Industries } from "../IndustryData";
|
||||
import { IndustryUpgrades } from "../IndustryUpgrades";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||
import { createProgressBarText } from "../../../utils/helpers/createProgressBarText";
|
||||
|
||||
export class IndustryOverview extends BaseReactComponent {
|
||||
renderMakeProductButton() {
|
||||
@ -109,6 +110,16 @@ export class IndustryOverview extends BaseReactComponent {
|
||||
const profitStr = `Profit: ${numeralWrapper.formatMoney(profit)} / s`;
|
||||
|
||||
const productionMultHelpTipOnClick = () => {
|
||||
// Wrapper for createProgressBarText()
|
||||
// Converts the industry's "effectiveness factors"
|
||||
// into a graphic (string) depicting how high that effectiveness is
|
||||
function convertEffectFacToGraphic(fac) {
|
||||
return createProgressBarText({
|
||||
progress: fac,
|
||||
totalTicks: 20,
|
||||
});
|
||||
}
|
||||
|
||||
dialogBoxCreate("Owning Hardware, Robots, AI Cores, and Real Estate " +
|
||||
"can boost your Industry's production. The effect these " +
|
||||
"materials have on your production varies between Industries. " +
|
||||
@ -118,7 +129,13 @@ export class IndustryOverview extends BaseReactComponent {
|
||||
"the individual production multiplier of each of its office locations. " +
|
||||
"This production multiplier is applied to each office. Therefore, it is " +
|
||||
"beneficial to expand into new cities as this can greatly increase the " +
|
||||
"production multiplier of your entire Division.");
|
||||
"production multiplier of your entire Division.<br><br>" +
|
||||
"Below are approximations for how effective each material is at boosting " +
|
||||
"this industry's production multiplier (Bigger bars = more effective):<br><br>" +
|
||||
`Hardware: ${convertEffectFacToGraphic(division.hwFac)}<br>` +
|
||||
`Robots: ${convertEffectFacToGraphic(division.robFac)}<br>` +
|
||||
`AI Cores: ${convertEffectFacToGraphic(division.aiFac)}<br>` +
|
||||
`Real Estate: ${convertEffectFacToGraphic(division.reFac)}`);
|
||||
}
|
||||
|
||||
return (
|
||||
@ -129,15 +146,15 @@ export class IndustryOverview extends BaseReactComponent {
|
||||
{popularity} <br />
|
||||
{
|
||||
(advertisingInfo !== false) &&
|
||||
<p className={"tooltip"}>Advertising Multiplier: {numeralWrapper.format(totalAdvertisingFac, "0.000")}
|
||||
<p className={"tooltip"}>Advertising Multiplier: x{numeralWrapper.format(totalAdvertisingFac, "0.000")}
|
||||
<span className={"tooltiptext cmpy-mgmt-advertising-info"}>
|
||||
Total multiplier for this industrys sales due to its awareness and popularity
|
||||
<br />
|
||||
Awareness Bonus: x{formatNumber(Math.pow(awarenessFac, 0.85), 3)}
|
||||
Awareness Bonus: x{numeralWrapper.format(Math.pow(awarenessFac, 0.85), "0.000")}
|
||||
<br />
|
||||
Popularity Bonus: x{formatNumber(Math.pow(popularityFac, 0.85), 3)}
|
||||
Popularity Bonus: x{numeralWrapper.format(Math.pow(popularityFac, 0.85), "0.000")}
|
||||
<br />
|
||||
Ratio Multiplier: x{formatNumber(Math.pow(ratioFac, 0.85), 3)}
|
||||
Ratio Multiplier: x{numeralWrapper.format(Math.pow(ratioFac, 0.85), "0.000")}
|
||||
</span>
|
||||
</p>
|
||||
}
|
||||
@ -157,7 +174,7 @@ export class IndustryOverview extends BaseReactComponent {
|
||||
<div className={"help-tip"} onClick={productionMultHelpTipOnClick}>?</div>
|
||||
<br /> <br />
|
||||
<p className={"tooltip"}>
|
||||
Scientific Research: {numeralWrapper.format(division.sciResearch.qty, "0.000")}
|
||||
Scientific Research: {numeralWrapper.format(division.sciResearch.qty, "0.000a")}
|
||||
<span className={"tooltiptext"}>
|
||||
Scientific Research increases the quality of the materials and
|
||||
products that you produce.
|
||||
@ -252,7 +269,7 @@ export class IndustryOverview extends BaseReactComponent {
|
||||
|
||||
{
|
||||
division.makesProducts &&
|
||||
{makeProductButton}
|
||||
makeProductButton
|
||||
}
|
||||
</div>
|
||||
)
|
||||
|
@ -1,38 +1,50 @@
|
||||
// React Component for displaying an Industry's warehouse information
|
||||
// (right-side panel in the Industry UI)
|
||||
import React from "react";
|
||||
import { BaseReactComponent } from "./BaseReactComponent";
|
||||
import { BaseReactComponent } from "./BaseReactComponent";
|
||||
|
||||
import { Material } from "../Material";
|
||||
import { Product } from "../Product";
|
||||
import { Material } from "../Material";
|
||||
import { Product } from "../Product";
|
||||
|
||||
import { Warehouse,
|
||||
WarehouseInitialCost,
|
||||
WarehouseUpgradeBaseCost } from "../Corporation";
|
||||
WarehouseUpgradeBaseCost,
|
||||
ProductProductionCostRatio } from "../Corporation";
|
||||
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||
|
||||
import { isString } from "../../../utils/helpers/isString";
|
||||
import { isString } from "../../../utils/helpers/isString";
|
||||
|
||||
// Creates the UI for a single Product type
|
||||
function ProductComponent(props) {
|
||||
const corp = props.corp;
|
||||
const division = props.division;
|
||||
const warehouse = props.warehouse;
|
||||
const city = props.city;
|
||||
const product = props.product;
|
||||
const eventHandler = props.eventHandler;
|
||||
|
||||
const nf = "0.000"; // Numeraljs formatter
|
||||
// Numeraljs formatters
|
||||
const nf = "0.000";
|
||||
const nfB = "0.000a"; // For numbers that might be big
|
||||
|
||||
const hasUpgradeDashboard = division.hasResearch("uPgrade: Dashboard");
|
||||
|
||||
// Total product gain = production - sale
|
||||
const totalGain = totalGain = product.data[city][1] - product.data[city][2];
|
||||
const totalGain = product.data[city][1] - product.data[city][2];
|
||||
|
||||
// Sell button
|
||||
const sellButtonText = product.sllman[city][1] === -1
|
||||
? "Sell (" + numeralWrapper.format(product.data[city][2], nf) + "/MAX)"
|
||||
: "Sell (" + numeralWrapper.format(product.data[city][2], nf) + "/" + numeralWrapper.format(product.sllman[city][1], nf) + ")";
|
||||
let sellButtonText;
|
||||
if (product.sllman[city][0]) {
|
||||
if (isString(product.sllman[city][1])) {
|
||||
sellButtonText = `Sell (${numeralWrapper.format(product.data[city][2], nfB)}/${product.sllman[city][1]})`;
|
||||
} else {
|
||||
sellButtonText = `Sell (${numeralWrapper.format(product.data[city][2], nfB)}/${numeralWrapper.format(product.sllman[city][1], nfB)})`;
|
||||
}
|
||||
} else {
|
||||
sellButtonText = "Sell (0.000/0.000)";
|
||||
}
|
||||
|
||||
if (product.sCost) {
|
||||
if (isString(product.sCost)) {
|
||||
sellButtonText += (" @ " + product.sCost);
|
||||
@ -40,14 +52,14 @@ function ProductComponent(props) {
|
||||
sellButtonText += (" @ " + numeralWrapper.format(product.sCost, "$0.000a"));
|
||||
}
|
||||
}
|
||||
const sellButtonOnClick = eventHandler.createSellProductPopup.bind(eventHandler, product);
|
||||
const sellButtonOnClick = eventHandler.createSellProductPopup.bind(eventHandler, product, city);
|
||||
|
||||
// Limit Production button
|
||||
const limitProductionButtonText = "Limit Production";
|
||||
if (product.prdman[city][0]) {
|
||||
limitProductionButtonText += " (" + numeralWrapper.format(product.prdman[city][1], nf) + ")";
|
||||
}
|
||||
const limitProductionButtonOnClick = eventHandler.createLimitProductProdutionPopup.bind(eventHandler, product);
|
||||
const limitProductionButtonOnClick = eventHandler.createLimitProductProdutionPopup.bind(eventHandler, product, city);
|
||||
|
||||
// Discontinue Button
|
||||
const discontinueButtonOnClick = eventHandler.createDiscontinueProductPopup.bind(eventHandler, product);
|
||||
@ -56,8 +68,8 @@ function ProductComponent(props) {
|
||||
if (!product.fin) {
|
||||
if (hasUpgradeDashboard) {
|
||||
return (
|
||||
<div className={"cmpy-mgmt-warehouse-product-div"}>
|
||||
<p>Designing {product.name}...</p>
|
||||
<div className={"cmpy-mgmt-warehouse-product-div"} key={product.name}>
|
||||
<p>Designing {product.name}...</p><br />
|
||||
<p>{numeralWrapper.format(product.prog, "0.00")}% complete</p>
|
||||
<br />
|
||||
|
||||
@ -76,8 +88,8 @@ function ProductComponent(props) {
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<div className={"cmpy-mgmt-warehouse-product-div"}>
|
||||
<p>Designing {product.name}...</p>
|
||||
<div className={"cmpy-mgmt-warehouse-product-div"} key={product.name}>
|
||||
<p>Designing {product.name}...</p><br />
|
||||
<p>{numeralWrapper.format(product.prog, "0.00")}% complete</p>
|
||||
</div>
|
||||
);
|
||||
@ -87,13 +99,13 @@ function ProductComponent(props) {
|
||||
return (
|
||||
<div className={"cmpy-mgmt-warehouse-product-div"} key={props.key}>
|
||||
<p className={"tooltip"}>
|
||||
{product.name}: {numeralWrapper.format(product.data[city][0], nf)} ({numeralWrapper.format(totalGain, nf)}/s)
|
||||
{product.name}: {numeralWrapper.format(product.data[city][0], nfB)} ({numeralWrapper.format(totalGain, nfB)}/s)
|
||||
<span className={"tooltiptext"}>
|
||||
Prod: {numeralWrapper.format(product.data[city][1], nf)}/s
|
||||
Prod: {numeralWrapper.format(product.data[city][1], nfB)}/s
|
||||
<br />
|
||||
Sell: {numeralWrapper.format(product.data[city][2], nf)} /s
|
||||
Sell: {numeralWrapper.format(product.data[city][2], nfB)} /s
|
||||
</span>
|
||||
</p>
|
||||
</p><br />
|
||||
<p className={"tooltip"}>
|
||||
Rating: {numeralWrapper.format(product.rat, nf)}
|
||||
<span className={"tooltiptext"}>
|
||||
@ -119,13 +131,13 @@ function ProductComponent(props) {
|
||||
}
|
||||
|
||||
</span>
|
||||
</p>
|
||||
</p><br />
|
||||
<p className={"tooltip"}>
|
||||
Est. Production Cost: {numeralWrapper.formatMoney(product.pCost / ProductProductionCostRatio)}
|
||||
<span className={"tooltiptext"}>
|
||||
An estimate of the material cost it takes to create this Product.
|
||||
</span>
|
||||
</p>
|
||||
</p><br />
|
||||
<p className={"tooltip"}>
|
||||
Est. Market Price: {numeralWrapper.formatMoney(product.pCost + product.rat / product.mku)}
|
||||
<span className={"tooltiptext"}>
|
||||
@ -161,6 +173,7 @@ function MaterialComponent(props) {
|
||||
|
||||
// Numeraljs formatter
|
||||
const nf = "0.000";
|
||||
const nfB = "0.000a"; // For numbers that might be biger
|
||||
|
||||
// Total gain or loss of this material (per second)
|
||||
const totalGain = mat.buy + mat.prd + mat.imp - mat.sll - mat.totalExp;
|
||||
@ -190,8 +203,12 @@ function MaterialComponent(props) {
|
||||
// Sell material button
|
||||
let sellButtonText;
|
||||
if (mat.sllman[0]) {
|
||||
sellButtonText = (mat.sllman[1] === -1 ? "Sell (" + numeralWrapper.format(mat.sll, nf) + "/MAX)" :
|
||||
"Sell (" + numeralWrapper.format(mat.sll, nf) + "/" + numeralWrapper.format(mat.sllman[1], nf) + ")");
|
||||
if (isString(mat.sllman[1])) {
|
||||
sellButtonText = `Sell (${numeralWrapper.format(mat.sll, nf)}/${mat.sllman[1]})`
|
||||
} else {
|
||||
sellButtonText = `Sell (${numeralWrapper.format(mat.sll, nf)}/${numeralWrapper.format(mat.sllman[1], nf)})`;
|
||||
}
|
||||
|
||||
if (mat.sCost) {
|
||||
if (mat.marketTa1) {
|
||||
sellButtonText += " @ " + numeralWrapper.formatMoney(mat.bCost + markupLimit);
|
||||
@ -214,13 +231,13 @@ function MaterialComponent(props) {
|
||||
<div className={"cmpy-mgmt-warehouse-material-div"} key={props.key}>
|
||||
<div style={{display: "inline-block"}}>
|
||||
<p className={"tooltip"}>
|
||||
{mat.name}: {numeralWrapper.format(mat.qty, nf)} ({numeralWrapper.format(totalGain, nf)}/s)
|
||||
{mat.name}: {numeralWrapper.format(mat.qty, nfB)} ({numeralWrapper.format(totalGain, nfB)}/s)
|
||||
<span className={"tooltiptext"}>
|
||||
Buy: {numeralWrapper.format(mat.buy, nf)} <br />
|
||||
Prod: {numeralWrapper.format(mat.prd, nf)} <br />
|
||||
Sell: {numeralWrapper.format(mat.sll, nf)} <br />
|
||||
Export: {numeralWrapper.format(mat.totalExp, nf)} <br />
|
||||
Import: {numeralWrapper.format(mat.imp, nf)}
|
||||
Buy: {numeralWrapper.format(mat.buy, nfB)} <br />
|
||||
Prod: {numeralWrapper.format(mat.prd, nfB)} <br />
|
||||
Sell: {numeralWrapper.format(mat.sll, nfB)} <br />
|
||||
Export: {numeralWrapper.format(mat.totalExp, nfB)} <br />
|
||||
Import: {numeralWrapper.format(mat.imp, nfB)}
|
||||
{
|
||||
corp.unlockUpgrades[2] === 1 && <br />
|
||||
}
|
||||
@ -244,7 +261,7 @@ function MaterialComponent(props) {
|
||||
</span>
|
||||
</p> <br />
|
||||
<p className={"tooltip"}>
|
||||
Quality: {numeralWrapper.format(mat.qlt, "0.00")}
|
||||
Quality: {numeralWrapper.format(mat.qlt, "0.00a")}
|
||||
<span className={"tooltiptext"}>
|
||||
The quality of your material. Higher quality will lead to more sales
|
||||
</span>
|
||||
@ -370,7 +387,8 @@ export class IndustryWarehouse extends BaseReactComponent {
|
||||
// Smart Supply Checkbox
|
||||
const smartSupplyCheckboxId = "cmpy-mgmt-smart-supply-checkbox";
|
||||
const smartSupplyOnChange = (e) => {
|
||||
warehouse.smartSupplyEnabled = e.target.value;
|
||||
warehouse.smartSupplyEnabled = e.target.checked;
|
||||
corp.rerender();
|
||||
}
|
||||
|
||||
// Materials that affect Production multiplier
|
||||
@ -409,14 +427,15 @@ export class IndustryWarehouse extends BaseReactComponent {
|
||||
if (division.makesProducts && Object.keys(division.products).length > 0) {
|
||||
for (const productName in division.products) {
|
||||
if (division.products[productName] instanceof Product) {
|
||||
products.push({
|
||||
products.push(ProductComponent({
|
||||
city: this.props.currentCity,
|
||||
corp: corp,
|
||||
division: division,
|
||||
eventHandler: this.eventHandler(),
|
||||
key: productName,
|
||||
product: division.products[productName],
|
||||
warehouse: warehouse,
|
||||
})
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -425,9 +444,7 @@ export class IndustryWarehouse extends BaseReactComponent {
|
||||
<div className={"cmpy-mgmt-warehouse-panel"}>
|
||||
<p className={"tooltip"} style={sizeUsageStyle}>
|
||||
Storage: {numeralWrapper.format(warehouse.sizeUsed, "0.000")} / {numeralWrapper.format(warehouse.size, "0.000")}
|
||||
<span className={"tooltiptext"}>
|
||||
{warehouse.breakdown}
|
||||
</span>
|
||||
<span className={"tooltiptext"} dangerouslySetInnerHTML={{__html: warehouse.breakdown}}></span>
|
||||
</p>
|
||||
|
||||
<button className={upgradeWarehouseClass} onClick={upgradeWarehouseOnClick}>
|
||||
@ -454,7 +471,7 @@ export class IndustryWarehouse extends BaseReactComponent {
|
||||
id={smartSupplyCheckboxId}
|
||||
onChange={smartSupplyOnChange}
|
||||
style={{margin: "3px"}}
|
||||
value={warehouse.smartSupplyEnabled}
|
||||
checked={warehouse.smartSupplyEnabled}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
@ -481,9 +498,11 @@ export class IndustryWarehouse extends BaseReactComponent {
|
||||
return this.renderWarehouseUI();
|
||||
} else {
|
||||
return (
|
||||
<button className={"std-button"} onClick={newWarehouseOnClick}>
|
||||
Purchase Warehouse ({numeralWrapper.formatMoney(WarehouseInitialCost)})
|
||||
</button>
|
||||
<div className={"cmpy-mgmt-warehouse-panel"}>
|
||||
<button className={"std-button"} onClick={newWarehouseOnClick}>
|
||||
Purchase Warehouse ({numeralWrapper.formatMoney(WarehouseInitialCost)})
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,15 @@ export class MainPanel extends BaseReactComponent {
|
||||
}
|
||||
}
|
||||
|
||||
// We can pass this setter to child components
|
||||
changeCityState(newCity) {
|
||||
if (Object.values(Cities).includes(newCity)) {
|
||||
this.state.city = newCity;
|
||||
} else {
|
||||
console.error(`Tried to change MainPanel's city state to an invalid city: ${newCity}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Determines what UI content to render based on routing
|
||||
renderContent() {
|
||||
if (this.routing().isOnOverviewPage()) {
|
||||
@ -68,11 +77,13 @@ export class MainPanel extends BaseReactComponent {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const cityTabs = (
|
||||
<CityTabs
|
||||
{...this.props}
|
||||
city={this.state.city}
|
||||
onClicks={onClicks}
|
||||
cityStateSetter={this.changeCityState.bind(this)}
|
||||
/>
|
||||
)
|
||||
|
||||
|
@ -64,7 +64,7 @@ export class Overview extends BaseReactComponent {
|
||||
dividendStr +
|
||||
"Publicly Traded: " + (this.corp().public ? "Yes" : "No") + "<br>" +
|
||||
"Owned Stock Shares: " + numeralWrapper.format(this.corp().numShares, '0.000a') + "<br>" +
|
||||
"Stock Price: " + (this.corp().public ? "$" + numeralWrapper.formatMoney(this.corp().sharePrice) : "N/A") + "<br>" +
|
||||
"Stock Price: " + (this.corp().public ? numeralWrapper.formatMoney(this.corp().sharePrice) : "N/A") + "<br>" +
|
||||
"<p class='tooltip'>Total Stock Shares: " + numeralWrapper.format(this.corp().totalShares, "0.000a") +
|
||||
"<span class='tooltiptext'>" +
|
||||
`Outstanding Shares: ${numeralWrapper.format(this.corp().issuedShares, "0.000a")}<br>` +
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { Script } from "./Script";
|
||||
|
||||
import { calculateRamUsage } from "./RamCalculations";
|
||||
import { isScriptFilename } from "./ScriptHelpersTS";
|
||||
|
||||
@ -269,7 +271,7 @@ function saveAndCloseScriptEditor() {
|
||||
}
|
||||
|
||||
//If the current script does NOT exist, create a new one
|
||||
var script = new Script();
|
||||
const script = new Script();
|
||||
script.saveScript(getCurrentEditor().getCode(), Player);
|
||||
s.scripts.push(script);
|
||||
} else if (filename.endsWith(".txt")) {
|
||||
|
45
src/utils/calculateEffectWithFactors.ts
Normal file
45
src/utils/calculateEffectWithFactors.ts
Normal file
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* This is a component that implements a mathematical formula used commonly throughout the
|
||||
* game. This formula is (typically) used to calculate the effect that various statistics
|
||||
* have on a game mechanic. It looks something like:
|
||||
*
|
||||
* (stat ^ exponential factor) + (stat / linear factor)
|
||||
*
|
||||
* where the exponential factor is a number between 0 and 1 and the linear factor
|
||||
* is typically a relatively larger number.
|
||||
*
|
||||
* This formula ensures that the effects of the statistic that is being processed
|
||||
* has diminishing returns, but never loses its effectiveness as you continue
|
||||
* to raise it.
|
||||
*
|
||||
* There are two implementations of this component. One is simply a function that
|
||||
* can be called with the stat and the exponential/linear factors. The other is a
|
||||
* class where the exponential and linear factors are defined upon construction.
|
||||
*/
|
||||
export function calculateEffectWithFactors(n: number, expFac: number, linearFac: number): number {
|
||||
if (expFac <= 0 || expFac >= 1) {
|
||||
console.warn(`Exponential factor is ${expFac}. This is not an intended value for it`);
|
||||
}
|
||||
if (linearFac < 1) {
|
||||
console.warn(`Linear factor is ${linearFac}. This is not an intended value for it`);
|
||||
}
|
||||
|
||||
return (Math.pow(n, expFac)) + (n / linearFac);
|
||||
}
|
||||
|
||||
export class EffectWithFactors {
|
||||
// Exponential factor
|
||||
private expFac: number;
|
||||
|
||||
// Linear Factor
|
||||
private linearFac: number;
|
||||
|
||||
constructor(expFac: number, linearFac: number) {
|
||||
this.expFac = expFac;
|
||||
this.linearFac = linearFac;
|
||||
}
|
||||
|
||||
calculate(n: number): number {
|
||||
return calculateEffectWithFactors(n, this.expFac, this.linearFac);
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ interface IError {
|
||||
}
|
||||
|
||||
export function exceptionAlert(e: IError): void {
|
||||
console.error(e);
|
||||
dialogBoxCreate("Caught an exception: " + e + "<br><br>" +
|
||||
"Filename: " + (e.fileName || "UNKNOWN FILE NAME") + "<br><br>" +
|
||||
"Line Number: " + (e.lineNumber || "UNKNOWN LINE NUMBER") + "<br><br>" +
|
||||
|
Loading…
Reference in New Issue
Block a user