mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-08 08:43:53 +01:00
CORPORATION: Corp changes prior to 2.3 finalization (#503)
This commit is contained in:
parent
e2e9b084bc
commit
2ae3ac52f1
@ -1,15 +1,15 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Corporation](./bitburner.corporation.md) > [getUnlockUpgradeCost](./bitburner.corporation.getunlockupgradecost.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Corporation](./bitburner.corporation.md) > [getUnlockCost](./bitburner.corporation.getunlockcost.md)
|
||||
|
||||
## Corporation.getUnlockUpgradeCost() method
|
||||
## Corporation.getUnlockCost() method
|
||||
|
||||
Gets the cost to unlock a one time unlockable upgrade
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getUnlockUpgradeCost(upgradeName: string): number;
|
||||
getUnlockCost(upgradeName: string): number;
|
||||
```
|
||||
|
||||
## Parameters
|
@ -1,15 +1,15 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Corporation](./bitburner.corporation.md) > [hasUnlockUpgrade](./bitburner.corporation.hasunlockupgrade.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Corporation](./bitburner.corporation.md) > [hasUnlock](./bitburner.corporation.hasunlock.md)
|
||||
|
||||
## Corporation.hasUnlockUpgrade() method
|
||||
## Corporation.hasUnlock() method
|
||||
|
||||
Check if you have a one time unlockable upgrade
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
hasUnlockUpgrade(upgradeName: string): boolean;
|
||||
hasUnlock(upgradeName: string): boolean;
|
||||
```
|
||||
|
||||
## Parameters
|
@ -30,15 +30,15 @@ export interface Corporation extends WarehouseAPI, OfficeAPI
|
||||
| [getIndustryData(industryName)](./bitburner.corporation.getindustrydata.md) | Get constant industry definition data for a specific industry |
|
||||
| [getInvestmentOffer()](./bitburner.corporation.getinvestmentoffer.md) | Get an offer for investment based on you companies current valuation |
|
||||
| [getMaterialData(materialName)](./bitburner.corporation.getmaterialdata.md) | Get constant data for a specific material |
|
||||
| [getUnlockUpgradeCost(upgradeName)](./bitburner.corporation.getunlockupgradecost.md) | Gets the cost to unlock a one time unlockable upgrade |
|
||||
| [getUnlockCost(upgradeName)](./bitburner.corporation.getunlockcost.md) | Gets the cost to unlock a one time unlockable upgrade |
|
||||
| [getUpgradeLevel(upgradeName)](./bitburner.corporation.getupgradelevel.md) | Get the level of a levelable upgrade |
|
||||
| [getUpgradeLevelCost(upgradeName)](./bitburner.corporation.getupgradelevelcost.md) | Gets the cost to unlock the next level of a levelable upgrade |
|
||||
| [goPublic(numShares)](./bitburner.corporation.gopublic.md) | Go public |
|
||||
| [hasCorporation()](./bitburner.corporation.hascorporation.md) | Returns whether the player has a corporation. Does not require API access. |
|
||||
| [hasUnlockUpgrade(upgradeName)](./bitburner.corporation.hasunlockupgrade.md) | Check if you have a one time unlockable upgrade |
|
||||
| [hasUnlock(upgradeName)](./bitburner.corporation.hasunlock.md) | Check if you have a one time unlockable upgrade |
|
||||
| [issueDividends(rate)](./bitburner.corporation.issuedividends.md) | Issue dividends |
|
||||
| [issueNewShares(amount)](./bitburner.corporation.issuenewshares.md) | Issue new shares |
|
||||
| [levelUpgrade(upgradeName)](./bitburner.corporation.levelupgrade.md) | Level an upgrade. |
|
||||
| [purchaseUnlock(upgradeName)](./bitburner.corporation.purchaseunlock.md) | Unlock an upgrade |
|
||||
| [sellShares(amount)](./bitburner.corporation.sellshares.md) | Sell Shares |
|
||||
| [unlockUpgrade(upgradeName)](./bitburner.corporation.unlockupgrade.md) | Unlock an upgrade |
|
||||
|
||||
|
6
markdown/bitburner.corporation.unlockupgrade.md → markdown/bitburner.corporation.purchaseunlock.md
6
markdown/bitburner.corporation.unlockupgrade.md → markdown/bitburner.corporation.purchaseunlock.md
@ -1,15 +1,15 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Corporation](./bitburner.corporation.md) > [unlockUpgrade](./bitburner.corporation.unlockupgrade.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Corporation](./bitburner.corporation.md) > [purchaseUnlock](./bitburner.corporation.purchaseunlock.md)
|
||||
|
||||
## Corporation.unlockUpgrade() method
|
||||
## Corporation.purchaseUnlock() method
|
||||
|
||||
Unlock an upgrade
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
unlockUpgrade(upgradeName: string): void;
|
||||
purchaseUnlock(upgradeName: string): void;
|
||||
```
|
||||
|
||||
## Parameters
|
@ -13,7 +13,6 @@ type CorpResearchName =
|
||||
| "AutoBrew"
|
||||
| "AutoPartyManager"
|
||||
| "Automatic Drug Administration"
|
||||
| "Bulk Purchasing"
|
||||
| "CPH4 Injections"
|
||||
| "Drones"
|
||||
| "Drones - Assembly"
|
||||
@ -21,7 +20,6 @@ type CorpResearchName =
|
||||
| "Go-Juice"
|
||||
| "HRBuddy-Recruitment"
|
||||
| "HRBuddy-Training"
|
||||
| "JoyWire"
|
||||
| "Market-TA.I"
|
||||
| "Market-TA.II"
|
||||
| "Overclock"
|
||||
|
@ -22,12 +22,12 @@ interface Division
|
||||
| [lastCycleRevenue](./bitburner.division.lastcyclerevenue.md) | | number | Revenue last cycle |
|
||||
| [makesProducts](./bitburner.division.makesproducts.md) | | boolean | Whether the industry this division is in is capable of making products |
|
||||
| [name](./bitburner.division.name.md) | | string | Name of the division |
|
||||
| [numAdVerts](./bitburner.division.numadverts.md) | | number | Number of times AdVert has been bought |
|
||||
| [popularity](./bitburner.division.popularity.md) | | number | Popularity of the division |
|
||||
| [prodMult](./bitburner.division.prodmult.md) | | number | Production multiplier |
|
||||
| [products](./bitburner.division.products.md) | | string\[\] | Products developed by this division |
|
||||
| [research](./bitburner.division.research.md) | | number | Amount of research in that division |
|
||||
| [productionMult](./bitburner.division.productionmult.md) | | number | Production multiplier |
|
||||
| [products](./bitburner.division.products.md) | | string\[\] | Names of Products developed by this division |
|
||||
| [researchPoints](./bitburner.division.researchpoints.md) | | number | Amount of research in that division |
|
||||
| [thisCycleExpenses](./bitburner.division.thiscycleexpenses.md) | | number | Expenses this cycle |
|
||||
| [thisCycleRevenue](./bitburner.division.thiscyclerevenue.md) | | number | Revenue this cycle |
|
||||
| [type](./bitburner.division.type.md) | | [CorpIndustryName](./bitburner.corpindustryname.md) | Type of division, like Agriculture |
|
||||
| [upgrades](./bitburner.division.upgrades.md) | | number\[\] | All research bought |
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Division](./bitburner.division.md) > [upgrades](./bitburner.division.upgrades.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Division](./bitburner.division.md) > [numAdVerts](./bitburner.division.numadverts.md)
|
||||
|
||||
## Division.upgrades property
|
||||
## Division.numAdVerts property
|
||||
|
||||
All research bought
|
||||
Number of times AdVert has been bought
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
upgrades: number[];
|
||||
numAdVerts: number;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Division](./bitburner.division.md) > [prodMult](./bitburner.division.prodmult.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Division](./bitburner.division.md) > [productionMult](./bitburner.division.productionmult.md)
|
||||
|
||||
## Division.prodMult property
|
||||
## Division.productionMult property
|
||||
|
||||
Production multiplier
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
prodMult: number;
|
||||
productionMult: number;
|
||||
```
|
@ -4,7 +4,7 @@
|
||||
|
||||
## Division.products property
|
||||
|
||||
Products developed by this division
|
||||
Names of Products developed by this division
|
||||
|
||||
**Signature:**
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Division](./bitburner.division.md) > [research](./bitburner.division.research.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Division](./bitburner.division.md) > [researchPoints](./bitburner.division.researchpoints.md)
|
||||
|
||||
## Division.research property
|
||||
## Division.researchPoints property
|
||||
|
||||
Amount of research in that division
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
research: number;
|
||||
researchPoints: number;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Export](./bitburner.export.md) > [amt](./bitburner.export.amt.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Export](./bitburner.export.md) > [amount](./bitburner.export.amount.md)
|
||||
|
||||
## Export.amt property
|
||||
## Export.amount property
|
||||
|
||||
Amount of material exported
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
amt: string;
|
||||
amount: string;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Export](./bitburner.export.md) > [loc](./bitburner.export.loc.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Export](./bitburner.export.md) > [city](./bitburner.export.city.md)
|
||||
|
||||
## Export.loc property
|
||||
## Export.city property
|
||||
|
||||
City the material is being exported to
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
loc: CityName;
|
||||
city: CityName;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Export](./bitburner.export.md) > [div](./bitburner.export.div.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Export](./bitburner.export.md) > [division](./bitburner.export.division.md)
|
||||
|
||||
## Export.div property
|
||||
## Export.division property
|
||||
|
||||
Division the material is being exported to
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
div: string;
|
||||
division: string;
|
||||
```
|
@ -16,7 +16,7 @@ interface Export
|
||||
|
||||
| Property | Modifiers | Type | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| [amt](./bitburner.export.amt.md) | | string | Amount of material exported |
|
||||
| [div](./bitburner.export.div.md) | | string | Division the material is being exported to |
|
||||
| [loc](./bitburner.export.loc.md) | | [CityName](./bitburner.cityname.md) | City the material is being exported to |
|
||||
| [amount](./bitburner.export.amount.md) | | string | Amount of material exported |
|
||||
| [city](./bitburner.export.city.md) | | [CityName](./bitburner.cityname.md) | City the material is being exported to |
|
||||
| [division](./bitburner.export.division.md) | | string | Division the material is being exported to |
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
## IndustryData.cost property
|
||||
|
||||
Cost to expand to the division
|
||||
Cost to make a new division of this industry type
|
||||
|
||||
**Signature:**
|
||||
|
||||
|
@ -16,7 +16,7 @@ interface IndustryData
|
||||
|
||||
| Property | Modifiers | Type | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| [cost](./bitburner.industrydata.cost.md) | | number | Cost to expand to the division |
|
||||
| [cost](./bitburner.industrydata.cost.md) | | number | Cost to make a new division of this industry type |
|
||||
| [makesMaterials](./bitburner.industrydata.makesmaterials.md) | | boolean | Whether the division makes materials |
|
||||
| [makesProducts](./bitburner.industrydata.makesproducts.md) | | boolean | Whether the division makes products |
|
||||
| [producedMaterials?](./bitburner.industrydata.producedmaterials.md) | | string\[\] | _(Optional)_ Materials produced |
|
||||
|
13
markdown/bitburner.material.actualsellamount.md
Normal file
13
markdown/bitburner.material.actualsellamount.md
Normal file
@ -0,0 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [actualSellAmount](./bitburner.material.actualsellamount.md)
|
||||
|
||||
## Material.actualSellAmount property
|
||||
|
||||
Amount of material sold last cycle
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
actualSellAmount: number;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [cmp](./bitburner.material.cmp.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [competition](./bitburner.material.competition.md)
|
||||
|
||||
## Material.cmp property
|
||||
## Material.competition property
|
||||
|
||||
Competition for the material, only present if "Market Research - Competition" unlocked
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
cmp: number | undefined;
|
||||
competition: number | undefined;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [dmd](./bitburner.material.dmd.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [demand](./bitburner.material.demand.md)
|
||||
|
||||
## Material.dmd property
|
||||
## Material.demand property
|
||||
|
||||
Demand for the material, only present if "Market Research - Demand" unlocked
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
dmd: number | undefined;
|
||||
demand: number | undefined;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [sell](./bitburner.material.sell.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [desiredSellAmount](./bitburner.material.desiredsellamount.md)
|
||||
|
||||
## Material.sell property
|
||||
## Material.desiredSellAmount property
|
||||
|
||||
Amount of material sold
|
||||
Sell amount, can be "PROD/2"
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
sell: number;
|
||||
desiredSellAmount: string | number;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [sCost](./bitburner.material.scost.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [desiredSellPrice](./bitburner.material.desiredsellprice.md)
|
||||
|
||||
## Material.sCost property
|
||||
## Material.desiredSellPrice property
|
||||
|
||||
Sell cost, can be "MP+5"
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
sCost: string | number;
|
||||
desiredSellPrice: string | number;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [exp](./bitburner.material.exp.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [exports](./bitburner.material.exports.md)
|
||||
|
||||
## Material.exp property
|
||||
## Material.exports property
|
||||
|
||||
Export orders
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
exp: Export[];
|
||||
exports: Export[];
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [cost](./bitburner.material.cost.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [marketPrice](./bitburner.material.marketprice.md)
|
||||
|
||||
## Material.cost property
|
||||
## Material.marketPrice property
|
||||
|
||||
Cost to buy material
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
cost: number;
|
||||
marketPrice: number;
|
||||
```
|
@ -16,15 +16,15 @@ interface Material
|
||||
|
||||
| Property | Modifiers | Type | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| [cmp](./bitburner.material.cmp.md) | | number \| undefined | Competition for the material, only present if "Market Research - Competition" unlocked |
|
||||
| [cost](./bitburner.material.cost.md) | | number | Cost to buy material |
|
||||
| [dmd](./bitburner.material.dmd.md) | | number \| undefined | Demand for the material, only present if "Market Research - Demand" unlocked |
|
||||
| [exp](./bitburner.material.exp.md) | | [Export](./bitburner.export.md)<!-- -->\[\] | Export orders |
|
||||
| [actualSellAmount](./bitburner.material.actualsellamount.md) | | number | Amount of material sold last cycle |
|
||||
| [competition](./bitburner.material.competition.md) | | number \| undefined | Competition for the material, only present if "Market Research - Competition" unlocked |
|
||||
| [demand](./bitburner.material.demand.md) | | number \| undefined | Demand for the material, only present if "Market Research - Demand" unlocked |
|
||||
| [desiredSellAmount](./bitburner.material.desiredsellamount.md) | | string \| number | Sell amount, can be "PROD/2" |
|
||||
| [desiredSellPrice](./bitburner.material.desiredsellprice.md) | | string \| number | Sell cost, can be "MP+5" |
|
||||
| [exports](./bitburner.material.exports.md) | | [Export](./bitburner.export.md)<!-- -->\[\] | Export orders |
|
||||
| [marketPrice](./bitburner.material.marketprice.md) | | number | Cost to buy material |
|
||||
| [name](./bitburner.material.name.md) | | [CorpMaterialName](./bitburner.corpmaterialname.md) | Name of the material |
|
||||
| [prod](./bitburner.material.prod.md) | | number | Amount of material produced |
|
||||
| [qlt](./bitburner.material.qlt.md) | | number | Quality of the material |
|
||||
| [qty](./bitburner.material.qty.md) | | number | Amount of material |
|
||||
| [sAmt](./bitburner.material.samt.md) | | string \| number | Sell amount, can be "PROD/2" |
|
||||
| [sCost](./bitburner.material.scost.md) | | string \| number | Sell cost, can be "MP+5" |
|
||||
| [sell](./bitburner.material.sell.md) | | number | Amount of material sold |
|
||||
| [productionAmount](./bitburner.material.productionamount.md) | | number | Amount of material produced last cycle |
|
||||
| [quality](./bitburner.material.quality.md) | | number | Quality of the material |
|
||||
| [stored](./bitburner.material.stored.md) | | number | Amount of material |
|
||||
|
||||
|
@ -1,13 +0,0 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [prod](./bitburner.material.prod.md)
|
||||
|
||||
## Material.prod property
|
||||
|
||||
Amount of material produced
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
prod: number;
|
||||
```
|
13
markdown/bitburner.material.productionamount.md
Normal file
13
markdown/bitburner.material.productionamount.md
Normal file
@ -0,0 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [productionAmount](./bitburner.material.productionamount.md)
|
||||
|
||||
## Material.productionAmount property
|
||||
|
||||
Amount of material produced last cycle
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
productionAmount: number;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [qlt](./bitburner.material.qlt.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [quality](./bitburner.material.quality.md)
|
||||
|
||||
## Material.qlt property
|
||||
## Material.quality property
|
||||
|
||||
Quality of the material
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
qlt: number;
|
||||
quality: number;
|
||||
```
|
@ -1,13 +0,0 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [sAmt](./bitburner.material.samt.md)
|
||||
|
||||
## Material.sAmt property
|
||||
|
||||
Sell amount, can be "PROD/2"
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
sAmt: string | number;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [qty](./bitburner.material.qty.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Material](./bitburner.material.md) > [stored](./bitburner.material.stored.md)
|
||||
|
||||
## Material.qty property
|
||||
## Material.stored property
|
||||
|
||||
Amount of material
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
qty: number;
|
||||
stored: number;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Office](./bitburner.office.md) > [avgEne](./bitburner.office.avgene.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Office](./bitburner.office.md) > [avgEnergy](./bitburner.office.avgenergy.md)
|
||||
|
||||
## Office.avgEne property
|
||||
## Office.avgEnergy property
|
||||
|
||||
Average energy of the employees
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
avgEne: number;
|
||||
avgEnergy: number;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Office](./bitburner.office.md) > [avgMor](./bitburner.office.avgmor.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Office](./bitburner.office.md) > [avgMorale](./bitburner.office.avgmorale.md)
|
||||
|
||||
## Office.avgMor property
|
||||
## Office.avgMorale property
|
||||
|
||||
Average morale of the employees
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
avgMor: number;
|
||||
avgMorale: number;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Office](./bitburner.office.md) > [loc](./bitburner.office.loc.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Office](./bitburner.office.md) > [city](./bitburner.office.city.md)
|
||||
|
||||
## Office.loc property
|
||||
## Office.city property
|
||||
|
||||
City of the office
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
loc: CityName;
|
||||
city: CityName;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Office](./bitburner.office.md) > [employeeProd](./bitburner.office.employeeprod.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Office](./bitburner.office.md) > [employeeProductionByJob](./bitburner.office.employeeproductionbyjob.md)
|
||||
|
||||
## Office.employeeProd property
|
||||
## Office.employeeProductionByJob property
|
||||
|
||||
Production of the employees
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
employeeProd: Record<CorpEmployeePosition, number>;
|
||||
employeeProductionByJob: Record<CorpEmployeePosition, number>;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Office](./bitburner.office.md) > [maxEne](./bitburner.office.maxene.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Office](./bitburner.office.md) > [maxEnergy](./bitburner.office.maxenergy.md)
|
||||
|
||||
## Office.maxEne property
|
||||
## Office.maxEnergy property
|
||||
|
||||
Maximum amount of energy of the employees
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
maxEne: number;
|
||||
maxEnergy: number;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Office](./bitburner.office.md) > [maxMor](./bitburner.office.maxmor.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Office](./bitburner.office.md) > [maxMorale](./bitburner.office.maxmorale.md)
|
||||
|
||||
## Office.maxMor property
|
||||
## Office.maxMorale property
|
||||
|
||||
Maximum morale of the employees
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
maxMor: number;
|
||||
maxMorale: number;
|
||||
```
|
@ -16,14 +16,14 @@ export interface Office
|
||||
|
||||
| Property | Modifiers | Type | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| [avgEne](./bitburner.office.avgene.md) | | number | Average energy of the employees |
|
||||
| [avgMor](./bitburner.office.avgmor.md) | | number | Average morale of the employees |
|
||||
| [avgEnergy](./bitburner.office.avgenergy.md) | | number | Average energy of the employees |
|
||||
| [avgMorale](./bitburner.office.avgmorale.md) | | number | Average morale of the employees |
|
||||
| [city](./bitburner.office.city.md) | | [CityName](./bitburner.cityname.md) | City of the office |
|
||||
| [employeeJobs](./bitburner.office.employeejobs.md) | | Record<[CorpEmployeePosition](./bitburner.corpemployeeposition.md)<!-- -->, number> | Positions of the employees |
|
||||
| [employeeProd](./bitburner.office.employeeprod.md) | | Record<[CorpEmployeePosition](./bitburner.corpemployeeposition.md)<!-- -->, number> | Production of the employees |
|
||||
| [employees](./bitburner.office.employees.md) | | number | Amount of employees |
|
||||
| [loc](./bitburner.office.loc.md) | | [CityName](./bitburner.cityname.md) | City of the office |
|
||||
| [maxEne](./bitburner.office.maxene.md) | | number | Maximum amount of energy of the employees |
|
||||
| [maxMor](./bitburner.office.maxmor.md) | | number | Maximum morale of the employees |
|
||||
| [employeeProductionByJob](./bitburner.office.employeeproductionbyjob.md) | | Record<[CorpEmployeePosition](./bitburner.corpemployeeposition.md)<!-- -->, number> | Production of the employees |
|
||||
| [maxEnergy](./bitburner.office.maxenergy.md) | | number | Maximum amount of energy of the employees |
|
||||
| [maxMorale](./bitburner.office.maxmorale.md) | | number | Maximum morale of the employees |
|
||||
| [numEmployees](./bitburner.office.numemployees.md) | | number | Amount of employees |
|
||||
| [size](./bitburner.office.size.md) | | number | Maximum number of employee |
|
||||
| [totalExperience](./bitburner.office.totalexperience.md) | | number | Total experience of all employees |
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Office](./bitburner.office.md) > [employees](./bitburner.office.employees.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Office](./bitburner.office.md) > [numEmployees](./bitburner.office.numemployees.md)
|
||||
|
||||
## Office.employees property
|
||||
## Office.numEmployees property
|
||||
|
||||
Amount of employees
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
employees: number;
|
||||
numEmployees: number;
|
||||
```
|
13
markdown/bitburner.product.actualsellamount.md
Normal file
13
markdown/bitburner.product.actualsellamount.md
Normal file
@ -0,0 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [actualSellAmount](./bitburner.product.actualsellamount.md)
|
||||
|
||||
## Product.actualSellAmount property
|
||||
|
||||
Amount of product sold last cycle
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
actualSellAmount: number;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [cmp](./bitburner.product.cmp.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [competition](./bitburner.product.competition.md)
|
||||
|
||||
## Product.cmp property
|
||||
## Product.competition property
|
||||
|
||||
Competition for the product, only present if "Market Research - Competition" unlocked
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
cmp: number | undefined;
|
||||
competition: number | undefined;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [dmd](./bitburner.product.dmd.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [demand](./bitburner.product.demand.md)
|
||||
|
||||
## Product.dmd property
|
||||
## Product.demand property
|
||||
|
||||
Demand for the product, only present if "Market Research - Demand" unlocked
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
dmd: number | undefined;
|
||||
demand: number | undefined;
|
||||
```
|
13
markdown/bitburner.product.desiredsellamount.md
Normal file
13
markdown/bitburner.product.desiredsellamount.md
Normal file
@ -0,0 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [desiredSellAmount](./bitburner.product.desiredsellamount.md)
|
||||
|
||||
## Product.desiredSellAmount property
|
||||
|
||||
Desired sell amount, e.g. "PROD/2"
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
desiredSellAmount: string | number;
|
||||
```
|
13
markdown/bitburner.product.desiredsellprice.md
Normal file
13
markdown/bitburner.product.desiredsellprice.md
Normal file
@ -0,0 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [desiredSellPrice](./bitburner.product.desiredsellprice.md)
|
||||
|
||||
## Product.desiredSellPrice property
|
||||
|
||||
Desired sell price, can be "MP+5"
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
desiredSellPrice: string | number;
|
||||
```
|
@ -4,7 +4,7 @@
|
||||
|
||||
## Product.developmentProgress property
|
||||
|
||||
Creation progress - A number between 0-100 representing percentage
|
||||
A number between 0-100 representing percentage completion
|
||||
|
||||
**Signature:**
|
||||
|
||||
|
13
markdown/bitburner.product.effectiverating.md
Normal file
13
markdown/bitburner.product.effectiverating.md
Normal file
@ -0,0 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [effectiveRating](./bitburner.product.effectiverating.md)
|
||||
|
||||
## Product.effectiveRating property
|
||||
|
||||
Effective rating in the specific city
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
effectiveRating: number;
|
||||
```
|
@ -1,13 +0,0 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [effRat](./bitburner.product.effrat.md)
|
||||
|
||||
## Product.effRat property
|
||||
|
||||
Effective rating
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
effRat: number;
|
||||
```
|
@ -16,17 +16,17 @@ interface Product
|
||||
|
||||
| Property | Modifiers | Type | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| [cmp](./bitburner.product.cmp.md) | | number \| undefined | Competition for the product, only present if "Market Research - Competition" unlocked |
|
||||
| [developmentProgress](./bitburner.product.developmentprogress.md) | | number | Creation progress - A number between 0-100 representing percentage |
|
||||
| [dmd](./bitburner.product.dmd.md) | | number \| undefined | Demand for the product, only present if "Market Research - Demand" unlocked |
|
||||
| [effRat](./bitburner.product.effrat.md) | | number | Effective rating |
|
||||
| [actualSellAmount](./bitburner.product.actualsellamount.md) | | number | Amount of product sold last cycle |
|
||||
| [competition](./bitburner.product.competition.md) | | number \| undefined | Competition for the product, only present if "Market Research - Competition" unlocked |
|
||||
| [demand](./bitburner.product.demand.md) | | number \| undefined | Demand for the product, only present if "Market Research - Demand" unlocked |
|
||||
| [desiredSellAmount](./bitburner.product.desiredsellamount.md) | | string \| number | Desired sell amount, e.g. "PROD/2" |
|
||||
| [desiredSellPrice](./bitburner.product.desiredsellprice.md) | | string \| number | Desired sell price, can be "MP+5" |
|
||||
| [developmentProgress](./bitburner.product.developmentprogress.md) | | number | A number between 0-100 representing percentage completion |
|
||||
| [effectiveRating](./bitburner.product.effectiverating.md) | | number | Effective rating in the specific city |
|
||||
| [name](./bitburner.product.name.md) | | string | Name of the product |
|
||||
| [pCost](./bitburner.product.pcost.md) | | number | Production cost |
|
||||
| [prod](./bitburner.product.prod.md) | | number | Amount of product produced |
|
||||
| [properties](./bitburner.product.properties.md) | | { \[key: string\]: number } | Product Properties. The data is {<!-- -->qlt, per, dur, rel, aes, fea<!-- -->} |
|
||||
| [qty](./bitburner.product.qty.md) | | number | Amount of product |
|
||||
| [rat](./bitburner.product.rat.md) | | number | Product Rating |
|
||||
| [sAmt](./bitburner.product.samt.md) | | string | Sell amount, can be "PROD/2" |
|
||||
| [sCost](./bitburner.product.scost.md) | | string | Sell cost, can be "MP+5" |
|
||||
| [sell](./bitburner.product.sell.md) | | number | Amount of product sold |
|
||||
| [productionAmount](./bitburner.product.productionamount.md) | | number | Amount of product produced last cycle |
|
||||
| [productionCost](./bitburner.product.productioncost.md) | | number | Production cost |
|
||||
| [rating](./bitburner.product.rating.md) | | number | Rating based on stats |
|
||||
| [stats](./bitburner.product.stats.md) | | { quality: number; performance: number; durability: number; reliability: number; aesthetics: number; features: number; } | Product stats |
|
||||
| [stored](./bitburner.product.stored.md) | | number | Amount of product stored in warehouse |
|
||||
|
||||
|
13
markdown/bitburner.product.productionamount.md
Normal file
13
markdown/bitburner.product.productionamount.md
Normal file
@ -0,0 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [productionAmount](./bitburner.product.productionamount.md)
|
||||
|
||||
## Product.productionAmount property
|
||||
|
||||
Amount of product produced last cycle
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
productionAmount: number;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [pCost](./bitburner.product.pcost.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [productionCost](./bitburner.product.productioncost.md)
|
||||
|
||||
## Product.pCost property
|
||||
## Product.productionCost property
|
||||
|
||||
Production cost
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
pCost: number;
|
||||
productionCost: number;
|
||||
```
|
@ -1,13 +0,0 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [properties](./bitburner.product.properties.md)
|
||||
|
||||
## Product.properties property
|
||||
|
||||
Product Properties. The data is {<!-- -->qlt, per, dur, rel, aes, fea<!-- -->}
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
properties: { [key: string]: number };
|
||||
```
|
@ -1,13 +0,0 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [rat](./bitburner.product.rat.md)
|
||||
|
||||
## Product.rat property
|
||||
|
||||
Product Rating
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
rat: number;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [prod](./bitburner.product.prod.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [rating](./bitburner.product.rating.md)
|
||||
|
||||
## Product.prod property
|
||||
## Product.rating property
|
||||
|
||||
Amount of product produced
|
||||
Rating based on stats
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
prod: number;
|
||||
rating: number;
|
||||
```
|
@ -1,13 +0,0 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [sAmt](./bitburner.product.samt.md)
|
||||
|
||||
## Product.sAmt property
|
||||
|
||||
Sell amount, can be "PROD/2"
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
sAmt: string;
|
||||
```
|
@ -1,13 +0,0 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [sCost](./bitburner.product.scost.md)
|
||||
|
||||
## Product.sCost property
|
||||
|
||||
Sell cost, can be "MP+5"
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
sCost: string;
|
||||
```
|
@ -1,13 +0,0 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [sell](./bitburner.product.sell.md)
|
||||
|
||||
## Product.sell property
|
||||
|
||||
Amount of product sold
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
sell: number;
|
||||
```
|
20
markdown/bitburner.product.stats.md
Normal file
20
markdown/bitburner.product.stats.md
Normal file
@ -0,0 +1,20 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [stats](./bitburner.product.stats.md)
|
||||
|
||||
## Product.stats property
|
||||
|
||||
Product stats
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
stats: {
|
||||
quality: number;
|
||||
performance: number;
|
||||
durability: number;
|
||||
reliability: number;
|
||||
aesthetics: number;
|
||||
features: number;
|
||||
};
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [qty](./bitburner.product.qty.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Product](./bitburner.product.md) > [stored](./bitburner.product.stored.md)
|
||||
|
||||
## Product.qty property
|
||||
## Product.stored property
|
||||
|
||||
Amount of product
|
||||
Amount of product stored in warehouse
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
qty: number;
|
||||
stored: number;
|
||||
```
|
@ -1,13 +1,13 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Warehouse](./bitburner.warehouse.md) > [loc](./bitburner.warehouse.loc.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Warehouse](./bitburner.warehouse.md) > [city](./bitburner.warehouse.city.md)
|
||||
|
||||
## Warehouse.loc property
|
||||
## Warehouse.city property
|
||||
|
||||
City in which the warehouse is located
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
loc: CityName;
|
||||
city: CityName;
|
||||
```
|
@ -16,8 +16,8 @@ interface Warehouse
|
||||
|
||||
| Property | Modifiers | Type | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| [city](./bitburner.warehouse.city.md) | | [CityName](./bitburner.cityname.md) | City in which the warehouse is located |
|
||||
| [level](./bitburner.warehouse.level.md) | | number | Amount of size upgrade bought |
|
||||
| [loc](./bitburner.warehouse.loc.md) | | [CityName](./bitburner.cityname.md) | City in which the warehouse is located |
|
||||
| [size](./bitburner.warehouse.size.md) | | number | Total space in the warehouse |
|
||||
| [sizeUsed](./bitburner.warehouse.sizeused.md) | | number | Used space in the warehouse |
|
||||
| [smartSupplyEnabled](./bitburner.warehouse.smartsupplyenabled.md) | | boolean | Smart Supply status in the warehouse |
|
||||
|
@ -9,7 +9,7 @@ Get product data
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getProduct(divisionName: string, city: CityName | `${CityName}`, productName: string): Product;
|
||||
getProduct(divisionName: string, cityName: CityName | `${CityName}`, productName: string): Product;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -17,7 +17,7 @@ getProduct(divisionName: string, city: CityName | `${CityName}`, productName: st
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| divisionName | string | Name of the division |
|
||||
| city | [CityName](./bitburner.cityname.md) \| \`${[CityName](./bitburner.cityname.md)<!-- -->}\` | Name of the city |
|
||||
| cityName | [CityName](./bitburner.cityname.md) \| \`${[CityName](./bitburner.cityname.md)<!-- -->}\` | |
|
||||
| productName | string | Name of the product |
|
||||
|
||||
**Returns:**
|
||||
|
@ -26,7 +26,7 @@ Requires the Warehouse API upgrade from your corporation.
|
||||
| [discontinueProduct(divisionName, productName)](./bitburner.warehouseapi.discontinueproduct.md) | Discontinue a product. |
|
||||
| [exportMaterial(sourceDivision, sourceCity, targetDivision, targetCity, materialName, amt)](./bitburner.warehouseapi.exportmaterial.md) | Set material export data |
|
||||
| [getMaterial(divisionName, city, materialName)](./bitburner.warehouseapi.getmaterial.md) | Get material data |
|
||||
| [getProduct(divisionName, city, productName)](./bitburner.warehouseapi.getproduct.md) | Get product data |
|
||||
| [getProduct(divisionName, cityName, productName)](./bitburner.warehouseapi.getproduct.md) | Get product data |
|
||||
| [getUpgradeWarehouseCost(divisionName, city, amt)](./bitburner.warehouseapi.getupgradewarehousecost.md) | Gets the cost to upgrade a warehouse to the next level |
|
||||
| [getWarehouse(divisionName, city)](./bitburner.warehouseapi.getwarehouse.md) | Get warehouse data |
|
||||
| [hasWarehouse(divisionName, city)](./bitburner.warehouseapi.haswarehouse.md) | Check if you have a warehouse in city |
|
||||
@ -38,8 +38,8 @@ Requires the Warehouse API upgrade from your corporation.
|
||||
| [sellProduct(divisionName, city, productName, amt, price, all)](./bitburner.warehouseapi.sellproduct.md) | Set product sell data. |
|
||||
| [setMaterialMarketTA1(divisionName, city, materialName, on)](./bitburner.warehouseapi.setmaterialmarketta1.md) | Set market TA 1 for a material. |
|
||||
| [setMaterialMarketTA2(divisionName, city, materialName, on)](./bitburner.warehouseapi.setmaterialmarketta2.md) | Set market TA 2 for a material. |
|
||||
| [setProductMarketTA1(divisionName, city, productName, on)](./bitburner.warehouseapi.setproductmarketta1.md) | Set market TA 1 for a product. |
|
||||
| [setProductMarketTA2(divisionName, city, productName, on)](./bitburner.warehouseapi.setproductmarketta2.md) | Set market TA 2 for a product. |
|
||||
| [setProductMarketTA1(divisionName, productName, on)](./bitburner.warehouseapi.setproductmarketta1.md) | \* Set market TA 1 for a product. |
|
||||
| [setProductMarketTA2(divisionName, productName, on)](./bitburner.warehouseapi.setproductmarketta2.md) | Set market TA 2 for a product. |
|
||||
| [setSmartSupply(divisionName, city, enabled)](./bitburner.warehouseapi.setsmartsupply.md) | Set smart supply |
|
||||
| [setSmartSupplyOption(divisionName, city, materialName, option)](./bitburner.warehouseapi.setsmartsupplyoption.md) | Set whether smart supply uses leftovers before buying |
|
||||
| [upgradeWarehouse(divisionName, city, amt)](./bitburner.warehouseapi.upgradewarehouse.md) | Upgrade warehouse |
|
||||
|
@ -4,12 +4,12 @@
|
||||
|
||||
## WarehouseAPI.setProductMarketTA1() method
|
||||
|
||||
Set market TA 1 for a product.
|
||||
\* Set market TA 1 for a product.
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
setProductMarketTA1(divisionName: string, city: CityName | `${CityName}`, productName: string, on: boolean): void;
|
||||
setProductMarketTA1(divisionName: string, productName: string, on: boolean): void;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -17,7 +17,6 @@ setProductMarketTA1(divisionName: string, city: CityName | `${CityName}`, produc
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| divisionName | string | Name of the division |
|
||||
| city | [CityName](./bitburner.cityname.md) \| \`${[CityName](./bitburner.cityname.md)<!-- -->}\` | Name of the city |
|
||||
| productName | string | Name of the product |
|
||||
| on | boolean | market ta enabled |
|
||||
|
||||
|
@ -9,7 +9,7 @@ Set market TA 2 for a product.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
setProductMarketTA2(divisionName: string, city: CityName | `${CityName}`, productName: string, on: boolean): void;
|
||||
setProductMarketTA2(divisionName: string, productName: string, on: boolean): void;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -17,7 +17,6 @@ setProductMarketTA2(divisionName: string, city: CityName | `${CityName}`, produc
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| divisionName | string | Name of the division |
|
||||
| city | [CityName](./bitburner.cityname.md) \| \`${[CityName](./bitburner.cityname.md)<!-- -->}\` | Name of the city |
|
||||
| productName | string | Name of the product |
|
||||
| on | boolean | market ta enabled |
|
||||
|
||||
|
@ -2,7 +2,7 @@ import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
|
||||
import { SkillNames } from "../Bladeburner/data/SkillNames";
|
||||
import { Skills } from "../Bladeburner/Skills";
|
||||
import { CONSTANTS } from "../Constants";
|
||||
import { IndustryType } from "../Corporation/data/Enums";
|
||||
import { CorpUnlockName, IndustryType } from "../Corporation/data/Enums";
|
||||
import { Exploit } from "../Exploits/Exploit";
|
||||
import { Factions } from "../Faction/Factions";
|
||||
import { AllGangs } from "../Gang/AllGangs";
|
||||
@ -27,6 +27,7 @@ import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import { workerScripts } from "../Netscript/WorkerScripts";
|
||||
|
||||
import type { PlayerObject } from "../PersonObjects/Player/PlayerObject";
|
||||
import { getRecordValues } from "../Types/Record";
|
||||
|
||||
// Unable to correctly cast the JSON data into AchievementDataJson type otherwise...
|
||||
const achievementData = (<AchievementDataJson>(<unknown>data)).achievements;
|
||||
@ -441,23 +442,28 @@ export const achievements: Record<string, Achievement> = {
|
||||
...achievementData.CORPORATION_BRIBE,
|
||||
Icon: "CORPLOBBY",
|
||||
Visible: () => hasAccessToSF(Player, 3),
|
||||
Condition: () => Player.corporation !== null && Player.corporation.unlockUpgrades[6] === 1,
|
||||
Condition: () => !!Player.corporation && Player.corporation.unlocks.has(CorpUnlockName.GovernmentPartnership),
|
||||
},
|
||||
CORPORATION_PROD_1000: {
|
||||
...achievementData.CORPORATION_PROD_1000,
|
||||
Icon: "CORP1000",
|
||||
Visible: () => hasAccessToSF(Player, 3),
|
||||
Condition: () => Player.corporation !== null && Player.corporation.divisions.some((d) => d.prodMult >= 1000),
|
||||
Condition: () => {
|
||||
if (!Player.corporation) return false;
|
||||
for (const division of Player.corporation.divisions.values()) {
|
||||
if (division.productionMult >= 1000) return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
CORPORATION_EMPLOYEE_3000: {
|
||||
...achievementData.CORPORATION_EMPLOYEE_3000,
|
||||
Icon: "CORPCITY",
|
||||
Visible: () => hasAccessToSF(Player, 3),
|
||||
Condition: (): boolean => {
|
||||
if (Player.corporation === null) return false;
|
||||
for (const d of Player.corporation.divisions) {
|
||||
let totalEmployees = 0;
|
||||
for (const o of Object.values(d.offices)) if (o && o.totalEmployees) totalEmployees += o.totalEmployees;
|
||||
if (!Player.corporation) return false;
|
||||
for (const division of Player.corporation.divisions.values()) {
|
||||
const totalEmployees = getRecordValues(division.offices).reduce((a, b) => a + b.numEmployees, 0);
|
||||
if (totalEmployees >= 3000) return true;
|
||||
}
|
||||
return false;
|
||||
@ -469,8 +475,13 @@ export const achievements: Record<string, Achievement> = {
|
||||
Name: "Own the land",
|
||||
Description: "Expand to the Real Estate division.",
|
||||
Visible: () => hasAccessToSF(Player, 3),
|
||||
Condition: () =>
|
||||
Player.corporation !== null && Player.corporation.divisions.some((d) => d.type === IndustryType.RealEstate),
|
||||
Condition: () => {
|
||||
if (!Player.corporation) return false;
|
||||
for (const division of Player.corporation.divisions.values()) {
|
||||
if (division.type === IndustryType.RealEstate) return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
INTELLIGENCE_255: {
|
||||
...achievementData.INTELLIGENCE_255,
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Class definition for a single Augmentation object
|
||||
import * as React from "react";
|
||||
|
||||
import type { CompletedProgramName } from "src/Programs/Programs";
|
||||
import type { CompletedProgramName } from "../Programs/Programs";
|
||||
import { Faction } from "../Faction/Faction";
|
||||
import { Factions } from "../Faction/Factions";
|
||||
import { formatPercent } from "../ui/formatNumber";
|
||||
|
@ -37,6 +37,7 @@ import { isSleeveSupportWork } from "../PersonObjects/Sleeve/Work/SleeveSupportW
|
||||
import { WorkStats, newWorkStats } from "../Work/WorkStats";
|
||||
import { CityName } from "../Enums";
|
||||
import { getRandomMember } from "../utils/helpers/enum";
|
||||
import { createEnumKeyedRecord } from "../Types/Record";
|
||||
|
||||
export interface BlackOpsAttempt {
|
||||
error?: string;
|
||||
@ -70,7 +71,7 @@ export class Bladeburner {
|
||||
type: ActionTypes.Idle,
|
||||
});
|
||||
|
||||
cities: Record<CityName, City>;
|
||||
cities = createEnumKeyedRecord(CityName, (name) => new City(name));
|
||||
city = CityName.Sector12;
|
||||
// Todo: better types for all these Record<string, etc> types. Will need custom types or enums for the named string categories (e.g. skills).
|
||||
skills: Record<string, number> = {};
|
||||
@ -101,10 +102,6 @@ export class Bladeburner {
|
||||
consoleLogs: string[] = ["Bladeburner Console", "Type 'help' to see console commands"];
|
||||
|
||||
constructor() {
|
||||
this.cities = {} as Record<CityName, City>;
|
||||
// This for loop ensures the above type is met for this.cities.
|
||||
for (const city of Object.values(CityName)) this.cities[city] = new City(city);
|
||||
|
||||
this.updateSkillMultipliers(); // Calls resetSkillMultipliers()
|
||||
|
||||
// Max Stamina is based on stats and Bladeburner-specific bonuses
|
||||
|
@ -2,33 +2,28 @@ import { Player } from "@player";
|
||||
import { MaterialInfo } from "./MaterialInfo";
|
||||
import { Corporation } from "./Corporation";
|
||||
import { IndustryResearchTrees, IndustriesData } from "./IndustryData";
|
||||
import { Industry } from "./Industry";
|
||||
import { Division } from "./Division";
|
||||
import * as corpConstants from "./data/Constants";
|
||||
import { OfficeSpace } from "./OfficeSpace";
|
||||
import { Material } from "./Material";
|
||||
import { Product } from "./Product";
|
||||
import { Warehouse } from "./Warehouse";
|
||||
import { CorporationUnlockUpgrade } from "./data/CorporationUnlockUpgrades";
|
||||
import { CorporationUpgrade } from "./data/CorporationUpgrades";
|
||||
import { Cities } from "../Locations/Cities";
|
||||
import { IndustryType } from "./data/Enums";
|
||||
import { ResearchMap } from "./ResearchMap";
|
||||
import { isRelevantMaterial } from "./ui/Helpers";
|
||||
import { CityName } from "../Enums";
|
||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||
import { CorpResearchName } from "@nsdefs";
|
||||
import { calculateUpgradeCost } from "./helpers";
|
||||
import { isInteger } from "lodash";
|
||||
import { getRecordValues } from "../Types/Record";
|
||||
|
||||
export function NewIndustry(corporation: Corporation, industry: IndustryType, name: string): void {
|
||||
if (corporation.divisions.length >= corporation.maxDivisions)
|
||||
if (corporation.divisions.size >= corporation.maxDivisions)
|
||||
throw new Error(`Cannot expand into ${industry} industry, too many divisions!`);
|
||||
|
||||
for (let i = 0; i < corporation.divisions.length; ++i) {
|
||||
if (corporation.divisions[i].name === name) {
|
||||
throw new Error("This division name is already in use!");
|
||||
}
|
||||
}
|
||||
if (corporation.divisions.has(name)) throw new Error(`Division name ${name} is already in use!`);
|
||||
// "Overview" is forbidden as a division name, see CorporationRoot.tsx for why this would cause issues.
|
||||
if (name === "Overview") throw new Error(`"Overview" is a forbidden division name.`);
|
||||
|
||||
const data = IndustriesData[industry];
|
||||
if (!data) throw new Error(`Invalid industry: '${industry}'`);
|
||||
@ -39,8 +34,9 @@ export function NewIndustry(corporation: Corporation, industry: IndustryType, na
|
||||
throw new Error("New division must have a name!");
|
||||
} else {
|
||||
corporation.funds = corporation.funds - cost;
|
||||
corporation.divisions.push(
|
||||
new Industry({
|
||||
corporation.divisions.set(
|
||||
name,
|
||||
new Division({
|
||||
corp: corporation,
|
||||
name: name,
|
||||
type: industry,
|
||||
@ -50,13 +46,11 @@ export function NewIndustry(corporation: Corporation, industry: IndustryType, na
|
||||
}
|
||||
|
||||
export function removeIndustry(corporation: Corporation, name: string) {
|
||||
const divIndex = corporation.divisions.findIndex((div) => div.name === name);
|
||||
if (divIndex === -1) throw new Error("There is no division called " + name);
|
||||
|
||||
corporation.divisions.splice(divIndex, 1);
|
||||
if (!corporation.divisions.has(name)) throw new Error("There is no division called " + name);
|
||||
corporation.divisions.delete(name);
|
||||
}
|
||||
|
||||
export function NewCity(corporation: Corporation, division: Industry, city: CityName): void {
|
||||
export function purchaseOffice(corporation: Corporation, division: Division, city: CityName): void {
|
||||
if (corporation.funds < corpConstants.officeInitialCost) {
|
||||
throw new Error("You don't have enough company funds to open a new office!");
|
||||
}
|
||||
@ -65,30 +59,11 @@ export function NewCity(corporation: Corporation, division: Industry, city: City
|
||||
}
|
||||
corporation.funds = corporation.funds - corpConstants.officeInitialCost;
|
||||
division.offices[city] = new OfficeSpace({
|
||||
loc: city,
|
||||
city: city,
|
||||
size: corpConstants.officeInitialSize,
|
||||
});
|
||||
}
|
||||
|
||||
export function UnlockUpgrade(corporation: Corporation, upgrade: CorporationUnlockUpgrade): void {
|
||||
if (corporation.funds < upgrade.price) {
|
||||
throw new Error("Insufficient funds");
|
||||
}
|
||||
if (corporation.unlockUpgrades[upgrade.index] === 1) {
|
||||
throw new Error(`You have already unlocked the ${upgrade.name} upgrade!`);
|
||||
}
|
||||
corporation.unlock(upgrade);
|
||||
}
|
||||
|
||||
export function LevelUpgrade(corporation: Corporation, upgrade: CorporationUpgrade, amount: number): void {
|
||||
const cost = calculateUpgradeCost(corporation, upgrade, amount);
|
||||
if (corporation.funds < cost) {
|
||||
throw new Error("Insufficient funds");
|
||||
} else {
|
||||
corporation.upgrade(upgrade, amount);
|
||||
}
|
||||
}
|
||||
|
||||
export function IssueDividends(corporation: Corporation, rate: number): void {
|
||||
if (isNaN(rate) || rate < 0 || rate > corpConstants.dividendMaxRate) {
|
||||
throw new Error(`Invalid value. Must be an number between 0 and ${corpConstants.dividendMaxRate}`);
|
||||
@ -124,9 +99,9 @@ export function IssueNewShares(corporation: Corporation, amount: number): [numbe
|
||||
return [profit, amount, privateShares];
|
||||
}
|
||||
|
||||
export function SellMaterial(mat: Material, amt: string, price: string): void {
|
||||
export function SellMaterial(material: Material, amount: string, price: string): void {
|
||||
if (price === "") price = "0";
|
||||
if (amt === "") amt = "0";
|
||||
if (amount === "") amount = "0";
|
||||
let cost = price.replace(/\s+/g, "");
|
||||
cost = cost.replace(/[^-()\d/*+.MPe]/g, ""); //Sanitize cost
|
||||
let temp = cost.replace(/MP/, "1.234e5");
|
||||
@ -142,19 +117,19 @@ export function SellMaterial(mat: Material, amt: string, price: string): void {
|
||||
}
|
||||
|
||||
if (cost.includes("MP")) {
|
||||
mat.sCost = cost; //Dynamically evaluated
|
||||
material.desiredSellPrice = cost; //Dynamically evaluated
|
||||
} else {
|
||||
mat.sCost = temp;
|
||||
material.desiredSellPrice = temp;
|
||||
}
|
||||
|
||||
//Parse quantity
|
||||
amt = amt.toUpperCase();
|
||||
if (amt.includes("MAX") || amt.includes("PROD") || amt.includes("INV")) {
|
||||
let q = amt.replace(/\s+/g, "");
|
||||
amount = amount.toUpperCase();
|
||||
if (amount.includes("MAX") || amount.includes("PROD") || amount.includes("INV")) {
|
||||
let q = amount.replace(/\s+/g, "");
|
||||
q = q.replace(/[^-()\d/*+.MAXPRODINV]/g, "");
|
||||
let tempQty = q.replace(/MAX/g, mat.maxsll.toString());
|
||||
tempQty = tempQty.replace(/PROD/g, mat.prd.toString());
|
||||
tempQty = tempQty.replace(/INV/g, mat.prd.toString());
|
||||
let tempQty = q.replace(/MAX/g, material.maxSellPerCycle.toString());
|
||||
tempQty = tempQty.replace(/PROD/g, material.productionAmount.toString());
|
||||
tempQty = tempQty.replace(/INV/g, material.productionAmount.toString());
|
||||
try {
|
||||
tempQty = eval(tempQty);
|
||||
} catch (e) {
|
||||
@ -164,26 +139,19 @@ export function SellMaterial(mat: Material, amt: string, price: string): void {
|
||||
if (tempQty == null || isNaN(parseFloat(tempQty))) {
|
||||
throw new Error("Invalid value or expression for sell quantity field");
|
||||
}
|
||||
mat.sllman[0] = true;
|
||||
mat.sllman[1] = q; //Use sanitized input
|
||||
} else if (isNaN(parseFloat(amt)) || parseFloat(amt) < 0) {
|
||||
material.desiredSellAmount = q; //Use sanitized input
|
||||
} else if (isNaN(parseFloat(amount)) || parseFloat(amount) < 0) {
|
||||
throw new Error("Invalid value for sell quantity field! Must be numeric or 'PROD' or 'MAX'");
|
||||
} else {
|
||||
let q = parseFloat(amt);
|
||||
let q = parseFloat(amount);
|
||||
if (isNaN(q)) {
|
||||
q = 0;
|
||||
}
|
||||
if (q === 0) {
|
||||
mat.sllman[0] = false;
|
||||
mat.sllman[1] = 0;
|
||||
} else {
|
||||
mat.sllman[0] = true;
|
||||
mat.sllman[1] = q;
|
||||
}
|
||||
material.desiredSellAmount = q;
|
||||
}
|
||||
}
|
||||
|
||||
export function SellProduct(product: Product, city: string, amt: string, price: string, all: boolean): void {
|
||||
export function SellProduct(product: Product, city: CityName, amt: string, price: string, all: boolean): void {
|
||||
//Parse price
|
||||
if (price.includes("MP")) {
|
||||
//Dynamically evaluated quantity. First test to make sure its valid
|
||||
@ -200,27 +168,24 @@ export function SellProduct(product: Product, city: string, amt: string, price:
|
||||
if (temp == null || isNaN(parseFloat(temp))) {
|
||||
throw new Error("Invalid value or expression for sell price field.");
|
||||
}
|
||||
product.sCost[city] = price; //Use sanitized price
|
||||
product.cityData[city].desiredSellPrice = price; //Use sanitized price
|
||||
} else {
|
||||
const cost = parseFloat(price);
|
||||
if (isNaN(cost)) {
|
||||
throw new Error("Invalid value for sell price field");
|
||||
}
|
||||
product.sCost[city] = cost;
|
||||
product.cityData[city].desiredSellPrice = cost;
|
||||
}
|
||||
|
||||
// Array of all cities. Used later
|
||||
const cities = Object.keys(Cities);
|
||||
|
||||
// Parse quantity
|
||||
amt = amt.toUpperCase();
|
||||
if (amt.includes("MAX") || amt.includes("PROD") || amt.includes("INV")) {
|
||||
//Dynamically evaluated quantity. First test to make sure its valid
|
||||
let qty = amt.replace(/\s+/g, "");
|
||||
qty = qty.replace(/[^-()\d/*+.MAXPRODINV]/g, "");
|
||||
let temp = qty.replace(/MAX/g, product.maxsll.toString());
|
||||
temp = temp.replace(/PROD/g, product.data[city][1].toString());
|
||||
temp = temp.replace(/INV/g, product.data[city][0].toString());
|
||||
let temp = qty.replace(/MAX/g, product.maxSellAmount.toString());
|
||||
temp = temp.replace(/PROD/g, product.cityData[city].productionAmount.toString());
|
||||
temp = temp.replace(/INV/g, product.cityData[city].stored.toString());
|
||||
try {
|
||||
temp = eval(temp);
|
||||
} catch (e) {
|
||||
@ -231,14 +196,11 @@ export function SellProduct(product: Product, city: string, amt: string, price:
|
||||
throw new Error("Invalid value or expression for sell quantity field");
|
||||
}
|
||||
if (all) {
|
||||
for (let i = 0; i < cities.length; ++i) {
|
||||
const tempCity = cities[i];
|
||||
product.sllman[tempCity][0] = true;
|
||||
product.sllman[tempCity][1] = qty; //Use sanitized input
|
||||
for (const cityName of Object.values(CityName)) {
|
||||
product.cityData[cityName].desiredSellAmount = qty; //Use sanitized input
|
||||
}
|
||||
} else {
|
||||
product.sllman[city][0] = true;
|
||||
product.sllman[city][1] = qty; //Use sanitized input
|
||||
product.cityData[city].desiredSellAmount = qty; //Use sanitized input
|
||||
}
|
||||
} else if (isNaN(parseFloat(amt)) || parseFloat(amt) < 0) {
|
||||
throw new Error("Invalid value for sell quantity field! Must be numeric or 'PROD' or 'MAX'");
|
||||
@ -249,24 +211,18 @@ export function SellProduct(product: Product, city: string, amt: string, price:
|
||||
}
|
||||
if (qty === 0) {
|
||||
if (all) {
|
||||
for (let i = 0; i < cities.length; ++i) {
|
||||
const tempCity = cities[i];
|
||||
product.sllman[tempCity][0] = false;
|
||||
product.sllman[tempCity][1] = "";
|
||||
for (const cityName of Object.values(CityName)) {
|
||||
product.cityData[cityName].desiredSellAmount = 0;
|
||||
}
|
||||
} else {
|
||||
product.sllman[city][0] = false;
|
||||
product.sllman[city][1] = "";
|
||||
product.cityData[city].desiredSellAmount = 0;
|
||||
}
|
||||
} else if (all) {
|
||||
for (let i = 0; i < cities.length; ++i) {
|
||||
const tempCity = cities[i];
|
||||
product.sllman[tempCity][0] = true;
|
||||
product.sllman[tempCity][1] = qty;
|
||||
for (const cityName of Object.values(CityName)) {
|
||||
product.cityData[cityName].desiredSellAmount = qty;
|
||||
}
|
||||
} else {
|
||||
product.sllman[city][0] = true;
|
||||
product.sllman[city][1] = qty;
|
||||
product.cityData[city].desiredSellAmount = qty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -286,7 +242,7 @@ export function BuyMaterial(material: Material, amt: number): void {
|
||||
if (isNaN(amt) || amt < 0) {
|
||||
throw new Error(`Invalid amount '${amt}' to buy material '${material.name}'`);
|
||||
}
|
||||
material.buy = amt;
|
||||
material.buyAmount = amt;
|
||||
}
|
||||
|
||||
export function BulkPurchase(corp: Corporation, warehouse: Warehouse, material: Material, amt: number): void {
|
||||
@ -298,10 +254,10 @@ export function BulkPurchase(corp: Corporation, warehouse: Warehouse, material:
|
||||
if (amt > maxAmount) {
|
||||
throw new Error(`You do not have enough warehouse size to fit this purchase`);
|
||||
}
|
||||
const cost = amt * material.bCost;
|
||||
const cost = amt * material.marketPrice;
|
||||
if (corp.funds >= cost) {
|
||||
corp.funds = corp.funds - cost;
|
||||
material.qty += amt;
|
||||
material.stored += amt;
|
||||
} else {
|
||||
throw new Error(`You cannot afford this purchase.`);
|
||||
}
|
||||
@ -365,7 +321,7 @@ export function BuyTea(corp: Corporation, office: OfficeSpace): boolean {
|
||||
|
||||
export function ThrowParty(corp: Corporation, office: OfficeSpace, costPerEmployee: number): number {
|
||||
const mult = 1 + costPerEmployee / 10e6;
|
||||
const cost = costPerEmployee * office.totalEmployees;
|
||||
const cost = costPerEmployee * office.numEmployees;
|
||||
if (corp.funds < cost) {
|
||||
return 0;
|
||||
}
|
||||
@ -378,16 +334,15 @@ export function ThrowParty(corp: Corporation, office: OfficeSpace, costPerEmploy
|
||||
return mult;
|
||||
}
|
||||
|
||||
export function PurchaseWarehouse(corp: Corporation, division: Industry, city: CityName): void {
|
||||
export function purchaseWarehouse(corp: Corporation, division: Division, city: CityName): void {
|
||||
if (corp.funds < corpConstants.warehouseInitialCost) return;
|
||||
if (division.warehouses[city]) return;
|
||||
corp.funds = corp.funds - corpConstants.warehouseInitialCost;
|
||||
division.warehouses[city] = new Warehouse({
|
||||
corp: corp,
|
||||
industry: division,
|
||||
division: division,
|
||||
loc: city,
|
||||
size: corpConstants.warehouseInitialSize,
|
||||
});
|
||||
corp.funds = corp.funds - corpConstants.warehouseInitialCost;
|
||||
}
|
||||
|
||||
export function UpgradeWarehouseCost(warehouse: Warehouse, amt: number): number {
|
||||
@ -397,7 +352,7 @@ export function UpgradeWarehouseCost(warehouse: Warehouse, amt: number): number
|
||||
);
|
||||
}
|
||||
|
||||
export function UpgradeWarehouse(corp: Corporation, division: Industry, warehouse: Warehouse, amt = 1): void {
|
||||
export function UpgradeWarehouse(corp: Corporation, division: Division, warehouse: Warehouse, amt = 1): void {
|
||||
const sizeUpgradeCost = UpgradeWarehouseCost(warehouse, amt);
|
||||
if (corp.funds < sizeUpgradeCost) return;
|
||||
warehouse.level += amt;
|
||||
@ -405,7 +360,7 @@ export function UpgradeWarehouse(corp: Corporation, division: Industry, warehous
|
||||
corp.funds = corp.funds - sizeUpgradeCost;
|
||||
}
|
||||
|
||||
export function HireAdVert(corp: Corporation, division: Industry): void {
|
||||
export function HireAdVert(corp: Corporation, division: Division): void {
|
||||
const cost = division.getAdVertCost();
|
||||
if (corp.funds < cost) return;
|
||||
corp.funds = corp.funds - cost;
|
||||
@ -414,7 +369,7 @@ export function HireAdVert(corp: Corporation, division: Industry): void {
|
||||
|
||||
export function MakeProduct(
|
||||
corp: Corporation,
|
||||
division: Industry,
|
||||
division: Division,
|
||||
city: CityName,
|
||||
productName: string,
|
||||
designInvest: number,
|
||||
@ -447,53 +402,46 @@ export function MakeProduct(
|
||||
} else if (division.hasResearch("uPgrade: Capacity.I")) {
|
||||
maxProducts = 4;
|
||||
}
|
||||
const products = division.products;
|
||||
if (Object.keys(products).length >= maxProducts) {
|
||||
if (division.products.size >= maxProducts) {
|
||||
throw new Error(`You are already at the max products (${maxProducts}) for division: ${division.name}!`);
|
||||
}
|
||||
|
||||
const product = new Product({
|
||||
name: productName.replace(/[<>]/g, "").trim(), //Sanitize for HTMl elements
|
||||
createCity: city,
|
||||
designCost: designInvest,
|
||||
advCost: marketingInvest,
|
||||
designInvestment: designInvest,
|
||||
advertisingInvestment: marketingInvest,
|
||||
});
|
||||
if (products[product.name]) {
|
||||
if (division.products.has(product.name)) {
|
||||
throw new Error(`You already have a product with this name!`);
|
||||
}
|
||||
|
||||
corp.funds = corp.funds - (designInvest + marketingInvest);
|
||||
products[product.name] = product;
|
||||
division.products.set(product.name, product);
|
||||
}
|
||||
|
||||
export function Research(division: Industry, researchName: CorpResearchName): void {
|
||||
export function Research(division: Division, researchName: CorpResearchName): void {
|
||||
const corp = Player.corporation;
|
||||
if (!corp) return;
|
||||
const researchTree = IndustryResearchTrees[division.type];
|
||||
if (researchTree === undefined) throw new Error(`No research tree for industry '${division.type}'`);
|
||||
const allResearch = researchTree.getAllNodes();
|
||||
if (!allResearch.includes(researchName)) throw new Error(`No research named '${researchName}'`);
|
||||
const research = ResearchMap[researchName];
|
||||
|
||||
if (division.researched[researchName]) return;
|
||||
if (division.sciResearch < research.cost)
|
||||
if (division.researched.has(researchName)) return;
|
||||
if (division.researchPoints < research.cost)
|
||||
throw new Error(`You do not have enough Scientific Research for ${research.name}`);
|
||||
division.sciResearch -= research.cost;
|
||||
division.researchPoints -= research.cost;
|
||||
|
||||
// Get the Node from the Research Tree and set its 'researched' property
|
||||
researchTree.research(researchName);
|
||||
division.researched[researchName] = true;
|
||||
division.researched.add(researchName);
|
||||
|
||||
// I couldn't figure out where else to put this so that warehouse size would get updated instantly
|
||||
// whether research is done by script or UI. All other stats gets calculated in every cycle
|
||||
// Warehouse size gets updated only when something increases it.
|
||||
if (researchName == "Drones - Transport") {
|
||||
for (const city of Object.values(CityName)) {
|
||||
const warehouse = division.warehouses[city];
|
||||
if (!warehouse) continue;
|
||||
|
||||
if (Player.corporation) {
|
||||
// Stores cycles in a "buffer". Processed separately using Engine Counters
|
||||
warehouse.updateSize(Player.corporation, division);
|
||||
}
|
||||
for (const warehouse of getRecordValues(division.warehouses)) {
|
||||
warehouse.updateSize(corp, division);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -503,7 +451,7 @@ export function ExportMaterial(
|
||||
cityName: CityName,
|
||||
material: Material,
|
||||
amt: string,
|
||||
division?: Industry,
|
||||
division?: Division,
|
||||
): void {
|
||||
// Sanitize amt
|
||||
let sanitizedAmt = amt.replace(/\s+/g, "").toUpperCase();
|
||||
@ -529,36 +477,36 @@ export function ExportMaterial(
|
||||
throw new Error(`You cannot export material: ${material.name} to division: ${divisionName}!`);
|
||||
}
|
||||
|
||||
const exportObj = { ind: divisionName, city: cityName, amt: sanitizedAmt };
|
||||
material.exp.push(exportObj);
|
||||
const exportObj = { division: divisionName, city: cityName, amount: sanitizedAmt };
|
||||
material.exports.push(exportObj);
|
||||
}
|
||||
|
||||
export function CancelExportMaterial(divisionName: string, cityName: string, material: Material, amt: string): void {
|
||||
for (let i = 0; i < material.exp.length; ++i) {
|
||||
if (material.exp[i].ind !== divisionName || material.exp[i].city !== cityName || material.exp[i].amt !== amt)
|
||||
for (let i = 0; i < material.exports.length; ++i) {
|
||||
if (
|
||||
material.exports[i].division !== divisionName ||
|
||||
material.exports[i].city !== cityName ||
|
||||
material.exports[i].amount !== amt
|
||||
)
|
||||
continue;
|
||||
material.exp.splice(i, 1);
|
||||
material.exports.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
export function LimitProductProduction(product: Product, cityName: string, qty: number): void {
|
||||
if (qty < 0 || isNaN(qty)) {
|
||||
product.prdman[cityName][0] = false;
|
||||
product.prdman[cityName][1] = 0;
|
||||
export function LimitProductProduction(product: Product, cityName: CityName, quantity: number): void {
|
||||
if (quantity < 0 || isNaN(quantity)) {
|
||||
product.cityData[cityName].productionLimit = null;
|
||||
} else {
|
||||
product.prdman[cityName][0] = true;
|
||||
product.prdman[cityName][1] = qty;
|
||||
product.cityData[cityName].productionLimit = quantity;
|
||||
}
|
||||
}
|
||||
|
||||
export function LimitMaterialProduction(material: Material, qty: number): void {
|
||||
if (qty < 0 || isNaN(qty)) {
|
||||
material.prdman[0] = false;
|
||||
material.prdman[1] = 0;
|
||||
export function LimitMaterialProduction(material: Material, quantity: number): void {
|
||||
if (quantity < 0 || isNaN(quantity)) {
|
||||
material.productionLimit = null;
|
||||
} else {
|
||||
material.prdman[0] = true;
|
||||
material.prdman[1] = qty;
|
||||
material.productionLimit = quantity;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { CorporationState } from "./CorporationState";
|
||||
import { CorporationUnlockUpgrade, CorporationUnlockUpgrades } from "./data/CorporationUnlockUpgrades";
|
||||
import { CorporationUpgrade, CorporationUpgrades } from "./data/CorporationUpgrades";
|
||||
import { CorpUnlocks } from "./data/CorporationUnlocks";
|
||||
import { CorpUpgrades } from "./data/CorporationUpgrades";
|
||||
import * as corpConstants from "./data/Constants";
|
||||
import { Industry } from "./Industry";
|
||||
import { Division } from "./Division";
|
||||
|
||||
import { BitNodeMultipliers } from "../BitNode/BitNodeMultipliers";
|
||||
import { showLiterature } from "../Literature/LiteratureHelpers";
|
||||
@ -11,9 +11,13 @@ import { Player } from "@player";
|
||||
|
||||
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
||||
import { constructorsForReviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../utils/JSONReviver";
|
||||
import { CityName } from "../Enums";
|
||||
import { CorpStateName } from "@nsdefs";
|
||||
import { calculateUpgradeCost } from "./helpers";
|
||||
import { JSONMap, JSONSet } from "../Types/Jsonable";
|
||||
import { CorpUnlockName, CorpUpgradeName } from "./data/Enums";
|
||||
import { formatMoney } from "../ui/formatNumber";
|
||||
import { isPositiveInteger } from "../types";
|
||||
import { createEnumKeyedRecord, getRecordValues } from "../Types/Record";
|
||||
|
||||
interface IParams {
|
||||
name?: string;
|
||||
@ -23,8 +27,8 @@ interface IParams {
|
||||
export class Corporation {
|
||||
name = "The Corporation";
|
||||
|
||||
//A division/business sector is represented by the object:
|
||||
divisions: Industry[] = [];
|
||||
/** Map keyed by division name */
|
||||
divisions = new JSONMap<string, Division>();
|
||||
maxDivisions = 20 * BitNodeMultipliers.CorporationDivisions;
|
||||
|
||||
//Financial stats
|
||||
@ -44,9 +48,12 @@ export class Corporation {
|
||||
sharePrice = 0;
|
||||
storedCycles = 0;
|
||||
|
||||
unlockUpgrades: number[];
|
||||
upgrades: number[];
|
||||
upgradeMultipliers: number[];
|
||||
unlocks = new JSONSet<CorpUnlockName>();
|
||||
upgrades = createEnumKeyedRecord(CorpUpgradeName, (name) => ({
|
||||
level: 0,
|
||||
// For dreamsense, value is not a multiplier so it starts at 0
|
||||
value: name === CorpUpgradeName.DreamSense ? 0 : 1,
|
||||
}));
|
||||
|
||||
cycleValuation = 0;
|
||||
valuationsList = [0];
|
||||
@ -58,11 +65,6 @@ export class Corporation {
|
||||
|
||||
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);
|
||||
this.seedFunded = params.seedFunded ?? false;
|
||||
}
|
||||
|
||||
@ -93,9 +95,6 @@ export class Corporation {
|
||||
|
||||
this.divisions.forEach((ind) => {
|
||||
ind.resetImports(state);
|
||||
});
|
||||
|
||||
this.divisions.forEach((ind) => {
|
||||
ind.process(marketCycles, state, this);
|
||||
});
|
||||
|
||||
@ -134,8 +133,6 @@ export class Corporation {
|
||||
this.funds = 150e9;
|
||||
}
|
||||
|
||||
// Process dividends
|
||||
this.updateDividendTax();
|
||||
if (this.dividendRate > 0 && cycleProfit > 0) {
|
||||
// Validate input again, just to be safe
|
||||
if (isNaN(this.dividendRate) || this.dividendRate < 0 || this.dividendRate > corpConstants.dividendMaxRate) {
|
||||
@ -157,16 +154,6 @@ export class Corporation {
|
||||
}
|
||||
}
|
||||
|
||||
updateDividendTax(): void {
|
||||
this.dividendTax = 1 - BitNodeMultipliers.CorporationSoftcap + 0.15;
|
||||
if (this.unlockUpgrades[5] === 1) {
|
||||
this.dividendTax -= 0.05;
|
||||
}
|
||||
if (this.unlockUpgrades[6] === 1) {
|
||||
this.dividendTax -= 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
getCycleDividends(): number {
|
||||
const profit = this.revenue - this.expenses;
|
||||
const cycleProfit = profit * corpConstants.secondsPerMarketCycle;
|
||||
@ -186,14 +173,14 @@ export class Corporation {
|
||||
}
|
||||
|
||||
val = this.funds + profit * 85e3;
|
||||
val *= Math.pow(1.1, this.divisions.length);
|
||||
val *= Math.pow(1.1, this.divisions.size);
|
||||
val = Math.max(val, 0);
|
||||
} else {
|
||||
val = 10e9 + Math.max(this.funds, 0) / 3; //Base valuation
|
||||
if (profit > 0) {
|
||||
val += profit * 315e3;
|
||||
}
|
||||
val *= Math.pow(1.1, this.divisions.length);
|
||||
val *= Math.pow(1.1, this.divisions.size);
|
||||
val -= val % 1e6; //Round down to nearest millionth
|
||||
}
|
||||
return val * BitNodeMultipliers.CorporationValuation;
|
||||
@ -293,145 +280,81 @@ export class Corporation {
|
||||
}
|
||||
}
|
||||
|
||||
//One time upgrades that unlock new features
|
||||
unlock(upgrade: CorporationUnlockUpgrade): void {
|
||||
const upgN = upgrade.index,
|
||||
price = upgrade.price;
|
||||
while (this.unlockUpgrades.length <= upgN) {
|
||||
this.unlockUpgrades.push(0);
|
||||
}
|
||||
if (this.funds < price) {
|
||||
dialogBoxCreate("You don't have enough funds to unlock this!");
|
||||
return;
|
||||
}
|
||||
this.unlockUpgrades[upgN] = 1;
|
||||
this.funds = this.funds - price;
|
||||
/** Purchasing a one-time unlock
|
||||
* @returns A string on failure, indicating the reason for failure. */
|
||||
purchaseUnlock(unlockName: CorpUnlockName): string | void {
|
||||
if (this.unlocks.has(unlockName)) return `The corporation has already unlocked ${unlockName}`;
|
||||
const price = CorpUnlocks[unlockName].price;
|
||||
if (this.funds < price) return `Insufficient funds to purchase ${unlockName}, requires ${formatMoney(price)}`;
|
||||
this.funds -= price;
|
||||
this.unlocks.add(unlockName);
|
||||
|
||||
// Apply effects for one-time upgrades
|
||||
this.updateDividendTax();
|
||||
// Apply effects for one-time unlocks
|
||||
if (unlockName === CorpUnlockName.ShadyAccounting) this.dividendTax -= 0.05;
|
||||
if (unlockName === CorpUnlockName.GovernmentPartnership) this.dividendTax -= 0.1;
|
||||
}
|
||||
|
||||
//Levelable upgrades
|
||||
upgrade(upgrade: CorporationUpgrade, amount: number): void {
|
||||
if (amount < 1) amount = 1;
|
||||
const upgN = upgrade.index,
|
||||
upgradeAmt = upgrade.benefit; //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);
|
||||
/** Purchasing a levelable upgrade
|
||||
* @returns A string on failure, indicating the reason for failure. */
|
||||
purchaseUpgrade(upgradeName: CorpUpgradeName, amount = 1): string | void {
|
||||
if (!isPositiveInteger(amount)) {
|
||||
return `Number of upgrade levels purchased must be a positive integer (attempted: ${amount}).`;
|
||||
}
|
||||
const upgrade = CorpUpgrades[upgradeName];
|
||||
const totalCost = calculateUpgradeCost(this, upgrade, amount);
|
||||
if (this.funds < totalCost) {
|
||||
dialogBoxCreate("You don't have enough funds to purchase this!");
|
||||
return;
|
||||
}
|
||||
this.upgrades[upgN] += amount;
|
||||
this.funds = this.funds - totalCost;
|
||||
if (this.funds < totalCost) return `Not enough funds to purchase ${amount} of upgrade ${upgradeName}.`;
|
||||
this.funds -= totalCost;
|
||||
this.upgrades[upgradeName].level += amount;
|
||||
this.upgrades[upgradeName].value += upgrade.benefit;
|
||||
|
||||
//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 (let i = 0; i < this.divisions.length; ++i) {
|
||||
const industry = this.divisions[i];
|
||||
for (const city of Object.keys(industry.warehouses) as CityName[]) {
|
||||
const warehouse = industry.warehouses[city];
|
||||
if (warehouse === 0) continue;
|
||||
if (Object.hasOwn(industry.warehouses, city) && warehouse) {
|
||||
warehouse.updateSize(this, industry);
|
||||
}
|
||||
// Apply effects for upgrades
|
||||
if (upgradeName === CorpUpgradeName.SmartStorage) {
|
||||
for (const division of this.divisions.values()) {
|
||||
for (const warehouse of getRecordValues(division.warehouses)) {
|
||||
warehouse.updateSize(this, division);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getProductionMultiplier(): number {
|
||||
const mult = this.upgradeMultipliers[0];
|
||||
if (isNaN(mult) || mult < 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return mult;
|
||||
}
|
||||
return this.upgrades[CorpUpgradeName.SmartFactories].value;
|
||||
}
|
||||
|
||||
getStorageMultiplier(): number {
|
||||
const mult = this.upgradeMultipliers[1];
|
||||
if (isNaN(mult) || mult < 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return mult;
|
||||
}
|
||||
return this.upgrades[CorpUpgradeName.SmartStorage].value;
|
||||
}
|
||||
|
||||
getDreamSenseGain(): number {
|
||||
const gain = this.upgradeMultipliers[2] - 1;
|
||||
return gain <= 0 ? 0 : gain;
|
||||
return this.upgrades[CorpUpgradeName.DreamSense].value;
|
||||
}
|
||||
|
||||
getAdvertisingMultiplier(): number {
|
||||
const mult = this.upgradeMultipliers[3];
|
||||
if (isNaN(mult) || mult < 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return mult;
|
||||
}
|
||||
return this.upgrades[CorpUpgradeName.WilsonAnalytics].value;
|
||||
}
|
||||
|
||||
getEmployeeCreMultiplier(): number {
|
||||
const mult = this.upgradeMultipliers[4];
|
||||
if (isNaN(mult) || mult < 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return mult;
|
||||
}
|
||||
return this.upgrades[CorpUpgradeName.NuoptimalNootropicInjectorImplants].value;
|
||||
}
|
||||
|
||||
getEmployeeChaMultiplier(): number {
|
||||
const mult = this.upgradeMultipliers[5];
|
||||
if (isNaN(mult) || mult < 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return mult;
|
||||
}
|
||||
getEmployeeChaMult(): number {
|
||||
return this.upgrades[CorpUpgradeName.SpeechProcessorImplants].value;
|
||||
}
|
||||
|
||||
getEmployeeIntMultiplier(): number {
|
||||
const mult = this.upgradeMultipliers[6];
|
||||
if (isNaN(mult) || mult < 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return mult;
|
||||
}
|
||||
getEmployeeIntMult(): number {
|
||||
return this.upgrades[CorpUpgradeName.NeuralAccelerators].value;
|
||||
}
|
||||
|
||||
getEmployeeEffMultiplier(): number {
|
||||
const mult = this.upgradeMultipliers[7];
|
||||
if (isNaN(mult) || mult < 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return mult;
|
||||
}
|
||||
getEmployeeEffMult(): number {
|
||||
return this.upgrades[CorpUpgradeName.FocusWires].value;
|
||||
}
|
||||
|
||||
getSalesMultiplier(): number {
|
||||
const mult = this.upgradeMultipliers[8];
|
||||
if (isNaN(mult) || mult < 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return mult;
|
||||
}
|
||||
getSalesMult(): number {
|
||||
return this.upgrades[CorpUpgradeName.ABCSalesBots].value;
|
||||
}
|
||||
|
||||
getScientificResearchMultiplier(): number {
|
||||
const mult = this.upgradeMultipliers[9];
|
||||
if (isNaN(mult) || mult < 1) {
|
||||
return 1;
|
||||
} else {
|
||||
return mult;
|
||||
}
|
||||
getScientificResearchMult(): number {
|
||||
return this.upgrades[CorpUpgradeName.ProjectInsight].value;
|
||||
}
|
||||
|
||||
// Adds the Corporation Handbook (Starter Guide) to the player's home computer.
|
||||
|
@ -15,14 +15,7 @@ export class CorporationState {
|
||||
|
||||
// Transition to the next state
|
||||
nextState(): void {
|
||||
if (this.state < 0 || this.state >= stateNames.length) {
|
||||
this.state = 0;
|
||||
}
|
||||
|
||||
++this.state;
|
||||
if (this.state >= stateNames.length) {
|
||||
this.state = 0;
|
||||
}
|
||||
this.state = (this.state + 1) % stateNames.length;
|
||||
}
|
||||
|
||||
// Serialize the current object to a JSON save state.
|
||||
|
1111
src/Corporation/Division.ts
Normal file
1111
src/Corporation/Division.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
import { CityName } from "../Enums";
|
||||
|
||||
export interface Export {
|
||||
ind: string;
|
||||
division: string;
|
||||
city: CityName;
|
||||
amt: string;
|
||||
amount: string;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,12 +1,12 @@
|
||||
import React from "react";
|
||||
import { ResearchTree } from "./ResearchTree";
|
||||
import { Corporation } from "./Corporation";
|
||||
import { getBaseResearchTreeCopy, getProductIndustryResearchTreeCopy } from "./data/BaseResearchTree";
|
||||
import { MoneyCost } from "./ui/MoneyCost";
|
||||
import { CorpIndustryData, CorpIndustryName } from "@nsdefs";
|
||||
import { CorpIndustryData } from "@nsdefs";
|
||||
import { IndustryType } from "./data/Enums";
|
||||
import { createFullRecordFromEntries } from "../Types/Record";
|
||||
|
||||
export const IndustriesData: Record<CorpIndustryName, CorpIndustryData> = {
|
||||
export const IndustriesData: Record<IndustryType, CorpIndustryData> = {
|
||||
[IndustryType.Agriculture]: {
|
||||
startingCost: 40e9,
|
||||
description: "Cultivate crops and breed livestock to produce food.",
|
||||
@ -315,9 +315,14 @@ export const IndustryDescriptions = (industry: IndustryType, corp: Corporation)
|
||||
);
|
||||
};
|
||||
|
||||
export const IndustryResearchTrees = {} as Record<IndustryType, ResearchTree>;
|
||||
resetIndustryResearchTrees();
|
||||
|
||||
export const IndustryResearchTrees = createFullRecordFromEntries(
|
||||
Object.values(IndustryType).map((industryType) => {
|
||||
return [
|
||||
industryType,
|
||||
IndustriesData[industryType].product ? getProductIndustryResearchTreeCopy() : getBaseResearchTreeCopy(),
|
||||
];
|
||||
}),
|
||||
);
|
||||
export function resetIndustryResearchTrees() {
|
||||
Object.values(IndustryType).forEach(
|
||||
(ind) =>
|
||||
|
@ -13,52 +13,51 @@ export class Material {
|
||||
name: CorpMaterialName;
|
||||
|
||||
// Amount of material owned
|
||||
qty = 0;
|
||||
stored = 0;
|
||||
|
||||
// Material's "quality". Unbounded
|
||||
qlt = 1;
|
||||
quality = 1;
|
||||
|
||||
// How much demand the Material has in the market, and the range of possible
|
||||
// values for this "demand"
|
||||
dmd = 0;
|
||||
dmdR: number[] = [0, 0];
|
||||
demand = 0;
|
||||
demandRange: number[] = [0, 0];
|
||||
|
||||
// How much competition there is for this Material in the market, and the range
|
||||
// of possible values for this "competition"
|
||||
cmp = 0;
|
||||
cmpR: number[] = [0, 0];
|
||||
competition = 0;
|
||||
competitionRange: number[] = [0, 0];
|
||||
|
||||
// Maximum volatility of this Materials stats
|
||||
mv = 0;
|
||||
maxVolatility = 0;
|
||||
|
||||
// Markup. Determines how high of a price you can charge on the material
|
||||
// compared to the market price without suffering loss in # of sales
|
||||
// Quality is divided by this to determine markup limits
|
||||
// e,g, If mku is 10 and quality is 100 then you can markup prices by 100/10 = 10
|
||||
mku = 0;
|
||||
markup = 0;
|
||||
|
||||
// How much of this material is being bought, sold, imported and produced every second
|
||||
buy = 0;
|
||||
sll = 0;
|
||||
prd = 0;
|
||||
imp = 0;
|
||||
buyAmount = 0;
|
||||
actualSellAmount = 0;
|
||||
productionAmount = 0;
|
||||
importAmount = 0;
|
||||
|
||||
// Exports of this material to another warehouse/industry
|
||||
exp: Export[] = [];
|
||||
exports: Export[] = [];
|
||||
|
||||
// Total amount of this material exported in the last cycle
|
||||
totalExp = 0;
|
||||
exportedLastCycle = 0;
|
||||
|
||||
// Cost / sec to buy this material. AKA Market Price
|
||||
bCost = 0;
|
||||
marketPrice = 0;
|
||||
|
||||
// Cost / sec to sell this material
|
||||
sCost: string | number = 0;
|
||||
/** null if there is no limit set on production. 0 actually limits production to 0. */
|
||||
productionLimit: number | null = null;
|
||||
|
||||
// Flags to keep track of whether production and/or sale of this material is limited
|
||||
// [Whether production/sale is limited, limit amount]
|
||||
prdman: [boolean, number] = [false, 0]; // Production
|
||||
sllman: [boolean, string | number] = [false, 0]; // Sale
|
||||
// Player inputs for sell price and amount.
|
||||
desiredSellAmount: string | number = 0;
|
||||
desiredSellPrice: string | number = 0;
|
||||
|
||||
// Flags that signal whether automatic sale pricing through Market TA is enabled
|
||||
marketTa1 = false;
|
||||
@ -66,62 +65,62 @@ export class Material {
|
||||
marketTa2Price = 0;
|
||||
|
||||
// Determines the maximum amount of this material that can be sold in one market cycle
|
||||
maxsll = 0;
|
||||
maxSellPerCycle = 0;
|
||||
|
||||
constructor(params?: IConstructorParams) {
|
||||
this.name = params?.name ?? materialNames[0];
|
||||
this.dmd = MaterialInfo[this.name].demandBase;
|
||||
this.dmdR = MaterialInfo[this.name].demandRange;
|
||||
this.cmp = MaterialInfo[this.name].competitionBase;
|
||||
this.cmpR = MaterialInfo[this.name].competitionRange;
|
||||
this.bCost = MaterialInfo[this.name].baseCost;
|
||||
this.mv = MaterialInfo[this.name].maxVolatility;
|
||||
this.mku = MaterialInfo[this.name].baseMarkup;
|
||||
this.demand = MaterialInfo[this.name].demandBase;
|
||||
this.demandRange = MaterialInfo[this.name].demandRange;
|
||||
this.competition = MaterialInfo[this.name].competitionBase;
|
||||
this.competitionRange = MaterialInfo[this.name].competitionRange;
|
||||
this.marketPrice = MaterialInfo[this.name].baseCost;
|
||||
this.maxVolatility = MaterialInfo[this.name].maxVolatility;
|
||||
this.markup = MaterialInfo[this.name].baseMarkup;
|
||||
}
|
||||
|
||||
getMarkupLimit(): number {
|
||||
return this.qlt / this.mku;
|
||||
return this.quality / this.markup;
|
||||
}
|
||||
|
||||
// Process change in demand, competition, and buy cost of this material
|
||||
processMarket(): void {
|
||||
// The price will change in accordance with demand and competition.
|
||||
// e.g. If demand goes up, then so does price. If competition goes up, price goes down
|
||||
const priceVolatility: number = (Math.random() * this.mv) / 300;
|
||||
const priceVolatility: number = (Math.random() * this.maxVolatility) / 300;
|
||||
const priceChange: number = 1 + priceVolatility;
|
||||
|
||||
//This 1st random check determines whether competition increases or decreases
|
||||
const compVolatility: number = (Math.random() * this.mv) / 100;
|
||||
const compVolatility: number = (Math.random() * this.maxVolatility) / 100;
|
||||
const compChange: number = 1 + compVolatility;
|
||||
if (Math.random() < 0.5) {
|
||||
this.cmp *= compChange;
|
||||
if (this.cmp > this.cmpR[1]) {
|
||||
this.cmp = this.cmpR[1];
|
||||
this.competition *= compChange;
|
||||
if (this.competition > this.competitionRange[1]) {
|
||||
this.competition = this.competitionRange[1];
|
||||
}
|
||||
this.bCost *= 1 / priceChange; // Competition increases, so price goes down
|
||||
this.marketPrice *= 1 / priceChange; // Competition increases, so price goes down
|
||||
} else {
|
||||
this.cmp *= 1 / compChange;
|
||||
if (this.cmp < this.cmpR[0]) {
|
||||
this.cmp = this.cmpR[0];
|
||||
this.competition *= 1 / compChange;
|
||||
if (this.competition < this.competitionRange[0]) {
|
||||
this.competition = this.competitionRange[0];
|
||||
}
|
||||
this.bCost *= priceChange; // Competition decreases, so price goes up
|
||||
this.marketPrice *= priceChange; // Competition decreases, so price goes up
|
||||
}
|
||||
|
||||
// This 2nd random check determines whether demand increases or decreases
|
||||
const dmdVolatility: number = (Math.random() * this.mv) / 100;
|
||||
const dmdVolatility: number = (Math.random() * this.maxVolatility) / 100;
|
||||
const dmdChange: number = 1 + dmdVolatility;
|
||||
if (Math.random() < 0.5) {
|
||||
this.dmd *= dmdChange;
|
||||
if (this.dmd > this.dmdR[1]) {
|
||||
this.dmd = this.dmdR[1];
|
||||
this.demand *= dmdChange;
|
||||
if (this.demand > this.demandRange[1]) {
|
||||
this.demand = this.demandRange[1];
|
||||
}
|
||||
this.bCost *= priceChange; // Demand increases, so price goes up
|
||||
this.marketPrice *= priceChange; // Demand increases, so price goes up
|
||||
} else {
|
||||
this.dmd *= 1 / dmdChange;
|
||||
if (this.dmd < this.dmdR[0]) {
|
||||
this.dmd = this.dmdR[0];
|
||||
this.demand *= 1 / dmdChange;
|
||||
if (this.demand < this.demandRange[0]) {
|
||||
this.demand = this.demandRange[0];
|
||||
}
|
||||
this.bCost *= 1 / priceChange;
|
||||
this.marketPrice *= 1 / priceChange;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,33 +1,34 @@
|
||||
import { EmployeePositions } from "./data/Enums";
|
||||
import { CorpEmployeeJob } from "./data/Enums";
|
||||
import * as corpConstants from "./data/Constants";
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, constructorsForReviver } from "../utils/JSONReviver";
|
||||
import { Industry } from "./Industry";
|
||||
import { Division } from "./Division";
|
||||
import { Corporation } from "./Corporation";
|
||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||
import { CityName } from "../Enums";
|
||||
import { createEnumKeyedRecord, getRecordKeys } from "../Types/Record";
|
||||
|
||||
interface IParams {
|
||||
loc?: CityName;
|
||||
size?: number;
|
||||
city: CityName;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export class OfficeSpace {
|
||||
loc: CityName;
|
||||
size: number;
|
||||
city = CityName.Sector12;
|
||||
size = 1;
|
||||
|
||||
maxEne = 100;
|
||||
maxMor = 100;
|
||||
maxEnergy = 100;
|
||||
maxMorale = 100;
|
||||
|
||||
avgEne = 75;
|
||||
avgMor = 75;
|
||||
avgEnergy = 75;
|
||||
avgMorale = 75;
|
||||
|
||||
avgInt = 75;
|
||||
avgCha = 75;
|
||||
totalExp = 0;
|
||||
avgCre = 75;
|
||||
avgEff = 75;
|
||||
avgIntelligence = 75;
|
||||
avgCharisma = 75;
|
||||
avgCreativity = 75;
|
||||
avgEfficiency = 75;
|
||||
|
||||
totalEmployees = 0;
|
||||
totalExperience = 0;
|
||||
numEmployees = 0;
|
||||
totalSalary = 0;
|
||||
|
||||
autoTea = false;
|
||||
@ -35,73 +36,49 @@ export class OfficeSpace {
|
||||
teaPending = false;
|
||||
partyMult = 1;
|
||||
|
||||
employeeProd: Record<EmployeePositions | "total", number> = {
|
||||
[EmployeePositions.Operations]: 0,
|
||||
[EmployeePositions.Engineer]: 0,
|
||||
[EmployeePositions.Business]: 0,
|
||||
[EmployeePositions.Management]: 0,
|
||||
[EmployeePositions.RandD]: 0,
|
||||
[EmployeePositions.Intern]: 0,
|
||||
[EmployeePositions.Unassigned]: 0,
|
||||
total: 0,
|
||||
};
|
||||
employeeJobs: Record<EmployeePositions, number> = {
|
||||
[EmployeePositions.Operations]: 0,
|
||||
[EmployeePositions.Engineer]: 0,
|
||||
[EmployeePositions.Business]: 0,
|
||||
[EmployeePositions.Management]: 0,
|
||||
[EmployeePositions.RandD]: 0,
|
||||
[EmployeePositions.Intern]: 0,
|
||||
[EmployeePositions.Unassigned]: 0,
|
||||
};
|
||||
employeeNextJobs: Record<EmployeePositions, number> = {
|
||||
[EmployeePositions.Operations]: 0,
|
||||
[EmployeePositions.Engineer]: 0,
|
||||
[EmployeePositions.Business]: 0,
|
||||
[EmployeePositions.Management]: 0,
|
||||
[EmployeePositions.RandD]: 0,
|
||||
[EmployeePositions.Intern]: 0,
|
||||
[EmployeePositions.Unassigned]: 0,
|
||||
};
|
||||
employeeProductionByJob = { total: 0, ...createEnumKeyedRecord(CorpEmployeeJob, () => 0) };
|
||||
employeeJobs = createEnumKeyedRecord(CorpEmployeeJob, () => 0);
|
||||
employeeNextJobs = createEnumKeyedRecord(CorpEmployeeJob, () => 0);
|
||||
|
||||
constructor(params: IParams = {}) {
|
||||
this.loc = params.loc ? params.loc : CityName.Sector12;
|
||||
this.size = params.size ? params.size : 1;
|
||||
constructor(params: IParams | null = null) {
|
||||
if (!params) return;
|
||||
this.city = params.city;
|
||||
this.size = params.size;
|
||||
}
|
||||
|
||||
atCapacity(): boolean {
|
||||
return this.totalEmployees >= this.size;
|
||||
return this.numEmployees >= this.size;
|
||||
}
|
||||
|
||||
process(marketCycles = 1, corporation: Corporation, industry: Industry): number {
|
||||
process(marketCycles = 1, corporation: Corporation, industry: Division): number {
|
||||
// HRBuddy AutoRecruitment and Interning
|
||||
if (industry.hasResearch("HRBuddy-Recruitment") && !this.atCapacity()) {
|
||||
this.hireRandomEmployee(
|
||||
industry.hasResearch("HRBuddy-Training") ? EmployeePositions.Intern : EmployeePositions.Unassigned,
|
||||
industry.hasResearch("HRBuddy-Training") ? CorpEmployeeJob.Intern : CorpEmployeeJob.Unassigned,
|
||||
);
|
||||
}
|
||||
|
||||
// Update employee jobs and job counts
|
||||
for (const [pos, jobCount] of Object.entries(this.employeeNextJobs) as [EmployeePositions, number][]) {
|
||||
for (const [pos, jobCount] of Object.entries(this.employeeNextJobs) as [CorpEmployeeJob, number][]) {
|
||||
this.employeeJobs[pos] = jobCount;
|
||||
}
|
||||
|
||||
// Process Office properties
|
||||
this.maxEne = 100;
|
||||
this.maxMor = 100;
|
||||
this.maxEnergy = 100;
|
||||
this.maxMorale = 100;
|
||||
|
||||
if (industry.hasResearch("Go-Juice")) this.maxEne += 10;
|
||||
if (industry.hasResearch("Sti.mu")) this.maxMor += 10;
|
||||
if (industry.hasResearch("Go-Juice")) this.maxEnergy += 10;
|
||||
if (industry.hasResearch("Sti.mu")) this.maxMorale += 10;
|
||||
if (industry.hasResearch("AutoBrew")) this.autoTea = true;
|
||||
if (industry.hasResearch("AutoPartyManager")) this.autoParty = true;
|
||||
|
||||
if (this.totalEmployees > 0) {
|
||||
if (this.numEmployees > 0) {
|
||||
/** Multiplier for employee morale/energy based on company performance */
|
||||
let perfMult = 1.002;
|
||||
if (this.totalEmployees >= 9) {
|
||||
if (this.numEmployees >= 9) {
|
||||
perfMult = Math.pow(
|
||||
1 +
|
||||
0.002 * Math.min(1 / 9, this.employeeJobs.Intern / this.totalEmployees - 1 / 9) * 9 -
|
||||
0.002 * Math.min(1 / 9, this.employeeJobs.Intern / this.numEmployees - 1 / 9) * 9 -
|
||||
(corporation.funds < 0 && industry.lastCycleRevenue < industry.lastCycleExpenses ? 0.001 : 0),
|
||||
marketCycles,
|
||||
);
|
||||
@ -111,121 +88,125 @@ export class OfficeSpace {
|
||||
const reduction = 0.002 * marketCycles;
|
||||
|
||||
if (this.autoTea) {
|
||||
this.avgEne = this.maxEne;
|
||||
this.avgEnergy = this.maxEnergy;
|
||||
} else {
|
||||
// Tea gives a flat +2 to energy
|
||||
this.avgEne = (this.avgEne - reduction * Math.random()) * perfMult + (this.teaPending ? 2 : 0);
|
||||
this.avgEnergy = (this.avgEnergy - reduction * Math.random()) * perfMult + (this.teaPending ? 2 : 0);
|
||||
}
|
||||
|
||||
if (this.autoParty) {
|
||||
this.avgMor = this.maxMor;
|
||||
this.avgMorale = this.maxMorale;
|
||||
} else {
|
||||
// Each 5% multiplier gives an extra flat +1 to morale to make recovering from low morale easier.
|
||||
const increase = this.partyMult > 1 ? (this.partyMult - 1) * 10 : 0;
|
||||
this.avgMor = ((this.avgMor - reduction * Math.random()) * perfMult + increase) * this.partyMult;
|
||||
this.avgMorale = ((this.avgMorale - reduction * Math.random()) * perfMult + increase) * this.partyMult;
|
||||
}
|
||||
|
||||
this.avgEne = Math.max(Math.min(this.avgEne, this.maxEne), corpConstants.minEmployeeDecay);
|
||||
this.avgMor = Math.max(Math.min(this.avgMor, this.maxMor), corpConstants.minEmployeeDecay);
|
||||
this.avgEnergy = Math.max(Math.min(this.avgEnergy, this.maxEnergy), corpConstants.minEmployeeDecay);
|
||||
this.avgMorale = Math.max(Math.min(this.avgMorale, this.maxMorale), corpConstants.minEmployeeDecay);
|
||||
|
||||
this.teaPending = false;
|
||||
this.partyMult = 1;
|
||||
}
|
||||
|
||||
// Get experience increase; unassigned employees do not contribute, interning employees contribute 10x
|
||||
this.totalExp +=
|
||||
this.totalExperience +=
|
||||
0.0015 *
|
||||
marketCycles *
|
||||
(this.totalEmployees -
|
||||
this.employeeJobs[EmployeePositions.Unassigned] +
|
||||
this.employeeJobs[EmployeePositions.Intern] * 9);
|
||||
(this.numEmployees -
|
||||
this.employeeJobs[CorpEmployeeJob.Unassigned] +
|
||||
this.employeeJobs[CorpEmployeeJob.Intern] * 9);
|
||||
|
||||
this.calculateEmployeeProductivity(corporation, industry);
|
||||
if (this.totalEmployees === 0) {
|
||||
if (this.numEmployees === 0) {
|
||||
this.totalSalary = 0;
|
||||
} else {
|
||||
this.totalSalary =
|
||||
corpConstants.employeeSalaryMultiplier *
|
||||
marketCycles *
|
||||
this.totalEmployees *
|
||||
(this.avgInt + this.avgCha + this.totalExp / this.totalEmployees + this.avgCre + this.avgEff);
|
||||
this.numEmployees *
|
||||
(this.avgIntelligence +
|
||||
this.avgCharisma +
|
||||
this.totalExperience / this.numEmployees +
|
||||
this.avgCreativity +
|
||||
this.avgEfficiency);
|
||||
}
|
||||
return this.totalSalary;
|
||||
}
|
||||
|
||||
calculateEmployeeProductivity(corporation: Corporation, industry: Industry): void {
|
||||
const effCre = this.avgCre * corporation.getEmployeeCreMultiplier() * industry.getEmployeeCreMultiplier(),
|
||||
effCha = this.avgCha * corporation.getEmployeeChaMultiplier() * industry.getEmployeeChaMultiplier(),
|
||||
effInt = this.avgInt * corporation.getEmployeeIntMultiplier() * industry.getEmployeeIntMultiplier(),
|
||||
effEff = this.avgEff * corporation.getEmployeeEffMultiplier() * industry.getEmployeeEffMultiplier();
|
||||
const prodBase = this.avgMor * this.avgEne * 1e-4;
|
||||
calculateEmployeeProductivity(corporation: Corporation, industry: Division): void {
|
||||
const effCre = this.avgCreativity * corporation.getEmployeeCreMultiplier() * industry.getEmployeeCreMultiplier(),
|
||||
effCha = this.avgCharisma * corporation.getEmployeeChaMult() * industry.getEmployeeChaMultiplier(),
|
||||
effInt = this.avgIntelligence * corporation.getEmployeeIntMult() * industry.getEmployeeIntMultiplier(),
|
||||
effEff = this.avgEfficiency * corporation.getEmployeeEffMult() * industry.getEmployeeEffMultiplier();
|
||||
const prodBase = this.avgMorale * this.avgEnergy * 1e-4;
|
||||
|
||||
let total = 0;
|
||||
const exp = this.totalExp / this.totalEmployees || 0;
|
||||
for (const name of Object.keys(this.employeeProd) as (EmployeePositions | "total")[]) {
|
||||
const exp = this.totalExperience / this.numEmployees || 0;
|
||||
for (const name of getRecordKeys(this.employeeProductionByJob)) {
|
||||
let prodMult = 0;
|
||||
switch (name) {
|
||||
case EmployeePositions.Operations:
|
||||
case CorpEmployeeJob.Operations:
|
||||
prodMult = 0.6 * effInt + 0.1 * effCha + exp + 0.5 * effCre + effEff;
|
||||
break;
|
||||
case EmployeePositions.Engineer:
|
||||
case CorpEmployeeJob.Engineer:
|
||||
prodMult = effInt + 0.1 * effCha + 1.5 * exp + effEff;
|
||||
break;
|
||||
case EmployeePositions.Business:
|
||||
case CorpEmployeeJob.Business:
|
||||
prodMult = 0.4 * effInt + effCha + 0.5 * exp;
|
||||
break;
|
||||
case EmployeePositions.Management:
|
||||
case CorpEmployeeJob.Management:
|
||||
prodMult = 2 * effCha + exp + 0.2 * effCre + 0.7 * effEff;
|
||||
break;
|
||||
case EmployeePositions.RandD:
|
||||
case CorpEmployeeJob.RandD:
|
||||
prodMult = 1.5 * effInt + 0.8 * exp + effCre + 0.5 * effEff;
|
||||
break;
|
||||
case EmployeePositions.Unassigned:
|
||||
case EmployeePositions.Intern:
|
||||
case CorpEmployeeJob.Unassigned:
|
||||
case CorpEmployeeJob.Intern:
|
||||
case "total":
|
||||
continue;
|
||||
default:
|
||||
console.error(`Invalid employee position: ${name}`);
|
||||
break;
|
||||
}
|
||||
this.employeeProd[name] = this.employeeJobs[name] * prodMult * prodBase;
|
||||
total += this.employeeProd[name];
|
||||
this.employeeProductionByJob[name] = this.employeeJobs[name] * prodMult * prodBase;
|
||||
total += this.employeeProductionByJob[name];
|
||||
}
|
||||
|
||||
this.employeeProd.total = total;
|
||||
this.employeeProductionByJob.total = total;
|
||||
}
|
||||
|
||||
hireRandomEmployee(position: EmployeePositions): boolean {
|
||||
hireRandomEmployee(position: CorpEmployeeJob): boolean {
|
||||
if (this.atCapacity()) return false;
|
||||
if (document.getElementById("cmpy-mgmt-hire-employee-popup") != null) return false;
|
||||
|
||||
++this.totalEmployees;
|
||||
++this.numEmployees;
|
||||
++this.employeeJobs[position];
|
||||
++this.employeeNextJobs[position];
|
||||
|
||||
this.totalExp += getRandomInt(50, 100);
|
||||
this.totalExperience += getRandomInt(50, 100);
|
||||
|
||||
this.avgMor = (this.avgMor * this.totalEmployees + getRandomInt(50, 100)) / (this.totalEmployees + 1);
|
||||
this.avgEne = (this.avgEne * this.totalEmployees + getRandomInt(50, 100)) / (this.totalEmployees + 1);
|
||||
this.avgMorale = (this.avgMorale * this.numEmployees + getRandomInt(50, 100)) / (this.numEmployees + 1);
|
||||
this.avgEnergy = (this.avgEnergy * this.numEmployees + getRandomInt(50, 100)) / (this.numEmployees + 1);
|
||||
|
||||
this.avgInt = (this.avgInt * this.totalEmployees + getRandomInt(50, 100)) / (this.totalEmployees + 1);
|
||||
this.avgCha = (this.avgCha * this.totalEmployees + getRandomInt(50, 100)) / (this.totalEmployees + 1);
|
||||
this.avgCre = (this.avgCre * this.totalEmployees + getRandomInt(50, 100)) / (this.totalEmployees + 1);
|
||||
this.avgEff = (this.avgEff * this.totalEmployees + getRandomInt(50, 100)) / (this.totalEmployees + 1);
|
||||
this.avgIntelligence = (this.avgIntelligence * this.numEmployees + getRandomInt(50, 100)) / (this.numEmployees + 1);
|
||||
this.avgCharisma = (this.avgCharisma * this.numEmployees + getRandomInt(50, 100)) / (this.numEmployees + 1);
|
||||
this.avgCreativity = (this.avgCreativity * this.numEmployees + getRandomInt(50, 100)) / (this.numEmployees + 1);
|
||||
this.avgEfficiency = (this.avgEfficiency * this.numEmployees + getRandomInt(50, 100)) / (this.numEmployees + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
autoAssignJob(job: EmployeePositions, target: number): boolean {
|
||||
if (job === EmployeePositions.Unassigned) {
|
||||
autoAssignJob(job: CorpEmployeeJob, target: number): boolean {
|
||||
if (job === CorpEmployeeJob.Unassigned) {
|
||||
throw new Error("internal autoAssignJob function called with EmployeePositions.Unassigned");
|
||||
}
|
||||
const diff = target - this.employeeNextJobs[job];
|
||||
|
||||
if (diff === 0) return true;
|
||||
// We are already at the desired number
|
||||
else if (diff <= this.employeeNextJobs[EmployeePositions.Unassigned]) {
|
||||
else if (diff <= this.employeeNextJobs[CorpEmployeeJob.Unassigned]) {
|
||||
// This covers both a negative diff (reducing the amount of employees in position) and a positive (increasing and using up unassigned employees)
|
||||
this.employeeNextJobs[EmployeePositions.Unassigned] -= diff;
|
||||
this.employeeNextJobs[CorpEmployeeJob.Unassigned] -= diff;
|
||||
this.employeeNextJobs[job] = target;
|
||||
return true;
|
||||
}
|
||||
@ -233,11 +214,11 @@ export class OfficeSpace {
|
||||
}
|
||||
|
||||
getTeaCost(): number {
|
||||
return corpConstants.teaCostPerEmployee * this.totalEmployees;
|
||||
return corpConstants.teaCostPerEmployee * this.numEmployees;
|
||||
}
|
||||
|
||||
setTea(): boolean {
|
||||
if (!this.teaPending && !this.autoTea && this.totalEmployees > 0) {
|
||||
if (!this.teaPending && !this.autoTea && this.numEmployees > 0) {
|
||||
this.teaPending = true;
|
||||
return true;
|
||||
}
|
||||
@ -245,7 +226,7 @@ export class OfficeSpace {
|
||||
}
|
||||
|
||||
setParty(mult: number): boolean {
|
||||
if (mult > 1 && this.partyMult === 1 && !this.autoParty && this.totalEmployees > 0) {
|
||||
if (mult > 1 && this.partyMult === 1 && !this.autoParty && this.numEmployees > 0) {
|
||||
this.partyMult = mult;
|
||||
return true;
|
||||
}
|
||||
@ -262,10 +243,10 @@ export class OfficeSpace {
|
||||
const empCopy: [{ data: { mor: number; ene: number; exp: number } }] = value.data.employees;
|
||||
delete value.data.employees;
|
||||
const ret = Generic_fromJSON(OfficeSpace, value.data);
|
||||
ret.totalEmployees = empCopy.length;
|
||||
ret.avgMor = empCopy.reduce((a, b) => a + b.data.mor, 0) / ret.totalEmployees || 75;
|
||||
ret.avgEne = empCopy.reduce((a, b) => a + b.data.ene, 0) / ret.totalEmployees || 75;
|
||||
ret.totalExp = empCopy.reduce((a, b) => a + b.data.exp, 0);
|
||||
ret.numEmployees = empCopy.length;
|
||||
ret.avgMorale = empCopy.reduce((a, b) => a + b.data.mor, 0) / ret.numEmployees || 75;
|
||||
ret.avgEnergy = empCopy.reduce((a, b) => a + b.data.ene, 0) / ret.numEmployees || 75;
|
||||
ret.totalExperience = empCopy.reduce((a, b) => a + b.data.exp, 0);
|
||||
return ret;
|
||||
}
|
||||
return Generic_fromJSON(OfficeSpace, value.data);
|
||||
|
@ -1,144 +1,119 @@
|
||||
import { EmployeePositions } from "./data/Enums";
|
||||
import { CorpEmployeeJob } from "./data/Enums";
|
||||
import { MaterialInfo } from "./MaterialInfo";
|
||||
import { Industry } from "./Industry";
|
||||
import { Division } from "./Division";
|
||||
import { IndustriesData } from "./IndustryData";
|
||||
|
||||
import { createCityMap } from "../Locations/createCityMap";
|
||||
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, constructorsForReviver } from "../utils/JSONReviver";
|
||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||
import { CityName } from "../Enums";
|
||||
import { materialNames } from "./data/Constants";
|
||||
import { CorpMaterialName } from "@nsdefs";
|
||||
import { PartialRecord, createEnumKeyedRecord, getRecordEntries, getRecordKeys } from "../Types/Record";
|
||||
|
||||
interface IConstructorParams {
|
||||
name?: string;
|
||||
demand?: number;
|
||||
competition?: number;
|
||||
markup?: number;
|
||||
createCity?: CityName;
|
||||
designCost?: number;
|
||||
advCost?: number;
|
||||
quality?: number;
|
||||
performance?: number;
|
||||
durability?: number;
|
||||
reliability?: number;
|
||||
aesthetics?: number;
|
||||
features?: number;
|
||||
loc?: string;
|
||||
size?: number;
|
||||
req?: Partial<Record<CorpMaterialName, number>>;
|
||||
name: string;
|
||||
createCity: CityName;
|
||||
designInvestment: number;
|
||||
advertisingInvestment: number;
|
||||
}
|
||||
|
||||
/** A corporation product. Products are shared across the entire division, unlike materials which are per-warehouse */
|
||||
export class Product {
|
||||
// Product name
|
||||
name = "";
|
||||
/** Name of the product */
|
||||
name = "DefaultProductName";
|
||||
|
||||
// The demand for this Product in the market. Gradually decreases
|
||||
dmd = 0;
|
||||
/** Demand for this product, which goes down over time. */
|
||||
demand = 0;
|
||||
|
||||
// How much competition there is in the market for this Product
|
||||
cmp = 0;
|
||||
/** Competition for this product */
|
||||
competition = 0;
|
||||
|
||||
// Markup. Affects how high of a price you can charge for this Product
|
||||
// without suffering a loss in the # of sales
|
||||
mku = 0;
|
||||
/** Markup. Affects how high of a price you can charge for this Product
|
||||
without suffering a loss in the # of sales */
|
||||
markup = 0;
|
||||
|
||||
// Production cost - estimation of how much money it costs to make this Product
|
||||
pCost = 0;
|
||||
/** Cost of producing this product if buying its component materials at market price */
|
||||
productionCost = 0;
|
||||
|
||||
// Sell costs
|
||||
sCost: Record<string, any> = createCityMap<any>(0);
|
||||
|
||||
// Variables for handling the creation process of this Product
|
||||
fin = false; // Whether this Product has finished being created
|
||||
prog = 0; // Creation progress - A number between 0-100 representing percentage
|
||||
createCity = CityName.Sector12; // City in which the product is/was being created
|
||||
designCost = 0; // How much money was invested into designing this Product
|
||||
advCost = 0; // How much money was invested into advertising this Product
|
||||
/** Whether the development for this product is finished yet */
|
||||
finished = false;
|
||||
developmentProgress = 0; // Creation progress - A number between 0-100 representing percentage
|
||||
creationCity = CityName.Sector12; // City in which the product is/was being created
|
||||
designInvestment = 0; // How much money was invested into designing this Product
|
||||
advertisingInvestment = 0; // How much money was invested into advertising this Product
|
||||
|
||||
// The average employee productivity and scientific research across the creation of the Product
|
||||
creationProd: Record<string, number> = {
|
||||
[EmployeePositions.Operations]: 0,
|
||||
[EmployeePositions.Engineer]: 0,
|
||||
[EmployeePositions.Business]: 0,
|
||||
[EmployeePositions.Management]: 0,
|
||||
[EmployeePositions.RandD]: 0,
|
||||
creationJobFactors = {
|
||||
[CorpEmployeeJob.Operations]: 0,
|
||||
[CorpEmployeeJob.Engineer]: 0,
|
||||
[CorpEmployeeJob.Business]: 0,
|
||||
[CorpEmployeeJob.Management]: 0,
|
||||
[CorpEmployeeJob.RandD]: 0,
|
||||
total: 0,
|
||||
};
|
||||
|
||||
// Aggregate score for this Product's 'rating'
|
||||
// This is based on the stats/properties below. The weighting of the
|
||||
// stats/properties below differs between different industries
|
||||
rat = 0;
|
||||
rating = 0;
|
||||
|
||||
// Stats/properties of this Product
|
||||
qlt = 0;
|
||||
per = 0;
|
||||
dur = 0;
|
||||
rel = 0;
|
||||
aes = 0;
|
||||
fea = 0;
|
||||
/** Stats of the product */
|
||||
stats = {
|
||||
quality: 0,
|
||||
performance: 0,
|
||||
durability: 0,
|
||||
reliability: 0,
|
||||
aesthetics: 0,
|
||||
features: 0,
|
||||
};
|
||||
|
||||
// Data refers to the production, sale, and quantity of the products
|
||||
// These values are specific to a city
|
||||
// For each city, the data is [qty, prod, sell, effRat]
|
||||
data: Record<string, number[]> = createCityMap<number[]>([0, 0, 0, 0]);
|
||||
// data that is stored per city
|
||||
cityData = createEnumKeyedRecord(CityName, () => ({
|
||||
/** Amount of product stored in warehouse */
|
||||
stored: 0,
|
||||
/** Amount of this product produced per cycle in this city */
|
||||
productionAmount: 0,
|
||||
/** Amount of this product that was sold last cycle in this city */
|
||||
actualSellAmount: 0,
|
||||
/** Total effective rating of the product in this city */
|
||||
effectiveRating: 0,
|
||||
/** Manual limit on production amount for the product in this city*/
|
||||
productionLimit: null as number | null,
|
||||
/** Player input sell amount e.g. "MAX" */
|
||||
desiredSellAmount: 0 as number | string,
|
||||
/** Player input sell price e.g. "MP * 5" */
|
||||
desiredSellPrice: 0 as number | string,
|
||||
}));
|
||||
|
||||
// Location of this Product
|
||||
// Only applies for location-based products like restaurants/hospitals
|
||||
loc = "";
|
||||
/** How much warehouse space is occupied per unit of this product */
|
||||
size = 0;
|
||||
|
||||
// How much space 1 unit of the Product takes (in the warehouse)
|
||||
// Not applicable for all Products
|
||||
siz = 0;
|
||||
|
||||
// Material requirements. An object that maps the name of a material to how much it requires
|
||||
// to make 1 unit of the product.
|
||||
reqMats: Partial<Record<CorpMaterialName, number>> = {};
|
||||
|
||||
// Data to keep track of whether production/sale of this Product is
|
||||
// manually limited. These values are specific to a city
|
||||
// [Whether production/sale is limited, limit amount]
|
||||
prdman: Record<string, any[]> = createCityMap<any[]>([false, 0]);
|
||||
sllman: Record<string, any[]> = createCityMap<any[]>([false, 0]);
|
||||
/** Required materials per unit of this product */
|
||||
requiredMaterials: PartialRecord<CorpMaterialName, number> = {};
|
||||
|
||||
// Flags that signal whether automatic sale pricing through Market TA is enabled
|
||||
marketTa1 = false;
|
||||
marketTa2 = false;
|
||||
marketTa2Price: Record<string, number> = createCityMap<number>(0);
|
||||
marketTa2Price = createEnumKeyedRecord(CityName, () => 0);
|
||||
|
||||
// Determines the maximum amount of this product that can be sold in one market cycle
|
||||
maxsll = 0;
|
||||
constructor(params: IConstructorParams = {}) {
|
||||
this.name = params.name ? params.name : "";
|
||||
this.dmd = params.demand ? params.demand : 0;
|
||||
this.cmp = params.competition ? params.competition : 0;
|
||||
this.mku = params.markup ? params.markup : 0;
|
||||
this.createCity = params.createCity ? params.createCity : CityName.Sector12;
|
||||
this.designCost = params.designCost ? params.designCost : 0;
|
||||
this.advCost = params.advCost ? params.advCost : 0;
|
||||
this.qlt = params.quality ? params.quality : 0;
|
||||
this.per = params.performance ? params.performance : 0;
|
||||
this.dur = params.durability ? params.durability : 0;
|
||||
this.rel = params.reliability ? params.reliability : 0;
|
||||
this.aes = params.aesthetics ? params.aesthetics : 0;
|
||||
this.fea = params.features ? params.features : 0;
|
||||
this.loc = params.loc ? params.loc : "";
|
||||
this.siz = params.size ? params.size : 0;
|
||||
this.reqMats = params.req ? params.req : {};
|
||||
/** Effective number that "MAX" represents in a sell amount */
|
||||
maxSellAmount = 0;
|
||||
|
||||
constructor(params: IConstructorParams | null = null) {
|
||||
if (!params) return;
|
||||
this.name = params.name;
|
||||
this.creationCity = params.createCity;
|
||||
this.designInvestment = params.designInvestment;
|
||||
this.advertisingInvestment = params.advertisingInvestment;
|
||||
}
|
||||
|
||||
// Make progress on this product based on current employee productivity
|
||||
createProduct(marketCycles: number, employeeProd: typeof this.creationProd): void {
|
||||
if (this.fin) {
|
||||
return;
|
||||
}
|
||||
createProduct(marketCycles: number, employeeProd: typeof Product.prototype.creationJobFactors): void {
|
||||
if (this.finished) return;
|
||||
|
||||
// Designing/Creating a Product is based mostly off Engineers
|
||||
const opProd = employeeProd[EmployeePositions.Operations];
|
||||
const engrProd = employeeProd[EmployeePositions.Engineer];
|
||||
const mgmtProd = employeeProd[EmployeePositions.Management];
|
||||
const opProd = employeeProd[CorpEmployeeJob.Operations];
|
||||
const engrProd = employeeProd[CorpEmployeeJob.Engineer];
|
||||
const mgmtProd = employeeProd[CorpEmployeeJob.Management];
|
||||
const total = opProd + engrProd + mgmtProd;
|
||||
if (total <= 0) {
|
||||
return;
|
||||
@ -147,119 +122,104 @@ export class Product {
|
||||
// Management is a multiplier for the production from Engineers
|
||||
const mgmtFactor = 1 + mgmtProd / (1.2 * total);
|
||||
const prodMult = (Math.pow(engrProd, 0.34) + Math.pow(opProd, 0.2)) * mgmtFactor;
|
||||
const progress = Math.min(marketCycles * 0.01 * prodMult, 100 - this.prog);
|
||||
const progress = Math.min(marketCycles * 0.01 * prodMult, 100 - this.developmentProgress);
|
||||
if (progress <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.prog += progress;
|
||||
for (const pos of Object.keys(employeeProd)) {
|
||||
this.creationProd[pos] += (employeeProd[pos] * progress) / 100;
|
||||
this.developmentProgress += progress;
|
||||
for (const pos of getRecordKeys(employeeProd)) {
|
||||
this.creationJobFactors[pos] += (employeeProd[pos] * progress) / 100;
|
||||
}
|
||||
}
|
||||
|
||||
// @param industry - Industry object. Reference to industry that makes this Product
|
||||
finishProduct(industry: Industry): void {
|
||||
this.fin = true;
|
||||
finishProduct(industry: Division): void {
|
||||
this.finished = true;
|
||||
|
||||
// Calculate properties
|
||||
const totalProd = this.creationProd.total;
|
||||
const engrRatio = this.creationProd[EmployeePositions.Engineer] / totalProd;
|
||||
const mgmtRatio = this.creationProd[EmployeePositions.Management] / totalProd;
|
||||
const rndRatio = this.creationProd[EmployeePositions.RandD] / totalProd;
|
||||
const opsRatio = this.creationProd[EmployeePositions.Operations] / totalProd;
|
||||
const busRatio = this.creationProd[EmployeePositions.Business] / totalProd;
|
||||
const totalProd = this.creationJobFactors.total;
|
||||
const engrRatio = this.creationJobFactors[CorpEmployeeJob.Engineer] / totalProd;
|
||||
const mgmtRatio = this.creationJobFactors[CorpEmployeeJob.Management] / totalProd;
|
||||
const rndRatio = this.creationJobFactors[CorpEmployeeJob.RandD] / totalProd;
|
||||
const opsRatio = this.creationJobFactors[CorpEmployeeJob.Operations] / totalProd;
|
||||
const busRatio = this.creationJobFactors[CorpEmployeeJob.Business] / totalProd;
|
||||
|
||||
const designMult = 1 + Math.pow(this.designCost, 0.1) / 100;
|
||||
const designMult = 1 + Math.pow(this.designInvestment, 0.1) / 100;
|
||||
const balanceMult = 1.2 * engrRatio + 0.9 * mgmtRatio + 1.3 * rndRatio + 1.5 * opsRatio + busRatio;
|
||||
const sciMult = 1 + Math.pow(industry.sciResearch, industry.sciFac) / 800;
|
||||
const sciMult = 1 + Math.pow(industry.researchPoints, industry.researchFactor) / 800;
|
||||
const totalMult = balanceMult * designMult * sciMult;
|
||||
|
||||
this.qlt =
|
||||
this.stats.quality =
|
||||
totalMult *
|
||||
(0.1 * this.creationProd[EmployeePositions.Engineer] +
|
||||
0.05 * this.creationProd[EmployeePositions.Management] +
|
||||
0.05 * this.creationProd[EmployeePositions.RandD] +
|
||||
0.02 * this.creationProd[EmployeePositions.Operations] +
|
||||
0.02 * this.creationProd[EmployeePositions.Business]);
|
||||
this.per =
|
||||
(0.1 * this.creationJobFactors[CorpEmployeeJob.Engineer] +
|
||||
0.05 * this.creationJobFactors[CorpEmployeeJob.Management] +
|
||||
0.05 * this.creationJobFactors[CorpEmployeeJob.RandD] +
|
||||
0.02 * this.creationJobFactors[CorpEmployeeJob.Operations] +
|
||||
0.02 * this.creationJobFactors[CorpEmployeeJob.Business]);
|
||||
this.stats.performance =
|
||||
totalMult *
|
||||
(0.15 * this.creationProd[EmployeePositions.Engineer] +
|
||||
0.02 * this.creationProd[EmployeePositions.Management] +
|
||||
0.02 * this.creationProd[EmployeePositions.RandD] +
|
||||
0.02 * this.creationProd[EmployeePositions.Operations] +
|
||||
0.02 * this.creationProd[EmployeePositions.Business]);
|
||||
this.dur =
|
||||
(0.15 * this.creationJobFactors[CorpEmployeeJob.Engineer] +
|
||||
0.02 * this.creationJobFactors[CorpEmployeeJob.Management] +
|
||||
0.02 * this.creationJobFactors[CorpEmployeeJob.RandD] +
|
||||
0.02 * this.creationJobFactors[CorpEmployeeJob.Operations] +
|
||||
0.02 * this.creationJobFactors[CorpEmployeeJob.Business]);
|
||||
this.stats.durability =
|
||||
totalMult *
|
||||
(0.05 * this.creationProd[EmployeePositions.Engineer] +
|
||||
0.02 * this.creationProd[EmployeePositions.Management] +
|
||||
0.08 * this.creationProd[EmployeePositions.RandD] +
|
||||
0.05 * this.creationProd[EmployeePositions.Operations] +
|
||||
0.05 * this.creationProd[EmployeePositions.Business]);
|
||||
this.rel =
|
||||
(0.05 * this.creationJobFactors[CorpEmployeeJob.Engineer] +
|
||||
0.02 * this.creationJobFactors[CorpEmployeeJob.Management] +
|
||||
0.08 * this.creationJobFactors[CorpEmployeeJob.RandD] +
|
||||
0.05 * this.creationJobFactors[CorpEmployeeJob.Operations] +
|
||||
0.05 * this.creationJobFactors[CorpEmployeeJob.Business]);
|
||||
this.stats.reliability =
|
||||
totalMult *
|
||||
(0.02 * this.creationProd[EmployeePositions.Engineer] +
|
||||
0.08 * this.creationProd[EmployeePositions.Management] +
|
||||
0.02 * this.creationProd[EmployeePositions.RandD] +
|
||||
0.05 * this.creationProd[EmployeePositions.Operations] +
|
||||
0.08 * this.creationProd[EmployeePositions.Business]);
|
||||
this.aes =
|
||||
(0.02 * this.creationJobFactors[CorpEmployeeJob.Engineer] +
|
||||
0.08 * this.creationJobFactors[CorpEmployeeJob.Management] +
|
||||
0.02 * this.creationJobFactors[CorpEmployeeJob.RandD] +
|
||||
0.05 * this.creationJobFactors[CorpEmployeeJob.Operations] +
|
||||
0.08 * this.creationJobFactors[CorpEmployeeJob.Business]);
|
||||
this.stats.aesthetics =
|
||||
totalMult *
|
||||
(0.0 * this.creationProd[EmployeePositions.Engineer] +
|
||||
0.08 * this.creationProd[EmployeePositions.Management] +
|
||||
0.05 * this.creationProd[EmployeePositions.RandD] +
|
||||
0.02 * this.creationProd[EmployeePositions.Operations] +
|
||||
0.1 * this.creationProd[EmployeePositions.Business]);
|
||||
this.fea =
|
||||
(0.0 * this.creationJobFactors[CorpEmployeeJob.Engineer] +
|
||||
0.08 * this.creationJobFactors[CorpEmployeeJob.Management] +
|
||||
0.05 * this.creationJobFactors[CorpEmployeeJob.RandD] +
|
||||
0.02 * this.creationJobFactors[CorpEmployeeJob.Operations] +
|
||||
0.1 * this.creationJobFactors[CorpEmployeeJob.Business]);
|
||||
this.stats.features =
|
||||
totalMult *
|
||||
(0.08 * this.creationProd[EmployeePositions.Engineer] +
|
||||
0.05 * this.creationProd[EmployeePositions.Management] +
|
||||
0.02 * this.creationProd[EmployeePositions.RandD] +
|
||||
0.05 * this.creationProd[EmployeePositions.Operations] +
|
||||
0.05 * this.creationProd[EmployeePositions.Business]);
|
||||
(0.08 * this.creationJobFactors[CorpEmployeeJob.Engineer] +
|
||||
0.05 * this.creationJobFactors[CorpEmployeeJob.Management] +
|
||||
0.02 * this.creationJobFactors[CorpEmployeeJob.RandD] +
|
||||
0.05 * this.creationJobFactors[CorpEmployeeJob.Operations] +
|
||||
0.05 * this.creationJobFactors[CorpEmployeeJob.Business]);
|
||||
this.calculateRating(industry);
|
||||
const advMult = 1 + Math.pow(this.advCost, 0.1) / 100;
|
||||
const advMult = 1 + Math.pow(this.advertisingInvestment, 0.1) / 100;
|
||||
const busmgtgRatio = Math.max(busRatio + mgmtRatio, 1 / totalProd);
|
||||
this.mku = 100 / (advMult * Math.pow(this.qlt + 0.001, 0.65) * busmgtgRatio);
|
||||
this.markup = 100 / (advMult * Math.pow(this.stats.quality + 0.001, 0.65) * busmgtgRatio);
|
||||
|
||||
// I actually don't understand well enough to know if this is right.
|
||||
// I'm adding this to prevent a crash.
|
||||
if (this.mku === 0 || !isFinite(this.mku)) this.mku = 1;
|
||||
if (this.markup === 0 || !isFinite(this.markup)) this.markup = 1;
|
||||
|
||||
this.dmd =
|
||||
this.demand =
|
||||
industry.awareness === 0 ? 20 : Math.min(100, advMult * (100 * (industry.popularity / industry.awareness)));
|
||||
this.cmp = getRandomInt(0, 70);
|
||||
this.competition = getRandomInt(0, 70);
|
||||
|
||||
//Calculate the product's required materials
|
||||
//For now, just set it to be the same as the requirements to make materials
|
||||
for (const matName of Object.keys(industry.reqMats) as CorpMaterialName[]) {
|
||||
if (Object.hasOwn(industry.reqMats, matName)) {
|
||||
const reqMat = industry.reqMats[matName];
|
||||
if (reqMat === undefined) continue;
|
||||
this.reqMats[matName] = reqMat;
|
||||
}
|
||||
}
|
||||
|
||||
//Calculate the product's size
|
||||
//For now, just set it to be the same size as the requirements to make materials
|
||||
this.siz = 0;
|
||||
for (const matName of Object.values(materialNames)) {
|
||||
const reqMat = industry.reqMats[matName];
|
||||
if (reqMat === undefined) continue;
|
||||
this.siz += MaterialInfo[matName].size * reqMat;
|
||||
//Calculate the product's required materials and size
|
||||
this.size = 0;
|
||||
for (const [matName, reqQty] of getRecordEntries(industry.requiredMaterials)) {
|
||||
this.requiredMaterials[matName] = reqQty;
|
||||
this.size += MaterialInfo[matName].size * reqQty;
|
||||
}
|
||||
}
|
||||
|
||||
calculateRating(industry: Industry): void {
|
||||
calculateRating(industry: Division): void {
|
||||
const weights = IndustriesData[industry.type].product?.ratingWeights;
|
||||
if (!weights) return console.error(`Could not find product rating weights for: ${industry}`);
|
||||
this.rat = 0;
|
||||
this.rat += weights.quality ? this.qlt * weights.quality : 0;
|
||||
this.rat += weights.performance ? this.per * weights.performance : 0;
|
||||
this.rat += weights.durability ? this.dur * weights.durability : 0;
|
||||
this.rat += weights.reliability ? this.rel * weights.reliability : 0;
|
||||
this.rat += weights.aesthetics ? this.aes * weights.aesthetics : 0;
|
||||
this.rat += weights.features ? this.fea * weights.features : 0;
|
||||
this.rating = getRecordEntries(weights).reduce(
|
||||
(total, [statName, weight]) => total + this.stats[statName] * weight,
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
// Serialize the current object to a JSON save state.
|
||||
@ -269,18 +229,6 @@ export class Product {
|
||||
|
||||
// Initializes a Product object from a JSON save state.
|
||||
static fromJSON(value: IReviverValue): Product {
|
||||
// TODO: Remove all corp graceful loading measures during major corp rebalance / rework.
|
||||
// For that version, Player.corporation will just get reset to null when loading from older version.
|
||||
|
||||
// Gracefully load saves from when RealEstate and AICores didn't have spaces
|
||||
if (value.data.reqMats?.RealEstate) {
|
||||
value.data.reqMats["Real Estate"] = value.data.reqMats.RealEstate;
|
||||
delete value.data.reqMats.RealEstate;
|
||||
}
|
||||
if (value.data.reqMats?.AICores) {
|
||||
value.data.reqMats["AI Cores"] = value.data.reqMats.AICores;
|
||||
delete value.data.reqMats.AICores;
|
||||
}
|
||||
return Generic_fromJSON(Product, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { CorpResearchName } from "@nsdefs";
|
||||
import { researchNames } from "./data/Constants";
|
||||
|
||||
export interface IConstructorParams {
|
||||
export interface ResearchParams {
|
||||
name: CorpResearchName;
|
||||
cost: number;
|
||||
desc: string;
|
||||
@ -19,13 +18,13 @@ export interface IConstructorParams {
|
||||
|
||||
export class Research {
|
||||
// Name of research. This will be used to identify researches in the Research Tree
|
||||
name: CorpResearchName;
|
||||
name: CorpResearchName = "AutoBrew";
|
||||
|
||||
// How much scientific research it costs to unlock this
|
||||
cost = 0;
|
||||
|
||||
// Description of what the Research does
|
||||
desc = "";
|
||||
description = "";
|
||||
|
||||
// All possible generic upgrades for the company, in the form of multipliers
|
||||
advertisingMult = 1;
|
||||
@ -39,39 +38,20 @@ export class Research {
|
||||
sciResearchMult = 1;
|
||||
storageMult = 1;
|
||||
|
||||
constructor(p: IConstructorParams = { name: researchNames[0], cost: 0, desc: "" }) {
|
||||
constructor(p: ResearchParams | null = null) {
|
||||
if (!p) return;
|
||||
this.name = p.name;
|
||||
this.cost = p.cost;
|
||||
this.desc = p.desc;
|
||||
if (p.advertisingMult) {
|
||||
this.advertisingMult = p.advertisingMult;
|
||||
}
|
||||
if (p.employeeChaMult) {
|
||||
this.employeeChaMult = p.employeeChaMult;
|
||||
}
|
||||
if (p.employeeCreMult) {
|
||||
this.employeeCreMult = p.employeeCreMult;
|
||||
}
|
||||
if (p.employeeEffMult) {
|
||||
this.employeeEffMult = p.employeeEffMult;
|
||||
}
|
||||
if (p.employeeIntMult) {
|
||||
this.employeeIntMult = p.employeeIntMult;
|
||||
}
|
||||
if (p.productionMult) {
|
||||
this.productionMult = p.productionMult;
|
||||
}
|
||||
if (p.productProductionMult) {
|
||||
this.productProductionMult = p.productProductionMult;
|
||||
}
|
||||
if (p.salesMult) {
|
||||
this.salesMult = p.salesMult;
|
||||
}
|
||||
if (p.sciResearchMult) {
|
||||
this.sciResearchMult = p.sciResearchMult;
|
||||
}
|
||||
if (p.storageMult) {
|
||||
this.storageMult = p.storageMult;
|
||||
}
|
||||
this.description = p.desc;
|
||||
this.advertisingMult = p.advertisingMult ?? 1;
|
||||
this.employeeChaMult = p.employeeChaMult ?? 1;
|
||||
this.employeeCreMult = p.employeeCreMult ?? 1;
|
||||
this.employeeEffMult = p.employeeEffMult ?? 1;
|
||||
this.employeeIntMult = p.employeeIntMult ?? 1;
|
||||
this.productionMult = p.productionMult ?? 1;
|
||||
this.productProductionMult = p.productProductionMult ?? 1;
|
||||
this.salesMult = p.salesMult ?? 1;
|
||||
this.sciResearchMult = p.sciResearchMult ?? 1;
|
||||
this.storageMult = p.storageMult ?? 1;
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,189 @@
|
||||
// The Research Map is an object that holds all Corporation Research objects
|
||||
// as values. They are identified by their names
|
||||
import { Research, IConstructorParams } from "./Research";
|
||||
import { researchMetadata } from "./data/ResearchMetadata";
|
||||
import { Research } from "./Research";
|
||||
import { CorpResearchName } from "@nsdefs";
|
||||
|
||||
export const ResearchMap: Record<string, Research> = {};
|
||||
// A full record ensures that every research name is present
|
||||
/** A record for looking up a research object from the name */
|
||||
export const ResearchMap: Record<CorpResearchName, Research> = {
|
||||
AutoBrew: new Research({
|
||||
name: "AutoBrew",
|
||||
cost: 12e3,
|
||||
desc:
|
||||
"Automatically keep your employees fully caffeinated with " +
|
||||
"tea injections. This research will keep the energy of all " +
|
||||
"employees at its maximum possible value, for no cost. " +
|
||||
"This will also disable the Tea upgrade.",
|
||||
}),
|
||||
AutoPartyManager: new Research({
|
||||
name: "AutoPartyManager",
|
||||
cost: 15e3,
|
||||
desc:
|
||||
"Automatically analyzes your employees' morale " +
|
||||
"and boosts them whenever it detects a decrease. This research will " +
|
||||
"keep the morale of all employees at their maximum possible " +
|
||||
"values, for no cost. " +
|
||||
"This will also disable the 'Throw Party' feature.",
|
||||
}),
|
||||
"Automatic Drug Administration": new Research({
|
||||
name: "Automatic Drug Administration",
|
||||
cost: 10e3,
|
||||
desc:
|
||||
"Research how to automatically administer performance-enhancing drugs to all of " +
|
||||
"your employees. This unlocks Drug-related Research.",
|
||||
}),
|
||||
"CPH4 Injections": new Research({
|
||||
name: "CPH4 Injections",
|
||||
cost: 25e3,
|
||||
desc:
|
||||
"Develop an advanced and harmless synthetic drug that is administered to " +
|
||||
"employees to increase all of their stats, except experience, by 10%.",
|
||||
employeeCreMult: 1.1,
|
||||
employeeChaMult: 1.1,
|
||||
employeeEffMult: 1.1,
|
||||
employeeIntMult: 1.1,
|
||||
}),
|
||||
Drones: new Research({
|
||||
name: "Drones",
|
||||
cost: 5e3,
|
||||
desc:
|
||||
"Acquire the knowledge needed to create advanced drones. This research does nothing " +
|
||||
"by itself, but unlocks other Drone-related research.",
|
||||
}),
|
||||
"Drones - Assembly": new Research({
|
||||
name: "Drones - Assembly",
|
||||
cost: 25e3,
|
||||
desc:
|
||||
"Manufacture and use Assembly Drones to improve the efficiency of " +
|
||||
"your production lines. This increases all production by 20%.",
|
||||
productionMult: 1.2,
|
||||
}),
|
||||
"Drones - Transport": new Research({
|
||||
name: "Drones - Transport",
|
||||
cost: 30e3,
|
||||
desc:
|
||||
"Manufacture and use intelligent Transport Drones to optimize " +
|
||||
"your warehouses. This increases the storage space of all warehouses " +
|
||||
"by 50%.",
|
||||
storageMult: 1.5,
|
||||
}),
|
||||
"Go-Juice": new Research({
|
||||
name: "Go-Juice",
|
||||
cost: 25e3,
|
||||
desc:
|
||||
"Provide employees with Go-Juice, a tea-derivative that further enhances " +
|
||||
"the brain's dopamine production. This increases the maximum energy of all " +
|
||||
"employees by 10.",
|
||||
}),
|
||||
"HRBuddy-Recruitment": new Research({
|
||||
name: "HRBuddy-Recruitment",
|
||||
cost: 15e3,
|
||||
desc:
|
||||
"Use automated software to handle the hiring of employees. With this " +
|
||||
"research, each office will automatically hire one employee per " +
|
||||
"market cycle if there is available space.",
|
||||
}),
|
||||
"HRBuddy-Training": new Research({
|
||||
name: "HRBuddy-Training",
|
||||
cost: 20e3,
|
||||
desc:
|
||||
"Use automated software to handle the training of employees. With this " +
|
||||
"research, each employee hired with HRBuddy-Recruitment will automatically " +
|
||||
"be assigned to 'Intern', rather than being unassigned.",
|
||||
}),
|
||||
"Hi-Tech R&D Laboratory": new Research({
|
||||
name: "Hi-Tech R&D Laboratory",
|
||||
cost: 5e3,
|
||||
desc:
|
||||
"Construct a cutting-edge facility dedicated to advanced research and " +
|
||||
"development. This allows you to spend Scientific Research " +
|
||||
"on powerful upgrades. It also globally increases Scientific Research " +
|
||||
"production by 10%.",
|
||||
sciResearchMult: 1.1,
|
||||
}),
|
||||
|
||||
function addResearch(p: IConstructorParams): void {
|
||||
if (ResearchMap[p.name] != null) {
|
||||
console.warn(`Duplicate Research being defined: ${p.name}`);
|
||||
}
|
||||
ResearchMap[p.name] = new Research(p);
|
||||
}
|
||||
|
||||
for (const metadata of researchMetadata) {
|
||||
addResearch(metadata);
|
||||
}
|
||||
"Market-TA.I": new Research({
|
||||
name: "Market-TA.I",
|
||||
cost: 20e3,
|
||||
desc:
|
||||
"Develop advanced AI software that uses technical analysis to " +
|
||||
"help you understand and exploit the market. This research " +
|
||||
"allows you to know what price to sell your Materials/Products " +
|
||||
"at in order to avoid losing sales due to having too high of a mark-up. " +
|
||||
"It also lets you automatically use that sale price.",
|
||||
}),
|
||||
"Market-TA.II": new Research({
|
||||
name: "Market-TA.II",
|
||||
cost: 50e3,
|
||||
desc:
|
||||
"Develop double-advanced AI software that uses technical analysis to " +
|
||||
"help you understand and exploit the market. This research " +
|
||||
"allows you to know how many sales of a Material/Product you lose or gain " +
|
||||
"from having too high or too low of a sale price. It also lets you automatically " +
|
||||
"set the sale price of your Materials/Products at the optimal price such that " +
|
||||
"the amount sold matches the amount produced.",
|
||||
}),
|
||||
Overclock: new Research({
|
||||
name: "Overclock",
|
||||
cost: 15e3,
|
||||
desc:
|
||||
"Equip employees with a headset that uses transcranial direct current " +
|
||||
"stimulation (tDCS) to increase the speed of their neurotransmitters. " +
|
||||
"This research increases the intelligence and efficiency of all " +
|
||||
"employees by 25%.",
|
||||
employeeEffMult: 1.25,
|
||||
employeeIntMult: 1.25,
|
||||
}),
|
||||
"Self-Correcting Assemblers": new Research({
|
||||
name: "Self-Correcting Assemblers",
|
||||
cost: 25e3,
|
||||
desc:
|
||||
"Create assemblers that can be used for universal production. " +
|
||||
"These assemblers use deep learning to improve their efficiency " +
|
||||
"at their tasks. This research increases all production by 10%.",
|
||||
productionMult: 1.1,
|
||||
}),
|
||||
"Sti.mu": new Research({
|
||||
name: "Sti.mu",
|
||||
cost: 30e3,
|
||||
desc:
|
||||
"Upgrade the tDCS headset to stimulate regions of the brain that " +
|
||||
"control confidence and enthusiasm. This research increases the maximum " +
|
||||
"morale of all employees by 10.",
|
||||
}),
|
||||
"sudo.Assist": new Research({
|
||||
name: "sudo.Assist",
|
||||
cost: 15e3,
|
||||
desc: "Develop a virtual assistant AI to handle and manage administrative issues for your corporation.",
|
||||
}),
|
||||
"uPgrade: Capacity.I": new Research({
|
||||
name: "uPgrade: Capacity.I",
|
||||
cost: 20e3,
|
||||
desc:
|
||||
"Expand the industry's capacity for designing and manufacturing its " +
|
||||
"various products. This increases the industry's maximum number of products " +
|
||||
"by 1 (from 3 to 4).",
|
||||
}),
|
||||
"uPgrade: Capacity.II": new Research({
|
||||
name: "uPgrade: Capacity.II",
|
||||
cost: 30e3,
|
||||
desc:
|
||||
"Expand the industry's capacity for designing and manufacturing its " +
|
||||
"various products. This increases the industry's maximum number of products " +
|
||||
"by 1 (from 4 to 5).",
|
||||
}),
|
||||
"uPgrade: Dashboard": new Research({
|
||||
name: "uPgrade: Dashboard",
|
||||
cost: 5e3,
|
||||
desc:
|
||||
"Improve the software used to manage the industry's production line " +
|
||||
"for its various products. This allows you to manage the production and " +
|
||||
"sale of a product before it's finished being designed.",
|
||||
}),
|
||||
"uPgrade: Fulcrum": new Research({
|
||||
name: "uPgrade: Fulcrum",
|
||||
cost: 10e3,
|
||||
desc:
|
||||
"Streamline the manufacturing of this industry's various products. " +
|
||||
"This research increases the production of your products by 5%.",
|
||||
productProductionMult: 1.05,
|
||||
}),
|
||||
};
|
||||
|
@ -4,14 +4,13 @@
|
||||
// not an actual Research object. The name can be used to obtain a reference
|
||||
// to the corresponding Research object using the ResearchMap
|
||||
import { CorpResearchName } from "@nsdefs";
|
||||
import { researchNames } from "./data/Constants";
|
||||
import { Research } from "./Research";
|
||||
import { ResearchMap } from "./ResearchMap";
|
||||
|
||||
interface IConstructorParams {
|
||||
children?: Node[];
|
||||
cost: number;
|
||||
text: CorpResearchName;
|
||||
researchName: CorpResearchName;
|
||||
parent?: Node | null;
|
||||
}
|
||||
|
||||
@ -34,14 +33,10 @@ export class Node {
|
||||
parent: Node | null = null;
|
||||
|
||||
// Name of the Research held in this Node
|
||||
text: CorpResearchName;
|
||||
researchName: CorpResearchName;
|
||||
|
||||
constructor(p: IConstructorParams = { cost: 0, text: researchNames[0] }) {
|
||||
if (ResearchMap[p.text] == null) {
|
||||
throw new Error(`Invalid Research name used when constructing ResearchTree Node: ${p.text}`);
|
||||
}
|
||||
|
||||
this.text = p.text;
|
||||
constructor(p: IConstructorParams) {
|
||||
this.researchName = p.researchName;
|
||||
this.cost = p.cost;
|
||||
|
||||
if (p.children && p.children.length > 0) {
|
||||
@ -59,16 +54,16 @@ export class Node {
|
||||
}
|
||||
|
||||
// Recursive function for finding a Node with the specified text
|
||||
findNode(text: string): Node | null {
|
||||
findNode(name: CorpResearchName): Node | null {
|
||||
// Is this the Node?
|
||||
if (this.text === text) {
|
||||
if (this.researchName === name) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// Recursively search children
|
||||
let res = null;
|
||||
for (let i = 0; i < this.children.length; ++i) {
|
||||
res = this.children[i].findNode(text);
|
||||
res = this.children[i].findNode(name);
|
||||
if (res != null) {
|
||||
return res;
|
||||
}
|
||||
@ -86,7 +81,7 @@ export class Node {
|
||||
// The root node in a Research Tree must always be the "Hi-Tech R&D Laboratory"
|
||||
export class ResearchTree {
|
||||
// Object containing names of all acquired Research by name
|
||||
researched: Record<string, boolean> = {};
|
||||
researched = new Set<CorpResearchName>();
|
||||
|
||||
// Root Node
|
||||
root: Node | null = null;
|
||||
@ -107,7 +102,7 @@ export class ResearchTree {
|
||||
continue;
|
||||
}
|
||||
|
||||
res.push(node.text);
|
||||
res.push(node.researchName);
|
||||
for (let i = 0; i < node.children.length; ++i) {
|
||||
queue.push(node.children[i]);
|
||||
}
|
||||
@ -175,11 +170,11 @@ export class ResearchTree {
|
||||
continue;
|
||||
}
|
||||
|
||||
const research: Research | null = ResearchMap[node.text];
|
||||
const research: Research | null = ResearchMap[node.researchName];
|
||||
|
||||
// Safety checks
|
||||
if (research == null) {
|
||||
console.warn(`Invalid Research name in node: ${node.text}`);
|
||||
console.warn(`Invalid Research name in node: ${node.researchName}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -197,7 +192,7 @@ export class ResearchTree {
|
||||
storageMult: research.storageMult,
|
||||
}[propName] ?? null;
|
||||
|
||||
if (mult == null) {
|
||||
if (mult === null) {
|
||||
console.warn(`Invalid propName specified in ResearchTree.getMultiplierHelper: ${propName}`);
|
||||
continue;
|
||||
}
|
||||
@ -230,13 +225,11 @@ export class ResearchTree {
|
||||
queue.push(this.root);
|
||||
while (queue.length !== 0) {
|
||||
const node: Node | undefined = queue.shift();
|
||||
if (node == null) {
|
||||
continue;
|
||||
}
|
||||
if (!node) continue;
|
||||
|
||||
if (node.text === name) {
|
||||
if (node.researchName === name) {
|
||||
node.researched = true;
|
||||
this.researched[name] = true;
|
||||
this.researched.add(name);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,18 +1,18 @@
|
||||
import { Material } from "./Material";
|
||||
import { Corporation } from "./Corporation";
|
||||
import { Industry } from "./Industry";
|
||||
import { Division } from "./Division";
|
||||
import { MaterialInfo } from "./MaterialInfo";
|
||||
import { Generic_fromJSON, Generic_toJSON, IReviverValue, constructorsForReviver } from "../utils/JSONReviver";
|
||||
import { exceptionAlert } from "../utils/helpers/exceptionAlert";
|
||||
import { CityName } from "../Enums";
|
||||
import { CorpMaterialName } from "@nsdefs";
|
||||
import { materialNames } from "./data/Constants";
|
||||
import { createFullRecordFromEntries, getRecordEntries } from "../Types/Record";
|
||||
import { CorpUnlockName } from "./data/Enums";
|
||||
import { Player } from "@player";
|
||||
|
||||
interface IConstructorParams {
|
||||
corp?: Corporation;
|
||||
industry?: Industry;
|
||||
loc?: CityName;
|
||||
size?: number;
|
||||
division: Division;
|
||||
loc: CityName;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export class Warehouse {
|
||||
@ -20,13 +20,13 @@ export class Warehouse {
|
||||
level = 1;
|
||||
|
||||
// City that this Warehouse is in
|
||||
loc: CityName;
|
||||
city = CityName.Sector12;
|
||||
|
||||
// Map of Materials held by this Warehouse
|
||||
materials: Record<CorpMaterialName, Material>;
|
||||
materials = createFullRecordFromEntries(materialNames.map((matName) => [matName, new Material({ name: matName })]));
|
||||
|
||||
// Maximum amount warehouse can hold
|
||||
size: number;
|
||||
size = 0;
|
||||
|
||||
// Amount of space currently used by warehouse
|
||||
sizeUsed = 0;
|
||||
@ -35,30 +35,22 @@ export class Warehouse {
|
||||
smartSupplyEnabled = false;
|
||||
|
||||
// Decide if smart supply should use the amount of materials imported into account when deciding on the amount to buy.
|
||||
smartSupplyOptions: Record<CorpMaterialName, string>;
|
||||
smartSupplyOptions = createFullRecordFromEntries(materialNames.map((matName) => [matName, "leftovers"]));
|
||||
|
||||
// Stores the amount of product to be produced. Used for Smart Supply unlock.
|
||||
// The production tracked by smart supply is always based on the previous cycle,
|
||||
// so it will always trail the "true" production by 1 cycle
|
||||
smartSupplyStore = 0;
|
||||
|
||||
constructor(params: IConstructorParams = {}) {
|
||||
this.loc = params.loc ? params.loc : CityName.Sector12;
|
||||
this.size = params.size ? params.size : 0;
|
||||
|
||||
this.materials = {} as Record<CorpMaterialName, Material>;
|
||||
this.smartSupplyOptions = {} as Record<CorpMaterialName, string>;
|
||||
for (const matName of materialNames) {
|
||||
this.materials[matName] = new Material({ name: matName });
|
||||
this.smartSupplyOptions[matName] = "leftovers";
|
||||
}
|
||||
|
||||
if (params.corp && params.industry) {
|
||||
this.updateSize(params.corp, params.industry);
|
||||
}
|
||||
constructor(params: IConstructorParams | null = null) {
|
||||
const corp = Player.corporation;
|
||||
if (!corp || params === null) return;
|
||||
this.city = params.loc;
|
||||
this.size = params.size;
|
||||
this.updateSize(corp, params.division);
|
||||
|
||||
// Default smart supply to being enabled if the upgrade is unlocked
|
||||
if (params.corp?.unlockUpgrades[1]) {
|
||||
if (corp.unlocks.has(CorpUnlockName.SmartSupply)) {
|
||||
this.smartSupplyEnabled = true;
|
||||
}
|
||||
}
|
||||
@ -66,21 +58,16 @@ export class Warehouse {
|
||||
// Re-calculate how much space is being used by this Warehouse
|
||||
updateMaterialSizeUsed(): void {
|
||||
this.sizeUsed = 0;
|
||||
for (const matName of Object.values(materialNames)) {
|
||||
const mat = this.materials[matName];
|
||||
this.sizeUsed += mat.qty * MaterialInfo[matName].size;
|
||||
for (const [matName, mat] of getRecordEntries(this.materials)) {
|
||||
this.sizeUsed += mat.stored * MaterialInfo[matName].size;
|
||||
}
|
||||
if (this.sizeUsed > this.size) {
|
||||
console.warn("Warehouse size used greater than capacity, something went wrong");
|
||||
}
|
||||
}
|
||||
|
||||
updateSize(corporation: Corporation, industry: Industry): void {
|
||||
try {
|
||||
this.size = this.level * 100 * corporation.getStorageMultiplier() * industry.getStorageMultiplier();
|
||||
} catch (e: unknown) {
|
||||
exceptionAlert(e);
|
||||
}
|
||||
updateSize(corporation: Corporation, division: Division): void {
|
||||
this.size = this.level * 100 * corporation.getStorageMultiplier() * division.getStorageMultiplier();
|
||||
}
|
||||
|
||||
// Serialize the current object to a JSON save state.
|
||||
@ -90,19 +77,6 @@ export class Warehouse {
|
||||
|
||||
// Initializes a Warehouse object from a JSON save state.
|
||||
static fromJSON(value: IReviverValue): Warehouse {
|
||||
//Gracefully load saves where AICores and RealEstate material names sometimes did not use spaces
|
||||
if (value.data?.materials?.AICores) {
|
||||
value.data.materials["AI Cores"] = value.data.materials.AICores;
|
||||
value.data.smartSupplyUseLeftovers["AI Cores"] = value.data.smartSupplyUseLeftovers.AICores;
|
||||
delete value.data.materials.AICores;
|
||||
delete value.data.smartSupplyUseLeftovers.AICores;
|
||||
}
|
||||
if (value.data?.materials?.RealEstate) {
|
||||
value.data.materials["Real Estate"] = value.data.materials.RealEstate;
|
||||
value.data.smartSupplyUseLeftovers["Real Estate"] = value.data.smartSupplyUseLeftovers.RealEstate;
|
||||
delete value.data.materials.RealEstate;
|
||||
delete value.data.smartSupplyUseLeftovers.RealEstate;
|
||||
}
|
||||
return Generic_fromJSON(Warehouse, value.data);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,13 @@
|
||||
// Defines the ResearchTree that is common to all Corporation Industries
|
||||
// i.e. all Industries have these types of Research available to unlock
|
||||
import { CorpResearchName } from "@nsdefs";
|
||||
import { Research } from "../Research";
|
||||
import { ResearchMap } from "../ResearchMap";
|
||||
import { ResearchTree, Node } from "../ResearchTree";
|
||||
|
||||
function makeNode(name: string): Node {
|
||||
const research: Research | null = ResearchMap[name];
|
||||
if (research == null) {
|
||||
throw new Error(`Invalid research name: ${name}`);
|
||||
}
|
||||
|
||||
return new Node({ text: research.name, cost: research.cost });
|
||||
function makeNode(name: CorpResearchName): Node {
|
||||
const research: Research = ResearchMap[name];
|
||||
return new Node({ researchName: research.name, cost: research.cost });
|
||||
}
|
||||
|
||||
// Creates the Nodes for the BaseResearchTree.
|
||||
|
@ -8,7 +8,8 @@ import {
|
||||
CorpUpgradeName,
|
||||
} from "@nsdefs";
|
||||
import { CONSTANTS } from "../../Constants";
|
||||
import { IndustryType, EmployeePositions } from "./Enums";
|
||||
import { IndustryType, CorpEmployeeJob } from "./Enums";
|
||||
import { PositiveInteger } from "../../types";
|
||||
|
||||
// For typed strings, we need runtime objects to do API typechecking against.
|
||||
|
||||
@ -18,7 +19,7 @@ import { IndustryType, EmployeePositions } from "./Enums";
|
||||
export const stateNames: CorpStateName[] = ["START", "PURCHASE", "PRODUCTION", "EXPORT", "SALE"],
|
||||
// TODO: remove IndustryType and EmployeePositions enums and just use the typed strings.
|
||||
/** Names of all corporation employee positions */
|
||||
employeePositions: CorpEmployeePosition[] = Object.values(EmployeePositions),
|
||||
employeePositions: CorpEmployeePosition[] = Object.values(CorpEmployeeJob),
|
||||
/** Names of all industries. */
|
||||
industryNames: CorpIndustryName[] = Object.values(IndustryType),
|
||||
/** Names of all materials */
|
||||
@ -66,7 +67,6 @@ export const stateNames: CorpStateName[] = ["START", "PURCHASE", "PRODUCTION", "
|
||||
"AutoBrew",
|
||||
"AutoPartyManager",
|
||||
"Automatic Drug Administration",
|
||||
"Bulk Purchasing",
|
||||
"CPH4 Injections",
|
||||
"Drones",
|
||||
"Drones - Assembly",
|
||||
@ -123,19 +123,11 @@ export const stateNames: CorpStateName[] = ["START", "PURCHASE", "PRODUCTION", "
|
||||
minEmployeeDecay = 10,
|
||||
/**smart supply ot */
|
||||
smartSupplyUseOptions = ["leftovers", "imports", "none"],
|
||||
PurchaseMultipliers: {
|
||||
[key: string]: number | "MAX" | undefined;
|
||||
x1: number;
|
||||
x5: number;
|
||||
x10: number;
|
||||
x50: number;
|
||||
x100: number;
|
||||
MAX: "MAX";
|
||||
} = {
|
||||
x1: 1,
|
||||
x5: 5,
|
||||
x10: 10,
|
||||
x50: 50,
|
||||
x100: 100,
|
||||
MAX: "MAX",
|
||||
PurchaseMultipliers = {
|
||||
x1: 1 as PositiveInteger,
|
||||
x5: 5 as PositiveInteger,
|
||||
x10: 10 as PositiveInteger,
|
||||
x50: 50 as PositiveInteger,
|
||||
x100: 100 as PositiveInteger,
|
||||
MAX: "MAX" as const,
|
||||
};
|
||||
|
@ -1,100 +1,85 @@
|
||||
export interface CorporationUnlockUpgrade {
|
||||
index: number;
|
||||
price: number;
|
||||
name: string;
|
||||
desc: string;
|
||||
}
|
||||
import { CorpUnlockName } from "./Enums";
|
||||
|
||||
export enum CorporationUnlockUpgradeIndex {
|
||||
Export = 0,
|
||||
SmartSupply = 1,
|
||||
MarketResearchDemand = 2,
|
||||
MarketDataCompetition = 3,
|
||||
VeChain = 4,
|
||||
ShadyAccounting = 5,
|
||||
GovernmentPartnership = 6,
|
||||
WarehouseAPI = 7,
|
||||
OfficeAPI = 8,
|
||||
export interface CorpUnlock {
|
||||
name: CorpUnlockName;
|
||||
price: number;
|
||||
desc: string;
|
||||
}
|
||||
|
||||
// Corporation Unlock Upgrades
|
||||
// Upgrades for entire corporation, unlocks features, either you have it or you don't.
|
||||
export const CorporationUnlockUpgrades: Record<CorporationUnlockUpgradeIndex, CorporationUnlockUpgrade> = {
|
||||
export const CorpUnlocks: Record<CorpUnlockName, CorpUnlock> = {
|
||||
//Lets you export goods
|
||||
[CorporationUnlockUpgradeIndex.Export]: {
|
||||
index: 0,
|
||||
[CorpUnlockName.Export]: {
|
||||
name: CorpUnlockName.Export,
|
||||
price: 20e9,
|
||||
name: "Export",
|
||||
desc:
|
||||
"Develop infrastructure to export your materials to your other facilities. " +
|
||||
"This allows you to move materials around between different divisions and cities.",
|
||||
},
|
||||
|
||||
//Lets you buy exactly however many required materials you need for production
|
||||
[CorporationUnlockUpgradeIndex.SmartSupply]: {
|
||||
index: 1,
|
||||
[CorpUnlockName.SmartSupply]: {
|
||||
name: CorpUnlockName.SmartSupply,
|
||||
price: 25e9,
|
||||
name: "Smart Supply",
|
||||
desc:
|
||||
"Use advanced AI to anticipate your supply needs. " +
|
||||
"This allows you to purchase exactly however many materials you need for production.",
|
||||
},
|
||||
|
||||
//Displays each material/product's demand
|
||||
[CorporationUnlockUpgradeIndex.MarketResearchDemand]: {
|
||||
index: 2,
|
||||
[CorpUnlockName.MarketResearchDemand]: {
|
||||
name: CorpUnlockName.MarketResearchDemand,
|
||||
price: 5e9,
|
||||
name: "Market Research - Demand",
|
||||
desc:
|
||||
"Mine and analyze market data to determine the demand of all resources. " +
|
||||
"The demand attribute, which affects sales, will be displayed for every material and product.",
|
||||
},
|
||||
|
||||
//Display's each material/product's competition
|
||||
[CorporationUnlockUpgradeIndex.MarketDataCompetition]: {
|
||||
index: 3,
|
||||
[CorpUnlockName.MarketDataCompetition]: {
|
||||
name: CorpUnlockName.MarketDataCompetition,
|
||||
price: 5e9,
|
||||
name: "Market Data - Competition",
|
||||
desc:
|
||||
"Mine and analyze market data to determine how much competition there is on the market " +
|
||||
"for all resources. The competition attribute, which affects sales, will be displayed for " +
|
||||
"every material and product.",
|
||||
},
|
||||
[CorporationUnlockUpgradeIndex.VeChain]: {
|
||||
index: 4,
|
||||
|
||||
[CorpUnlockName.VeChain]: {
|
||||
name: CorpUnlockName.VeChain,
|
||||
price: 10e9,
|
||||
name: "VeChain",
|
||||
desc:
|
||||
"Use AI and blockchain technology to identify where you can improve your supply chain systems. " +
|
||||
"This upgrade will allow you to view a wide array of useful statistics about your " +
|
||||
"Corporation.",
|
||||
},
|
||||
[CorporationUnlockUpgradeIndex.ShadyAccounting]: {
|
||||
index: 5,
|
||||
|
||||
[CorpUnlockName.ShadyAccounting]: {
|
||||
name: CorpUnlockName.ShadyAccounting,
|
||||
price: 500e12,
|
||||
name: "Shady Accounting",
|
||||
desc:
|
||||
"Utilize unscrupulous accounting practices and pay off government officials to save money " +
|
||||
"on taxes. This reduces the dividend tax rate by 5%.",
|
||||
},
|
||||
[CorporationUnlockUpgradeIndex.GovernmentPartnership]: {
|
||||
index: 6,
|
||||
|
||||
[CorpUnlockName.GovernmentPartnership]: {
|
||||
name: CorpUnlockName.GovernmentPartnership,
|
||||
price: 2e15,
|
||||
name: "Government Partnership",
|
||||
desc:
|
||||
"Help national governments further their agendas in exchange for lowered taxes. " +
|
||||
"This reduces the dividend tax rate by 10%",
|
||||
},
|
||||
[CorporationUnlockUpgradeIndex.WarehouseAPI]: {
|
||||
index: 7,
|
||||
|
||||
[CorpUnlockName.WarehouseAPI]: {
|
||||
name: CorpUnlockName.WarehouseAPI,
|
||||
price: 50e9,
|
||||
name: "Warehouse API",
|
||||
desc: "Enables the warehouse API.",
|
||||
},
|
||||
[CorporationUnlockUpgradeIndex.OfficeAPI]: {
|
||||
index: 8,
|
||||
|
||||
[CorpUnlockName.OfficeAPI]: {
|
||||
name: CorpUnlockName.OfficeAPI,
|
||||
price: 50e9,
|
||||
name: "Office API",
|
||||
desc: "Enables the office API.",
|
||||
},
|
||||
};
|
@ -1,59 +1,43 @@
|
||||
export interface CorporationUpgrade {
|
||||
index: number;
|
||||
import { CorpUpgradeName } from "./Enums";
|
||||
|
||||
export interface CorpUpgrade {
|
||||
name: CorpUpgradeName;
|
||||
basePrice: number;
|
||||
priceMult: number;
|
||||
benefit: number;
|
||||
name: string;
|
||||
desc: string;
|
||||
}
|
||||
|
||||
export enum CorporationUpgradeIndex {
|
||||
SmartFactories = 0,
|
||||
SmartStorage = 1,
|
||||
DreamSense = 2,
|
||||
WilsonAnalytics = 3,
|
||||
NuoptimalNootropicInjectorImplants = 4,
|
||||
SpeechProcessorImplants = 5,
|
||||
NeuralAccelerators = 6,
|
||||
FocusWires = 7,
|
||||
ABCSalesBots = 8,
|
||||
ProjectInsight = 9,
|
||||
}
|
||||
|
||||
// Corporation Upgrades
|
||||
// Upgrades for entire corporation, levelable upgrades
|
||||
export const CorporationUpgrades: Record<CorporationUpgradeIndex, CorporationUpgrade> = {
|
||||
/** Levelable upgrades that affect the entire corporation */
|
||||
export const CorpUpgrades: Record<CorpUpgradeName, CorpUpgrade> = {
|
||||
//Smart factories, increases production
|
||||
[CorporationUpgradeIndex.SmartFactories]: {
|
||||
index: CorporationUpgradeIndex.SmartFactories,
|
||||
[CorpUpgradeName.SmartFactories]: {
|
||||
name: CorpUpgradeName.SmartFactories,
|
||||
basePrice: 2e9,
|
||||
priceMult: 1.06,
|
||||
benefit: 0.03,
|
||||
name: "Smart Factories",
|
||||
desc:
|
||||
"Advanced AI automatically optimizes the operation and productivity " +
|
||||
"of factories. Each level of this upgrade increases your global production by 3% (additive).",
|
||||
},
|
||||
|
||||
//Smart warehouses, increases storage size
|
||||
[CorporationUpgradeIndex.SmartStorage]: {
|
||||
index: CorporationUpgradeIndex.SmartStorage,
|
||||
[CorpUpgradeName.SmartStorage]: {
|
||||
name: CorpUpgradeName.SmartStorage,
|
||||
basePrice: 2e9,
|
||||
priceMult: 1.06,
|
||||
benefit: 0.1,
|
||||
name: "Smart Storage",
|
||||
desc:
|
||||
"Advanced AI automatically optimizes your warehouse storage methods. " +
|
||||
"Each level of this upgrade increases your global warehouse storage size by 10% (additive).",
|
||||
},
|
||||
|
||||
//Advertise through dreams, passive popularity/ awareness gain
|
||||
[CorporationUpgradeIndex.DreamSense]: {
|
||||
index: CorporationUpgradeIndex.DreamSense,
|
||||
[CorpUpgradeName.DreamSense]: {
|
||||
name: CorpUpgradeName.DreamSense,
|
||||
basePrice: 4e9,
|
||||
priceMult: 1.1,
|
||||
benefit: 0.001,
|
||||
name: "DreamSense",
|
||||
desc:
|
||||
"Use DreamSense LCC Technologies to advertise your corporation " +
|
||||
"to consumers through their dreams. Each level of this upgrade provides a passive " +
|
||||
@ -63,12 +47,11 @@ export const CorporationUpgrades: Record<CorporationUpgradeIndex, CorporationUpg
|
||||
},
|
||||
|
||||
//Makes advertising more effective
|
||||
[CorporationUpgradeIndex.WilsonAnalytics]: {
|
||||
index: CorporationUpgradeIndex.WilsonAnalytics,
|
||||
[CorpUpgradeName.WilsonAnalytics]: {
|
||||
name: CorpUpgradeName.WilsonAnalytics,
|
||||
basePrice: 4e9,
|
||||
priceMult: 2,
|
||||
benefit: 0.005,
|
||||
name: "Wilson Analytics",
|
||||
desc:
|
||||
"Purchase data and analysis from Wilson, a marketing research " +
|
||||
"firm. Each level of this upgrade increases the effectiveness of your " +
|
||||
@ -76,12 +59,11 @@ export const CorporationUpgrades: Record<CorporationUpgradeIndex, CorporationUpg
|
||||
},
|
||||
|
||||
//Augmentation for employees, increases cre
|
||||
[CorporationUpgradeIndex.NuoptimalNootropicInjectorImplants]: {
|
||||
index: CorporationUpgradeIndex.NuoptimalNootropicInjectorImplants,
|
||||
[CorpUpgradeName.NuoptimalNootropicInjectorImplants]: {
|
||||
name: CorpUpgradeName.NuoptimalNootropicInjectorImplants,
|
||||
basePrice: 1e9,
|
||||
priceMult: 1.06,
|
||||
benefit: 0.1,
|
||||
name: "Nuoptimal Nootropic Injector Implants",
|
||||
desc:
|
||||
"Purchase the Nuoptimal Nootropic " +
|
||||
"Injector augmentation for your employees. Each level of this upgrade " +
|
||||
@ -89,24 +71,22 @@ export const CorporationUpgrades: Record<CorporationUpgradeIndex, CorporationUpg
|
||||
},
|
||||
|
||||
//Augmentation for employees, increases cha
|
||||
[CorporationUpgradeIndex.SpeechProcessorImplants]: {
|
||||
index: CorporationUpgradeIndex.SpeechProcessorImplants,
|
||||
[CorpUpgradeName.SpeechProcessorImplants]: {
|
||||
name: CorpUpgradeName.SpeechProcessorImplants,
|
||||
basePrice: 1e9,
|
||||
priceMult: 1.06,
|
||||
benefit: 0.1,
|
||||
name: "Speech Processor Implants",
|
||||
desc:
|
||||
"Purchase the Speech Processor augmentation for your employees. " +
|
||||
"Each level of this upgrade globally increases the charisma of your employees by 10% (additive).",
|
||||
},
|
||||
|
||||
//Augmentation for employees, increases int
|
||||
[CorporationUpgradeIndex.NeuralAccelerators]: {
|
||||
index: CorporationUpgradeIndex.NeuralAccelerators,
|
||||
[CorpUpgradeName.NeuralAccelerators]: {
|
||||
name: CorpUpgradeName.NeuralAccelerators,
|
||||
basePrice: 1e9,
|
||||
priceMult: 1.06,
|
||||
benefit: 0.1,
|
||||
name: "Neural Accelerators",
|
||||
desc:
|
||||
"Purchase the Neural Accelerator augmentation for your employees. " +
|
||||
"Each level of this upgrade globally increases the intelligence of your employees " +
|
||||
@ -114,24 +94,22 @@ export const CorporationUpgrades: Record<CorporationUpgradeIndex, CorporationUpg
|
||||
},
|
||||
|
||||
//Augmentation for employees, increases eff
|
||||
[CorporationUpgradeIndex.FocusWires]: {
|
||||
index: CorporationUpgradeIndex.FocusWires,
|
||||
[CorpUpgradeName.FocusWires]: {
|
||||
name: CorpUpgradeName.FocusWires,
|
||||
basePrice: 1e9,
|
||||
priceMult: 1.06,
|
||||
benefit: 0.1,
|
||||
name: "FocusWires",
|
||||
desc:
|
||||
"Purchase the FocusWire augmentation for your employees. Each level " +
|
||||
"of this upgrade globally increases the efficiency of your employees by 10% (additive).",
|
||||
},
|
||||
|
||||
//Improves sales of materials/products
|
||||
[CorporationUpgradeIndex.ABCSalesBots]: {
|
||||
index: CorporationUpgradeIndex.ABCSalesBots,
|
||||
[CorpUpgradeName.ABCSalesBots]: {
|
||||
name: CorpUpgradeName.ABCSalesBots,
|
||||
basePrice: 1e9,
|
||||
priceMult: 1.07,
|
||||
benefit: 0.01,
|
||||
name: "ABC SalesBots",
|
||||
desc:
|
||||
"Always Be Closing. Purchase these robotic salesmen to increase the amount of " +
|
||||
"materials and products you sell. Each level of this upgrade globally increases your sales " +
|
||||
@ -139,12 +117,11 @@ export const CorporationUpgrades: Record<CorporationUpgradeIndex, CorporationUpg
|
||||
},
|
||||
|
||||
//Improves scientific research rate
|
||||
[CorporationUpgradeIndex.ProjectInsight]: {
|
||||
index: CorporationUpgradeIndex.ProjectInsight,
|
||||
[CorpUpgradeName.ProjectInsight]: {
|
||||
name: CorpUpgradeName.ProjectInsight,
|
||||
basePrice: 5e9,
|
||||
priceMult: 1.07,
|
||||
benefit: 0.05,
|
||||
name: "Project Insight",
|
||||
desc:
|
||||
"Purchase 'Project Insight', a R&D service provided by the secretive " +
|
||||
"Fulcrum Technologies. Each level of this upgrade globally increases the amount of " +
|
||||
|
@ -16,7 +16,7 @@ export enum IndustryType {
|
||||
RealEstate = "Real Estate",
|
||||
}
|
||||
|
||||
export enum EmployeePositions {
|
||||
export enum CorpEmployeeJob {
|
||||
Operations = "Operations",
|
||||
Engineer = "Engineer",
|
||||
Business = "Business",
|
||||
@ -25,3 +25,28 @@ export enum EmployeePositions {
|
||||
Intern = "Intern",
|
||||
Unassigned = "Unassigned",
|
||||
}
|
||||
|
||||
export enum CorpUnlockName {
|
||||
Export = "Export",
|
||||
SmartSupply = "Smart Supply",
|
||||
MarketResearchDemand = "Market Research - Demand",
|
||||
MarketDataCompetition = "Market Data - Competition",
|
||||
VeChain = "VeChain",
|
||||
ShadyAccounting = "Shady Accounting",
|
||||
GovernmentPartnership = "Government Partnership",
|
||||
WarehouseAPI = "Warehouse API",
|
||||
OfficeAPI = "Office API",
|
||||
}
|
||||
|
||||
export enum CorpUpgradeName {
|
||||
SmartFactories = "Smart Factories",
|
||||
SmartStorage = "Smart Storage",
|
||||
DreamSense = "DreamSense",
|
||||
WilsonAnalytics = "Wilson Analytics",
|
||||
NuoptimalNootropicInjectorImplants = "Nuoptimal Nootropic Injector Implants",
|
||||
SpeechProcessorImplants = "Speech Processor Implants",
|
||||
NeuralAccelerators = "Neural Accelerators",
|
||||
FocusWires = "FocusWires",
|
||||
ABCSalesBots = "ABC SalesBots",
|
||||
ProjectInsight = "Project Insight",
|
||||
}
|
||||
|
@ -1,185 +0,0 @@
|
||||
import { IConstructorParams } from "../Research";
|
||||
|
||||
export const researchMetadata: IConstructorParams[] = [
|
||||
{
|
||||
name: "AutoBrew",
|
||||
cost: 12e3,
|
||||
desc:
|
||||
"Automatically keep your employees fully caffeinated with " +
|
||||
"tea injections. This research will keep the energy of all " +
|
||||
"employees at its maximum possible value, for no cost. " +
|
||||
"This will also disable the Tea upgrade.",
|
||||
},
|
||||
{
|
||||
name: "AutoPartyManager",
|
||||
cost: 15e3,
|
||||
desc:
|
||||
"Automatically analyzes your employees' morale " +
|
||||
"and boosts them whenever it detects a decrease. This research will " +
|
||||
"keep the morale of all employees at their maximum possible " +
|
||||
"values, for no cost. " +
|
||||
"This will also disable the 'Throw Party' feature.",
|
||||
},
|
||||
{
|
||||
name: "Automatic Drug Administration",
|
||||
cost: 10e3,
|
||||
desc:
|
||||
"Research how to automatically administer performance-enhancing drugs to all of " +
|
||||
"your employees. This unlocks Drug-related Research.",
|
||||
},
|
||||
{
|
||||
name: "CPH4 Injections",
|
||||
cost: 25e3,
|
||||
desc:
|
||||
"Develop an advanced and harmless synthetic drug that is administered to " +
|
||||
"employees to increase all of their stats, except experience, by 10%.",
|
||||
employeeCreMult: 1.1,
|
||||
employeeChaMult: 1.1,
|
||||
employeeEffMult: 1.1,
|
||||
employeeIntMult: 1.1,
|
||||
},
|
||||
{
|
||||
name: "Drones",
|
||||
cost: 5e3,
|
||||
desc:
|
||||
"Acquire the knowledge needed to create advanced drones. This research does nothing " +
|
||||
"by itself, but unlocks other Drone-related research.",
|
||||
},
|
||||
{
|
||||
name: "Drones - Assembly",
|
||||
cost: 25e3,
|
||||
desc:
|
||||
"Manufacture and use Assembly Drones to improve the efficiency of " +
|
||||
"your production lines. This increases all production by 20%.",
|
||||
productionMult: 1.2,
|
||||
},
|
||||
{
|
||||
name: "Drones - Transport",
|
||||
cost: 30e3,
|
||||
desc:
|
||||
"Manufacture and use intelligent Transport Drones to optimize " +
|
||||
"your warehouses. This increases the storage space of all warehouses " +
|
||||
"by 50%.",
|
||||
storageMult: 1.5,
|
||||
},
|
||||
{
|
||||
name: "Go-Juice",
|
||||
cost: 25e3,
|
||||
desc:
|
||||
"Provide employees with Go-Juice, a tea-derivative that further enhances " +
|
||||
"the brain's dopamine production. This increases the maximum energy of all " +
|
||||
"employees by 10.",
|
||||
},
|
||||
{
|
||||
name: "Hi-Tech R&D Laboratory",
|
||||
cost: 5e3,
|
||||
desc:
|
||||
"Construct a cutting-edge facility dedicated to advanced research and " +
|
||||
"development. This allows you to spend Scientific Research " +
|
||||
"on powerful upgrades. It also globally increases Scientific Research " +
|
||||
"production by 10%.",
|
||||
sciResearchMult: 1.1,
|
||||
},
|
||||
{
|
||||
name: "HRBuddy-Recruitment",
|
||||
cost: 15e3,
|
||||
desc:
|
||||
"Use automated software to handle the hiring of employees. With this " +
|
||||
"research, each office will automatically hire one employee per " +
|
||||
"market cycle if there is available space.",
|
||||
},
|
||||
{
|
||||
name: "HRBuddy-Training",
|
||||
cost: 20e3,
|
||||
desc:
|
||||
"Use automated software to handle the training of employees. With this " +
|
||||
"research, each employee hired with HRBuddy-Recruitment will automatically " +
|
||||
"be assigned to 'Intern', rather than being unassigned.",
|
||||
},
|
||||
{
|
||||
name: "Market-TA.I",
|
||||
cost: 20e3,
|
||||
desc:
|
||||
"Develop advanced AI software that uses technical analysis to " +
|
||||
"help you understand and exploit the market. This research " +
|
||||
"allows you to know what price to sell your Materials/Products " +
|
||||
"at in order to avoid losing sales due to having too high of a mark-up. " +
|
||||
"It also lets you automatically use that sale price.",
|
||||
},
|
||||
{
|
||||
name: "Market-TA.II",
|
||||
cost: 50e3,
|
||||
desc:
|
||||
"Develop double-advanced AI software that uses technical analysis to " +
|
||||
"help you understand and exploit the market. This research " +
|
||||
"allows you to know how many sales of a Material/Product you lose or gain " +
|
||||
"from having too high or too low of a sale price. It also lets you automatically " +
|
||||
"set the sale price of your Materials/Products at the optimal price such that " +
|
||||
"the amount sold matches the amount produced.",
|
||||
},
|
||||
{
|
||||
name: "Overclock",
|
||||
cost: 15e3,
|
||||
desc:
|
||||
"Equip employees with a headset that uses transcranial direct current " +
|
||||
"stimulation (tDCS) to increase the speed of their neurotransmitters. " +
|
||||
"This research increases the intelligence and efficiency of all " +
|
||||
"employees by 25%.",
|
||||
employeeEffMult: 1.25,
|
||||
employeeIntMult: 1.25,
|
||||
},
|
||||
{
|
||||
name: "Self-Correcting Assemblers",
|
||||
cost: 25e3,
|
||||
desc:
|
||||
"Create assemblers that can be used for universal production. " +
|
||||
"These assemblers use deep learning to improve their efficiency " +
|
||||
"at their tasks. This research increases all production by 10%.",
|
||||
productionMult: 1.1,
|
||||
},
|
||||
{
|
||||
name: "Sti.mu",
|
||||
cost: 30e3,
|
||||
desc:
|
||||
"Upgrade the tDCS headset to stimulate regions of the brain that " +
|
||||
"control confidence and enthusiasm. This research increases the maximum " +
|
||||
"morale of all employees by 10.",
|
||||
},
|
||||
{
|
||||
name: "sudo.Assist",
|
||||
cost: 15e3,
|
||||
desc: "Develop a virtual assistant AI to handle and manage administrative issues for your corporation.",
|
||||
},
|
||||
{
|
||||
name: "uPgrade: Capacity.I",
|
||||
cost: 20e3,
|
||||
desc:
|
||||
"Expand the industry's capacity for designing and manufacturing its " +
|
||||
"various products. This increases the industry's maximum number of products " +
|
||||
"by 1 (from 3 to 4).",
|
||||
},
|
||||
{
|
||||
name: "uPgrade: Capacity.II",
|
||||
cost: 30e3,
|
||||
desc:
|
||||
"Expand the industry's capacity for designing and manufacturing its " +
|
||||
"various products. This increases the industry's maximum number of products " +
|
||||
"by 1 (from 4 to 5).",
|
||||
},
|
||||
{
|
||||
name: "uPgrade: Dashboard",
|
||||
cost: 5e3,
|
||||
desc:
|
||||
"Improve the software used to manage the industry's production line " +
|
||||
"for its various products. This allows you to manage the production and " +
|
||||
"sale of a product before it's finished being designed.",
|
||||
},
|
||||
{
|
||||
name: "uPgrade: Fulcrum",
|
||||
cost: 10e3,
|
||||
desc:
|
||||
"Streamline the manufacturing of this industry's various products. " +
|
||||
"This research increases the production of your products by 5%.",
|
||||
productProductionMult: 1.05,
|
||||
},
|
||||
];
|
@ -1,35 +1,32 @@
|
||||
import { PositiveInteger } from "../types";
|
||||
import { Corporation } from "./Corporation";
|
||||
import { CorporationUpgrade } from "./data/CorporationUpgrades";
|
||||
import { CorpUpgrade } from "./data/CorporationUpgrades";
|
||||
|
||||
export function calculateUpgradeCost(corporation: Corporation, upgrade: CorporationUpgrade, amount: number): number {
|
||||
if (amount < 1) return 0;
|
||||
export function calculateUpgradeCost(corporation: Corporation, upgrade: CorpUpgrade, amount: PositiveInteger): number {
|
||||
const priceMult = upgrade.priceMult;
|
||||
const level = corporation.upgrades[upgrade.index];
|
||||
const level = corporation.upgrades[upgrade.name].level;
|
||||
const baseCost = upgrade.basePrice * Math.pow(priceMult, level);
|
||||
const cost = (baseCost * (1 - Math.pow(priceMult, amount))) / (1 - priceMult);
|
||||
return cost;
|
||||
}
|
||||
|
||||
// There ought to be a more clever mathematical solution for this
|
||||
export function calculateMaxAffordableUpgrade(
|
||||
corporation: Corporation,
|
||||
upgrade: CorporationUpgrade,
|
||||
amount: number | "MAX",
|
||||
): number {
|
||||
if (amount != "MAX") {
|
||||
if (amount === 0) return 0;
|
||||
if (calculateUpgradeCost(corporation, upgrade, amount) < corporation.funds) return amount;
|
||||
}
|
||||
|
||||
corp: Corporation,
|
||||
upgrade: CorpUpgrade,
|
||||
amount: PositiveInteger | "MAX",
|
||||
): 0 | PositiveInteger {
|
||||
if (amount !== "MAX" && calculateUpgradeCost(corp, upgrade, amount) < corp.funds) return amount;
|
||||
if (calculateUpgradeCost(corp, upgrade, 1 as PositiveInteger) > corp.funds) return 0;
|
||||
// We can definitely afford 1 of the upgrade
|
||||
let n = 1;
|
||||
while (
|
||||
calculateUpgradeCost(corporation, upgrade, n * 2) < corporation.funds &&
|
||||
(amount != "MAX" ? n < amount : true)
|
||||
) {
|
||||
n *= 2;
|
||||
// Multiply by 2 until we can't afford it anymore
|
||||
while (calculateUpgradeCost(corp, upgrade, (n * 2) as PositiveInteger) <= corp.funds) n *= 2;
|
||||
let tooHigh = n * 2;
|
||||
while (tooHigh - n > 1) {
|
||||
const nextCheck = (Math.ceil((tooHigh - n) / 2) + n) as PositiveInteger;
|
||||
if (calculateUpgradeCost(corp, upgrade, nextCheck) <= corp.funds) n = nextCheck;
|
||||
else tooHigh = nextCheck;
|
||||
}
|
||||
for (let i = n / 2; i >= 1; i /= 2) {
|
||||
if (calculateUpgradeCost(corporation, upgrade, n + i) < corporation.funds) n += i;
|
||||
}
|
||||
|
||||
return amount === "MAX" ? n : Math.min(n, amount);
|
||||
return n as PositiveInteger;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import { useDivision } from "./Context";
|
||||
import Tabs from "@mui/material/Tabs";
|
||||
import Tab from "@mui/material/Tab";
|
||||
import { CityName } from "../../Enums";
|
||||
import { getRecordKeys } from "../../Types/Record";
|
||||
|
||||
interface IProps {
|
||||
city: CityName | "Expand";
|
||||
@ -23,7 +24,7 @@ export function CityTabs(props: IProps): React.ReactElement {
|
||||
mainContent = <ExpandNewCity cityStateSetter={setCity} />;
|
||||
} else {
|
||||
const office = division.offices[city];
|
||||
if (office === 0) {
|
||||
if (!office) {
|
||||
setCity(CityName.Sector12);
|
||||
return <></>;
|
||||
}
|
||||
@ -31,7 +32,7 @@ export function CityTabs(props: IProps): React.ReactElement {
|
||||
<Industry rerender={props.rerender} city={city} warehouse={division.warehouses[city]} office={office} />
|
||||
);
|
||||
}
|
||||
const canExpand = Object.values(CityName).filter((cityName) => division.offices[cityName] === 0).length > 0;
|
||||
const canExpand = Object.values(CityName).length > getRecordKeys(division.offices).length;
|
||||
function handleChange(event: React.SyntheticEvent, tab: CityName | "Expand"): void {
|
||||
setCity(tab);
|
||||
}
|
||||
@ -40,7 +41,8 @@ export function CityTabs(props: IProps): React.ReactElement {
|
||||
<>
|
||||
<Tabs variant="fullWidth" value={city} onChange={handleChange} sx={{ maxWidth: "65vw" }}>
|
||||
{Object.values(division.offices).map(
|
||||
(office: OfficeSpace | 0) => office !== 0 && <Tab key={office.loc} label={office.loc} value={office.loc} />,
|
||||
(office: OfficeSpace | 0) =>
|
||||
office !== 0 && <Tab key={office.city} label={office.city} value={office.city} />,
|
||||
)}
|
||||
{canExpand && <Tab label={"Expand"} value={"Expand"} />}
|
||||
</Tabs>
|
||||
|
@ -1,11 +1,11 @@
|
||||
import React, { useContext } from "react";
|
||||
import { Corporation } from "../Corporation";
|
||||
import { Industry } from "../Industry";
|
||||
import { Division } from "../Division";
|
||||
|
||||
export const Context = {
|
||||
Corporation: React.createContext<Corporation>({} as Corporation),
|
||||
Division: React.createContext<Industry>({} as Industry),
|
||||
Division: React.createContext<Division>({} as Division),
|
||||
};
|
||||
|
||||
export const useCorporation = (): Corporation => useContext(Context.Corporation);
|
||||
export const useDivision = (): Industry => useContext(Context.Division);
|
||||
export const useDivision = (): Division => useContext(Context.Division);
|
||||
|
@ -3,7 +3,6 @@
|
||||
// divisions, see an overview of your corporation, or create a new industry
|
||||
import React, { useState } from "react";
|
||||
import { MainPanel } from "./MainPanel";
|
||||
import { IndustryType } from "../data/Enums";
|
||||
import { ExpandIndustryTab } from "./ExpandIndustryTab";
|
||||
import { Player } from "@player";
|
||||
import { Context } from "./Context";
|
||||
@ -22,16 +21,13 @@ export function CorporationRoot(): React.ReactElement {
|
||||
setDivisionName(tab);
|
||||
}
|
||||
|
||||
const canExpand =
|
||||
Object.values(IndustryType).filter(
|
||||
(industryType) => corporation.divisions.find((division) => division.type === industryType) === undefined,
|
||||
).length > 0;
|
||||
const canExpand = corporation.divisions.size < corporation.maxDivisions;
|
||||
|
||||
return (
|
||||
<Context.Corporation.Provider value={corporation}>
|
||||
<Tabs variant="scrollable" value={divisionName} onChange={handleChange} sx={{ maxWidth: "65vw" }} scrollButtons>
|
||||
<Tab label={corporation.name} value={"Overview"} />
|
||||
{corporation.divisions.map((div) => (
|
||||
{[...corporation.divisions.values()].map((div) => (
|
||||
<Tab key={div.name} label={div.name} value={div.name} />
|
||||
))}
|
||||
{canExpand && <Tab label={"Expand"} value={-1} />}
|
||||
|
@ -6,13 +6,12 @@ import { useCorporation } from "./Context";
|
||||
import { NewIndustry } from "../Actions";
|
||||
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import { ButtonWithTooltip } from "../../ui/Components/ButtonWithTooltip";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import Box from "@mui/material/Box";
|
||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||
import { KEY } from "../../utils/helpers/keyCodes";
|
||||
|
||||
interface IProps {
|
||||
setDivisionName: (name: string) => void;
|
||||
}
|
||||
@ -26,10 +25,15 @@ export function ExpandIndustryTab(props: IProps): React.ReactElement {
|
||||
const data = IndustriesData[industry];
|
||||
if (!data) return <></>;
|
||||
|
||||
const disabled = corp.funds < data.startingCost && corp.divisions.length < corp.maxDivisions;
|
||||
const disabledText =
|
||||
corp.divisions.size >= corp.maxDivisions
|
||||
? "Corporation already has the maximum number of divisions"
|
||||
: corp.funds < data.startingCost
|
||||
? "Insufficient corporation funds"
|
||||
: "";
|
||||
|
||||
function newIndustry(): void {
|
||||
if (disabled) return;
|
||||
if (disabledText) return;
|
||||
try {
|
||||
NewIndustry(corp, industry, name);
|
||||
} catch (err) {
|
||||
@ -60,7 +64,7 @@ export function ExpandIndustryTab(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
<Typography>
|
||||
{corp.name} has {corp.divisions.length}/{corp.maxDivisions} divisions.
|
||||
{corp.name} has {corp.divisions.size} of {corp.maxDivisions} divisions.
|
||||
</Typography>
|
||||
<Typography>Create a new division to expand into a new industry:</Typography>
|
||||
<Select value={industry} onChange={onIndustryChange}>
|
||||
@ -77,20 +81,10 @@ export function ExpandIndustryTab(props: IProps): React.ReactElement {
|
||||
<Typography>Division name:</Typography>
|
||||
|
||||
<Box display="flex" alignItems="center">
|
||||
<TextField
|
||||
autoFocus={true}
|
||||
value={name}
|
||||
onChange={onNameChange}
|
||||
onKeyDown={onKeyDown}
|
||||
type="text"
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<Button disabled={disabled} sx={{ mx: 1 }} onClick={newIndustry}>
|
||||
Expand
|
||||
</Button>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<TextField autoFocus={true} value={name} onChange={onNameChange} onKeyDown={onKeyDown} type="text"></TextField>{" "}
|
||||
<ButtonWithTooltip disabledTooltip={disabledText} onClick={newIndustry}>
|
||||
Expand
|
||||
</ButtonWithTooltip>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
|
@ -1,13 +1,13 @@
|
||||
import React, { useState } from "react";
|
||||
import * as corpConstants from "../data/Constants";
|
||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||
import { NewCity } from "../Actions";
|
||||
import { purchaseOffice } from "../Actions";
|
||||
import { MoneyCost } from "./MoneyCost";
|
||||
import { useCorporation, useDivision } from "./Context";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||
import Button from "@mui/material/Button";
|
||||
import { ButtonWithTooltip } from "../../ui/Components/ButtonWithTooltip";
|
||||
import { CityName } from "../../Enums";
|
||||
|
||||
interface IProps {
|
||||
@ -17,10 +17,10 @@ interface IProps {
|
||||
export function ExpandNewCity(props: IProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const division = useDivision();
|
||||
const possibleCities = Object.values(CityName).filter((cityName) => division.offices[cityName] === 0);
|
||||
const possibleCities = Object.values(CityName).filter((cityName) => !(cityName in division.offices));
|
||||
const [city, setCity] = useState(possibleCities[0]);
|
||||
|
||||
const disabled = corp.funds < corpConstants.officeInitialCost;
|
||||
const disabledText = corp.funds < corpConstants.officeInitialCost ? "Insufficient corporation funds" : "";
|
||||
|
||||
function onCityChange(event: SelectChangeEvent): void {
|
||||
setCity(event.target.value as CityName);
|
||||
@ -28,7 +28,7 @@ export function ExpandNewCity(props: IProps): React.ReactElement {
|
||||
|
||||
function expand(): void {
|
||||
try {
|
||||
NewCity(corp, division, city);
|
||||
purchaseOffice(corp, division, city);
|
||||
} catch (err) {
|
||||
dialogBoxCreate(err + "");
|
||||
return;
|
||||
@ -44,21 +44,16 @@ export function ExpandNewCity(props: IProps): React.ReactElement {
|
||||
Would you like to expand into a new city by opening an office? This would cost{" "}
|
||||
<MoneyCost money={corpConstants.officeInitialCost} corp={corp} />
|
||||
</Typography>
|
||||
<Select
|
||||
endAdornment={
|
||||
<Button onClick={expand} disabled={disabled}>
|
||||
Confirm
|
||||
</Button>
|
||||
}
|
||||
value={city}
|
||||
onChange={onCityChange}
|
||||
>
|
||||
<Select value={city} onChange={onCityChange}>
|
||||
{possibleCities.map((cityName: string) => (
|
||||
<MenuItem key={cityName} value={cityName}>
|
||||
{cityName}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
<ButtonWithTooltip onClick={expand} disabledTooltip={disabledText}>
|
||||
Confirm
|
||||
</ButtonWithTooltip>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { CorpMaterialName } from "@nsdefs";
|
||||
import { Industry } from "../Industry";
|
||||
import { Division } from "../Division";
|
||||
|
||||
// Returns a boolean indicating whether the given material is relevant for the
|
||||
// current industry.
|
||||
export function isRelevantMaterial(matName: CorpMaterialName, division: Industry): boolean {
|
||||
export function isRelevantMaterial(matName: CorpMaterialName, division: Division): boolean {
|
||||
// Materials that affect Production multiplier
|
||||
const prodMultiplierMats: CorpMaterialName[] = ["Hardware", "Robots", "AI Cores", "Real Estate"];
|
||||
|
||||
if (Object.keys(division.reqMats).includes(matName)) return true;
|
||||
if (division.prodMats.includes(matName)) return true;
|
||||
if (Object.keys(division.requiredMaterials).includes(matName)) return true;
|
||||
if (division.producedMaterials.includes(matName)) return true;
|
||||
if (prodMultiplierMats.includes(matName)) return true;
|
||||
|
||||
return false;
|
||||
|
@ -13,7 +13,7 @@ import { CityName } from "../../Enums";
|
||||
|
||||
interface IProps {
|
||||
city: CityName;
|
||||
warehouse: Warehouse | 0;
|
||||
warehouse?: Warehouse;
|
||||
office: OfficeSpace;
|
||||
rerender: () => void;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { OfficeSpace } from "../OfficeSpace";
|
||||
import { EmployeePositions } from "../data/Enums";
|
||||
import { CorpUnlockName, CorpEmployeeJob } from "../data/Enums";
|
||||
import { BuyTea } from "../Actions";
|
||||
|
||||
import { MoneyCost } from "./MoneyCost";
|
||||
@ -15,7 +15,7 @@ import { Money } from "../../ui/React/Money";
|
||||
import { useCorporation, useDivision } from "./Context";
|
||||
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import { ButtonWithTooltip } from "../../ui/Components/ButtonWithTooltip";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import ArrowForwardIcon from "@mui/icons-material/ArrowForward";
|
||||
@ -35,7 +35,7 @@ interface IProps {
|
||||
|
||||
interface IAutoAssignProps {
|
||||
office: OfficeSpace;
|
||||
job: EmployeePositions;
|
||||
job: CorpEmployeeJob;
|
||||
desc: string;
|
||||
rerender: () => void;
|
||||
}
|
||||
@ -53,7 +53,7 @@ function EmployeeCount(props: { num: number; next: number }): React.ReactElement
|
||||
function AutoAssignJob(props: IAutoAssignProps): React.ReactElement {
|
||||
const currJob = props.office.employeeJobs[props.job];
|
||||
const nextJob = props.office.employeeNextJobs[props.job];
|
||||
const nextUna = props.office.employeeNextJobs[EmployeePositions.Unassigned];
|
||||
const nextUna = props.office.employeeNextJobs[CorpEmployeeJob.Unassigned];
|
||||
|
||||
function assignEmployee(): void {
|
||||
if (nextUna <= 0) return console.warn("Cannot assign employee. No unassigned employees available");
|
||||
@ -94,10 +94,9 @@ function AutoAssignJob(props: IAutoAssignProps): React.ReactElement {
|
||||
function AutoManagement(props: IProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const division = useDivision();
|
||||
const vechain = corp.unlockUpgrades[4] === 1; // Has Vechain upgrade
|
||||
|
||||
const currUna = props.office.employeeJobs[EmployeePositions.Unassigned];
|
||||
const nextUna = props.office.employeeNextJobs[EmployeePositions.Unassigned];
|
||||
const currUna = props.office.employeeJobs[CorpEmployeeJob.Unassigned];
|
||||
const nextUna = props.office.employeeNextJobs[CorpEmployeeJob.Unassigned];
|
||||
|
||||
return (
|
||||
<Table padding="none">
|
||||
@ -115,7 +114,7 @@ function AutoManagement(props: IProps): React.ReactElement {
|
||||
<Typography>Avg Employee Morale:</Typography>
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<Typography>{formatCorpStat(props.office.avgMor)}</Typography>
|
||||
<Typography>{formatCorpStat(props.office.avgMorale)}</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
@ -123,7 +122,7 @@ function AutoManagement(props: IProps): React.ReactElement {
|
||||
<Typography>Avg Employee Energy:</Typography>
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<Typography>{formatCorpStat(props.office.avgEne)}</Typography>
|
||||
<Typography>{formatCorpStat(props.office.avgEnergy)}</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
@ -131,7 +130,7 @@ function AutoManagement(props: IProps): React.ReactElement {
|
||||
<Typography>Avg Employee Experience:</Typography>
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<Typography>{formatCorpStat(props.office.totalExp / props.office.totalEmployees || 0)}</Typography>
|
||||
<Typography>{formatCorpStat(props.office.totalExperience / props.office.numEmployees || 0)}</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
@ -144,7 +143,7 @@ function AutoManagement(props: IProps): React.ReactElement {
|
||||
</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
{vechain && (
|
||||
{corp.unlocks.has(CorpUnlockName.VeChain) && (
|
||||
<>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
@ -201,14 +200,14 @@ function AutoManagement(props: IProps): React.ReactElement {
|
||||
<AutoAssignJob
|
||||
rerender={props.rerender}
|
||||
office={props.office}
|
||||
job={EmployeePositions.Operations}
|
||||
job={CorpEmployeeJob.Operations}
|
||||
desc={"Manages supply chain operations. Improves the amount of Materials and Products you produce."}
|
||||
/>
|
||||
|
||||
<AutoAssignJob
|
||||
rerender={props.rerender}
|
||||
office={props.office}
|
||||
job={EmployeePositions.Engineer}
|
||||
job={CorpEmployeeJob.Engineer}
|
||||
desc={
|
||||
"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)."
|
||||
}
|
||||
@ -217,14 +216,14 @@ function AutoManagement(props: IProps): React.ReactElement {
|
||||
<AutoAssignJob
|
||||
rerender={props.rerender}
|
||||
office={props.office}
|
||||
job={EmployeePositions.Business}
|
||||
job={CorpEmployeeJob.Business}
|
||||
desc={"Handles sales and finances. Improves the amount of Materials and Products you can sell."}
|
||||
/>
|
||||
|
||||
<AutoAssignJob
|
||||
rerender={props.rerender}
|
||||
office={props.office}
|
||||
job={EmployeePositions.Management}
|
||||
job={CorpEmployeeJob.Management}
|
||||
desc={
|
||||
"Leads and oversees employees and office operations. Improves the effectiveness of Engineer and Operations employees."
|
||||
}
|
||||
@ -233,7 +232,7 @@ function AutoManagement(props: IProps): React.ReactElement {
|
||||
<AutoAssignJob
|
||||
rerender={props.rerender}
|
||||
office={props.office}
|
||||
job={EmployeePositions.RandD}
|
||||
job={CorpEmployeeJob.RandD}
|
||||
desc={
|
||||
"Research new innovative ways to improve the company. Generates Scientific Research. Also increases the quality of everything you produce (not as much as Engineer, however)."
|
||||
}
|
||||
@ -242,7 +241,7 @@ function AutoManagement(props: IProps): React.ReactElement {
|
||||
<AutoAssignJob
|
||||
rerender={props.rerender}
|
||||
office={props.office}
|
||||
job={EmployeePositions.Intern}
|
||||
job={CorpEmployeeJob.Intern}
|
||||
desc={
|
||||
"Set employee to intern, which will increase some of their stats. Employees in intern do not affect any company operations, but gain increased exp and improve morale and energy."
|
||||
}
|
||||
@ -260,32 +259,38 @@ export function IndustryOffice(props: IProps): React.ReactElement {
|
||||
|
||||
function autohireEmployeeButtonOnClick(): void {
|
||||
if (props.office.atCapacity()) return;
|
||||
props.office.hireRandomEmployee(EmployeePositions.Unassigned);
|
||||
props.office.hireRandomEmployee(CorpEmployeeJob.Unassigned);
|
||||
props.rerender();
|
||||
}
|
||||
|
||||
const hireEmployeeDisabledText = props.office.atCapacity() ? "Insufficient office space" : "";
|
||||
const teaDisabledText =
|
||||
corp.funds < props.office.getTeaCost()
|
||||
? "Insufficient corporation funds"
|
||||
: props.office.teaPending
|
||||
? "Tea is already pending for this cycle"
|
||||
: "";
|
||||
const partyPending = props.office.partyMult > 1;
|
||||
const partyDisabledText =
|
||||
corp.funds < 0 ? "Insufficient corporation funds" : partyPending ? "A party is already pending for this cycle" : "";
|
||||
|
||||
return (
|
||||
<Paper>
|
||||
<Typography>Office Space</Typography>
|
||||
<Typography>
|
||||
Size: {props.office.totalEmployees} / {props.office.size} employees
|
||||
Size: {props.office.numEmployees} / {props.office.size} employees
|
||||
</Typography>
|
||||
<Box sx={{ display: "grid", gridTemplateColumns: "1fr", width: "fit-content" }}>
|
||||
<Box sx={{ gridTemplateColumns: "repeat(3, 1fr)" }}>
|
||||
<Tooltip title={<Typography>Hires an employee</Typography>}>
|
||||
<span>
|
||||
<Button disabled={props.office.atCapacity()} onClick={autohireEmployeeButtonOnClick}>
|
||||
Hire Employee
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Tooltip title={<Typography>Upgrade the office's size so that it can hold more employees!</Typography>}>
|
||||
<span>
|
||||
<Button disabled={corp.funds < 0} onClick={() => setUpgradeOfficeSizeOpen(true)}>
|
||||
Upgrade size
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
<ButtonWithTooltip disabledTooltip={hireEmployeeDisabledText} onClick={autohireEmployeeButtonOnClick}>
|
||||
Hire Employee
|
||||
</ButtonWithTooltip>
|
||||
<ButtonWithTooltip
|
||||
normalTooltip={"Upgrade the office's size so that it can hold more employees!"}
|
||||
onClick={() => setUpgradeOfficeSizeOpen(true)}
|
||||
>
|
||||
Upgrade size
|
||||
</ButtonWithTooltip>
|
||||
<UpgradeOfficeSizeModal
|
||||
rerender={props.rerender}
|
||||
office={props.office}
|
||||
@ -294,44 +299,32 @@ export function IndustryOffice(props: IProps): React.ReactElement {
|
||||
/>
|
||||
|
||||
{!division.hasResearch("AutoBrew") && (
|
||||
<>
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
Provide your employees with tea, increasing their energy by half the difference to 100%, plus 1.5%
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<span>
|
||||
<Button
|
||||
disabled={corp.funds < props.office.getTeaCost() || props.office.teaPending}
|
||||
onClick={() => BuyTea(corp, props.office)}
|
||||
>
|
||||
{props.office.teaPending ? (
|
||||
"Buying tea..."
|
||||
) : (
|
||||
<span>
|
||||
Buy Tea - <MoneyCost money={props.office.getTeaCost()} corp={corp} />
|
||||
</span>
|
||||
)}
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
</>
|
||||
<ButtonWithTooltip
|
||||
normalTooltip={
|
||||
"Provide your employees with tea, increasing their energy by half the difference to 100%, plus 1.5%"
|
||||
}
|
||||
disabledTooltip={teaDisabledText}
|
||||
onClick={() => BuyTea(corp, props.office)}
|
||||
>
|
||||
{props.office.teaPending ? (
|
||||
"Buying Tea"
|
||||
) : (
|
||||
<>
|
||||
Buy Tea - <MoneyCost money={props.office.getTeaCost()} corp={corp} />
|
||||
</>
|
||||
)}
|
||||
</ButtonWithTooltip>
|
||||
)}
|
||||
|
||||
{!division.hasResearch("AutoPartyManager") && (
|
||||
<>
|
||||
<Tooltip title={<Typography>Throw an office party to increase your employee's morale</Typography>}>
|
||||
<span>
|
||||
<Button
|
||||
disabled={corp.funds < 0 || props.office.partyMult > 1}
|
||||
onClick={() => setThrowPartyOpen(true)}
|
||||
>
|
||||
{props.office.partyMult > 1 ? "Throwing Party..." : "Throw Party"}
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
<ButtonWithTooltip
|
||||
normalTooltip={"Throw an office party to increase your employees' morale"}
|
||||
disabledTooltip={partyDisabledText}
|
||||
onClick={() => setThrowPartyOpen(true)}
|
||||
>
|
||||
{props.office.partyMult > 1 ? "Throwing Party..." : "Throw Party"}
|
||||
</ButtonWithTooltip>
|
||||
<ThrowPartyModal
|
||||
rerender={props.rerender}
|
||||
office={props.office}
|
||||
|
@ -2,7 +2,7 @@
|
||||
// (top-left panel in the Industry UI)
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { IndustryType } from "../data/Enums";
|
||||
import { CorpUnlockName, IndustryType } from "../data/Enums";
|
||||
import { HireAdVert } from "../Actions";
|
||||
import { formatBigNumber } from "../../ui/formatNumber";
|
||||
import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
|
||||
@ -16,6 +16,7 @@ import { MoneyCost } from "./MoneyCost";
|
||||
import { useCorporation, useDivision } from "./Context";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import { ButtonWithTooltip } from "../../ui/Components/ButtonWithTooltip";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
@ -30,7 +31,7 @@ function MakeProductButton(): React.ReactElement {
|
||||
const hasMaxProducts = division.hasMaximumNumberProducts();
|
||||
|
||||
function shouldFlash(): boolean {
|
||||
return Object.keys(division.products).length === 0;
|
||||
return division.products.size === 0;
|
||||
}
|
||||
|
||||
function onButtonClick() {
|
||||
@ -69,38 +70,35 @@ function MakeProductButton(): React.ReactElement {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const disabledText = hasMaxProducts
|
||||
? `${division.name} already has the maximum number of products (${division.getMaximumNumberProducts()})`
|
||||
: corp.funds < 0
|
||||
? "Insufficient corporation funds"
|
||||
: "";
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip
|
||||
title={
|
||||
hasMaxProducts ? (
|
||||
<Typography>
|
||||
You have reached the maximum number of products: {division.getMaximumNumberProducts()}
|
||||
</Typography>
|
||||
) : (
|
||||
""
|
||||
)
|
||||
}
|
||||
<ButtonWithTooltip
|
||||
disabledTooltip={disabledText}
|
||||
onClick={onButtonClick}
|
||||
buttonProps={{ color: shouldFlash() ? "error" : "primary" }}
|
||||
>
|
||||
<Button color={shouldFlash() ? "error" : "primary"} onClick={onButtonClick} disabled={corp.funds < 0}>
|
||||
{createProductButtonText}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{createProductButtonText}
|
||||
</ButtonWithTooltip>
|
||||
<MakeProductModal open={makeOpen} onClose={() => setMakeOpen(false)} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
interface IProps {
|
||||
interface IndustryOverviewProps {
|
||||
rerender: () => void;
|
||||
}
|
||||
|
||||
export function IndustryOverview(props: IProps): React.ReactElement {
|
||||
export function IndustryOverview(props: IndustryOverviewProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const division = useDivision();
|
||||
const [helpOpen, setHelpOpen] = useState(false);
|
||||
const [researchOpen, setResearchOpen] = useState(false);
|
||||
const vechain = corp.unlockUpgrades[4] === 1;
|
||||
const profit = division.lastCycleRevenue - division.lastCycleExpenses;
|
||||
|
||||
let advertisingInfo = false;
|
||||
@ -109,7 +107,7 @@ export function IndustryOverview(props: IProps): React.ReactElement {
|
||||
const popularityFac = advertisingFactors[2];
|
||||
const ratioFac = advertisingFactors[3];
|
||||
const totalAdvertisingFac = advertisingFactors[0];
|
||||
if (vechain) {
|
||||
if (corp.unlocks.has(CorpUnlockName.VeChain)) {
|
||||
advertisingInfo = true;
|
||||
}
|
||||
|
||||
@ -162,13 +160,13 @@ export function IndustryOverview(props: IProps): React.ReactElement {
|
||||
<Box display="flex" alignItems="center">
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
<>
|
||||
Production gain from owning production-boosting materials such as hardware, Robots, AI Cores, and Real
|
||||
Estate.
|
||||
</Typography>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Typography>Production Multiplier: {formatBigNumber(division.prodMult)}</Typography>
|
||||
<Typography>Production Multiplier: {formatBigNumber(division.productionMult)}</Typography>
|
||||
</Tooltip>
|
||||
<IconButton onClick={() => setHelpOpen(true)}>
|
||||
<HelpIcon />
|
||||
@ -189,25 +187,19 @@ export function IndustryOverview(props: IProps): React.ReactElement {
|
||||
multiplier (Bigger bars = more effective):
|
||||
<br />
|
||||
<br />
|
||||
Hardware: {convertEffectFacToGraphic(division.hwFac)}
|
||||
Hardware: {convertEffectFacToGraphic(division.hardwareFactor)}
|
||||
<br />
|
||||
Robots: {convertEffectFacToGraphic(division.robFac)}
|
||||
Robots: {convertEffectFacToGraphic(division.robotFactor)}
|
||||
<br />
|
||||
AI Cores: {convertEffectFacToGraphic(division.aiFac)}
|
||||
AI Cores: {convertEffectFacToGraphic(division.aiCoreFactor)}
|
||||
<br />
|
||||
Real Estate: {convertEffectFacToGraphic(division.reFac)}
|
||||
Real Estate: {convertEffectFacToGraphic(division.realEstateFactor)}
|
||||
</Typography>
|
||||
</StaticModal>
|
||||
</Box>
|
||||
<Box display="flex" alignItems="center">
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
Scientific Research increases the quality of the materials and products that you produce.
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<Typography>Scientific Research: {formatBigNumber(division.sciResearch)}</Typography>
|
||||
<Tooltip title={"Scientific Research increases the quality of the materials and products that you produce."}>
|
||||
<Typography>Scientific Research: {formatBigNumber(division.researchPoints)}</Typography>
|
||||
</Tooltip>
|
||||
<Button sx={{ mx: 1 }} onClick={() => setResearchOpen(true)}>
|
||||
Research
|
||||
@ -216,26 +208,23 @@ export function IndustryOverview(props: IProps): React.ReactElement {
|
||||
</Box>
|
||||
<br />
|
||||
<Box display="flex" alignItems="center">
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
<ButtonWithTooltip
|
||||
normalTooltip={
|
||||
<>
|
||||
Hire AdVert.Inc to advertise your company. Each level of this upgrade grants your company a static
|
||||
increase of 3 and 1 to its awareness and popularity, respectively. It will then increase your company's
|
||||
increase of 3 and 1 to its awareness and popularity, respectively. It will then increase your company's" +
|
||||
awareness by 1%, and its popularity by a random percentage between 1% and 3%. These effects are increased
|
||||
by other upgrades that increase the power of your advertising.
|
||||
</Typography>
|
||||
</>
|
||||
}
|
||||
disabledTooltip={division.getAdVertCost() > corp.funds ? "Insufficient corporation funds" : ""}
|
||||
onClick={() => {
|
||||
HireAdVert(corp, division);
|
||||
props.rerender();
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
disabled={division.getAdVertCost() > corp.funds}
|
||||
onClick={function () {
|
||||
HireAdVert(corp, division);
|
||||
props.rerender();
|
||||
}}
|
||||
>
|
||||
Hire AdVert - <MoneyCost money={division.getAdVertCost()} corp={corp} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
Hire AdVert - <MoneyCost money={division.getAdVertCost()} corp={corp} />
|
||||
</ButtonWithTooltip>
|
||||
{division.makesProducts && <MakeProductButton />}
|
||||
</Box>
|
||||
</Paper>
|
||||
|
@ -1,20 +1,20 @@
|
||||
import React from "react";
|
||||
import { Industry } from "../Industry";
|
||||
import { Division } from "../Division";
|
||||
import { MathJax } from "better-react-mathjax";
|
||||
import { CorpMaterialName } from "@nsdefs";
|
||||
|
||||
interface IProps {
|
||||
division: Industry;
|
||||
division: Division;
|
||||
}
|
||||
|
||||
export function IndustryProductEquation(props: IProps): React.ReactElement {
|
||||
const reqs = [];
|
||||
for (const reqMat of Object.keys(props.division.reqMats) as CorpMaterialName[]) {
|
||||
const reqAmt = props.division.reqMats[reqMat];
|
||||
for (const reqMat of Object.keys(props.division.requiredMaterials) as CorpMaterialName[]) {
|
||||
const reqAmt = props.division.requiredMaterials[reqMat];
|
||||
if (reqAmt === undefined) continue;
|
||||
reqs.push(String.raw`${reqAmt}\text{ }${reqMat}`);
|
||||
}
|
||||
const prod = props.division.prodMats.map((p) => `1\\text{ }${p}`);
|
||||
const prod = props.division.producedMaterials.map((p) => `1\\text{ }${p}`);
|
||||
if (props.division.makesProducts) {
|
||||
prod.push("Products");
|
||||
}
|
||||
|
@ -12,26 +12,28 @@ import { MaterialInfo } from "../MaterialInfo";
|
||||
import { formatBigNumber, formatMaterialSize } from "../../ui/formatNumber";
|
||||
|
||||
import { Corporation } from "../Corporation";
|
||||
import { Industry } from "../Industry";
|
||||
import { Division } from "../Division";
|
||||
import { MoneyCost } from "./MoneyCost";
|
||||
import { isRelevantMaterial } from "./Helpers";
|
||||
import { IndustryProductEquation } from "./IndustryProductEquation";
|
||||
import { PurchaseWarehouse } from "../Actions";
|
||||
import { purchaseWarehouse } from "../Actions";
|
||||
import { useCorporation, useDivision } from "./Context";
|
||||
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import { ButtonWithTooltip } from "../../ui/Components/ButtonWithTooltip";
|
||||
import Button from "@mui/material/Button";
|
||||
import Box from "@mui/material/Box";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import { CityName } from "../../Enums";
|
||||
import { CorpUnlockName } from "../data/Enums";
|
||||
|
||||
interface IProps {
|
||||
corp: Corporation;
|
||||
division: Industry;
|
||||
warehouse: Warehouse | 0;
|
||||
division: Division;
|
||||
warehouse?: Warehouse;
|
||||
currentCity: CityName;
|
||||
rerender: () => void;
|
||||
}
|
||||
@ -48,14 +50,13 @@ function WarehouseRoot(props: IProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const division = useDivision();
|
||||
const [smartSupplyOpen, setSmartSupplyOpen] = useState(false);
|
||||
if (props.warehouse === 0) return <></>;
|
||||
if (!props.warehouse) return <></>;
|
||||
|
||||
// Upgrade Warehouse size button
|
||||
const sizeUpgradeCost = corpConstants.warehouseSizeUpgradeCostBase * Math.pow(1.07, props.warehouse.level + 1);
|
||||
const canAffordUpgrade = corp.funds > sizeUpgradeCost;
|
||||
function upgradeWarehouseOnClick(): void {
|
||||
if (division === null) return;
|
||||
if (props.warehouse === 0) return;
|
||||
if (!props.warehouse) return;
|
||||
if (!canAffordUpgrade) return;
|
||||
++props.warehouse.level;
|
||||
props.warehouse.updateSize(corp, division);
|
||||
@ -93,7 +94,7 @@ function WarehouseRoot(props: IProps): React.ReactElement {
|
||||
for (const matName of Object.values(corpConstants.materialNames)) {
|
||||
if (!props.warehouse.materials[matName]) continue;
|
||||
// Only create UI for materials that are relevant for the industry or in stock
|
||||
const isInStock = props.warehouse.materials[matName].qty > 0;
|
||||
const isInStock = props.warehouse.materials[matName].stored > 0;
|
||||
const isRelevant = isRelevantMaterial(matName, division);
|
||||
if (!isInStock && !isRelevant) continue;
|
||||
mats.push(
|
||||
@ -108,51 +109,31 @@ function WarehouseRoot(props: IProps): React.ReactElement {
|
||||
}
|
||||
|
||||
// Create React components for products
|
||||
const products = [];
|
||||
if (division.makesProducts && Object.keys(division.products).length > 0) {
|
||||
for (const productName of Object.keys(division.products)) {
|
||||
const product = division.products[productName];
|
||||
if (!product) continue;
|
||||
products.push(
|
||||
const productElements = [];
|
||||
if (division.makesProducts && division.products.size > 0) {
|
||||
for (const [productName, product] of division.products) {
|
||||
productElements.push(
|
||||
<ProductElem rerender={props.rerender} city={props.currentCity} key={productName} product={product} />,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const breakdownItems: JSX.Element[] = [];
|
||||
for (const matName of Object.values(corpConstants.materialNames)) {
|
||||
const breakdownItems: string[] = [];
|
||||
for (const matName of corpConstants.materialNames) {
|
||||
const mat = props.warehouse.materials[matName];
|
||||
if (!Object.hasOwn(MaterialInfo, matName)) continue;
|
||||
if (mat.qty === 0) continue;
|
||||
breakdownItems.push(
|
||||
<>
|
||||
{matName}: {formatMaterialSize(mat.qty * MaterialInfo[matName].size)}
|
||||
</>,
|
||||
);
|
||||
if (mat.stored === 0) continue;
|
||||
breakdownItems.push(`${matName}: ${formatMaterialSize(mat.stored * MaterialInfo[matName].size)}`);
|
||||
}
|
||||
|
||||
for (const prodName of Object.keys(division.products)) {
|
||||
const prod = division.products[prodName];
|
||||
if (prod === undefined) continue;
|
||||
for (const [prodName, product] of division.products) {
|
||||
breakdownItems.push(
|
||||
<>
|
||||
{prodName}: {formatMaterialSize(prod.data[props.warehouse.loc][0] * prod.siz)}
|
||||
</>,
|
||||
`${prodName}: ${formatMaterialSize(product.cityData[props.currentCity].stored * product.size)}`,
|
||||
);
|
||||
}
|
||||
|
||||
let breakdown;
|
||||
if (breakdownItems && breakdownItems.length > 0) {
|
||||
breakdown = breakdownItems.reduce(
|
||||
(previous: JSX.Element, current: JSX.Element): JSX.Element =>
|
||||
(previous && (
|
||||
<>
|
||||
{previous}
|
||||
<br />
|
||||
{current}
|
||||
</>
|
||||
)) || <>{current}</>,
|
||||
);
|
||||
if (breakdownItems.length > 0) {
|
||||
breakdown = breakdownItems.map((item, i) => <p key={i}>{item}</p>);
|
||||
} else {
|
||||
breakdown = <>No items in storage.</>;
|
||||
}
|
||||
@ -160,27 +141,20 @@ function WarehouseRoot(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<Paper>
|
||||
<Box display="flex" alignItems="center">
|
||||
<Tooltip
|
||||
title={
|
||||
props.warehouse.sizeUsed !== 0 ? (
|
||||
<Typography>
|
||||
<>{breakdown}</>
|
||||
</Typography>
|
||||
) : (
|
||||
""
|
||||
)
|
||||
}
|
||||
>
|
||||
<Tooltip title={breakdown}>
|
||||
<Typography color={props.warehouse.sizeUsed >= props.warehouse.size ? "error" : "primary"}>
|
||||
Storage: {formatBigNumber(props.warehouse.sizeUsed)} / {formatBigNumber(props.warehouse.size)}
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
|
||||
<Button disabled={!canAffordUpgrade} onClick={upgradeWarehouseOnClick}>
|
||||
<ButtonWithTooltip
|
||||
disabledTooltip={canAffordUpgrade ? "" : "Insufficient corporation funds"}
|
||||
onClick={upgradeWarehouseOnClick}
|
||||
>
|
||||
Upgrade Warehouse Size -
|
||||
<MoneyCost money={sizeUpgradeCost} corp={corp} />
|
||||
</Button>
|
||||
</ButtonWithTooltip>
|
||||
|
||||
<Typography>This industry uses the following equation for its production: </Typography>
|
||||
<br />
|
||||
@ -196,7 +170,7 @@ function WarehouseRoot(props: IProps): React.ReactElement {
|
||||
|
||||
<Typography className={classes.retainHeight}>{stateText}</Typography>
|
||||
|
||||
{corp.unlockUpgrades[1] && (
|
||||
{corp.unlocks.has(CorpUnlockName.SmartSupply) && (
|
||||
<>
|
||||
<Button onClick={() => setSmartSupplyOpen(true)}>Configure Smart Supply</Button>
|
||||
<SmartSupplyModal
|
||||
@ -209,7 +183,7 @@ function WarehouseRoot(props: IProps): React.ReactElement {
|
||||
|
||||
{mats}
|
||||
|
||||
{products}
|
||||
{productElements}
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
@ -230,18 +204,18 @@ interface IEmptyProps {
|
||||
function EmptyWarehouse(props: IEmptyProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const division = useDivision();
|
||||
const disabled = corp.funds < corpConstants.warehouseInitialCost;
|
||||
function purchaseWarehouse(): void {
|
||||
if (disabled) return;
|
||||
PurchaseWarehouse(corp, division, props.city);
|
||||
const disabledText = corp.funds < corpConstants.warehouseInitialCost ? "Insufficient corporation funds" : "";
|
||||
function newWarehouse(): void {
|
||||
if (disabledText) return;
|
||||
purchaseWarehouse(corp, division, props.city);
|
||||
props.rerender();
|
||||
}
|
||||
return (
|
||||
<Paper>
|
||||
<Button onClick={purchaseWarehouse} disabled={disabled}>
|
||||
<ButtonWithTooltip onClick={newWarehouse} disabledTooltip={disabledText}>
|
||||
Purchase Warehouse (
|
||||
<MoneyCost money={corpConstants.warehouseInitialCost} corp={corp} />)
|
||||
</Button>
|
||||
</ButtonWithTooltip>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
@ -2,49 +2,48 @@
|
||||
import React from "react";
|
||||
|
||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||
import { CorporationUpgrade } from "../data/CorporationUpgrades";
|
||||
import { LevelUpgrade } from "../Actions";
|
||||
import { CorpUpgrades } from "../data/CorporationUpgrades";
|
||||
import { MoneyCost } from "./MoneyCost";
|
||||
import { useCorporation } from "./Context";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import Button from "@mui/material/Button";
|
||||
import { ButtonWithTooltip } from "../../ui/Components/ButtonWithTooltip";
|
||||
import Box from "@mui/material/Box";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { calculateMaxAffordableUpgrade, calculateUpgradeCost } from "../helpers";
|
||||
import { CorpUpgradeName } from "../data/Enums";
|
||||
import { PositiveInteger } from "../../types";
|
||||
|
||||
interface IProps {
|
||||
upgrade: CorporationUpgrade;
|
||||
amount: number | "MAX";
|
||||
upgradeName: CorpUpgradeName;
|
||||
mult: PositiveInteger | "MAX";
|
||||
rerender: () => void;
|
||||
}
|
||||
|
||||
export function LevelableUpgrade(props: IProps): React.ReactElement {
|
||||
export function LevelableUpgrade({ upgradeName, mult, rerender }: IProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const data = props.upgrade;
|
||||
const level = corp.upgrades[data.index];
|
||||
const amount = props.amount;
|
||||
const data = CorpUpgrades[upgradeName];
|
||||
const level = corp.upgrades[upgradeName].level;
|
||||
|
||||
const maxUpgrades = amount === "MAX" ? calculateMaxAffordableUpgrade(corp, data, amount) : amount;
|
||||
const cost = calculateUpgradeCost(corp, data, maxUpgrades);
|
||||
const amount = mult === "MAX" ? calculateMaxAffordableUpgrade(corp, data, mult) : mult;
|
||||
const cost = amount === 0 ? 0 : calculateUpgradeCost(corp, data, amount);
|
||||
const tooltip = data.desc;
|
||||
function onClick(): void {
|
||||
if (corp.funds < cost) return;
|
||||
try {
|
||||
LevelUpgrade(corp, props.upgrade, maxUpgrades);
|
||||
} catch (err) {
|
||||
dialogBoxCreate(err + "");
|
||||
}
|
||||
props.rerender();
|
||||
const message = corp.purchaseUpgrade(upgradeName, amount);
|
||||
if (message) dialogBoxCreate(`Could not upgrade ${upgradeName} ${amount} times:\n${message}`);
|
||||
rerender();
|
||||
}
|
||||
|
||||
return (
|
||||
<Grid item xs={4}>
|
||||
<Box display="flex" alignItems="center" flexDirection="row-reverse">
|
||||
<Button disabled={corp.funds < cost} sx={{ mx: 1 }} onClick={onClick}>
|
||||
+{maxUpgrades} -
|
||||
<MoneyCost money={cost} corp={corp} />
|
||||
</Button>
|
||||
<ButtonWithTooltip
|
||||
disabledTooltip={corp.funds < cost || amount === 0 ? "Insufficient corporation funds" : ""}
|
||||
onClick={onClick}
|
||||
>
|
||||
+{amount} - <MoneyCost money={cost} corp={corp} />
|
||||
</ButtonWithTooltip>
|
||||
<Tooltip title={tooltip}>
|
||||
<Typography>
|
||||
{data.name} - lvl {level}
|
||||
|
@ -4,7 +4,6 @@
|
||||
import React from "react";
|
||||
|
||||
import { CityTabs } from "./CityTabs";
|
||||
import { Industry } from "../Industry";
|
||||
import { Context, useCorporation } from "./Context";
|
||||
|
||||
import { CityName } from "../../Enums";
|
||||
@ -16,12 +15,8 @@ interface IProps {
|
||||
|
||||
export function MainPanel(props: IProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const division =
|
||||
props.divisionName !== "Overview"
|
||||
? corp.divisions.find((division: Industry) => division.name === props.divisionName)
|
||||
: undefined; // use undefined because find returns undefined
|
||||
|
||||
if (division === undefined) throw new Error("Cannot find division");
|
||||
const division = corp.divisions.get(props.divisionName);
|
||||
if (!division) throw new Error("Cannot find division");
|
||||
return (
|
||||
<Context.Division.Provider value={division}>
|
||||
<CityTabs rerender={props.rerender} city={CityName.Sector12} />
|
||||
|
@ -22,6 +22,7 @@ import Button from "@mui/material/Button";
|
||||
import Box from "@mui/material/Box";
|
||||
import { LimitMaterialProductionModal } from "./modals/LimitMaterialProductionModal";
|
||||
import { CityName } from "../../Enums";
|
||||
import { CorpUnlockName } from "../data/Enums";
|
||||
|
||||
interface IMaterialProps {
|
||||
warehouse: Warehouse;
|
||||
@ -50,29 +51,33 @@ export function MaterialElem(props: IMaterialProps): React.ReactElement {
|
||||
}
|
||||
|
||||
// Total gain or loss of this material (per second)
|
||||
const totalGain = mat.buy + mat.prd + mat.imp - mat.sll - mat.totalExp;
|
||||
const totalGain =
|
||||
mat.buyAmount + mat.productionAmount + mat.importAmount - mat.actualSellAmount - mat.exportedLastCycle;
|
||||
|
||||
// Flag that determines whether this industry is "new" and the current material should be
|
||||
// marked with flashing-red lights
|
||||
const tutorial =
|
||||
division.newInd && Object.keys(division.reqMats).includes(mat.name) && mat.buy === 0 && mat.imp === 0;
|
||||
division.newInd &&
|
||||
Object.keys(division.requiredMaterials).includes(mat.name) &&
|
||||
mat.buyAmount === 0 &&
|
||||
mat.importAmount === 0;
|
||||
|
||||
// Purchase material button
|
||||
const purchaseButtonText = `Buy (${formatBigNumber(mat.buy)})`;
|
||||
const purchaseButtonText = `Buy (${formatBigNumber(mat.buyAmount)})`;
|
||||
|
||||
// Sell material button
|
||||
let sellButtonText: JSX.Element;
|
||||
if (mat.sllman[0]) {
|
||||
if (isString(mat.sllman[1])) {
|
||||
if (mat.desiredSellAmount) {
|
||||
if (isString(mat.desiredSellAmount)) {
|
||||
sellButtonText = (
|
||||
<>
|
||||
Sell ({formatBigNumber(mat.sll)}/{mat.sllman[1]})
|
||||
Sell ({formatBigNumber(mat.actualSellAmount)}/{mat.desiredSellAmount[1]})
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
sellButtonText = (
|
||||
<>
|
||||
Sell ({formatBigNumber(mat.sll)}/{formatBigNumber(mat.sllman[1])})
|
||||
Sell ({formatBigNumber(mat.actualSellAmount)}/{formatBigNumber(mat.desiredSellAmount)})
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -86,12 +91,12 @@ export function MaterialElem(props: IMaterialProps): React.ReactElement {
|
||||
} else if (mat.marketTa1) {
|
||||
sellButtonText = (
|
||||
<>
|
||||
{sellButtonText} @ <Money money={mat.bCost + markupLimit} />
|
||||
{sellButtonText} @ <Money money={mat.marketPrice + markupLimit} />
|
||||
</>
|
||||
);
|
||||
} else if (mat.sCost) {
|
||||
if (isString(mat.sCost)) {
|
||||
const sCost = mat.sCost.replace(/MP/g, mat.bCost + "");
|
||||
} else if (mat.desiredSellPrice) {
|
||||
if (isString(mat.desiredSellPrice)) {
|
||||
const sCost = mat.desiredSellPrice.replace(/MP/g, mat.marketPrice + "");
|
||||
sellButtonText = (
|
||||
<>
|
||||
{sellButtonText} @ <Money money={eval(sCost)} />
|
||||
@ -100,7 +105,7 @@ export function MaterialElem(props: IMaterialProps): React.ReactElement {
|
||||
} else {
|
||||
sellButtonText = (
|
||||
<>
|
||||
{sellButtonText} @ <Money money={mat.sCost} />
|
||||
{sellButtonText} @ <Money money={mat.desiredSellPrice} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -111,8 +116,8 @@ export function MaterialElem(props: IMaterialProps): React.ReactElement {
|
||||
|
||||
// Limit Production button
|
||||
let limitMaterialButtonText = "Limit Material";
|
||||
if (mat.prdman[0]) {
|
||||
limitMaterialButtonText += " (" + formatCorpStat(mat.prdman[1]) + ")";
|
||||
if (mat.productionLimit !== null) {
|
||||
limitMaterialButtonText += " (" + formatCorpStat(mat.productionLimit) + ")";
|
||||
}
|
||||
|
||||
return (
|
||||
@ -122,20 +127,28 @@ export function MaterialElem(props: IMaterialProps): React.ReactElement {
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
Buy: {mat.buy >= 1e33 ? mat.buy.toExponential(3) : formatBigNumber(mat.buy)} <br />
|
||||
Prod: {formatBigNumber(mat.prd)} <br />
|
||||
Sell: {formatBigNumber(mat.sll)} <br />
|
||||
Export: {formatBigNumber(mat.totalExp)} <br />
|
||||
Import: {formatBigNumber(mat.imp)}
|
||||
{corp.unlockUpgrades[2] === 1 && <br />}
|
||||
{corp.unlockUpgrades[2] === 1 && "Demand: " + formatCorpStat(mat.dmd)}
|
||||
{corp.unlockUpgrades[3] === 1 && <br />}
|
||||
{corp.unlockUpgrades[3] === 1 && "Competition: " + formatCorpStat(mat.cmp)}
|
||||
Buy: {mat.buyAmount >= 1e33 ? mat.buyAmount.toExponential(3) : formatBigNumber(mat.buyAmount)} <br />
|
||||
Prod: {formatBigNumber(mat.productionAmount)} <br />
|
||||
Sell: {formatBigNumber(mat.actualSellAmount)} <br />
|
||||
Export: {formatBigNumber(mat.exportedLastCycle)} <br />
|
||||
Import: {formatBigNumber(mat.importAmount)}
|
||||
{corp.unlocks.has(CorpUnlockName.MarketResearchDemand) && (
|
||||
<>
|
||||
<br />
|
||||
Demand: {formatCorpStat(mat.demand)}
|
||||
</>
|
||||
)}
|
||||
{corp.unlocks.has(CorpUnlockName.MarketDataCompetition) && (
|
||||
<>
|
||||
<br />
|
||||
Competition: {formatCorpStat(mat.competition)}
|
||||
</>
|
||||
)}
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<Typography>
|
||||
{mat.name}: {formatBigNumber(mat.qty)} (
|
||||
{mat.name}: {formatBigNumber(mat.stored)} (
|
||||
{totalGain >= 1e33 ? totalGain.toExponential(3) : formatBigNumber(totalGain)}/s)
|
||||
</Typography>
|
||||
</Tooltip>
|
||||
@ -146,12 +159,12 @@ export function MaterialElem(props: IMaterialProps): React.ReactElement {
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<Typography>MP: {formatMoney(mat.bCost)}</Typography>
|
||||
<Typography>MP: {formatMoney(mat.marketPrice)}</Typography>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
title={<Typography>The quality of your material. Higher quality will lead to more sales</Typography>}
|
||||
>
|
||||
<Typography>Quality: {formatQuality(mat.qlt)}</Typography>
|
||||
<Typography>Quality: {formatQuality(mat.quality)}</Typography>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
|
||||
@ -167,13 +180,11 @@ export function MaterialElem(props: IMaterialProps): React.ReactElement {
|
||||
mat={mat}
|
||||
warehouse={warehouse}
|
||||
open={purchaseMaterialOpen}
|
||||
disablePurchaseLimit={
|
||||
props.warehouse.smartSupplyEnabled && Object.keys(division.reqMats).includes(props.mat.name)
|
||||
}
|
||||
disablePurchaseLimit={props.warehouse.smartSupplyEnabled && props.mat.name in division.requiredMaterials}
|
||||
onClose={() => setPurchaseMaterialOpen(false)}
|
||||
/>
|
||||
|
||||
{corp.unlockUpgrades[0] === 1 && (
|
||||
{corp.unlocks.has(CorpUnlockName.Export) && (
|
||||
<>
|
||||
<Button onClick={() => setExportOpen(true)}>Export</Button>
|
||||
|
||||
@ -182,7 +193,7 @@ export function MaterialElem(props: IMaterialProps): React.ReactElement {
|
||||
)}
|
||||
|
||||
<Button
|
||||
color={division.prodMats.includes(props.mat.name) && !mat.sllman[0] ? "error" : "primary"}
|
||||
color={division.producedMaterials.includes(props.mat.name) && !mat.desiredSellAmount ? "error" : "primary"}
|
||||
onClick={() => setSellMaterialOpen(true)}
|
||||
>
|
||||
{sellButtonText}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user