mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2025-01-08 22:37:37 +01:00
more conversion
This commit is contained in:
parent
d4349e85b1
commit
67be13c6d6
3
src/Corporation/Corporation.d.ts
vendored
3
src/Corporation/Corporation.d.ts
vendored
@ -1,3 +0,0 @@
|
|||||||
export class Industry {
|
|
||||||
constructor(props: any)
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
464
src/Corporation/Corporation.tsx
Normal file
464
src/Corporation/Corporation.tsx
Normal file
@ -0,0 +1,464 @@
|
|||||||
|
import { AllCorporationStates,
|
||||||
|
CorporationState } from "./CorporationState";
|
||||||
|
import {
|
||||||
|
CorporationUnlockUpgrade,
|
||||||
|
CorporationUnlockUpgrades } from "./data/CorporationUnlockUpgrades";
|
||||||
|
import { CorporationUpgrade, CorporationUpgrades } from "./data/CorporationUpgrades";
|
||||||
|
import { EmployeePositions } from "./EmployeePositions";
|
||||||
|
import { Industries,
|
||||||
|
IndustryStartingCosts,
|
||||||
|
IndustryResearchTrees } from "./IndustryData";
|
||||||
|
import { IndustryUpgrades } from "./IndustryUpgrades";
|
||||||
|
import { Material } from "./Material";
|
||||||
|
import { MaterialSizes } from "./MaterialSizes";
|
||||||
|
import { Product } from "./Product";
|
||||||
|
import { ResearchMap } from "./ResearchMap";
|
||||||
|
import { Warehouse } from "./Warehouse";
|
||||||
|
import { OfficeSpace } from "./OfficeSpace";
|
||||||
|
import { CorporationConstants } from "./data/Constants";
|
||||||
|
import { Industry } from "./Industry";
|
||||||
|
|
||||||
|
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||||
|
import { showLiterature } from "../Literature/LiteratureHelpers";
|
||||||
|
import { LiteratureNames } from "../Literature/data/LiteratureNames";
|
||||||
|
import { CityName } from "../Locations/data/CityNames";
|
||||||
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
|
||||||
|
import { numeralWrapper } from "../ui/numeralFormat";
|
||||||
|
import { Page, routing } from "../ui/navigationTracking";
|
||||||
|
|
||||||
|
import { calculateEffectWithFactors } from "../utils/calculateEffectWithFactors";
|
||||||
|
|
||||||
|
import { dialogBoxCreate } from "../../utils/DialogBox";
|
||||||
|
import { Reviver,
|
||||||
|
Generic_toJSON,
|
||||||
|
Generic_fromJSON } from "../../utils/JSONReviver";
|
||||||
|
import { appendLineBreaks } from "../../utils/uiHelpers/appendLineBreaks";
|
||||||
|
import { createElement } from "../../utils/uiHelpers/createElement";
|
||||||
|
import { createPopup } from "../../utils/uiHelpers/createPopup";
|
||||||
|
import { createPopupCloseButton } from "../../utils/uiHelpers/createPopupCloseButton";
|
||||||
|
import { formatNumber } from "../../utils/StringHelperFunctions";
|
||||||
|
import { getRandomInt } from "../../utils/helpers/getRandomInt";
|
||||||
|
import { isString } from "../../utils/helpers/isString";
|
||||||
|
import { KEY } from "../../utils/helpers/keyCodes";
|
||||||
|
import { removeElement } from "../../utils/uiHelpers/removeElement";
|
||||||
|
import { removeElementById } from "../../utils/uiHelpers/removeElementById";
|
||||||
|
|
||||||
|
// UI Related Imports
|
||||||
|
import React from "react";
|
||||||
|
import ReactDOM from "react-dom";
|
||||||
|
import { CorporationRoot } from "./ui/Root";
|
||||||
|
import { CorporationRouting } from "./ui/Routing";
|
||||||
|
|
||||||
|
import Decimal from "decimal.js";
|
||||||
|
|
||||||
|
/* Constants */
|
||||||
|
export const INITIALSHARES = 1e9; //Total number of shares you have at your company
|
||||||
|
export const SHARESPERPRICEUPDATE = 1e6; //When selling large number of shares, price is dynamically updated for every batch of this amount
|
||||||
|
|
||||||
|
export const CyclesPerMarketCycle = 50;
|
||||||
|
export const CyclesPerIndustryStateCycle = CyclesPerMarketCycle / AllCorporationStates.length;
|
||||||
|
export const SecsPerMarketCycle = CyclesPerMarketCycle / 5;
|
||||||
|
|
||||||
|
export const DividendMaxPercentage = 50;
|
||||||
|
|
||||||
|
interface IParams {
|
||||||
|
name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
let corpRouting: any;
|
||||||
|
let companyManagementDiv: any;
|
||||||
|
|
||||||
|
export class Corporation {
|
||||||
|
name = "The Corporation";
|
||||||
|
|
||||||
|
//A division/business sector is represented by the object:
|
||||||
|
divisions: Industry[] = [];
|
||||||
|
|
||||||
|
//Financial stats
|
||||||
|
funds = new Decimal(150e9);
|
||||||
|
revenue = new Decimal(0);
|
||||||
|
expenses = new Decimal(0);
|
||||||
|
fundingRound = 0;
|
||||||
|
public = false; //Publicly traded
|
||||||
|
totalShares = CorporationConstants.INITIALSHARES; // Total existing shares
|
||||||
|
numShares = CorporationConstants.INITIALSHARES; // Total shares owned by player
|
||||||
|
shareSalesUntilPriceUpdate = CorporationConstants.SHARESPERPRICEUPDATE;
|
||||||
|
shareSaleCooldown = 0; // Game cycles until player can sell shares again
|
||||||
|
issueNewSharesCooldown = 0; // Game cycles until player can issue shares again
|
||||||
|
dividendPercentage = 0;
|
||||||
|
dividendTaxPercentage = 50;
|
||||||
|
issuedShares = 0;
|
||||||
|
sharePrice = 0;
|
||||||
|
storedCycles = 0;
|
||||||
|
|
||||||
|
unlockUpgrades: number[];
|
||||||
|
upgrades: number[];
|
||||||
|
upgradeMultipliers: number[];
|
||||||
|
|
||||||
|
state = new CorporationState();
|
||||||
|
|
||||||
|
constructor(params: IParams = {}) {
|
||||||
|
this.name = params.name ? params.name : "The Corporation";
|
||||||
|
const numUnlockUpgrades = Object.keys(CorporationUnlockUpgrades).length;
|
||||||
|
const numUpgrades = Object.keys(CorporationUpgrades).length;
|
||||||
|
this.unlockUpgrades = Array(numUnlockUpgrades).fill(0);
|
||||||
|
this.upgrades = Array(numUpgrades).fill(0);
|
||||||
|
this.upgradeMultipliers = Array(numUpgrades).fill(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
addFunds(amt: number) {
|
||||||
|
if(!isFinite(amt)) {
|
||||||
|
console.error('Trying to add invalid amount of funds. Report to a developper.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.funds = this.funds.plus(amt);
|
||||||
|
}
|
||||||
|
|
||||||
|
getState(): string {
|
||||||
|
return this.state.getState();
|
||||||
|
}
|
||||||
|
|
||||||
|
storeCycles(numCycles=1): void {
|
||||||
|
this.storedCycles += numCycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
process(player: IPlayer) {
|
||||||
|
if (this.storedCycles >= CyclesPerIndustryStateCycle) {
|
||||||
|
const state = this.getState();
|
||||||
|
const marketCycles = 1;
|
||||||
|
const gameCycles = (marketCycles * CyclesPerIndustryStateCycle);
|
||||||
|
this.storedCycles -= gameCycles;
|
||||||
|
|
||||||
|
this.divisions.forEach((ind) => {
|
||||||
|
ind.process(marketCycles, state, this);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Process cooldowns
|
||||||
|
if (this.shareSaleCooldown > 0) {
|
||||||
|
this.shareSaleCooldown -= gameCycles;
|
||||||
|
}
|
||||||
|
if (this.issueNewSharesCooldown > 0) {
|
||||||
|
this.issueNewSharesCooldown -= gameCycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
//At the start of a new cycle, calculate profits from previous cycle
|
||||||
|
if (state === "START") {
|
||||||
|
this.revenue = new Decimal(0);
|
||||||
|
this.expenses = new Decimal(0);
|
||||||
|
this.divisions.forEach((ind) => {
|
||||||
|
if (ind.lastCycleRevenue === -Infinity || ind.lastCycleRevenue === Infinity) { return; }
|
||||||
|
if (ind.lastCycleExpenses === -Infinity || ind.lastCycleExpenses === Infinity) { return; }
|
||||||
|
this.revenue = this.revenue.plus(ind.lastCycleRevenue);
|
||||||
|
this.expenses = this.expenses.plus(ind.lastCycleExpenses);
|
||||||
|
});
|
||||||
|
var profit = this.revenue.minus(this.expenses);
|
||||||
|
const cycleProfit = profit.times(marketCycles * SecsPerMarketCycle);
|
||||||
|
if (isNaN(this.funds) || this.funds === Infinity || this.funds === -Infinity) {
|
||||||
|
dialogBoxCreate("There was an error calculating your Corporations funds and they got reset to 0. " +
|
||||||
|
"This is a bug. Please report to game developer.<br><br>" +
|
||||||
|
"(Your funds have been set to $150b for the inconvenience)");
|
||||||
|
this.funds = new Decimal(150e9);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process dividends
|
||||||
|
if (this.dividendPercentage > 0 && cycleProfit > 0) {
|
||||||
|
// Validate input again, just to be safe
|
||||||
|
if (isNaN(this.dividendPercentage) || this.dividendPercentage < 0 || this.dividendPercentage > DividendMaxPercentage) {
|
||||||
|
console.error(`Invalid Corporation dividend percentage: ${this.dividendPercentage}`);
|
||||||
|
} else {
|
||||||
|
const totalDividends = (this.dividendPercentage / 100) * cycleProfit;
|
||||||
|
const retainedEarnings = cycleProfit - totalDividends;
|
||||||
|
const dividendsPerShare = totalDividends / this.totalShares;
|
||||||
|
const profit = this.numShares * dividendsPerShare * (1 - (this.dividendTaxPercentage / 100));
|
||||||
|
player.gainMoney(profit);
|
||||||
|
player.recordMoneySource(profit, "corporation");
|
||||||
|
this.addFunds(retainedEarnings);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.addFunds(cycleProfit);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateSharePrice();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.state.nextState();
|
||||||
|
|
||||||
|
if (routing.isOn(Page.Corporation)) this.rerender(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
determineValuation() {
|
||||||
|
var val, profit = (this.revenue.minus(this.expenses)).toNumber();
|
||||||
|
if (this.public) {
|
||||||
|
// Account for dividends
|
||||||
|
if (this.dividendPercentage > 0) {
|
||||||
|
profit *= ((100 - this.dividendPercentage) / 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
val = this.funds.toNumber() + (profit * 85e3);
|
||||||
|
val *= (Math.pow(1.1, this.divisions.length));
|
||||||
|
val = Math.max(val, 0);
|
||||||
|
} else {
|
||||||
|
val = 10e9 + Math.max(this.funds.toNumber(), 0) / 3; //Base valuation
|
||||||
|
if (profit > 0) {
|
||||||
|
val += (profit * 315e3);
|
||||||
|
val *= (Math.pow(1.1, this.divisions.length));
|
||||||
|
} else {
|
||||||
|
val = 10e9 * Math.pow(1.1, this.divisions.length);
|
||||||
|
}
|
||||||
|
val -= (val % 1e6); //Round down to nearest millionth
|
||||||
|
}
|
||||||
|
return val * BitNodeMultipliers.CorporationValuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTargetSharePrice() {
|
||||||
|
// Note: totalShares - numShares is not the same as issuedShares because
|
||||||
|
// issuedShares does not account for private investors
|
||||||
|
return this.determineValuation() / (2 * (this.totalShares - this.numShares) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSharePrice() {
|
||||||
|
const targetPrice = this.getTargetSharePrice();
|
||||||
|
if (this.sharePrice <= targetPrice) {
|
||||||
|
this.sharePrice *= (1 + (Math.random() * 0.01));
|
||||||
|
} else {
|
||||||
|
this.sharePrice *= (1 - (Math.random() * 0.01));
|
||||||
|
}
|
||||||
|
if (this.sharePrice <= 0.01) {this.sharePrice = 0.01;}
|
||||||
|
}
|
||||||
|
|
||||||
|
immediatelyUpdateSharePrice() {
|
||||||
|
this.sharePrice = this.getTargetSharePrice();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates how much money will be made and what the resulting stock price
|
||||||
|
// will be when the player sells his/her shares
|
||||||
|
// @return - [Player profit, final stock price, end shareSalesUntilPriceUpdate property]
|
||||||
|
calculateShareSale(numShares: number): [number, number, number] {
|
||||||
|
let sharesTracker = numShares;
|
||||||
|
let sharesUntilUpdate = this.shareSalesUntilPriceUpdate;
|
||||||
|
let sharePrice = this.sharePrice;
|
||||||
|
let sharesSold = 0;
|
||||||
|
let profit = 0;
|
||||||
|
|
||||||
|
const maxIterations = Math.ceil(numShares / SHARESPERPRICEUPDATE);
|
||||||
|
if (isNaN(maxIterations) || maxIterations > 10e6) {
|
||||||
|
console.error(`Something went wrong or unexpected when calculating share sale. Maxiterations calculated to be ${maxIterations}`);
|
||||||
|
return [0, 0, 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < maxIterations; ++i) {
|
||||||
|
if (sharesTracker < sharesUntilUpdate) {
|
||||||
|
profit += (sharePrice * sharesTracker);
|
||||||
|
sharesUntilUpdate -= sharesTracker;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
profit += (sharePrice * sharesUntilUpdate);
|
||||||
|
sharesUntilUpdate = SHARESPERPRICEUPDATE;
|
||||||
|
sharesTracker -= sharesUntilUpdate;
|
||||||
|
sharesSold += sharesUntilUpdate;
|
||||||
|
|
||||||
|
// Calculate what new share price would be
|
||||||
|
sharePrice = this.determineValuation() / (2 * (this.totalShares + sharesSold - this.numShares));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [profit, sharePrice, sharesUntilUpdate];
|
||||||
|
}
|
||||||
|
|
||||||
|
convertCooldownToString(cd: number) {
|
||||||
|
// The cooldown value is based on game cycles. Convert to a simple string
|
||||||
|
const seconds = cd / 5;
|
||||||
|
|
||||||
|
const SecondsPerMinute = 60;
|
||||||
|
const SecondsPerHour = 3600;
|
||||||
|
|
||||||
|
if (seconds > SecondsPerHour) {
|
||||||
|
return `${Math.floor(seconds / SecondsPerHour)} hour(s)`;
|
||||||
|
} else if (seconds > SecondsPerMinute) {
|
||||||
|
return `${Math.floor(seconds / SecondsPerMinute)} minute(s)`;
|
||||||
|
} else {
|
||||||
|
return `${Math.floor(seconds)} second(s)`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//One time upgrades that unlock new features
|
||||||
|
unlock(upgrade: CorporationUnlockUpgrade): void {
|
||||||
|
const upgN = upgrade[0], price = upgrade[1];
|
||||||
|
while (this.unlockUpgrades.length <= upgN) {
|
||||||
|
this.unlockUpgrades.push(0);
|
||||||
|
}
|
||||||
|
if (this.funds.lt(price)) {
|
||||||
|
dialogBoxCreate("You don't have enough funds to unlock this!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.unlockUpgrades[upgN] = 1;
|
||||||
|
this.funds = this.funds.minus(price);
|
||||||
|
|
||||||
|
// Apply effects for one-time upgrades
|
||||||
|
if (upgN === 5) {
|
||||||
|
this.dividendTaxPercentage -= 5;
|
||||||
|
} else if (upgN === 6) {
|
||||||
|
this.dividendTaxPercentage -= 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Levelable upgrades
|
||||||
|
upgrade(upgrade: CorporationUpgrade): void {
|
||||||
|
var upgN = upgrade[0], basePrice = upgrade[1], priceMult = upgrade[2],
|
||||||
|
upgradeAmt = upgrade[3]; //Amount by which the upgrade multiplier gets increased (additive)
|
||||||
|
while (this.upgrades.length <= upgN) {this.upgrades.push(0);}
|
||||||
|
while (this.upgradeMultipliers.length <= upgN) {this.upgradeMultipliers.push(1);}
|
||||||
|
var totalCost = basePrice * Math.pow(priceMult, this.upgrades[upgN]);
|
||||||
|
if (this.funds.lt(totalCost)) {
|
||||||
|
dialogBoxCreate("You don't have enough funds to purchase this!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
++this.upgrades[upgN];
|
||||||
|
this.funds = this.funds.minus(totalCost);
|
||||||
|
|
||||||
|
//Increase upgrade multiplier
|
||||||
|
this.upgradeMultipliers[upgN] = 1 + (this.upgrades[upgN] * upgradeAmt);
|
||||||
|
|
||||||
|
//If storage size is being updated, update values in Warehouse objects
|
||||||
|
if (upgN === 1) {
|
||||||
|
for (var i = 0; i < this.divisions.length; ++i) {
|
||||||
|
var industry = this.divisions[i];
|
||||||
|
for (var city in industry.warehouses) {
|
||||||
|
if (industry.warehouses.hasOwnProperty(city) && industry.warehouses[city] instanceof Warehouse) {
|
||||||
|
industry.warehouses[city].updateSize(this, industry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getProductionMultiplier() {
|
||||||
|
var mult = this.upgradeMultipliers[0];
|
||||||
|
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
|
||||||
|
}
|
||||||
|
|
||||||
|
getStorageMultiplier() {
|
||||||
|
var mult = this.upgradeMultipliers[1];
|
||||||
|
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
|
||||||
|
}
|
||||||
|
|
||||||
|
getDreamSenseGain() {
|
||||||
|
var gain = this.upgradeMultipliers[2] - 1;
|
||||||
|
return gain <= 0 ? 0 : gain;
|
||||||
|
}
|
||||||
|
|
||||||
|
getAdvertisingMultiplier() {
|
||||||
|
var mult = this.upgradeMultipliers[3];
|
||||||
|
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
|
||||||
|
}
|
||||||
|
|
||||||
|
getEmployeeCreMultiplier() {
|
||||||
|
var mult = this.upgradeMultipliers[4];
|
||||||
|
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
|
||||||
|
}
|
||||||
|
|
||||||
|
getEmployeeChaMultiplier() {
|
||||||
|
var mult = this.upgradeMultipliers[5];
|
||||||
|
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
|
||||||
|
}
|
||||||
|
|
||||||
|
getEmployeeIntMultiplier() {
|
||||||
|
var mult = this.upgradeMultipliers[6];
|
||||||
|
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
|
||||||
|
}
|
||||||
|
|
||||||
|
getEmployeeEffMultiplier() {
|
||||||
|
var mult = this.upgradeMultipliers[7];
|
||||||
|
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
|
||||||
|
}
|
||||||
|
|
||||||
|
getSalesMultiplier() {
|
||||||
|
var mult = this.upgradeMultipliers[8];
|
||||||
|
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
|
||||||
|
}
|
||||||
|
|
||||||
|
getScientificResearchMultiplier() {
|
||||||
|
var mult = this.upgradeMultipliers[9];
|
||||||
|
if (isNaN(mult) || mult < 1) {return 1;} else {return mult;}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds the Corporation Handbook (Starter Guide) to the player's home computer.
|
||||||
|
// This is a lit file that gives introductory info to the player
|
||||||
|
// This occurs when the player clicks the "Getting Started Guide" button on the overview panel
|
||||||
|
getStarterGuide(player: IPlayer) {
|
||||||
|
// Check if player already has Corporation Handbook
|
||||||
|
let homeComp = player.getHomeComputer(),
|
||||||
|
hasHandbook = false,
|
||||||
|
handbookFn = LiteratureNames.CorporationManagementHandbook;
|
||||||
|
for (let i = 0; i < homeComp.messages.length; ++i) {
|
||||||
|
if (isString(homeComp.messages[i]) && homeComp.messages[i] === handbookFn) {
|
||||||
|
hasHandbook = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasHandbook) { homeComp.messages.push(handbookFn); }
|
||||||
|
showLiterature(handbookFn);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
createUI(player: IPlayer) {
|
||||||
|
companyManagementDiv = createElement("div", {
|
||||||
|
id:"cmpy-mgmt-container",
|
||||||
|
position:"fixed",
|
||||||
|
class:"generic-menupage-container",
|
||||||
|
});
|
||||||
|
const game = document.getElementById("entire-game-container");
|
||||||
|
if(game)
|
||||||
|
game.appendChild(companyManagementDiv);
|
||||||
|
|
||||||
|
corpRouting = new CorporationRouting(this);
|
||||||
|
|
||||||
|
this.rerender(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
rerender(player: IPlayer) {
|
||||||
|
if (companyManagementDiv == null || corpRouting == null) {
|
||||||
|
console.warn(`Corporation.rerender() called when companyManagementDiv, corpRouting, or eventHandler is null`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!routing.isOn(Page.Corporation)) return;
|
||||||
|
|
||||||
|
ReactDOM.render(<CorporationRoot
|
||||||
|
corp={this}
|
||||||
|
routing={corpRouting}
|
||||||
|
player={player}
|
||||||
|
/>, companyManagementDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
clearUI() {
|
||||||
|
if (companyManagementDiv instanceof HTMLElement) {
|
||||||
|
ReactDOM.unmountComponentAtNode(companyManagementDiv);
|
||||||
|
removeElementById(companyManagementDiv.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
companyManagementDiv = null;
|
||||||
|
const character = document.getElementById("character-overview-wrapper");
|
||||||
|
if(character)
|
||||||
|
character.style.visibility = "visible";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize the current object to a JSON save state.
|
||||||
|
*/
|
||||||
|
toJSON(): any {
|
||||||
|
return Generic_toJSON("Corporation", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiatizes a Corporation object from a JSON save state.
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
|
static fromJSON(value: any): Corporation {
|
||||||
|
return Generic_fromJSON(Corporation, value.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Reviver.constructors.Corporation = Corporation;
|
1328
src/Corporation/Industry.ts
Normal file
1328
src/Corporation/Industry.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,11 @@
|
|||||||
import { IMap } from "../types";
|
import { IMap } from "../types";
|
||||||
|
|
||||||
|
export type IndustryUpgrade = [number, number, number, number, string, string];
|
||||||
|
|
||||||
// Industry upgrades
|
// Industry upgrades
|
||||||
// The data structure is an array with the following format:
|
// The data structure is an array with the following format:
|
||||||
// [index in array, base price, price mult, benefit mult (if applicable), name, desc]
|
// [index in array, base price, price mult, benefit mult (if applicable), name, desc]
|
||||||
export const IndustryUpgrades: IMap<any[]> = {
|
export const IndustryUpgrades: IMap<IndustryUpgrade> = {
|
||||||
"0": [0, 500e3, 1, 1.05,
|
"0": [0, 500e3, 1, 1.05,
|
||||||
"Coffee", "Provide your employees with coffee, increasing their energy by 5%."],
|
"Coffee", "Provide your employees with coffee, increasing their energy by 5%."],
|
||||||
"1": [1, 1e9, 1.06, 1.03,
|
"1": [1, 1e9, 1.06, 1.03,
|
||||||
|
@ -60,7 +60,7 @@ export class Product {
|
|||||||
pCost = 0;
|
pCost = 0;
|
||||||
|
|
||||||
// Sell cost
|
// Sell cost
|
||||||
sCost = 0;
|
sCost: string | number = 0;
|
||||||
|
|
||||||
// Variables for handling the creation process of this Product
|
// Variables for handling the creation process of this Product
|
||||||
fin = false; // Whether this Product has finished being created
|
fin = false; // Whether this Product has finished being created
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { IMap } from "../../types";
|
import { IMap } from "../../types";
|
||||||
|
|
||||||
|
export type CorporationUnlockUpgrade = [number, number, string, string];
|
||||||
|
|
||||||
// Corporation Unlock Upgrades
|
// Corporation Unlock Upgrades
|
||||||
// Upgrades for entire corporation, unlocks features, either you have it or you dont
|
// Upgrades for entire corporation, unlocks features, either you have it or you dont
|
||||||
// The data structure is an array with the following format:
|
// The data structure is an array with the following format:
|
||||||
// [index in Corporation feature upgrades array, price, name, description]
|
// [index in Corporation feature upgrades array, price, name, description]
|
||||||
export const CorporationUnlockUpgrades: IMap<any[]> = {
|
export const CorporationUnlockUpgrades: IMap<CorporationUnlockUpgrade> = {
|
||||||
//Lets you export goods
|
//Lets you export goods
|
||||||
"0": [0, 20e9, "Export",
|
"0": [0, 20e9, "Export",
|
||||||
"Develop infrastructure to export your materials to your other facilities. " +
|
"Develop infrastructure to export your materials to your other facilities. " +
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { IMap } from "../../types";
|
import { IMap } from "../../types";
|
||||||
|
|
||||||
|
export type CorporationUpgrade = [number, number, number, number, string, string];
|
||||||
|
|
||||||
// Corporation Upgrades
|
// Corporation Upgrades
|
||||||
// Upgrades for entire corporation, levelable upgrades
|
// Upgrades for entire corporation, levelable upgrades
|
||||||
// The data structure is an array with the following format
|
// The data structure is an array with the following format
|
||||||
// [index in Corporation upgrades array, base price, price mult, benefit mult (additive), name, desc]
|
// [index in Corporation upgrades array, base price, price mult, benefit mult (additive), name, desc]
|
||||||
export const CorporationUpgrades: IMap<any[]> = {
|
export const CorporationUpgrades: IMap<CorporationUpgrade> = {
|
||||||
//Smart factories, increases production
|
//Smart factories, increases production
|
||||||
"0": [0, 2e9, 1.06, 0.03,
|
"0": [0, 2e9, 1.06, 0.03,
|
||||||
"Smart Factories", "Advanced AI automatically optimizes the operation and productivity " +
|
"Smart Factories", "Advanced AI automatically optimizes the operation and productivity " +
|
||||||
|
63
src/Corporation/ui/FindInvestorsPopup.tsx
Normal file
63
src/Corporation/ui/FindInvestorsPopup.tsx
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Warehouse } from "../Warehouse";
|
||||||
|
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||||
|
import { createElement } from "../../../utils/uiHelpers/createElement";
|
||||||
|
import { removePopup } from "../../ui/React/createPopup";
|
||||||
|
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
|
||||||
|
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
|
||||||
|
import { getSelectText,
|
||||||
|
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
|
||||||
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
import { CorporationConstants } from "../data/Constants";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
corp: any;
|
||||||
|
popupId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a popup that lets the player manage exports
|
||||||
|
export function FindInvestorsPopup(props: IProps): React.ReactElement {
|
||||||
|
const val = props.corp.determineValuation()
|
||||||
|
let percShares = 0;
|
||||||
|
let roundMultiplier = 4;
|
||||||
|
switch (props.corp.fundingRound) {
|
||||||
|
case 0: //Seed
|
||||||
|
percShares = 0.10;
|
||||||
|
roundMultiplier = 4;
|
||||||
|
break;
|
||||||
|
case 1: //Series A
|
||||||
|
percShares = 0.35;
|
||||||
|
roundMultiplier = 3;
|
||||||
|
break;
|
||||||
|
case 2: //Series B
|
||||||
|
percShares = 0.25;
|
||||||
|
roundMultiplier = 3;
|
||||||
|
break;
|
||||||
|
case 3: //Series C
|
||||||
|
percShares = 0.20;
|
||||||
|
roundMultiplier = 2.5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return (<></>);
|
||||||
|
}
|
||||||
|
const funding = val * percShares * roundMultiplier;
|
||||||
|
const investShares = Math.floor(CorporationConstants.INITIALSHARES * percShares);
|
||||||
|
|
||||||
|
function findInvestors(): void {
|
||||||
|
props.corp.fundingRound++;
|
||||||
|
props.corp.addFunds(funding);
|
||||||
|
props.corp.numShares -= investShares;
|
||||||
|
props.corp.rerender();
|
||||||
|
removePopup(props.popupId);
|
||||||
|
}
|
||||||
|
return (<>
|
||||||
|
<p>
|
||||||
|
An investment firm has offered you {numeralWrapper.formatMoney(funding)} in
|
||||||
|
funding in exchange for a {numeralWrapper.format(percShares*100, "0.000a")}%
|
||||||
|
stake in the company ({numeralWrapper.format(investShares, '0.000a')} shares).<br /><br />
|
||||||
|
Do you accept or reject this offer?<br /><br />
|
||||||
|
Hint: Investment firms will offer more money if your corporation is turning a profit
|
||||||
|
</p>
|
||||||
|
<button onClick={findInvestors} className="std-button">Accept</button>
|
||||||
|
</>);
|
||||||
|
}
|
67
src/Corporation/ui/GoPublicPopup.tsx
Normal file
67
src/Corporation/ui/GoPublicPopup.tsx
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Warehouse } from "../Warehouse";
|
||||||
|
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||||
|
import { createElement } from "../../../utils/uiHelpers/createElement";
|
||||||
|
import { removePopup } from "../../ui/React/createPopup";
|
||||||
|
import { createOptionElement } from "../../../utils/uiHelpers/createOptionElement";
|
||||||
|
import { clearSelector } from "../../../utils/uiHelpers/clearSelector";
|
||||||
|
import { getSelectText,
|
||||||
|
getSelectValue } from "../../../utils/uiHelpers/getSelectData";
|
||||||
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
import { CorporationConstants } from "../data/Constants";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
corp: any;
|
||||||
|
popupId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a popup that lets the player manage exports
|
||||||
|
export function GoPublicPopup(props: IProps): React.ReactElement {
|
||||||
|
const [shares, setShares] = useState('');
|
||||||
|
const initialSharePrice = props.corp.determineValuation() / (props.corp.totalShares);
|
||||||
|
|
||||||
|
function goPublic(): void {
|
||||||
|
const numShares = parseFloat(shares);
|
||||||
|
const initialSharePrice = props.corp.determineValuation() / (props.corp.totalShares);
|
||||||
|
if (isNaN(numShares)) {
|
||||||
|
dialogBoxCreate("Invalid value for number of issued shares");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (numShares > props.corp.numShares) {
|
||||||
|
dialogBoxCreate("Error: You don't have that many shares to issue!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
props.corp.public = true;
|
||||||
|
props.corp.sharePrice = initialSharePrice;
|
||||||
|
props.corp.issuedShares = numShares;
|
||||||
|
props.corp.numShares -= numShares;
|
||||||
|
props.corp.addFunds(numShares * initialSharePrice);
|
||||||
|
props.corp.rerender();
|
||||||
|
dialogBoxCreate(`You took your ${props.corp.name} public and earned ` +
|
||||||
|
`${numeralWrapper.formatMoney(numShares * initialSharePrice)} in your IPO`);
|
||||||
|
removePopup(props.popupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onKeyDown(event: React.KeyboardEvent<HTMLInputElement>): void {
|
||||||
|
if (event.keyCode === 13) goPublic();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||||
|
setShares(event.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (<>
|
||||||
|
<p>
|
||||||
|
Enter the number of shares you would like to issue
|
||||||
|
for your IPO. These shares will be publicly sold
|
||||||
|
and you will no longer own them. Your Corporation will
|
||||||
|
receive {numeralWrapper.formatMoney(initialSharePrice)} per share
|
||||||
|
(the IPO money will be deposited directly into your Corporation's funds).
|
||||||
|
<br /><br />
|
||||||
|
You have a total of {numeralWrapper.format(props.corp.numShares, "0.000a")} of
|
||||||
|
shares that you can issue.
|
||||||
|
</p>
|
||||||
|
<input className="text-input" value={shares} onChange={onChange} autoFocus={true} type="number" placeholder="Shares to issue" onKeyDown={onKeyDown} />
|
||||||
|
<button className="std-button" onClick={goPublic}>Go Public</button>
|
||||||
|
</>);
|
||||||
|
}
|
@ -11,7 +11,7 @@ import {
|
|||||||
Industries,
|
Industries,
|
||||||
IndustryStartingCosts,
|
IndustryStartingCosts,
|
||||||
IndustryDescriptions } from "../IndustryData";
|
IndustryDescriptions } from "../IndustryData";
|
||||||
import { Industry } from "../Corporation";
|
import { Industry } from "../Industry";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
corp: any;
|
corp: any;
|
||||||
|
@ -7,6 +7,8 @@ import { SellSharesPopup } from "./SellSharesPopup";
|
|||||||
import { BuybackSharesPopup } from "./BuybackSharesPopup";
|
import { BuybackSharesPopup } from "./BuybackSharesPopup";
|
||||||
import { IssueDividendsPopup } from "./IssueDividendsPopup";
|
import { IssueDividendsPopup } from "./IssueDividendsPopup";
|
||||||
import { IssueNewSharesPopup } from "./IssueNewSharesPopup";
|
import { IssueNewSharesPopup } from "./IssueNewSharesPopup";
|
||||||
|
import { FindInvestorsPopup } from "./FindInvestorsPopup";
|
||||||
|
import { GoPublicPopup } from "./GoPublicPopup";
|
||||||
|
|
||||||
import { CorporationConstants } from "../data/Constants";
|
import { CorporationConstants } from "../data/Constants";
|
||||||
import { CorporationUnlockUpgrades } from "../data/CorporationUnlockUpgrades";
|
import { CorporationUnlockUpgrades } from "../data/CorporationUnlockUpgrades";
|
||||||
@ -168,12 +170,25 @@ export function Overview(props: IProps): React.ReactElement {
|
|||||||
const findInvestorsClassName = fundingAvailable ? "std-button" : "a-link-button-inactive";
|
const findInvestorsClassName = fundingAvailable ? "std-button" : "a-link-button-inactive";
|
||||||
const findInvestorsTooltip = fundingAvailable ? "Search for private investors who will give you startup funding in exchangefor equity (stock shares) in your company" : null;
|
const findInvestorsTooltip = fundingAvailable ? "Search for private investors who will give you startup funding in exchangefor equity (stock shares) in your company" : null;
|
||||||
|
|
||||||
const findInvestorsOnClick = props.corp.getInvestment.bind(props.corp);
|
function openFindInvestorsPopup(): void {
|
||||||
const goPublicOnClick = props.corp.goPublic.bind(props.corp);
|
const popupId = "cmpy-mgmt-find-investors-popup";
|
||||||
|
createPopup(popupId, FindInvestorsPopup, {
|
||||||
|
popupId: popupId,
|
||||||
|
corp: props.corp,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function openGoPublicPopup(): void {
|
||||||
|
const popupId = "cmpy-mgmt-go-public-popup";
|
||||||
|
createPopup(popupId, GoPublicPopup, {
|
||||||
|
popupId: popupId,
|
||||||
|
corp: props.corp,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const findInvestorsBtn = createButton({
|
const findInvestorsBtn = createButton({
|
||||||
class: findInvestorsClassName,
|
class: findInvestorsClassName,
|
||||||
onClick: findInvestorsOnClick,
|
onClick: openFindInvestorsPopup,
|
||||||
style: "inline-block",
|
style: "inline-block",
|
||||||
text: "Find Investors",
|
text: "Find Investors",
|
||||||
tooltip: findInvestorsTooltip,
|
tooltip: findInvestorsTooltip,
|
||||||
@ -181,7 +196,7 @@ export function Overview(props: IProps): React.ReactElement {
|
|||||||
});
|
});
|
||||||
const goPublicBtn = createButton({
|
const goPublicBtn = createButton({
|
||||||
class: "std-button",
|
class: "std-button",
|
||||||
onClick: goPublicOnClick,
|
onClick: openGoPublicPopup,
|
||||||
style: "inline-block",
|
style: "inline-block",
|
||||||
display: "inline-block",
|
display: "inline-block",
|
||||||
text: "Go Public",
|
text: "Go Public",
|
||||||
|
@ -3,9 +3,10 @@ import React from "react";
|
|||||||
|
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||||
|
import { CorporationUnlockUpgrade } from "../data/CorporationUnlockUpgrades";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
upgradeData: number[];
|
upgradeData: CorporationUnlockUpgrade;
|
||||||
corp: any;
|
corp: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
src/ThirdParty/decimal.js.d.ts
vendored
Normal file
1
src/ThirdParty/decimal.js.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
declare module "decimal.js";
|
@ -454,7 +454,7 @@ const Engine = {
|
|||||||
if (Player.corporation instanceof Corporation) {
|
if (Player.corporation instanceof Corporation) {
|
||||||
Engine.hideAllContent();
|
Engine.hideAllContent();
|
||||||
routing.navigateTo(Page.Corporation);
|
routing.navigateTo(Page.Corporation);
|
||||||
Player.corporation.createUI();
|
Player.corporation.createUI(Player);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -537,7 +537,7 @@ const Engine = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Player.corporation instanceof Corporation) {
|
if (Player.corporation instanceof Corporation) {
|
||||||
Player.corporation.clearUI();
|
Player.corporation.clearUI(Player);
|
||||||
}
|
}
|
||||||
|
|
||||||
clearResleevesPage();
|
clearResleevesPage();
|
||||||
@ -856,7 +856,7 @@ const Engine = {
|
|||||||
|
|
||||||
if (Engine.Counters.mechanicProcess <= 0) {
|
if (Engine.Counters.mechanicProcess <= 0) {
|
||||||
if (Player.corporation instanceof Corporation) {
|
if (Player.corporation instanceof Corporation) {
|
||||||
Player.corporation.process();
|
Player.corporation.process(Player);
|
||||||
}
|
}
|
||||||
if (Player.bladeburner instanceof Bladeburner) {
|
if (Player.bladeburner instanceof Bladeburner) {
|
||||||
try {
|
try {
|
||||||
|
@ -641,6 +641,5 @@ if (htmlWebpackPlugin.options.googleAnalytics.trackingId) { %>
|
|||||||
|
|
||||||
<!-- Misc Scripts -->
|
<!-- Misc Scripts -->
|
||||||
<script src="src/ThirdParty/raphael.min.js"></script>
|
<script src="src/ThirdParty/raphael.min.js"></script>
|
||||||
<script src="src/ThirdParty/Treant.js"></script>
|
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
Reference in New Issue
Block a user