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