mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-08 08:43:53 +01:00
CORP: rework (#428)
* corp overhaul: Corp production quality now depends on materials * corp overhaul: Product price can be set separately for each city * corp overhaul: export uses relatives * corp overhaul: ignore energy in quality * corp overhaul: getProduct() is city dependant * corp overhaul: bulkbuy available from start * corp overhaul: add multibuy for leveled upgrads * corp overhaul: changes to UI * corp overhaul: base quality 1, reqmat changes * corp overhaul: puchased material quality is 1 * corp overhaul: get rid of the text box from ta2 * corp overhaul: sold shares limitations * corp overhaul: coffee -> tea, training -> intern * corp overhaul: smartsupply has multiple options * corp overhaul: restart, literature, investore, ui * corp overhaul: nerf advertising * corp overhaul: bunch of stuff
This commit is contained in:
parent
5ffefcca80
commit
1f98eecb57
6
.gitignore
vendored
6
.gitignore
vendored
@ -20,9 +20,9 @@ dist/assets
|
||||
dist/*.worker.*
|
||||
|
||||
# tmp folder for build and electron
|
||||
.app
|
||||
.package
|
||||
.build
|
||||
.app
|
||||
.package
|
||||
.build
|
||||
|
||||
# editor files
|
||||
.vscode
|
||||
|
@ -1,11 +0,0 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [CorpConstants](./bitburner.corpconstants.md) > [coffeeCostPerEmployee](./bitburner.corpconstants.coffeecostperemployee.md)
|
||||
|
||||
## CorpConstants.coffeeCostPerEmployee property
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
coffeeCostPerEmployee: number;
|
||||
```
|
@ -19,7 +19,6 @@ interface CorpConstants
|
||||
| [baseProductProfitMult](./bitburner.corpconstants.baseproductprofitmult.md) | | number | |
|
||||
| [bribeAmountPerReputation](./bitburner.corpconstants.bribeamountperreputation.md) | | number | |
|
||||
| [bribeThreshold](./bitburner.corpconstants.bribethreshold.md) | | number | |
|
||||
| [coffeeCostPerEmployee](./bitburner.corpconstants.coffeecostperemployee.md) | | number | |
|
||||
| [dividendMaxRate](./bitburner.corpconstants.dividendmaxrate.md) | | number | |
|
||||
| [employeeRaiseAmount](./bitburner.corpconstants.employeeraiseamount.md) | | number | |
|
||||
| [employeeSalaryMultiplier](./bitburner.corpconstants.employeesalarymultiplier.md) | | number | Conversion factor for employee stats to initial salary |
|
||||
@ -31,7 +30,7 @@ interface CorpConstants
|
||||
| [marketCyclesPerEmployeeRaise](./bitburner.corpconstants.marketcyclesperemployeeraise.md) | | number | |
|
||||
| [materialNames](./bitburner.corpconstants.materialnames.md) | | [CorpMaterialName](./bitburner.corpmaterialname.md)<!-- -->\[\] | Names of all materials |
|
||||
| [maxProductsBase](./bitburner.corpconstants.maxproductsbase.md) | | number | Max products for a division without upgrades |
|
||||
| [minEmployeeDecay](./bitburner.corpconstants.minemployeedecay.md) | | number | The minimum decay value for happiness/morale/energy |
|
||||
| [minEmployeeDecay](./bitburner.corpconstants.minemployeedecay.md) | | number | The minimum decay value for morale/energy |
|
||||
| [officeInitialCost](./bitburner.corpconstants.officeinitialcost.md) | | number | |
|
||||
| [officeInitialSize](./bitburner.corpconstants.officeinitialsize.md) | | number | |
|
||||
| [officeSizeUpgradeCostBase](./bitburner.corpconstants.officesizeupgradecostbase.md) | | number | |
|
||||
@ -42,6 +41,7 @@ interface CorpConstants
|
||||
| [sellSharesCooldown](./bitburner.corpconstants.sellsharescooldown.md) | | number | Cooldown for selling shares in game cycles (1 game cycle = 200ms) |
|
||||
| [sharesPerPriceUpdate](./bitburner.corpconstants.sharesperpriceupdate.md) | | number | When selling large number of shares, price is dynamically updated for every batch of this amount |
|
||||
| [stateNames](./bitburner.corpconstants.statenames.md) | | [CorpStateName](./bitburner.corpstatename.md)<!-- -->\[\] | Names of all corporation game states |
|
||||
| [teaCostPerEmployee](./bitburner.corpconstants.teacostperemployee.md) | | number | |
|
||||
| [unlockNames](./bitburner.corpconstants.unlocknames.md) | | [CorpUnlockName](./bitburner.corpunlockname.md)<!-- -->\[\] | Names of all one-time corporation-wide unlocks |
|
||||
| [upgradeNames](./bitburner.corpconstants.upgradenames.md) | | [CorpUpgradeName](./bitburner.corpupgradename.md)<!-- -->\[\] | Names of all corporation-wide upgrades |
|
||||
| [warehouseInitialCost](./bitburner.corpconstants.warehouseinitialcost.md) | | number | |
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
## CorpConstants.minEmployeeDecay property
|
||||
|
||||
The minimum decay value for happiness/morale/energy
|
||||
The minimum decay value for morale/energy
|
||||
|
||||
**Signature:**
|
||||
|
||||
|
11
markdown/bitburner.corpconstants.teacostperemployee.md
Normal file
11
markdown/bitburner.corpconstants.teacostperemployee.md
Normal file
@ -0,0 +1,11 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [CorpConstants](./bitburner.corpconstants.md) > [teaCostPerEmployee](./bitburner.corpconstants.teacostperemployee.md)
|
||||
|
||||
## CorpConstants.teaCostPerEmployee property
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
teaCostPerEmployee: number;
|
||||
```
|
@ -14,6 +14,6 @@ type CorpEmployeePosition =
|
||||
| "Business"
|
||||
| "Management"
|
||||
| "Research & Development"
|
||||
| "Training"
|
||||
| "Intern"
|
||||
| "Unassigned";
|
||||
```
|
||||
|
@ -9,12 +9,13 @@
|
||||
|
||||
```typescript
|
||||
type CorpIndustryName =
|
||||
| "Energy"
|
||||
| "Spring Water"
|
||||
| "Water Utilities"
|
||||
| "Agriculture"
|
||||
| "Fishing"
|
||||
| "Mining"
|
||||
| "Food"
|
||||
| "Refinery"
|
||||
| "Restaurant"
|
||||
| "Tobacco"
|
||||
| "Chemical"
|
||||
| "Pharmaceutical"
|
||||
|
@ -9,8 +9,9 @@
|
||||
|
||||
```typescript
|
||||
type CorpMaterialName =
|
||||
| "Minerals"
|
||||
| "Ore"
|
||||
| "Water"
|
||||
| "Energy"
|
||||
| "Food"
|
||||
| "Plants"
|
||||
| "Metal"
|
||||
|
@ -16,7 +16,7 @@ buyBackShares(amount: number): void;
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| amount | number | Amount of shares to buy back. |
|
||||
| amount | number | Amount of shares to buy back, must be integer and larger than 0 |
|
||||
|
||||
**Returns:**
|
||||
|
||||
|
@ -16,7 +16,7 @@ sellShares(amount: number): void;
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| amount | number | Amount of shares to sell. |
|
||||
| amount | number | Amount of shares to sell, must be integer between 1 and 100t |
|
||||
|
||||
**Returns:**
|
||||
|
||||
|
@ -24,6 +24,7 @@ interface Material
|
||||
| [prod](./bitburner.material.prod.md) | | number | Amount of material produced |
|
||||
| [qlt](./bitburner.material.qlt.md) | | number | Quality of the material |
|
||||
| [qty](./bitburner.material.qty.md) | | number | Amount of material |
|
||||
| [sAmt](./bitburner.material.samt.md) | | string \| number | Sell amount, can be "PROD/2" |
|
||||
| [sCost](./bitburner.material.scost.md) | | string \| number | Sell cost, can be "MP+5" |
|
||||
| [sell](./bitburner.material.sell.md) | | number | Amount of material sold |
|
||||
|
||||
|
13
markdown/bitburner.material.samt.md
Normal file
13
markdown/bitburner.material.samt.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) > [sAmt](./bitburner.material.samt.md)
|
||||
|
||||
## Material.sAmt property
|
||||
|
||||
Sell amount, can be "PROD/2"
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
sAmt: string | number;
|
||||
```
|
@ -1,13 +0,0 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Office](./bitburner.office.md) > [avgHap](./bitburner.office.avghap.md)
|
||||
|
||||
## Office.avgHap property
|
||||
|
||||
Average happiness of the employees
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
avgHap: number;
|
||||
```
|
@ -1,13 +0,0 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [Office](./bitburner.office.md) > [maxHap](./bitburner.office.maxhap.md)
|
||||
|
||||
## Office.maxHap property
|
||||
|
||||
Maximum happiness of the employees
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
maxHap: number;
|
||||
```
|
@ -17,14 +17,12 @@ export interface Office
|
||||
| Property | Modifiers | Type | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| [avgEne](./bitburner.office.avgene.md) | | number | Average energy of the employees |
|
||||
| [avgHap](./bitburner.office.avghap.md) | | number | Average happiness of the employees |
|
||||
| [avgMor](./bitburner.office.avgmor.md) | | number | Average morale 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 |
|
||||
| [employees](./bitburner.office.employees.md) | | number | Amount of employees |
|
||||
| [loc](./bitburner.office.loc.md) | | [CityName](./bitburner.cityname.md) | City of the office |
|
||||
| [maxEne](./bitburner.office.maxene.md) | | number | Maximum amount of energy of the employees |
|
||||
| [maxHap](./bitburner.office.maxhap.md) | | number | Maximum happiness of the employees |
|
||||
| [maxMor](./bitburner.office.maxmor.md) | | number | Maximum morale of the employees |
|
||||
| [size](./bitburner.office.size.md) | | number | Maximum number of employee |
|
||||
| [totalExperience](./bitburner.office.totalexperience.md) | | number | Total experience of all employees |
|
||||
|
@ -1,15 +1,15 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [OfficeAPI](./bitburner.officeapi.md) > [buyCoffee](./bitburner.officeapi.buycoffee.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [OfficeAPI](./bitburner.officeapi.md) > [buyTea](./bitburner.officeapi.buytea.md)
|
||||
|
||||
## OfficeAPI.buyCoffee() method
|
||||
## OfficeAPI.buyTea() method
|
||||
|
||||
Buy coffee for your employees
|
||||
Buy tea for your employees
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
buyCoffee(divisionName: string, city: CityName | `${CityName}`): boolean;
|
||||
buyTea(divisionName: string, city: CityName | `${CityName}`): boolean;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -23,5 +23,5 @@ buyCoffee(divisionName: string, city: CityName | `${CityName}`): boolean;
|
||||
|
||||
boolean
|
||||
|
||||
true if buying coffee was successful, false otherwise
|
||||
true if buying tea was successful, false otherwise
|
||||
|
@ -20,7 +20,7 @@ requires the Office API upgrade from your corporation.
|
||||
|
||||
| Method | Description |
|
||||
| --- | --- |
|
||||
| [buyCoffee(divisionName, city)](./bitburner.officeapi.buycoffee.md) | Buy coffee for your employees |
|
||||
| [buyTea(divisionName, city)](./bitburner.officeapi.buytea.md) | Buy tea for your employees |
|
||||
| [getHireAdVertCost(divisionName)](./bitburner.officeapi.gethireadvertcost.md) | Get the cost to hire AdVert. |
|
||||
| [getHireAdVertCount(divisionName)](./bitburner.officeapi.gethireadvertcount.md) | Get the number of times you have hired AdVert. |
|
||||
| [getOffice(divisionName, city)](./bitburner.officeapi.getoffice.md) | Get data about an office |
|
||||
|
@ -24,5 +24,5 @@ throwParty(divisionName: string, city: CityName | `${CityName}`, costPerEmployee
|
||||
|
||||
number
|
||||
|
||||
Multiplier for happiness and morale, or zero on failure
|
||||
Multiplier for morale, or zero on failure
|
||||
|
||||
|
@ -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) > [cityData](./bitburner.product.citydata.md)
|
||||
|
||||
## Product.cityData property
|
||||
|
||||
Data refers to the production, sale, and quantity of the products These values are specific to a city For each city, the data is \[qty, prod, sell\]
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
cityData: Record<CityName | `${CityName}`, number[]>;
|
||||
```
|
13
markdown/bitburner.product.effrat.md
Normal file
13
markdown/bitburner.product.effrat.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) > [effRat](./bitburner.product.effrat.md)
|
||||
|
||||
## Product.effRat property
|
||||
|
||||
Effective rating
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
effRat: number;
|
||||
```
|
@ -16,13 +16,17 @@ interface Product
|
||||
|
||||
| Property | Modifiers | Type | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| [cityData](./bitburner.product.citydata.md) | | Record<[CityName](./bitburner.cityname.md) \| \`${[CityName](./bitburner.cityname.md)<!-- -->}\`, number\[\]> | Data refers to the production, sale, and quantity of the products These values are specific to a city For each city, the data is \[qty, prod, sell\] |
|
||||
| [cmp](./bitburner.product.cmp.md) | | number \| undefined | Competition for the product, only present if "Market Research - Competition" unlocked |
|
||||
| [developmentProgress](./bitburner.product.developmentprogress.md) | | number | Creation progress - A number between 0-100 representing percentage |
|
||||
| [dmd](./bitburner.product.dmd.md) | | number \| undefined | Demand for the product, only present if "Market Research - Demand" unlocked |
|
||||
| [effRat](./bitburner.product.effrat.md) | | number | Effective rating |
|
||||
| [name](./bitburner.product.name.md) | | string | Name of the product |
|
||||
| [pCost](./bitburner.product.pcost.md) | | number | Production cost |
|
||||
| [prod](./bitburner.product.prod.md) | | number | Amount of product produced |
|
||||
| [properties](./bitburner.product.properties.md) | | { \[key: string\]: number } | Product Properties. The data is {<!-- -->qlt, per, dur, rel, aes, fea<!-- -->} |
|
||||
| [qty](./bitburner.product.qty.md) | | number | Amount of product |
|
||||
| [rat](./bitburner.product.rat.md) | | number | Product Rating |
|
||||
| [sCost](./bitburner.product.scost.md) | | string \| number | Sell cost, can be "MP+5" |
|
||||
| [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.prod.md
Normal file
13
markdown/bitburner.product.prod.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) > [prod](./bitburner.product.prod.md)
|
||||
|
||||
## Product.prod property
|
||||
|
||||
Amount of product produced
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
prod: number;
|
||||
```
|
13
markdown/bitburner.product.qty.md
Normal file
13
markdown/bitburner.product.qty.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) > [qty](./bitburner.product.qty.md)
|
||||
|
||||
## Product.qty property
|
||||
|
||||
Amount of product
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
qty: number;
|
||||
```
|
13
markdown/bitburner.product.samt.md
Normal file
13
markdown/bitburner.product.samt.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) > [sAmt](./bitburner.product.samt.md)
|
||||
|
||||
## Product.sAmt property
|
||||
|
||||
Sell amount, can be "PROD/2"
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
sAmt: string;
|
||||
```
|
@ -9,5 +9,5 @@ Sell cost, can be "MP+5"
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
sCost: string | number;
|
||||
sCost: string;
|
||||
```
|
||||
|
13
markdown/bitburner.product.sell.md
Normal file
13
markdown/bitburner.product.sell.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) > [sell](./bitburner.product.sell.md)
|
||||
|
||||
## Product.sell property
|
||||
|
||||
Amount of product sold
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
sell: number;
|
||||
```
|
@ -9,7 +9,7 @@ Get product data
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
getProduct(divisionName: string, productName: string): Product;
|
||||
getProduct(divisionName: string, city: CityName | `${CityName}`, productName: string): Product;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -17,6 +17,7 @@ getProduct(divisionName: string, productName: string): Product;
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| divisionName | string | Name of the division |
|
||||
| city | [CityName](./bitburner.cityname.md) \| \`${[CityName](./bitburner.cityname.md)<!-- -->}\` | Name of the city |
|
||||
| productName | string | Name of the product |
|
||||
|
||||
**Returns:**
|
||||
|
@ -26,7 +26,7 @@ Requires the Warehouse API upgrade from your corporation.
|
||||
| [discontinueProduct(divisionName, productName)](./bitburner.warehouseapi.discontinueproduct.md) | Discontinue a product. |
|
||||
| [exportMaterial(sourceDivision, sourceCity, targetDivision, targetCity, materialName, amt)](./bitburner.warehouseapi.exportmaterial.md) | Set material export data |
|
||||
| [getMaterial(divisionName, city, materialName)](./bitburner.warehouseapi.getmaterial.md) | Get material data |
|
||||
| [getProduct(divisionName, productName)](./bitburner.warehouseapi.getproduct.md) | Get product data |
|
||||
| [getProduct(divisionName, city, productName)](./bitburner.warehouseapi.getproduct.md) | Get product data |
|
||||
| [getUpgradeWarehouseCost(divisionName, city, amt)](./bitburner.warehouseapi.getupgradewarehousecost.md) | Gets the cost to upgrade a warehouse to the next level |
|
||||
| [getWarehouse(divisionName, city)](./bitburner.warehouseapi.getwarehouse.md) | Get warehouse data |
|
||||
| [hasWarehouse(divisionName, city)](./bitburner.warehouseapi.haswarehouse.md) | Check if you have a warehouse in city |
|
||||
@ -38,9 +38,9 @@ Requires the Warehouse API upgrade from your corporation.
|
||||
| [sellProduct(divisionName, city, productName, amt, price, all)](./bitburner.warehouseapi.sellproduct.md) | Set product sell data. |
|
||||
| [setMaterialMarketTA1(divisionName, city, materialName, on)](./bitburner.warehouseapi.setmaterialmarketta1.md) | Set market TA 1 for a material. |
|
||||
| [setMaterialMarketTA2(divisionName, city, materialName, on)](./bitburner.warehouseapi.setmaterialmarketta2.md) | Set market TA 2 for a material. |
|
||||
| [setProductMarketTA1(divisionName, productName, on)](./bitburner.warehouseapi.setproductmarketta1.md) | Set market TA 1 for a product. |
|
||||
| [setProductMarketTA2(divisionName, productName, on)](./bitburner.warehouseapi.setproductmarketta2.md) | Set market TA 2 for a product. |
|
||||
| [setProductMarketTA1(divisionName, city, productName, on)](./bitburner.warehouseapi.setproductmarketta1.md) | Set market TA 1 for a product. |
|
||||
| [setProductMarketTA2(divisionName, city, productName, on)](./bitburner.warehouseapi.setproductmarketta2.md) | Set market TA 2 for a product. |
|
||||
| [setSmartSupply(divisionName, city, enabled)](./bitburner.warehouseapi.setsmartsupply.md) | Set smart supply |
|
||||
| [setSmartSupplyUseLeftovers(divisionName, city, materialName, enabled)](./bitburner.warehouseapi.setsmartsupplyuseleftovers.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 |
|
||||
|
||||
|
@ -9,7 +9,7 @@ Set market TA 1 for a product.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
setProductMarketTA1(divisionName: string, productName: string, on: boolean): void;
|
||||
setProductMarketTA1(divisionName: string, city: CityName | `${CityName}`, productName: string, on: boolean): void;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -17,6 +17,7 @@ setProductMarketTA1(divisionName: string, productName: string, on: boolean): voi
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| divisionName | string | Name of the division |
|
||||
| city | [CityName](./bitburner.cityname.md) \| \`${[CityName](./bitburner.cityname.md)<!-- -->}\` | Name of the city |
|
||||
| productName | string | Name of the product |
|
||||
| on | boolean | market ta enabled |
|
||||
|
||||
|
@ -9,7 +9,7 @@ Set market TA 2 for a product.
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
setProductMarketTA2(divisionName: string, productName: string, on: boolean): void;
|
||||
setProductMarketTA2(divisionName: string, city: CityName | `${CityName}`, productName: string, on: boolean): void;
|
||||
```
|
||||
|
||||
## Parameters
|
||||
@ -17,6 +17,7 @@ setProductMarketTA2(divisionName: string, productName: string, on: boolean): voi
|
||||
| Parameter | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| divisionName | string | Name of the division |
|
||||
| city | [CityName](./bitburner.cityname.md) \| \`${[CityName](./bitburner.cityname.md)<!-- -->}\` | Name of the city |
|
||||
| productName | string | Name of the product |
|
||||
| on | boolean | market ta enabled |
|
||||
|
||||
|
@ -1,19 +1,19 @@
|
||||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [WarehouseAPI](./bitburner.warehouseapi.md) > [setSmartSupplyUseLeftovers](./bitburner.warehouseapi.setsmartsupplyuseleftovers.md)
|
||||
[Home](./index.md) > [bitburner](./bitburner.md) > [WarehouseAPI](./bitburner.warehouseapi.md) > [setSmartSupplyOption](./bitburner.warehouseapi.setsmartsupplyoption.md)
|
||||
|
||||
## WarehouseAPI.setSmartSupplyUseLeftovers() method
|
||||
## WarehouseAPI.setSmartSupplyOption() method
|
||||
|
||||
Set whether smart supply uses leftovers before buying
|
||||
|
||||
**Signature:**
|
||||
|
||||
```typescript
|
||||
setSmartSupplyUseLeftovers(
|
||||
setSmartSupplyOption(
|
||||
divisionName: string,
|
||||
city: CityName | `${CityName}`,
|
||||
materialName: string,
|
||||
enabled: boolean,
|
||||
option: string,
|
||||
): void;
|
||||
```
|
||||
|
||||
@ -24,7 +24,7 @@ setSmartSupplyUseLeftovers(
|
||||
| divisionName | string | Name of the division |
|
||||
| city | [CityName](./bitburner.cityname.md) \| \`${[CityName](./bitburner.cityname.md)<!-- -->}\` | Name of the city |
|
||||
| materialName | string | Name of the material |
|
||||
| enabled | boolean | smart supply use leftovers enabled |
|
||||
| option | string | smart supply option, "leftovers" to use leftovers, "imports" to use only imported materials, "none" to not use materials from store |
|
||||
|
||||
**Returns:**
|
||||
|
@ -499,6 +499,7 @@ export const defaultMultipliers: IBitNodeMultipliers = {
|
||||
|
||||
CorporationValuation: 1,
|
||||
CorporationSoftcap: 1,
|
||||
CorporationDivisions: 1,
|
||||
|
||||
BladeburnerRank: 1,
|
||||
BladeburnerSkillCost: 1,
|
||||
@ -538,6 +539,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
||||
FactionWorkRepGain: 0.5,
|
||||
|
||||
CorporationSoftcap: 0.9,
|
||||
CorporationDivisions: 0.9,
|
||||
|
||||
InfiltrationMoney: 3,
|
||||
StaneksGiftPowerMultiplier: 2,
|
||||
@ -623,7 +625,8 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
||||
InfiltrationMoney: 1.5,
|
||||
InfiltrationRep: 1.5,
|
||||
|
||||
CorporationValuation: 0.5,
|
||||
CorporationValuation: 0.75,
|
||||
CorporationDivisions: 0.75,
|
||||
|
||||
GangUniqueAugs: 0.5,
|
||||
|
||||
@ -654,6 +657,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
||||
|
||||
CorporationValuation: 0.2,
|
||||
CorporationSoftcap: 0.9,
|
||||
CorporationDivisions: 0.8,
|
||||
|
||||
GangSoftcap: 0.7,
|
||||
GangUniqueAugs: 0.2,
|
||||
@ -692,6 +696,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
||||
|
||||
CorporationValuation: 0.2,
|
||||
CorporationSoftcap: 0.9,
|
||||
CorporationDivisions: 0.8,
|
||||
|
||||
BladeburnerRank: 0.6,
|
||||
BladeburnerSkillCost: 2,
|
||||
@ -725,6 +730,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
||||
|
||||
CorporationValuation: 0,
|
||||
CorporationSoftcap: 0,
|
||||
CorporationDivisions: 0,
|
||||
|
||||
BladeburnerRank: 0,
|
||||
|
||||
@ -760,7 +766,8 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
||||
FourSigmaMarketDataApiCost: 4,
|
||||
|
||||
CorporationValuation: 0.5,
|
||||
CorporationSoftcap: 0.7,
|
||||
CorporationSoftcap: 0.75,
|
||||
CorporationDivisions: 0.8,
|
||||
|
||||
BladeburnerRank: 0.9,
|
||||
BladeburnerSkillCost: 1.2,
|
||||
@ -804,6 +811,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
||||
|
||||
CorporationValuation: 0.5,
|
||||
CorporationSoftcap: 0.9,
|
||||
CorporationDivisions: 0.9,
|
||||
|
||||
BladeburnerRank: 0.8,
|
||||
|
||||
@ -844,6 +852,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
||||
|
||||
CorporationValuation: 0.1,
|
||||
CorporationSoftcap: 0.9,
|
||||
CorporationDivisions: 0.9,
|
||||
|
||||
GangUniqueAugs: 0.75,
|
||||
|
||||
@ -907,6 +916,7 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
||||
|
||||
CorporationValuation: dec,
|
||||
CorporationSoftcap: 0.8,
|
||||
CorporationDivisions: 0.5,
|
||||
|
||||
BladeburnerRank: dec,
|
||||
BladeburnerSkillCost: inc,
|
||||
@ -952,7 +962,8 @@ export function getBitNodeMultipliers(n: number, lvl: number): IBitNodeMultiplie
|
||||
FourSigmaMarketDataApiCost: 10,
|
||||
|
||||
CorporationValuation: 0.001,
|
||||
CorporationSoftcap: 0.3,
|
||||
CorporationSoftcap: 0.4,
|
||||
CorporationDivisions: 0.4,
|
||||
|
||||
BladeburnerRank: 0.45,
|
||||
BladeburnerSkillCost: 2,
|
||||
|
@ -154,9 +154,12 @@ export interface IBitNodeMultipliers {
|
||||
/** Influences the hacking skill required to backdoor the world daemon. */
|
||||
WorldDaemonDifficulty: number;
|
||||
|
||||
/** Influences corporation dividends. */
|
||||
/** Influences profits from corporation dividends and selling shares. */
|
||||
CorporationSoftcap: number;
|
||||
|
||||
/** Influences number of divisions a corporation can have. */
|
||||
CorporationDivisions: number;
|
||||
|
||||
// Index signature
|
||||
[key: string]: number;
|
||||
}
|
||||
|
@ -343,6 +343,7 @@ function CorporationMults({ mults }: IMultsProps): React.ReactElement {
|
||||
content: mults.CorporationSoftcap.toFixed(3),
|
||||
},
|
||||
CorporationValuation: { name: "Valuation" },
|
||||
CorporationDivisions: { name: "Division limit" },
|
||||
};
|
||||
|
||||
return <BNMultTable sectionName="Corporation" rowData={rows} mults={mults} />;
|
||||
|
@ -17,10 +17,12 @@ import { isRelevantMaterial } from "./ui/Helpers";
|
||||
import { CityName } from "../Enums";
|
||||
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||
import { CorpResearchName } from "@nsdefs";
|
||||
import { calculateUpgradeCost } from "./helpers";
|
||||
import { isInteger } from "lodash";
|
||||
|
||||
export function NewIndustry(corporation: Corporation, industry: IndustryType, name: string): void {
|
||||
if (corporation.divisions.find(({ type }) => industry == type))
|
||||
throw new Error(`You have already expanded into the ${industry} industry!`);
|
||||
if (corporation.divisions.length >= corporation.maxDivisions)
|
||||
throw new Error(`Cannot expand into ${industry} industry, too many divisions!`);
|
||||
|
||||
for (let i = 0; i < corporation.divisions.length; ++i) {
|
||||
if (corporation.divisions[i].name === name) {
|
||||
@ -47,6 +49,13 @@ export function NewIndustry(corporation: Corporation, industry: IndustryType, na
|
||||
}
|
||||
}
|
||||
|
||||
export function removeIndustry(corporation: Corporation, name: string) {
|
||||
const divIndex = corporation.divisions.findIndex((div) => div.name === name);
|
||||
if (divIndex === -1) throw new Error("There is no division called " + name);
|
||||
|
||||
corporation.divisions.splice(divIndex, 1);
|
||||
}
|
||||
|
||||
export function NewCity(corporation: Corporation, division: Industry, city: CityName): void {
|
||||
if (corporation.funds < corpConstants.officeInitialCost) {
|
||||
throw new Error("You don't have enough company funds to open a new office!");
|
||||
@ -71,15 +80,12 @@ export function UnlockUpgrade(corporation: Corporation, upgrade: CorporationUnlo
|
||||
corporation.unlock(upgrade);
|
||||
}
|
||||
|
||||
export function LevelUpgrade(corporation: Corporation, upgrade: CorporationUpgrade): void {
|
||||
const baseCost = upgrade.basePrice;
|
||||
const priceMult = upgrade.priceMult;
|
||||
const level = corporation.upgrades[upgrade.index];
|
||||
const cost = baseCost * Math.pow(priceMult, level);
|
||||
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);
|
||||
corporation.upgrade(upgrade, amount);
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,7 +107,7 @@ export function IssueNewShares(corporation: Corporation, amount: number): [numbe
|
||||
throw new Error(`Invalid value. Must be an number between 10m and ${max} (20% of total shares)`);
|
||||
}
|
||||
|
||||
const newSharePrice = Math.round(corporation.sharePrice * 0.9);
|
||||
const newSharePrice = Math.round(corporation.sharePrice * 0.8);
|
||||
|
||||
const profit = amount * newSharePrice;
|
||||
corporation.issueNewSharesCooldown = corpConstants.issueNewSharesCooldown;
|
||||
@ -143,21 +149,21 @@ export function SellMaterial(mat: Material, amt: string, price: string): void {
|
||||
|
||||
//Parse quantity
|
||||
amt = amt.toUpperCase();
|
||||
if (amt.includes("MAX") || amt.includes("PROD")) {
|
||||
if (amt.includes("MAX") || amt.includes("PROD") || amt.includes("INV")) {
|
||||
let q = amt.replace(/\s+/g, "");
|
||||
q = q.replace(/[^-()\d/*+.MAXPROD]/g, "");
|
||||
q = q.replace(/[^-()\d/*+.MAXPRODINV]/g, "");
|
||||
let tempQty = q.replace(/MAX/g, mat.maxsll.toString());
|
||||
tempQty = tempQty.replace(/PROD/g, mat.prd.toString());
|
||||
tempQty = tempQty.replace(/INV/g, mat.prd.toString());
|
||||
try {
|
||||
tempQty = eval(tempQty);
|
||||
} catch (e) {
|
||||
throw new Error("Invalid value or expression for sell quantity field: " + e);
|
||||
}
|
||||
|
||||
if (tempQty == null || isNaN(parseFloat(tempQty)) || parseFloat(tempQty) < 0) {
|
||||
if (tempQty == null || isNaN(parseFloat(tempQty))) {
|
||||
throw new Error("Invalid value or expression for sell quantity field");
|
||||
}
|
||||
|
||||
mat.sllman[0] = true;
|
||||
mat.sllman[1] = q; //Use sanitized input
|
||||
} else if (isNaN(parseFloat(amt)) || parseFloat(amt) < 0) {
|
||||
@ -194,13 +200,13 @@ export function SellProduct(product: Product, city: string, amt: string, price:
|
||||
if (temp == null || isNaN(parseFloat(temp))) {
|
||||
throw new Error("Invalid value or expression for sell price field.");
|
||||
}
|
||||
product.sCost = price; //Use sanitized price
|
||||
product.sCost[city] = price; //Use sanitized price
|
||||
} else {
|
||||
const cost = parseFloat(price);
|
||||
if (isNaN(cost)) {
|
||||
throw new Error("Invalid value for sell price field");
|
||||
}
|
||||
product.sCost = cost;
|
||||
product.sCost[city] = cost;
|
||||
}
|
||||
|
||||
// Array of all cities. Used later
|
||||
@ -208,19 +214,20 @@ export function SellProduct(product: Product, city: string, amt: string, price:
|
||||
|
||||
// Parse quantity
|
||||
amt = amt.toUpperCase();
|
||||
if (amt.includes("MAX") || amt.includes("PROD")) {
|
||||
if (amt.includes("MAX") || amt.includes("PROD") || amt.includes("INV")) {
|
||||
//Dynamically evaluated quantity. First test to make sure its valid
|
||||
let qty = amt.replace(/\s+/g, "");
|
||||
qty = qty.replace(/[^-()\d/*+.MAXPROD]/g, "");
|
||||
qty = qty.replace(/[^-()\d/*+.MAXPRODINV]/g, "");
|
||||
let temp = qty.replace(/MAX/g, product.maxsll.toString());
|
||||
temp = temp.replace(/PROD/g, product.data[city][1].toString());
|
||||
temp = temp.replace(/INV/g, product.data[city][0].toString());
|
||||
try {
|
||||
temp = eval(temp);
|
||||
} catch (e) {
|
||||
throw new Error("Invalid value or expression for sell quantity field: " + e);
|
||||
}
|
||||
|
||||
if (temp == null || isNaN(parseFloat(temp)) || parseFloat(temp) < 0) {
|
||||
if (temp == null || isNaN(parseFloat(temp))) {
|
||||
throw new Error("Invalid value or expression for sell quantity field");
|
||||
}
|
||||
if (all) {
|
||||
@ -268,8 +275,11 @@ export function SetSmartSupply(warehouse: Warehouse, smartSupply: boolean): void
|
||||
warehouse.smartSupplyEnabled = smartSupply;
|
||||
}
|
||||
|
||||
export function SetSmartSupplyUseLeftovers(warehouse: Warehouse, material: Material, useLeftover: boolean): void {
|
||||
warehouse.smartSupplyUseLeftovers[material.name] = useLeftover;
|
||||
export function SetSmartSupplyOption(warehouse: Warehouse, material: Material, useOption: string): void {
|
||||
if (!corpConstants.smartSupplyUseOptions.includes(useOption)) {
|
||||
throw new Error(`Invalid Smart Supply option '${useOption}'`);
|
||||
}
|
||||
warehouse.smartSupplyOptions[material.name] = useOption;
|
||||
}
|
||||
|
||||
export function BuyMaterial(material: Material, amt: number): void {
|
||||
@ -298,9 +308,11 @@ export function BulkPurchase(corp: Corporation, warehouse: Warehouse, material:
|
||||
}
|
||||
|
||||
export function SellShares(corporation: Corporation, numShares: number): number {
|
||||
if (isNaN(numShares)) throw new Error("Invalid value for number of shares");
|
||||
if (numShares < 0) throw new Error("Invalid value for number of shares");
|
||||
if (isNaN(numShares) || !isInteger(numShares)) throw new Error("Invalid value for number of shares");
|
||||
if (numShares <= 0) throw new Error("Invalid value for number of shares");
|
||||
if (numShares > corporation.numShares) throw new Error("You don't have that many shares to sell!");
|
||||
if (numShares === corporation.numShares) throw new Error("You cant't sell all your shares!");
|
||||
if (numShares > 1e14) throw new Error("Invalid value for number of shares");
|
||||
if (!corporation.public) throw new Error("You haven't gone public!");
|
||||
if (corporation.shareSaleCooldown) throw new Error("Share sale on cooldown!");
|
||||
const stockSaleResults = corporation.calculateShareSale(numShares);
|
||||
@ -318,8 +330,8 @@ export function SellShares(corporation: Corporation, numShares: number): number
|
||||
}
|
||||
|
||||
export function BuyBackShares(corporation: Corporation, numShares: number): boolean {
|
||||
if (isNaN(numShares)) throw new Error("Invalid value for number of shares");
|
||||
if (numShares < 0) throw new Error("Invalid value for number of shares");
|
||||
if (isNaN(numShares) || !isInteger(numShares)) throw new Error("Invalid value for number of shares");
|
||||
if (numShares <= 0) throw new Error("Invalid value for number of shares");
|
||||
if (numShares > corporation.issuedShares) throw new Error("You don't have that many shares to buy!");
|
||||
if (!corporation.public) throw new Error("You haven't gone public!");
|
||||
const buybackPrice = corporation.sharePrice * 1.1;
|
||||
@ -344,9 +356,9 @@ export function UpgradeOfficeSize(corp: Corporation, office: OfficeSpace, size:
|
||||
corp.funds = corp.funds - cost;
|
||||
}
|
||||
|
||||
export function BuyCoffee(corp: Corporation, office: OfficeSpace): boolean {
|
||||
const cost = office.getCoffeeCost();
|
||||
if (corp.funds < cost || !office.setCoffee()) return false;
|
||||
export function BuyTea(corp: Corporation, office: OfficeSpace): boolean {
|
||||
const cost = office.getTeaCost();
|
||||
if (corp.funds < cost || !office.setTea()) return false;
|
||||
corp.funds -= cost;
|
||||
return true;
|
||||
}
|
||||
@ -495,8 +507,12 @@ export function ExportMaterial(
|
||||
): void {
|
||||
// Sanitize amt
|
||||
let sanitizedAmt = amt.replace(/\s+/g, "").toUpperCase();
|
||||
sanitizedAmt = sanitizedAmt.replace(/[^-()\d/*+.MAX]/g, "");
|
||||
sanitizedAmt = sanitizedAmt.replace(/[^-()\d/*+.MAXEPRODINV]/g, "");
|
||||
let temp = sanitizedAmt.replace(/MAX/g, "1");
|
||||
temp = temp.replace(/IPROD/g, "1");
|
||||
temp = temp.replace(/EPROD/g, "1");
|
||||
temp = temp.replace(/IINV/g, "1");
|
||||
temp = temp.replace(/EINV/g, "1");
|
||||
try {
|
||||
temp = eval(temp);
|
||||
} catch (e) {
|
||||
@ -505,7 +521,7 @@ export function ExportMaterial(
|
||||
|
||||
const n = parseFloat(temp);
|
||||
|
||||
if (n == null || isNaN(n) || n < 0) {
|
||||
if (n == null || isNaN(n)) {
|
||||
throw new Error("Invalid amount entered for export");
|
||||
}
|
||||
|
||||
|
@ -14,9 +14,11 @@ import { Reviver, Generic_toJSON, Generic_fromJSON, IReviverValue } from "../uti
|
||||
import { isString } from "../utils/helpers/isString";
|
||||
import { CityName } from "../Enums";
|
||||
import { CorpStateName } from "@nsdefs";
|
||||
import { calculateUpgradeCost } from "./helpers";
|
||||
|
||||
interface IParams {
|
||||
name?: string;
|
||||
seedFunded?: boolean;
|
||||
}
|
||||
|
||||
export class Corporation {
|
||||
@ -24,6 +26,7 @@ export class Corporation {
|
||||
|
||||
//A division/business sector is represented by the object:
|
||||
divisions: Industry[] = [];
|
||||
maxDivisions = 20 * BitNodeMultipliers.CorporationDivisions;
|
||||
|
||||
//Financial stats
|
||||
funds = 150e9;
|
||||
@ -50,6 +53,8 @@ export class Corporation {
|
||||
valuationsList = [0];
|
||||
valuation = 0;
|
||||
|
||||
seedFunded: boolean;
|
||||
|
||||
state = new CorporationState();
|
||||
|
||||
constructor(params: IParams = {}) {
|
||||
@ -59,6 +64,7 @@ export class Corporation {
|
||||
this.unlockUpgrades = Array(numUnlockUpgrades).fill(0);
|
||||
this.upgrades = Array(numUpgrades).fill(0);
|
||||
this.upgradeMultipliers = Array(numUpgrades).fill(1);
|
||||
this.seedFunded = params.seedFunded ?? false;
|
||||
}
|
||||
|
||||
addFunds(amt: number): void {
|
||||
@ -78,6 +84,8 @@ export class Corporation {
|
||||
}
|
||||
|
||||
process(): void {
|
||||
if (this.storedCycles < 0) this.storedCycles = 0;
|
||||
|
||||
if (this.storedCycles >= corpConstants.gameCyclesPerCorpStateCycle) {
|
||||
const state = this.getState();
|
||||
const marketCycles = 1;
|
||||
@ -305,10 +313,9 @@ export class Corporation {
|
||||
}
|
||||
|
||||
//Levelable upgrades
|
||||
upgrade(upgrade: CorporationUpgrade): void {
|
||||
upgrade(upgrade: CorporationUpgrade, amount: number): void {
|
||||
if (amount < 1) amount = 1;
|
||||
const upgN = upgrade.index,
|
||||
basePrice = upgrade.basePrice,
|
||||
priceMult = upgrade.priceMult,
|
||||
upgradeAmt = upgrade.benefit; //Amount by which the upgrade multiplier gets increased (additive)
|
||||
while (this.upgrades.length <= upgN) {
|
||||
this.upgrades.push(0);
|
||||
@ -316,12 +323,12 @@ export class Corporation {
|
||||
while (this.upgradeMultipliers.length <= upgN) {
|
||||
this.upgradeMultipliers.push(1);
|
||||
}
|
||||
const totalCost = basePrice * Math.pow(priceMult, this.upgrades[upgN]);
|
||||
const totalCost = calculateUpgradeCost(this, upgrade, amount);
|
||||
if (this.funds < totalCost) {
|
||||
dialogBoxCreate("You don't have enough funds to purchase this!");
|
||||
return;
|
||||
}
|
||||
++this.upgrades[upgN];
|
||||
this.upgrades[upgN] += amount;
|
||||
this.funds = this.funds - totalCost;
|
||||
|
||||
//Increase upgrade multiplier
|
||||
|
@ -321,6 +321,7 @@ export class Industry {
|
||||
|
||||
buyAmt = Math.min(buyAmt, maxAmt);
|
||||
if (buyAmt > 0) {
|
||||
mat.qlt = Math.max(0.1, (mat.qlt * mat.qty + 1 * buyAmt) / (mat.qty + buyAmt));
|
||||
mat.qty += buyAmt;
|
||||
expenses += buyAmt * mat.bCost;
|
||||
}
|
||||
@ -382,18 +383,25 @@ export class Industry {
|
||||
|
||||
// Use the materials already in the warehouse if the option is on.
|
||||
for (const matName of Object.keys(smartBuy) as CorpMaterialName[]) {
|
||||
if (!warehouse.smartSupplyUseLeftovers[matName]) continue;
|
||||
if (warehouse.smartSupplyOptions[matName] === "none") continue;
|
||||
const mat = warehouse.materials[matName];
|
||||
const buyAmt = smartBuy[matName];
|
||||
if (buyAmt === undefined) throw new Error(`Somehow smartbuy matname is undefined`);
|
||||
smartBuy[matName] = Math.max(0, buyAmt - mat.qty);
|
||||
if (warehouse.smartSupplyOptions[matName] === "leftovers") {
|
||||
smartBuy[matName] = Math.max(0, buyAmt - mat.qty);
|
||||
} else {
|
||||
smartBuy[matName] = Math.max(0, buyAmt - mat.imp);
|
||||
}
|
||||
}
|
||||
|
||||
// buy them
|
||||
for (const [matName, buyAmt] of Object.entries(smartBuy) as [CorpMaterialName, number][]) {
|
||||
const mat = warehouse.materials[matName];
|
||||
if (buyAmt === undefined) throw new Error(`Somehow smartbuy matname is undefined`);
|
||||
if (mat.qty + buyAmt != 0) mat.qlt = (mat.qlt * mat.qty + 1 * buyAmt) / (mat.qty + buyAmt);
|
||||
else mat.qlt = 1;
|
||||
mat.qty += buyAmt;
|
||||
mat.buy = buyAmt / 10;
|
||||
expenses += buyAmt * mat.bCost;
|
||||
}
|
||||
break;
|
||||
@ -463,6 +471,8 @@ export class Industry {
|
||||
|
||||
// Make our materials if they are producable
|
||||
if (producableFrac > 0 && prod > 0) {
|
||||
let avgQlt = 0;
|
||||
let divider = 0;
|
||||
for (const reqMatName of Object.keys(this.reqMats) as CorpMaterialName[]) {
|
||||
const reqMat = this.reqMats[reqMatName];
|
||||
if (reqMat === undefined) continue;
|
||||
@ -471,13 +481,26 @@ export class Industry {
|
||||
warehouse.materials[reqMatName].prd = 0;
|
||||
warehouse.materials[reqMatName].prd -=
|
||||
reqMatQtyNeeded / (corpConstants.secondsPerMarketCycle * marketCycles);
|
||||
|
||||
avgQlt += warehouse.materials[reqMatName].qlt;
|
||||
divider++;
|
||||
}
|
||||
avgQlt /= divider;
|
||||
avgQlt = Math.max(avgQlt, 1);
|
||||
for (let j = 0; j < this.prodMats.length; ++j) {
|
||||
warehouse.materials[this.prodMats[j]].qty += prod * producableFrac;
|
||||
warehouse.materials[this.prodMats[j]].qlt =
|
||||
let tempQlt =
|
||||
office.employeeProd[EmployeePositions.Engineer] / 90 +
|
||||
Math.pow(this.sciResearch, this.sciFac) +
|
||||
Math.pow(warehouse.materials["AI Cores"].qty, this.aiFac) / 10e3;
|
||||
const logQlt = Math.max(Math.pow(tempQlt, 0.5), 1);
|
||||
tempQlt = Math.min(tempQlt, avgQlt * logQlt);
|
||||
warehouse.materials[this.prodMats[j]].qlt = Math.max(
|
||||
1,
|
||||
(warehouse.materials[this.prodMats[j]].qlt * warehouse.materials[this.prodMats[j]].qty +
|
||||
tempQlt * prod * producableFrac) /
|
||||
(warehouse.materials[this.prodMats[j]].qty + prod * producableFrac),
|
||||
);
|
||||
warehouse.materials[this.prodMats[j]].qty += prod * producableFrac;
|
||||
}
|
||||
} else {
|
||||
for (const reqMatName of Object.keys(this.reqMats) as CorpMaterialName[]) {
|
||||
@ -610,6 +633,28 @@ export class Industry {
|
||||
corporation.getSalesMultiplier() *
|
||||
advertisingFactor *
|
||||
this.getSalesMultiplier();
|
||||
if (isString(mat.sllman[1])) {
|
||||
//Dynamically evaluated
|
||||
let tmp = (mat.sllman[1] as string).replace(/MAX/g, (mat.maxsll + "").toUpperCase());
|
||||
tmp = tmp.replace(/PROD/g, mat.prd + "");
|
||||
|
||||
try {
|
||||
sellAmt = eval(tmp);
|
||||
} catch (e) {
|
||||
dialogBoxCreate(
|
||||
`Error evaluating your sell amount for material ${mat.name} in ${this.name}'s ${city} office. The sell amount is being set to zero, sellAmt is set to ${sellAmt}`,
|
||||
);
|
||||
sellAmt = 0;
|
||||
}
|
||||
sellAmt = Math.min(mat.maxsll, sellAmt);
|
||||
sellAmt = Math.max(sellAmt, 0);
|
||||
} else if (mat.sllman[1] === -1) {
|
||||
//Backwards compatibility, -1 = MAX
|
||||
sellAmt = mat.maxsll;
|
||||
} else {
|
||||
//Player's input value is just a number
|
||||
sellAmt = Math.min(mat.maxsll, mat.sllman[1] as number);
|
||||
}
|
||||
sellAmt = Math.min(mat.maxsll, sellAmt);
|
||||
sellAmt = sellAmt * corpConstants.secondsPerMarketCycle * marketCycles;
|
||||
sellAmt = Math.min(mat.qty, sellAmt);
|
||||
@ -636,10 +681,27 @@ export class Industry {
|
||||
mat.totalExp = 0; //Reset export
|
||||
for (let expI = 0; expI < mat.exp.length; ++expI) {
|
||||
const exp = mat.exp[expI];
|
||||
const amtStr = exp.amt.replace(
|
||||
|
||||
const expIndustry = corporation.divisions.find((div) => div.name === exp.ind);
|
||||
if (!expIndustry) {
|
||||
console.error(`Invalid export! ${exp.ind}`);
|
||||
continue;
|
||||
}
|
||||
const expWarehouse = expIndustry.warehouses[exp.city];
|
||||
if (!expWarehouse) {
|
||||
console.error(`Invalid export! ${expIndustry.name} ${exp.city}`);
|
||||
continue;
|
||||
}
|
||||
const tempMaterial = expWarehouse.materials[matName];
|
||||
|
||||
let amtStr = exp.amt.replace(
|
||||
/MAX/g,
|
||||
(mat.qty / (corpConstants.secondsPerMarketCycle * marketCycles) + "").toUpperCase(),
|
||||
);
|
||||
amtStr = amtStr.replace(/EPROD/g, mat.prd.toString());
|
||||
amtStr = amtStr.replace(/IPROD/g, tempMaterial.prd.toString());
|
||||
amtStr = amtStr.replace(/EINV/g, mat.qty.toString());
|
||||
amtStr = amtStr.replace(/IINV/g, tempMaterial.qty.toString());
|
||||
let amt = 0;
|
||||
try {
|
||||
amt = eval(amtStr);
|
||||
@ -660,38 +722,33 @@ export class Industry {
|
||||
if (mat.qty < amt) {
|
||||
amt = mat.qty;
|
||||
}
|
||||
if (amt === 0) {
|
||||
break; //None left
|
||||
}
|
||||
for (let foo = 0; foo < corporation.divisions.length; ++foo) {
|
||||
if (corporation.divisions[foo].name === exp.ind) {
|
||||
const expIndustry = corporation.divisions[foo];
|
||||
const expWarehouse = expIndustry.warehouses[exp.city];
|
||||
if (!expWarehouse) {
|
||||
console.error(`Invalid export! ${expIndustry.name} ${exp.city}`);
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure theres enough space in warehouse
|
||||
if (expWarehouse.sizeUsed >= expWarehouse.size) {
|
||||
// Warehouse at capacity. Exporting doesn't
|
||||
// affect revenue so just return 0's
|
||||
return [0, 0];
|
||||
} else {
|
||||
const maxAmt = Math.floor(
|
||||
(expWarehouse.size - expWarehouse.sizeUsed) / MaterialInfo[matName].size,
|
||||
);
|
||||
amt = Math.min(maxAmt, amt);
|
||||
}
|
||||
expWarehouse.materials[matName].imp += amt / (corpConstants.secondsPerMarketCycle * marketCycles);
|
||||
expWarehouse.materials[matName].qty += amt;
|
||||
expWarehouse.materials[matName].qlt = mat.qlt;
|
||||
mat.qty -= amt;
|
||||
mat.totalExp += amt;
|
||||
expIndustry.updateWarehouseSizeUsed(expWarehouse);
|
||||
break;
|
||||
}
|
||||
// Make sure theres enough space in warehouse
|
||||
if (expWarehouse.sizeUsed >= expWarehouse.size) {
|
||||
// Warehouse at capacity. Exporting doesn't
|
||||
// affect revenue so just return 0's
|
||||
continue;
|
||||
} else {
|
||||
const maxAmt = Math.floor((expWarehouse.size - expWarehouse.sizeUsed) / MaterialInfo[matName].size);
|
||||
amt = Math.min(maxAmt, amt);
|
||||
}
|
||||
if (amt <= 0) {
|
||||
continue;
|
||||
}
|
||||
expWarehouse.materials[matName].imp += amt / (corpConstants.secondsPerMarketCycle * marketCycles);
|
||||
|
||||
//Pretty sure this can cause some issues if there are multiple sources importing same material to same warehouse
|
||||
//but this will do for now
|
||||
expWarehouse.materials[matName].qlt = Math.max(
|
||||
0.1,
|
||||
(expWarehouse.materials[matName].qlt * expWarehouse.materials[matName].qty + amt * mat.qlt) /
|
||||
(expWarehouse.materials[matName].qty + amt),
|
||||
);
|
||||
|
||||
expWarehouse.materials[matName].qty += amt;
|
||||
mat.qty -= amt;
|
||||
mat.totalExp += amt;
|
||||
expIndustry.updateWarehouseSizeUsed(expWarehouse);
|
||||
}
|
||||
//totalExp should be per second
|
||||
mat.totalExp /= corpConstants.secondsPerMarketCycle * marketCycles;
|
||||
@ -814,12 +871,20 @@ export class Industry {
|
||||
|
||||
//Make our Products if they are producable
|
||||
if (producableFrac > 0 && prod > 0) {
|
||||
let avgQlt = 1;
|
||||
for (const [reqMatName, reqQty] of Object.entries(product.reqMats) as [CorpMaterialName, number][]) {
|
||||
const reqMatQtyNeeded = reqQty * prod * producableFrac;
|
||||
warehouse.materials[reqMatName].qty -= reqMatQtyNeeded;
|
||||
warehouse.materials[reqMatName].prd -=
|
||||
reqMatQtyNeeded / (corpConstants.secondsPerMarketCycle * marketCycles);
|
||||
avgQlt += warehouse.materials[reqMatName].qlt;
|
||||
}
|
||||
avgQlt /= Object.keys(product.reqMats).length;
|
||||
const tempEffRat = Math.min(product.rat, avgQlt * Math.pow(product.rat, 0.5));
|
||||
//Effective Rating
|
||||
product.data[city][3] =
|
||||
(product.data[city][3] * product.data[city][0] + tempEffRat * prod * producableFrac) /
|
||||
(product.data[city][0] + prod * producableFrac);
|
||||
//Quantity
|
||||
product.data[city][0] += prod * producableFrac;
|
||||
}
|
||||
@ -874,7 +939,7 @@ export class Industry {
|
||||
}
|
||||
|
||||
// Calculate Sale Cost (sCost), which could be dynamically evaluated
|
||||
const markupLimit = product.rat / product.mku;
|
||||
const markupLimit = Math.max(product.data[city][3], 0.001) / product.mku;
|
||||
let sCost;
|
||||
if (product.marketTa2) {
|
||||
// Reverse engineer the 'maxSell' formula
|
||||
@ -885,7 +950,7 @@ export class Industry {
|
||||
const sqrtNumerator = sellAmt;
|
||||
const sqrtDenominator =
|
||||
0.5 *
|
||||
Math.pow(product.rat, 0.65) *
|
||||
Math.pow(product.data[city][3], 0.65) *
|
||||
marketFactor *
|
||||
corporation.getSalesMultiplier() *
|
||||
businessFactor *
|
||||
@ -909,16 +974,16 @@ export class Industry {
|
||||
sCost = optimalPrice;
|
||||
} else if (product.marketTa1) {
|
||||
sCost = product.pCost + markupLimit;
|
||||
} else if (isString(product.sCost)) {
|
||||
const sCostString = product.sCost as string;
|
||||
} else if (isString(product.sCost[city])) {
|
||||
const sCostString = product.sCost[city] as string;
|
||||
if (product.mku === 0) {
|
||||
console.error(`mku is zero, reverting to 1 to avoid Infinity`);
|
||||
product.mku = 1;
|
||||
}
|
||||
sCost = sCostString.replace(/MP/g, product.pCost + product.rat / product.mku + "");
|
||||
sCost = sCostString.replace(/MP/g, product.pCost + "");
|
||||
sCost = Math.max(product.pCost, eval(sCost));
|
||||
} else {
|
||||
sCost = product.sCost;
|
||||
sCost = product.sCost[city];
|
||||
}
|
||||
|
||||
let markup = 1;
|
||||
@ -930,7 +995,7 @@ export class Industry {
|
||||
|
||||
product.maxsll =
|
||||
0.5 *
|
||||
Math.pow(product.rat, 0.65) *
|
||||
Math.pow(product.data[city][3], 0.65) *
|
||||
marketFactor *
|
||||
corporation.getSalesMultiplier() *
|
||||
Math.pow(markup, 2) *
|
||||
@ -996,10 +1061,10 @@ export class Industry {
|
||||
|
||||
applyAdVert(corporation: Corporation): void {
|
||||
const advMult = corporation.getAdvertisingMultiplier() * this.getAdvertisingMultiplier();
|
||||
const awareness = (this.awareness + 3 * advMult) * (1.01 * advMult);
|
||||
const awareness = (this.awareness + 3 * advMult) * (1.005 * advMult);
|
||||
this.awareness = Math.min(awareness, Number.MAX_VALUE);
|
||||
|
||||
const popularity = (this.popularity + 1 * advMult) * ((1 + getRandomInt(1, 3) / 100) * advMult);
|
||||
const popularity = (this.popularity + 1 * advMult) * ((1 + getRandomInt(1, 3) / 200) * advMult);
|
||||
this.popularity = Math.min(popularity, Number.MAX_VALUE);
|
||||
|
||||
++this.numAdVerts;
|
||||
@ -1154,7 +1219,7 @@ export class Industry {
|
||||
const matNameMap = { AICores: "AI Cores", RealEstate: "Real Estate" };
|
||||
const indNameMap = {
|
||||
RealEstate: IndustryType.RealEstate,
|
||||
Utilities: IndustryType.Utilities,
|
||||
Water: IndustryType.Water,
|
||||
Computers: IndustryType.Computers,
|
||||
Computer: IndustryType.Computers,
|
||||
};
|
||||
|
@ -17,9 +17,35 @@ export const IndustriesData: Record<CorpIndustryName, CorpIndustryData> = {
|
||||
robotFactor: 0.3,
|
||||
aiCoreFactor: 0.3,
|
||||
advertisingFactor: 0.04,
|
||||
requiredMaterials: { Water: 0.5, Energy: 0.5 },
|
||||
requiredMaterials: { Water: 0.5, Chemicals: 0.2 },
|
||||
producedMaterials: ["Plants", "Food"],
|
||||
},
|
||||
[IndustryType.Spring]: {
|
||||
startingCost: 10e9,
|
||||
description: "Gather water through passive means.",
|
||||
recommendStarting: false,
|
||||
realEstateFactor: 0.2,
|
||||
scienceFactor: 0.1,
|
||||
hardwareFactor: 0.0,
|
||||
robotFactor: 0.0,
|
||||
aiCoreFactor: 0.1,
|
||||
advertisingFactor: 0.03,
|
||||
requiredMaterials: {},
|
||||
producedMaterials: ["Plants", "Food"],
|
||||
},
|
||||
[IndustryType.Refinery]: {
|
||||
startingCost: 50e9,
|
||||
description: "Refine ore into usable metal.",
|
||||
recommendStarting: true,
|
||||
realEstateFactor: 0.3,
|
||||
scienceFactor: 0.5,
|
||||
hardwareFactor: 0.5,
|
||||
robotFactor: 0.4,
|
||||
aiCoreFactor: 0.3,
|
||||
advertisingFactor: 0.04,
|
||||
requiredMaterials: { Ore: 1 },
|
||||
producedMaterials: ["Metal"],
|
||||
},
|
||||
[IndustryType.Chemical]: {
|
||||
startingCost: 70e9,
|
||||
description: "Produce industrial chemicals.",
|
||||
@ -30,7 +56,7 @@ export const IndustriesData: Record<CorpIndustryName, CorpIndustryData> = {
|
||||
robotFactor: 0.25,
|
||||
aiCoreFactor: 0.2,
|
||||
advertisingFactor: 0.07,
|
||||
requiredMaterials: { Plants: 1, Energy: 0.5, Water: 0.5 },
|
||||
requiredMaterials: { Plants: 1, Water: 0.5 },
|
||||
producedMaterials: ["Chemicals"],
|
||||
},
|
||||
[IndustryType.Computers]: {
|
||||
@ -55,21 +81,9 @@ export const IndustriesData: Record<CorpIndustryName, CorpIndustryData> = {
|
||||
robotFactor: 0.36,
|
||||
aiCoreFactor: 0.19,
|
||||
advertisingFactor: 0.17,
|
||||
requiredMaterials: { Metal: 2, Energy: 1 },
|
||||
requiredMaterials: { Metal: 2 },
|
||||
producedMaterials: ["Hardware"],
|
||||
},
|
||||
[IndustryType.Energy]: {
|
||||
startingCost: 225e9,
|
||||
description: "Engage in the production and distribution of energy.",
|
||||
recommendStarting: false,
|
||||
realEstateFactor: 0.65,
|
||||
scienceFactor: 0.7,
|
||||
robotFactor: 0.05,
|
||||
aiCoreFactor: 0.3,
|
||||
advertisingFactor: 0.08,
|
||||
requiredMaterials: { Hardware: 0.1, Metal: 0.2 },
|
||||
producedMaterials: ["Energy"],
|
||||
},
|
||||
[IndustryType.Fishing]: {
|
||||
startingCost: 80e9,
|
||||
description: "Produce food through the breeding and processing of fish and fish products.",
|
||||
@ -80,10 +94,10 @@ export const IndustriesData: Record<CorpIndustryName, CorpIndustryData> = {
|
||||
robotFactor: 0.5,
|
||||
aiCoreFactor: 0.2,
|
||||
advertisingFactor: 0.08,
|
||||
requiredMaterials: { Energy: 0.5 },
|
||||
requiredMaterials: { Plants: 0.5 },
|
||||
producedMaterials: ["Food"],
|
||||
},
|
||||
[IndustryType.Food]: {
|
||||
[IndustryType.Restaurant]: {
|
||||
startingCost: 10e9,
|
||||
description: "Create your own restaurants all around the world.",
|
||||
product: {
|
||||
@ -103,7 +117,7 @@ export const IndustriesData: Record<CorpIndustryName, CorpIndustryData> = {
|
||||
aiCoreFactor: 0.25,
|
||||
advertisingFactor: 0.25,
|
||||
realEstateFactor: 0.05,
|
||||
requiredMaterials: { Food: 0.5, Water: 0.5, Energy: 0.2 },
|
||||
requiredMaterials: { Food: 0.5, Water: 0.5 },
|
||||
},
|
||||
[IndustryType.Healthcare]: {
|
||||
startingCost: 750e9,
|
||||
@ -127,7 +141,7 @@ export const IndustriesData: Record<CorpIndustryName, CorpIndustryData> = {
|
||||
hardwareFactor: 0.1,
|
||||
robotFactor: 0.1,
|
||||
aiCoreFactor: 0.1,
|
||||
requiredMaterials: { Robots: 10, "AI Cores": 5, Energy: 5, Water: 5 },
|
||||
requiredMaterials: { Robots: 10, "AI Cores": 5, Drugs: 5, Food: 5 },
|
||||
},
|
||||
[IndustryType.Mining]: {
|
||||
startingCost: 300e9,
|
||||
@ -139,8 +153,8 @@ export const IndustriesData: Record<CorpIndustryName, CorpIndustryData> = {
|
||||
robotFactor: 0.45,
|
||||
aiCoreFactor: 0.45,
|
||||
advertisingFactor: 0.06,
|
||||
requiredMaterials: { Energy: 0.8 },
|
||||
producedMaterials: ["Metal"],
|
||||
requiredMaterials: { Hardware: 0.1 },
|
||||
producedMaterials: ["Ore", "Minerals"],
|
||||
},
|
||||
[IndustryType.Pharmaceutical]: {
|
||||
startingCost: 200e9,
|
||||
@ -164,7 +178,7 @@ export const IndustriesData: Record<CorpIndustryName, CorpIndustryData> = {
|
||||
robotFactor: 0.25,
|
||||
aiCoreFactor: 0.2,
|
||||
advertisingFactor: 0.16,
|
||||
requiredMaterials: { Chemicals: 2, Energy: 1, Water: 0.5 },
|
||||
requiredMaterials: { Chemicals: 2, Water: 0.5 },
|
||||
producedMaterials: ["Drugs"],
|
||||
},
|
||||
[IndustryType.RealEstate]: {
|
||||
@ -188,7 +202,7 @@ export const IndustriesData: Record<CorpIndustryName, CorpIndustryData> = {
|
||||
advertisingFactor: 0.25,
|
||||
scienceFactor: 0.05,
|
||||
hardwareFactor: 0.05,
|
||||
requiredMaterials: { Metal: 5, Energy: 5, Water: 2, Hardware: 4 },
|
||||
requiredMaterials: { Metal: 5, Plants: 1, Water: 2, Hardware: 4 },
|
||||
producedMaterials: ["Real Estate"],
|
||||
},
|
||||
[IndustryType.Robotics]: {
|
||||
@ -213,7 +227,7 @@ export const IndustriesData: Record<CorpIndustryName, CorpIndustryData> = {
|
||||
aiCoreFactor: 0.36,
|
||||
advertisingFactor: 0.18,
|
||||
hardwareFactor: 0.19,
|
||||
requiredMaterials: { Hardware: 5, Energy: 3 },
|
||||
requiredMaterials: { Hardware: 5, "AI Cores": 3 },
|
||||
producedMaterials: ["Robots"],
|
||||
},
|
||||
[IndustryType.Software]: {
|
||||
@ -238,7 +252,7 @@ export const IndustriesData: Record<CorpIndustryName, CorpIndustryData> = {
|
||||
realEstateFactor: 0.15,
|
||||
aiCoreFactor: 0.18,
|
||||
robotFactor: 0.05,
|
||||
requiredMaterials: { Hardware: 0.5, Energy: 0.5 },
|
||||
requiredMaterials: { Hardware: 0.5 },
|
||||
producedMaterials: ["AI Cores"],
|
||||
},
|
||||
[IndustryType.Tobacco]: {
|
||||
@ -261,9 +275,9 @@ export const IndustriesData: Record<CorpIndustryName, CorpIndustryData> = {
|
||||
robotFactor: 0.2,
|
||||
aiCoreFactor: 0.15,
|
||||
advertisingFactor: 0.2,
|
||||
requiredMaterials: { Plants: 1, Water: 0.2 },
|
||||
requiredMaterials: { Plants: 1 },
|
||||
},
|
||||
[IndustryType.Utilities]: {
|
||||
[IndustryType.Water]: {
|
||||
startingCost: 150e9,
|
||||
description: "Distribute water and provide wastewater services.",
|
||||
recommendStarting: false,
|
||||
@ -272,7 +286,7 @@ export const IndustriesData: Record<CorpIndustryName, CorpIndustryData> = {
|
||||
robotFactor: 0.4,
|
||||
aiCoreFactor: 0.4,
|
||||
advertisingFactor: 0.08,
|
||||
requiredMaterials: { Hardware: 0.1, Metal: 0.1 },
|
||||
requiredMaterials: { Hardware: 0.1 },
|
||||
producedMaterials: ["Water"],
|
||||
},
|
||||
};
|
||||
|
@ -16,7 +16,7 @@ export class Material {
|
||||
qty = 0;
|
||||
|
||||
// Material's "quality". Unbounded
|
||||
qlt = 0;
|
||||
qlt = 1;
|
||||
|
||||
// How much demand the Material has in the market, and the range of possible
|
||||
// values for this "demand"
|
||||
|
@ -13,14 +13,25 @@ export const MaterialInfo: Record<CorpMaterialName, CorpMaterialConstantData> =
|
||||
maxVolatility: 0.2,
|
||||
baseMarkup: 6,
|
||||
},
|
||||
Energy: {
|
||||
name: "Energy",
|
||||
Ore: {
|
||||
name: "Ore",
|
||||
size: 0.01,
|
||||
demandBase: 90,
|
||||
demandRange: [80, 99],
|
||||
demandBase: 50,
|
||||
demandRange: [40, 60],
|
||||
competitionBase: 80,
|
||||
competitionRange: [65, 95],
|
||||
baseCost: 2000,
|
||||
baseCost: 500,
|
||||
maxVolatility: 0.2,
|
||||
baseMarkup: 6,
|
||||
},
|
||||
Minerals: {
|
||||
name: "Minerals",
|
||||
size: 0.04,
|
||||
demandBase: 75,
|
||||
demandRange: [90, 60],
|
||||
competitionBase: 80,
|
||||
competitionRange: [65, 95],
|
||||
baseCost: 500,
|
||||
maxVolatility: 0.2,
|
||||
baseMarkup: 6,
|
||||
},
|
||||
|
@ -16,11 +16,9 @@ export class OfficeSpace {
|
||||
size: number;
|
||||
|
||||
maxEne = 100;
|
||||
maxHap = 100;
|
||||
maxMor = 100;
|
||||
|
||||
avgEne = 75;
|
||||
avgHap = 75;
|
||||
avgMor = 75;
|
||||
|
||||
avgInt = 75;
|
||||
@ -32,9 +30,9 @@ export class OfficeSpace {
|
||||
totalEmployees = 0;
|
||||
totalSalary = 0;
|
||||
|
||||
autoCoffee = false;
|
||||
autoTea = false;
|
||||
autoParty = false;
|
||||
coffeePending = false;
|
||||
teaPending = false;
|
||||
partyMult = 1;
|
||||
|
||||
employeeProd: Record<EmployeePositions | "total", number> = {
|
||||
@ -43,7 +41,7 @@ export class OfficeSpace {
|
||||
[EmployeePositions.Business]: 0,
|
||||
[EmployeePositions.Management]: 0,
|
||||
[EmployeePositions.RandD]: 0,
|
||||
[EmployeePositions.Training]: 0,
|
||||
[EmployeePositions.Intern]: 0,
|
||||
[EmployeePositions.Unassigned]: 0,
|
||||
total: 0,
|
||||
};
|
||||
@ -53,7 +51,7 @@ export class OfficeSpace {
|
||||
[EmployeePositions.Business]: 0,
|
||||
[EmployeePositions.Management]: 0,
|
||||
[EmployeePositions.RandD]: 0,
|
||||
[EmployeePositions.Training]: 0,
|
||||
[EmployeePositions.Intern]: 0,
|
||||
[EmployeePositions.Unassigned]: 0,
|
||||
};
|
||||
employeeNextJobs: Record<EmployeePositions, number> = {
|
||||
@ -62,7 +60,7 @@ export class OfficeSpace {
|
||||
[EmployeePositions.Business]: 0,
|
||||
[EmployeePositions.Management]: 0,
|
||||
[EmployeePositions.RandD]: 0,
|
||||
[EmployeePositions.Training]: 0,
|
||||
[EmployeePositions.Intern]: 0,
|
||||
[EmployeePositions.Unassigned]: 0,
|
||||
};
|
||||
|
||||
@ -76,10 +74,10 @@ export class OfficeSpace {
|
||||
}
|
||||
|
||||
process(marketCycles = 1, corporation: Corporation, industry: Industry): number {
|
||||
// HRBuddy AutoRecruitment and training
|
||||
// HRBuddy AutoRecruitment and Interning
|
||||
if (industry.hasResearch("HRBuddy-Recruitment") && !this.atCapacity()) {
|
||||
this.hireRandomEmployee(
|
||||
industry.hasResearch("HRBuddy-Training") ? EmployeePositions.Training : EmployeePositions.Unassigned,
|
||||
industry.hasResearch("HRBuddy-Training") ? EmployeePositions.Intern : EmployeePositions.Unassigned,
|
||||
);
|
||||
}
|
||||
|
||||
@ -90,62 +88,57 @@ export class OfficeSpace {
|
||||
|
||||
// Process Office properties
|
||||
this.maxEne = 100;
|
||||
this.maxHap = 100;
|
||||
this.maxMor = 100;
|
||||
|
||||
if (industry.hasResearch("Go-Juice")) this.maxEne += 10;
|
||||
if (industry.hasResearch("JoyWire")) this.maxHap += 10;
|
||||
if (industry.hasResearch("Sti.mu")) this.maxMor += 10;
|
||||
if (industry.hasResearch("AutoBrew")) this.autoCoffee = true;
|
||||
if (industry.hasResearch("AutoBrew")) this.autoTea = true;
|
||||
if (industry.hasResearch("AutoPartyManager")) this.autoParty = true;
|
||||
|
||||
if (this.totalEmployees > 0) {
|
||||
/** Multiplier for employee morale/happiness/energy based on company performance */
|
||||
const perfMult = Math.pow(
|
||||
1.002 -
|
||||
(corporation.funds < 0 ? 0.002 : 0) -
|
||||
(industry.lastCycleRevenue < industry.lastCycleExpenses ? 0.002 : 0),
|
||||
marketCycles,
|
||||
);
|
||||
/** Multiplier for employee morale/energy based on company performance */
|
||||
let perfMult = 1.002;
|
||||
if (this.totalEmployees >= 9) {
|
||||
perfMult = Math.pow(
|
||||
1 +
|
||||
0.002 * Math.min(1 / 9, this.employeeJobs.Intern / this.totalEmployees - 1 / 9) * 9 -
|
||||
(corporation.funds < 0 && industry.lastCycleRevenue < industry.lastCycleExpenses ? 0.001 : 0),
|
||||
marketCycles,
|
||||
);
|
||||
}
|
||||
// Flat reduction per cycle.
|
||||
// This does not cause a noticable decrease (it's only -.001% per cycle), it only serves
|
||||
// to make the numbers slightly different between Happiness and Morale.
|
||||
const reduction = 0.001 * marketCycles;
|
||||
// This does not cause a noticable decrease (it's only -.001% per cycle).
|
||||
const reduction = 0.002 * marketCycles;
|
||||
|
||||
if (this.autoCoffee) {
|
||||
if (this.autoTea) {
|
||||
this.avgEne = this.maxEne;
|
||||
} else {
|
||||
// Coffee gives a flat +3 to energy
|
||||
this.avgEne = (this.avgEne - reduction) * perfMult + (this.coffeePending ? 3 : 0);
|
||||
// Coffee also halves the difference between current and max energy
|
||||
if (this.coffeePending) this.avgEne = this.maxEne - (this.maxEne - this.avgEne) / 2;
|
||||
// Tea gives a flat +2 to energy
|
||||
this.avgEne = (this.avgEne - reduction * Math.random()) * perfMult + (this.teaPending ? 2 : 0);
|
||||
}
|
||||
|
||||
if (this.autoParty) {
|
||||
this.avgMor = this.maxMor;
|
||||
this.avgHap = this.maxHap;
|
||||
} else {
|
||||
// Each 5% multiplier gives an extra flat +1 to morale and happiness to make recovering from low morale easier.
|
||||
const increase = this.partyMult > 1 ? (this.partyMult - 1) * 20 : 0;
|
||||
this.avgHap = ((this.avgHap - reduction) * perfMult + increase) * this.partyMult;
|
||||
this.avgMor = (this.avgMor * perfMult + increase) * this.partyMult;
|
||||
// Each 5% multiplier gives an extra flat +1 to morale to make recovering from low morale easier.
|
||||
const increase = this.partyMult > 1 ? (this.partyMult - 1) * 10 : 0;
|
||||
this.avgMor = ((this.avgMor - reduction * Math.random()) * perfMult + increase) * this.partyMult;
|
||||
}
|
||||
|
||||
this.avgEne = Math.max(Math.min(this.avgEne, this.maxEne), corpConstants.minEmployeeDecay);
|
||||
this.avgMor = Math.max(Math.min(this.avgMor, this.maxMor), corpConstants.minEmployeeDecay);
|
||||
this.avgHap = Math.max(Math.min(this.avgHap, this.maxHap), corpConstants.minEmployeeDecay);
|
||||
|
||||
this.coffeePending = false;
|
||||
this.teaPending = false;
|
||||
this.partyMult = 1;
|
||||
}
|
||||
|
||||
// Get experience increase; unassigned employees do not contribute, employees in training contribute 5x
|
||||
// Get experience increase; unassigned employees do not contribute, interning employees contribute 10x
|
||||
this.totalExp +=
|
||||
0.0015 *
|
||||
marketCycles *
|
||||
(this.totalEmployees -
|
||||
this.employeeJobs[EmployeePositions.Unassigned] +
|
||||
this.employeeJobs[EmployeePositions.Training] * 4);
|
||||
this.employeeJobs[EmployeePositions.Intern] * 9);
|
||||
|
||||
this.calculateEmployeeProductivity(corporation, industry);
|
||||
if (this.totalEmployees === 0) {
|
||||
@ -165,7 +158,7 @@ export class OfficeSpace {
|
||||
effCha = this.avgCha * corporation.getEmployeeChaMultiplier() * industry.getEmployeeChaMultiplier(),
|
||||
effInt = this.avgInt * corporation.getEmployeeIntMultiplier() * industry.getEmployeeIntMultiplier(),
|
||||
effEff = this.avgEff * corporation.getEmployeeEffMultiplier() * industry.getEmployeeEffMultiplier();
|
||||
const prodBase = this.avgMor * this.avgHap * this.avgEne * 1e-6;
|
||||
const prodBase = this.avgMor * this.avgEne * 1e-4;
|
||||
|
||||
let total = 0;
|
||||
const exp = this.totalExp / this.totalEmployees || 0;
|
||||
@ -188,7 +181,7 @@ export class OfficeSpace {
|
||||
prodMult = 1.5 * effInt + 0.8 * exp + effCre + 0.5 * effEff;
|
||||
break;
|
||||
case EmployeePositions.Unassigned:
|
||||
case EmployeePositions.Training:
|
||||
case EmployeePositions.Intern:
|
||||
case "total":
|
||||
continue;
|
||||
default:
|
||||
@ -213,7 +206,6 @@ export class OfficeSpace {
|
||||
this.totalExp += getRandomInt(50, 100);
|
||||
|
||||
this.avgMor = (this.avgMor * this.totalEmployees + getRandomInt(50, 100)) / (this.totalEmployees + 1);
|
||||
this.avgHap = (this.avgHap * this.totalEmployees + getRandomInt(50, 100)) / (this.totalEmployees + 1);
|
||||
this.avgEne = (this.avgEne * this.totalEmployees + getRandomInt(50, 100)) / (this.totalEmployees + 1);
|
||||
|
||||
this.avgInt = (this.avgInt * this.totalEmployees + getRandomInt(50, 100)) / (this.totalEmployees + 1);
|
||||
@ -240,13 +232,13 @@ export class OfficeSpace {
|
||||
return false;
|
||||
}
|
||||
|
||||
getCoffeeCost(): number {
|
||||
return corpConstants.coffeeCostPerEmployee * this.totalEmployees;
|
||||
getTeaCost(): number {
|
||||
return corpConstants.teaCostPerEmployee * this.totalEmployees;
|
||||
}
|
||||
|
||||
setCoffee(): boolean {
|
||||
if (!this.coffeePending && !this.autoCoffee && this.totalEmployees > 0) {
|
||||
this.coffeePending = true;
|
||||
setTea(): boolean {
|
||||
if (!this.teaPending && !this.autoTea && this.totalEmployees > 0) {
|
||||
this.teaPending = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -267,11 +259,10 @@ export class OfficeSpace {
|
||||
static fromJSON(value: IReviverValue): OfficeSpace {
|
||||
// Convert employees from the old version
|
||||
if (value.data.hasOwnProperty("employees")) {
|
||||
const empCopy: [{ data: { hap: number; 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;
|
||||
const ret = Generic_fromJSON(OfficeSpace, value.data);
|
||||
ret.totalEmployees = empCopy.length;
|
||||
ret.avgHap = empCopy.reduce((a, b) => a + b.data.hap, 0) / ret.totalEmployees || 75;
|
||||
ret.avgMor = empCopy.reduce((a, b) => a + b.data.mor, 0) / ret.totalEmployees || 75;
|
||||
ret.avgEne = empCopy.reduce((a, b) => a + b.data.ene, 0) / ret.totalEmployees || 75;
|
||||
ret.totalExp = empCopy.reduce((a, b) => a + b.data.exp, 0);
|
||||
|
@ -47,8 +47,8 @@ export class Product {
|
||||
// Production cost - estimation of how much money it costs to make this Product
|
||||
pCost = 0;
|
||||
|
||||
// Sell cost
|
||||
sCost: string | number = 0;
|
||||
// Sell costs
|
||||
sCost: Record<string, any> = createCityMap<any>(0);
|
||||
|
||||
// Variables for handling the creation process of this Product
|
||||
fin = false; // Whether this Product has finished being created
|
||||
@ -82,8 +82,8 @@ export class Product {
|
||||
|
||||
// Data refers to the production, sale, and quantity of the products
|
||||
// These values are specific to a city
|
||||
// For each city, the data is [qty, prod, sell]
|
||||
data: Record<string, number[]> = createCityMap<number[]>([0, 0, 0]);
|
||||
// For each city, the data is [qty, prod, sell, effRat]
|
||||
data: Record<string, number[]> = createCityMap<number[]>([0, 0, 0, 0]);
|
||||
|
||||
// Location of this Product
|
||||
// Only applies for location-based products like restaurants/hospitals
|
||||
@ -130,7 +130,7 @@ export class Product {
|
||||
}
|
||||
|
||||
// Make progress on this product based on current employee productivity
|
||||
createProduct(marketCycles: number, employeeProd: typeof this["creationProd"]): void {
|
||||
createProduct(marketCycles: number, employeeProd: typeof this.creationProd): void {
|
||||
if (this.fin) {
|
||||
return;
|
||||
}
|
||||
|
@ -34,8 +34,8 @@ export class Warehouse {
|
||||
// Whether Smart Supply is enabled for this Industry (the Industry that this Warehouse is for)
|
||||
smartSupplyEnabled = false;
|
||||
|
||||
// Decide if smart supply should use the materials already in the warehouse when deciding on the amount to buy.
|
||||
smartSupplyUseLeftovers: Record<CorpMaterialName, boolean>;
|
||||
// Decide if smart supply should use the amount of materials imported into account when deciding on the amount to buy.
|
||||
smartSupplyOptions: Record<CorpMaterialName, string>;
|
||||
|
||||
// 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,
|
||||
@ -47,10 +47,10 @@ export class Warehouse {
|
||||
this.size = params.size ? params.size : 0;
|
||||
|
||||
this.materials = {} as Record<CorpMaterialName, Material>;
|
||||
this.smartSupplyUseLeftovers = {} as Record<CorpMaterialName, boolean>;
|
||||
this.smartSupplyOptions = {} as Record<CorpMaterialName, string>;
|
||||
for (const matName of materialNames) {
|
||||
this.materials[matName] = new Material({ name: matName });
|
||||
this.smartSupplyUseLeftovers[matName] = true;
|
||||
this.smartSupplyOptions[matName] = "leftovers";
|
||||
}
|
||||
|
||||
if (params.corp && params.industry) {
|
||||
|
@ -20,7 +20,6 @@ function createBaseResearchTreeNodes(): Node {
|
||||
const autoBrew: Node = makeNode("AutoBrew");
|
||||
const autoParty: Node = makeNode("AutoPartyManager");
|
||||
const autoDrugs: Node = makeNode("Automatic Drug Administration");
|
||||
const bulkPurchasing: Node = makeNode("Bulk Purchasing");
|
||||
const cph4: Node = makeNode("CPH4 Injections");
|
||||
const drones: Node = makeNode("Drones");
|
||||
const dronesAssembly: Node = makeNode("Drones - Assembly");
|
||||
@ -28,7 +27,6 @@ function createBaseResearchTreeNodes(): Node {
|
||||
const goJuice: Node = makeNode("Go-Juice");
|
||||
const hrRecruitment: Node = makeNode("HRBuddy-Recruitment");
|
||||
const hrTraining: Node = makeNode("HRBuddy-Training");
|
||||
const joywire: Node = makeNode("JoyWire");
|
||||
const marketta1: Node = makeNode("Market-TA.I");
|
||||
const marketta2: Node = makeNode("Market-TA.II");
|
||||
const overclock: Node = makeNode("Overclock");
|
||||
@ -50,10 +48,8 @@ function createBaseResearchTreeNodes(): Node {
|
||||
rootNode.addChild(autoBrew);
|
||||
rootNode.addChild(autoParty);
|
||||
rootNode.addChild(autoDrugs);
|
||||
rootNode.addChild(bulkPurchasing);
|
||||
rootNode.addChild(drones);
|
||||
rootNode.addChild(hrRecruitment);
|
||||
rootNode.addChild(joywire);
|
||||
rootNode.addChild(marketta1);
|
||||
rootNode.addChild(overclock);
|
||||
rootNode.addChild(scAssemblers);
|
||||
|
@ -24,7 +24,8 @@ export const stateNames: CorpStateName[] = ["START", "PURCHASE", "PRODUCTION", "
|
||||
/** Names of all materials */
|
||||
materialNames: CorpMaterialName[] = [
|
||||
"Water",
|
||||
"Energy",
|
||||
"Ore",
|
||||
"Minerals",
|
||||
"Food",
|
||||
"Plants",
|
||||
"Metal",
|
||||
@ -73,7 +74,6 @@ export const stateNames: CorpStateName[] = ["START", "PURCHASE", "PRODUCTION", "
|
||||
"Go-Juice",
|
||||
"HRBuddy-Recruitment",
|
||||
"HRBuddy-Training",
|
||||
"JoyWire",
|
||||
"Market-TA.I",
|
||||
"Market-TA.II",
|
||||
"Overclock",
|
||||
@ -96,7 +96,7 @@ export const stateNames: CorpStateName[] = ["START", "PURCHASE", "PRODUCTION", "
|
||||
issueNewSharesCooldown = 216e3,
|
||||
/** Cooldown for selling shares in game cycles. 1 hour. */
|
||||
sellSharesCooldown = 18e3,
|
||||
coffeeCostPerEmployee = 500e3,
|
||||
teaCostPerEmployee = 500e3,
|
||||
gameCyclesPerMarketCycle = 50,
|
||||
gameCyclesPerCorpStateCycle = gameCyclesPerMarketCycle / stateNames.length,
|
||||
secondsPerMarketCycle = (gameCyclesPerMarketCycle * CONSTANTS.MilliPerCycle) / 1000,
|
||||
@ -117,7 +117,25 @@ export const stateNames: CorpStateName[] = ["START", "PURCHASE", "PRODUCTION", "
|
||||
/** Max products for a division without upgrades */
|
||||
maxProductsBase = 3,
|
||||
fundingRoundShares = [0.1, 0.35, 0.25, 0.2],
|
||||
fundingRoundMultiplier = [4, 3, 3, 2.5],
|
||||
valuationLength = 5,
|
||||
/** Minimum decay value for employee morale/happiness/energy */
|
||||
minEmployeeDecay = 10;
|
||||
fundingRoundMultiplier = [3, 2, 2, 1.5],
|
||||
valuationLength = 10,
|
||||
/** Minimum decay value for employee morale/energy */
|
||||
minEmployeeDecay = 10,
|
||||
/**smart supply ot */
|
||||
smartSupplyUseOptions = ["leftovers", "imports", "none"],
|
||||
PurchaseMultipliers: {
|
||||
[key: string]: number | "MAX" | undefined;
|
||||
x1: number;
|
||||
x5: number;
|
||||
x10: number;
|
||||
x50: number;
|
||||
x100: number;
|
||||
MAX: "MAX";
|
||||
} = {
|
||||
x1: 1,
|
||||
x5: 5,
|
||||
x10: 10,
|
||||
x50: 50,
|
||||
x100: 100,
|
||||
MAX: "MAX",
|
||||
};
|
||||
|
@ -66,7 +66,7 @@ export const CorporationUpgrades: Record<CorporationUpgradeIndex, CorporationUpg
|
||||
[CorporationUpgradeIndex.WilsonAnalytics]: {
|
||||
index: CorporationUpgradeIndex.WilsonAnalytics,
|
||||
basePrice: 4e9,
|
||||
priceMult: 1.5,
|
||||
priceMult: 2,
|
||||
benefit: 0.005,
|
||||
name: "Wilson Analytics",
|
||||
desc:
|
||||
|
@ -1,10 +1,11 @@
|
||||
export enum IndustryType {
|
||||
Energy = "Energy",
|
||||
Utilities = "Water Utilities",
|
||||
Water = "Water Utilities",
|
||||
Spring = "Spring Water",
|
||||
Agriculture = "Agriculture",
|
||||
Fishing = "Fishing",
|
||||
Mining = "Mining",
|
||||
Food = "Food",
|
||||
Refinery = "Refinery",
|
||||
Restaurant = "Restaurant",
|
||||
Tobacco = "Tobacco",
|
||||
Chemical = "Chemical",
|
||||
Pharmaceutical = "Pharmaceutical",
|
||||
@ -21,6 +22,6 @@ export enum EmployeePositions {
|
||||
Business = "Business",
|
||||
Management = "Management",
|
||||
RandD = "Research & Development",
|
||||
Training = "Training",
|
||||
Intern = "Intern",
|
||||
Unassigned = "Unassigned",
|
||||
}
|
||||
|
@ -6,17 +6,17 @@ export const researchMetadata: IConstructorParams[] = [
|
||||
cost: 12e3,
|
||||
desc:
|
||||
"Automatically keep your employees fully caffeinated with " +
|
||||
"coffee injections. This research will keep the energy of all " +
|
||||
"tea injections. This research will keep the energy of all " +
|
||||
"employees at its maximum possible value, for no cost. " +
|
||||
"This will also disable the Coffee upgrade.",
|
||||
"This will also disable the Tea upgrade.",
|
||||
},
|
||||
{
|
||||
name: "AutoPartyManager",
|
||||
cost: 15e3,
|
||||
desc:
|
||||
"Automatically analyzes your employees' happiness and morale " +
|
||||
"Automatically analyzes your employees' morale " +
|
||||
"and boosts them whenever it detects a decrease. This research will " +
|
||||
"keep the morale and happiness of all employees at their maximum possible " +
|
||||
"keep the morale of all employees at their maximum possible " +
|
||||
"values, for no cost. " +
|
||||
"This will also disable the 'Throw Party' feature.",
|
||||
},
|
||||
@ -27,13 +27,6 @@ export const researchMetadata: IConstructorParams[] = [
|
||||
"Research how to automatically administer performance-enhancing drugs to all of " +
|
||||
"your employees. This unlocks Drug-related Research.",
|
||||
},
|
||||
{
|
||||
name: "Bulk Purchasing",
|
||||
cost: 5e3,
|
||||
desc:
|
||||
"Research the art of buying materials in bulk. This allows you to purchase " +
|
||||
"any amount of a material instantly.",
|
||||
},
|
||||
{
|
||||
name: "CPH4 Injections",
|
||||
cost: 25e3,
|
||||
@ -73,7 +66,7 @@ export const researchMetadata: IConstructorParams[] = [
|
||||
name: "Go-Juice",
|
||||
cost: 25e3,
|
||||
desc:
|
||||
"Provide employees with Go-Juice, a coffee-derivative that further enhances " +
|
||||
"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.",
|
||||
},
|
||||
@ -101,12 +94,7 @@ export const researchMetadata: IConstructorParams[] = [
|
||||
desc:
|
||||
"Use automated software to handle the training of employees. With this " +
|
||||
"research, each employee hired with HRBuddy-Recruitment will automatically " +
|
||||
"be assigned to 'Training', rather than being unassigned.",
|
||||
},
|
||||
{
|
||||
name: "JoyWire",
|
||||
cost: 20e3,
|
||||
desc: "A brain implant which is installed in employees, increasing their maximum happiness by 10.",
|
||||
"be assigned to 'Intern', rather than being unassigned.",
|
||||
},
|
||||
{
|
||||
name: "Market-TA.I",
|
||||
|
35
src/Corporation/helpers.tsx
Normal file
35
src/Corporation/helpers.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import { Corporation } from "./Corporation";
|
||||
import { CorporationUpgrade } from "./data/CorporationUpgrades";
|
||||
|
||||
export function calculateUpgradeCost(corporation: Corporation, upgrade: CorporationUpgrade, amount: number): number {
|
||||
if (amount < 1) return 0;
|
||||
const priceMult = upgrade.priceMult;
|
||||
const level = corporation.upgrades[upgrade.index];
|
||||
const baseCost = upgrade.basePrice * Math.pow(priceMult, level);
|
||||
const cost = (baseCost * (1 - Math.pow(priceMult, amount))) / (1 - priceMult);
|
||||
return cost;
|
||||
}
|
||||
|
||||
export function calculateMaxAffordableUpgrade(
|
||||
corporation: Corporation,
|
||||
upgrade: CorporationUpgrade,
|
||||
amount: number | "MAX",
|
||||
): number {
|
||||
if (amount != "MAX") {
|
||||
if (amount === 0) return 0;
|
||||
if (calculateUpgradeCost(corporation, upgrade, amount) < corporation.funds) return amount;
|
||||
}
|
||||
|
||||
let n = 1;
|
||||
while (
|
||||
calculateUpgradeCost(corporation, upgrade, n * 2) < corporation.funds &&
|
||||
(amount != "MAX" ? n < amount : true)
|
||||
) {
|
||||
n *= 2;
|
||||
}
|
||||
for (let i = n / 2; i >= 1; i /= 2) {
|
||||
if (calculateUpgradeCost(corporation, upgrade, n + i) < corporation.funds) n += i;
|
||||
}
|
||||
|
||||
return amount === "MAX" ? n : Math.min(n, amount);
|
||||
}
|
@ -3,7 +3,6 @@ import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||
import { IndustryDescriptions, IndustriesData } from "../IndustryData";
|
||||
import { IndustryType } from "../data/Enums";
|
||||
import { useCorporation } from "./Context";
|
||||
import { Industry } from "../Industry";
|
||||
import { NewIndustry } from "../Actions";
|
||||
|
||||
import Typography from "@mui/material/Typography";
|
||||
@ -21,20 +20,13 @@ interface IProps {
|
||||
export function ExpandIndustryTab(props: IProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const allIndustries = Object.values(IndustryType).sort();
|
||||
const possibleIndustries = allIndustries.filter(
|
||||
(industryType: IndustryType) =>
|
||||
corp.divisions.find((division: Industry) => division.type === industryType) === undefined,
|
||||
);
|
||||
const [industry, setIndustry] = useState(possibleIndustries[0]);
|
||||
const [industry, setIndustry] = useState(allIndustries[0]);
|
||||
const [name, setName] = useState("");
|
||||
|
||||
//If there are no possible industries to expand into, nothing to render in this tab.
|
||||
if (possibleIndustries.length === 0) return <></>;
|
||||
|
||||
const data = IndustriesData[industry];
|
||||
if (!data) return <></>;
|
||||
|
||||
const disabled = corp.funds < data.startingCost;
|
||||
const disabled = corp.funds < data.startingCost && corp.divisions.length < corp.maxDivisions;
|
||||
|
||||
function newIndustry(): void {
|
||||
if (disabled) return;
|
||||
@ -67,9 +59,12 @@ export function ExpandIndustryTab(props: IProps): React.ReactElement {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography>
|
||||
{corp.name} has {corp.divisions.length}/{corp.maxDivisions} divisions.
|
||||
</Typography>
|
||||
<Typography>Create a new division to expand into a new industry:</Typography>
|
||||
<Select value={industry} onChange={onIndustryChange}>
|
||||
{possibleIndustries.map((industry) => (
|
||||
{allIndustries.map((industry) => (
|
||||
<MenuItem key={industry} value={industry}>
|
||||
{industry}
|
||||
</MenuItem>
|
||||
|
@ -4,7 +4,7 @@ import React, { useState } from "react";
|
||||
|
||||
import { OfficeSpace } from "../OfficeSpace";
|
||||
import { EmployeePositions } from "../data/Enums";
|
||||
import { BuyCoffee } from "../Actions";
|
||||
import { BuyTea } from "../Actions";
|
||||
|
||||
import { MoneyCost } from "./MoneyCost";
|
||||
import { formatCorpStat } from "../../ui/formatNumber";
|
||||
@ -118,14 +118,6 @@ function AutoManagement(props: IProps): React.ReactElement {
|
||||
<Typography>{formatCorpStat(props.office.avgMor)}</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Typography>Avg Employee Happiness:</Typography>
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<Typography>{formatCorpStat(props.office.avgHap)}</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell>
|
||||
<Typography>Avg Employee Energy:</Typography>
|
||||
@ -218,7 +210,7 @@ function AutoManagement(props: IProps): React.ReactElement {
|
||||
office={props.office}
|
||||
job={EmployeePositions.Engineer}
|
||||
desc={
|
||||
"Develops and maintains products and production systems. Increases the quality of everything you produce. Also increases the amount you produce (not as much as Operations, however)"
|
||||
"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)."
|
||||
}
|
||||
/>
|
||||
|
||||
@ -242,15 +234,17 @@ function AutoManagement(props: IProps): React.ReactElement {
|
||||
rerender={props.rerender}
|
||||
office={props.office}
|
||||
job={EmployeePositions.RandD}
|
||||
desc={"Research new innovative ways to improve the company. Generates Scientific Research."}
|
||||
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)."
|
||||
}
|
||||
/>
|
||||
|
||||
<AutoAssignJob
|
||||
rerender={props.rerender}
|
||||
office={props.office}
|
||||
job={EmployeePositions.Training}
|
||||
job={EmployeePositions.Intern}
|
||||
desc={
|
||||
"Set employee to training, which will increase some of their stats. Employees in training do not affect any company operations."
|
||||
"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."
|
||||
}
|
||||
/>
|
||||
</TableBody>
|
||||
@ -304,21 +298,20 @@ export function IndustryOffice(props: IProps): React.ReactElement {
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
Provide your employees with coffee, increasing their energy by half the difference to 100%, plus
|
||||
1.5%
|
||||
Provide your employees with tea, increasing their energy by half the difference to 100%, plus 1.5%
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<span>
|
||||
<Button
|
||||
disabled={corp.funds < props.office.getCoffeeCost() || props.office.coffeePending}
|
||||
onClick={() => BuyCoffee(corp, props.office)}
|
||||
disabled={corp.funds < props.office.getTeaCost() || props.office.teaPending}
|
||||
onClick={() => BuyTea(corp, props.office)}
|
||||
>
|
||||
{props.office.coffeePending ? (
|
||||
"Buying coffee..."
|
||||
{props.office.teaPending ? (
|
||||
"Buying tea..."
|
||||
) : (
|
||||
<span>
|
||||
Buy Coffee - <MoneyCost money={props.office.getCoffeeCost()} corp={corp} />
|
||||
Buy Tea - <MoneyCost money={props.office.getTeaCost()} corp={corp} />
|
||||
</span>
|
||||
)}
|
||||
</Button>
|
||||
@ -329,9 +322,7 @@ export function IndustryOffice(props: IProps): React.ReactElement {
|
||||
|
||||
{!division.hasResearch("AutoPartyManager") && (
|
||||
<>
|
||||
<Tooltip
|
||||
title={<Typography>Throw an office party to increase your employee's morale and happiness</Typography>}
|
||||
>
|
||||
<Tooltip title={<Typography>Throw an office party to increase your employee's morale</Typography>}>
|
||||
<span>
|
||||
<Button
|
||||
disabled={corp.funds < 0 || props.office.partyMult > 1}
|
||||
|
@ -40,7 +40,7 @@ function MakeProductButton(): React.ReactElement {
|
||||
|
||||
let createProductButtonText = "";
|
||||
switch (division.type) {
|
||||
case IndustryType.Food:
|
||||
case IndustryType.Restaurant:
|
||||
createProductButtonText = "Build Restaurant";
|
||||
break;
|
||||
case IndustryType.Tobacco:
|
||||
|
@ -11,9 +11,11 @@ import Tooltip from "@mui/material/Tooltip";
|
||||
import Button from "@mui/material/Button";
|
||||
import Box from "@mui/material/Box";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { calculateMaxAffordableUpgrade, calculateUpgradeCost } from "../helpers";
|
||||
|
||||
interface IProps {
|
||||
upgrade: CorporationUpgrade;
|
||||
amount: number | "MAX";
|
||||
rerender: () => void;
|
||||
}
|
||||
|
||||
@ -21,16 +23,15 @@ export function LevelableUpgrade(props: IProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const data = props.upgrade;
|
||||
const level = corp.upgrades[data.index];
|
||||
const amount = props.amount;
|
||||
|
||||
const baseCost = data.basePrice;
|
||||
const priceMult = data.priceMult;
|
||||
const cost = baseCost * Math.pow(priceMult, level);
|
||||
|
||||
const maxUpgrades = amount === "MAX" ? calculateMaxAffordableUpgrade(corp, data, amount) : amount;
|
||||
const cost = calculateUpgradeCost(corp, data, maxUpgrades);
|
||||
const tooltip = data.desc;
|
||||
function onClick(): void {
|
||||
if (corp.funds < cost) return;
|
||||
try {
|
||||
LevelUpgrade(corp, props.upgrade);
|
||||
LevelUpgrade(corp, props.upgrade, maxUpgrades);
|
||||
} catch (err) {
|
||||
dialogBoxCreate(err + "");
|
||||
}
|
||||
@ -41,6 +42,7 @@ export function LevelableUpgrade(props: IProps): React.ReactElement {
|
||||
<Grid item xs={4}>
|
||||
<Box display="flex" alignItems="center" flexDirection="row-reverse">
|
||||
<Button disabled={corp.funds < cost} sx={{ mx: 1 }} onClick={onClick}>
|
||||
+{maxUpgrades} -
|
||||
<MoneyCost money={cost} corp={corp} />
|
||||
</Button>
|
||||
<Tooltip title={tooltip}>
|
||||
|
50
src/Corporation/ui/MultiplierButtons.tsx
Normal file
50
src/Corporation/ui/MultiplierButtons.tsx
Normal file
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* React Component for the Multiplier buttons on the Hacknet page.
|
||||
* These buttons let the player control how many Nodes/Upgrades they're
|
||||
* purchasing when using the UI (x1, x5, x10, MAX)
|
||||
*/
|
||||
import React from "react";
|
||||
|
||||
import { PurchaseMultipliers } from "../data/Constants";
|
||||
import Button from "@mui/material/Button";
|
||||
|
||||
interface IMultiplierProps {
|
||||
disabled: boolean;
|
||||
onClick: () => void;
|
||||
text: string;
|
||||
}
|
||||
|
||||
function MultiplierButton(props: IMultiplierProps): React.ReactElement {
|
||||
return (
|
||||
<Button disabled={props.disabled} onClick={props.onClick}>
|
||||
{props.text}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
interface IProps {
|
||||
purchaseMultiplier: number | string;
|
||||
onClicks: (() => void)[];
|
||||
}
|
||||
|
||||
export function MultiplierButtons(props: IProps): React.ReactElement {
|
||||
if (props.purchaseMultiplier == null) {
|
||||
throw new Error(`MultiplierButtons constructed without required props`);
|
||||
}
|
||||
|
||||
const mults = ["x1", "x5", "x10", "x50", "x100", "MAX"];
|
||||
const onClicks = props.onClicks;
|
||||
const buttons = [];
|
||||
for (let i = 0; i < mults.length; ++i) {
|
||||
const mult = mults[i];
|
||||
const btnProps = {
|
||||
disabled: props.purchaseMultiplier === PurchaseMultipliers[mult],
|
||||
onClick: onClicks[i],
|
||||
text: mult,
|
||||
};
|
||||
|
||||
buttons.push(<MultiplierButton key={mult} {...btnProps} />);
|
||||
}
|
||||
|
||||
return <>{buttons}</>;
|
||||
}
|
@ -29,10 +29,14 @@ import Button from "@mui/material/Button";
|
||||
import Box from "@mui/material/Box";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import { MultiplierButtons } from "./MultiplierButtons";
|
||||
import { SellCorporationModal } from "./modals/SellCorporationModal";
|
||||
import { SellDivisionModal } from "./modals/SellDivisionModal";
|
||||
|
||||
interface IProps {
|
||||
rerender: () => void;
|
||||
}
|
||||
|
||||
export function Overview({ rerender }: IProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const profit: number = corp.revenue - corp.expenses;
|
||||
@ -100,6 +104,8 @@ export function Overview({ rerender }: IProps): React.ReactElement {
|
||||
</Tooltip>
|
||||
{corp.public ? <PublicButtons rerender={rerender} /> : <PrivateButtons rerender={rerender} />}
|
||||
<BribeButton />
|
||||
{corp.divisions.length != 0 ? <SellDivisionButton /> : <></>}
|
||||
<RestartButton />
|
||||
</Box>
|
||||
<br />
|
||||
<Upgrades rerender={rerender} />
|
||||
@ -155,25 +161,40 @@ function Upgrades({ rerender }: IUpgradeProps): React.ReactElement {
|
||||
return <Typography variant="h4">Upgrades are unlocked once you create an industry.</Typography>;
|
||||
}
|
||||
|
||||
const [purchaseMultiplier, setPurchaseMultiplier] = useState<number | "MAX">(corpConstants.PurchaseMultipliers.x1);
|
||||
|
||||
// onClick event handlers for purchase multiplier buttons
|
||||
const purchaseMultiplierOnClicks = [
|
||||
() => setPurchaseMultiplier(corpConstants.PurchaseMultipliers.x1),
|
||||
() => setPurchaseMultiplier(corpConstants.PurchaseMultipliers.x5),
|
||||
() => setPurchaseMultiplier(corpConstants.PurchaseMultipliers.x10),
|
||||
() => setPurchaseMultiplier(corpConstants.PurchaseMultipliers.x50),
|
||||
() => setPurchaseMultiplier(corpConstants.PurchaseMultipliers.x100),
|
||||
() => setPurchaseMultiplier(corpConstants.PurchaseMultipliers.MAX),
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<Paper sx={{ p: 1, my: 1 }}>
|
||||
<Typography variant="h4">Unlocks</Typography>
|
||||
<Grid container>
|
||||
{Object.values(CorporationUnlockUpgrades)
|
||||
.filter((upgrade: CorporationUnlockUpgrade) => !corp.unlockUpgrades[upgrade.index])
|
||||
.map((upgrade: CorporationUnlockUpgrade) => (
|
||||
<UnlockUpgrade rerender={rerender} upgradeData={upgrade} key={upgrade.index} />
|
||||
))}
|
||||
{Object.values(CorporationUnlockUpgrades).map((upgrade: CorporationUnlockUpgrade) => (
|
||||
<UnlockUpgrade rerender={rerender} upgradeData={upgrade} key={upgrade.index} />
|
||||
))}
|
||||
</Grid>
|
||||
</Paper>
|
||||
<Paper sx={{ p: 1, my: 1 }}>
|
||||
<Typography variant="h4">Upgrades</Typography>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={6}>
|
||||
<MultiplierButtons onClicks={purchaseMultiplierOnClicks} purchaseMultiplier={purchaseMultiplier} />
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container>
|
||||
{corp.upgrades
|
||||
.map((level: number, i: number) => CorporationUpgrades[i as CorporationUpgradeIndex])
|
||||
.map((upgrade: CorporationUpgrade) => (
|
||||
<LevelableUpgrade rerender={rerender} upgrade={upgrade} key={upgrade.index} />
|
||||
<LevelableUpgrade rerender={rerender} upgrade={upgrade} key={upgrade.index} amount={purchaseMultiplier} />
|
||||
))}
|
||||
</Grid>
|
||||
</Paper>
|
||||
@ -265,6 +286,39 @@ function BribeButton(): React.ReactElement {
|
||||
);
|
||||
}
|
||||
|
||||
function SellDivisionButton(): React.ReactElement {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
function sellDiv(): void {
|
||||
setOpen(true);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Tooltip title={"Sell a division to make room for other divisions"}>
|
||||
<Button onClick={sellDiv}>Sell division</Button>
|
||||
</Tooltip>
|
||||
<SellDivisionModal open={open} onClose={() => setOpen(false)} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function RestartButton(): React.ReactElement {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
function restart(): void {
|
||||
setOpen(true);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip title={"Sell corporation and start over"}>
|
||||
<Button onClick={restart}>Sell CEO position</Button>
|
||||
</Tooltip>
|
||||
<SellCorporationModal open={open} onClose={() => setOpen(false)} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
interface IDividendsStatsProps {
|
||||
profit: number;
|
||||
}
|
||||
|
@ -76,9 +76,9 @@ export function ProductElem(props: IProductProps): React.ReactElement {
|
||||
{sellButtonText} @ <Money money={product.pCost + markupLimit} />
|
||||
</>
|
||||
);
|
||||
} else if (product.sCost) {
|
||||
if (isString(product.sCost)) {
|
||||
const sCost = (product.sCost as string).replace(/MP/g, product.pCost + product.rat / product.mku + "");
|
||||
} else if (product.sCost[city]) {
|
||||
if (isString(product.sCost[city])) {
|
||||
const sCost = (product.sCost[city] as string).replace(/MP/g, product.pCost + product.rat / product.mku + "");
|
||||
sellButtonText = (
|
||||
<>
|
||||
{sellButtonText} @ <Money money={eval(sCost)} />
|
||||
@ -87,7 +87,7 @@ export function ProductElem(props: IProductProps): React.ReactElement {
|
||||
} else {
|
||||
sellButtonText = (
|
||||
<>
|
||||
{sellButtonText} @ <Money money={product.sCost} />
|
||||
{sellButtonText} @ <Money money={product.sCost[city]} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -138,6 +138,8 @@ export function ProductElem(props: IProductProps): React.ReactElement {
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
Effective rating is calculated from product rating and the quality of materials used <br />
|
||||
Rating: {formatCorpStat(product.rat)} <br /> <br />
|
||||
Quality: {formatCorpStat(product.qlt)} <br />
|
||||
Performance: {formatCorpStat(product.per)} <br />
|
||||
Durability: {formatCorpStat(product.dur)} <br />
|
||||
@ -151,7 +153,7 @@ export function ProductElem(props: IProductProps): React.ReactElement {
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<Typography>Rating: {formatCorpStat(product.rat)}</Typography>
|
||||
<Typography>Effective rating: {formatCorpStat(product.data[city][3])}</Typography>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
<Box display="flex">
|
||||
|
@ -21,7 +21,10 @@ export function UnlockUpgrade(props: IProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const data = props.upgradeData;
|
||||
const tooltip = data.desc;
|
||||
const price = corp.unlockUpgrades[data.index] === 0 ? data.price : 0;
|
||||
|
||||
function onClick(): void {
|
||||
if (corp.unlockUpgrades[data.index] === 1) return;
|
||||
if (corp.funds < data.price) return;
|
||||
try {
|
||||
UU(corp, props.upgradeData);
|
||||
@ -34,8 +37,12 @@ export function UnlockUpgrade(props: IProps): React.ReactElement {
|
||||
return (
|
||||
<Grid item xs={4}>
|
||||
<Box display="flex" alignItems="center" flexDirection="row-reverse">
|
||||
<Button disabled={corp.funds < data.price} sx={{ mx: 1 }} onClick={onClick}>
|
||||
<MoneyCost money={data.price} corp={corp} />
|
||||
<Button
|
||||
disabled={corp.funds < data.price || corp.unlockUpgrades[data.index] === 1}
|
||||
sx={{ mx: 1 }}
|
||||
onClick={onClick}
|
||||
>
|
||||
<MoneyCost money={price} corp={corp} />
|
||||
</Button>
|
||||
<Tooltip title={tooltip}>
|
||||
<Typography>{data.name}</Typography>
|
||||
|
@ -30,7 +30,7 @@ export function CreateCorporationModal(props: IProps): React.ReactElement {
|
||||
if (!canSelfFund) return;
|
||||
if (name == "") return;
|
||||
|
||||
Player.startCorporation(name);
|
||||
Player.startCorporation(name, false);
|
||||
Player.loseMoney(150e9, "corporation");
|
||||
|
||||
props.onClose();
|
||||
@ -42,7 +42,7 @@ export function CreateCorporationModal(props: IProps): React.ReactElement {
|
||||
return;
|
||||
}
|
||||
|
||||
Player.startCorporation(name, 500e6);
|
||||
Player.startCorporation(name, true);
|
||||
|
||||
props.onClose();
|
||||
Router.toPage(Page.Corporation);
|
||||
|
@ -82,7 +82,25 @@ export function ExportModal(props: IProps): React.ReactElement {
|
||||
<Modal open={props.open} onClose={props.onClose}>
|
||||
<Typography>
|
||||
Select the industry and city to export this material to, as well as how much of this material to export per
|
||||
second. You can set the export amount to 'MAX' to export all of the materials in this warehouse.
|
||||
second.
|
||||
<br />
|
||||
<br />
|
||||
You can use 'MAX', 'EINV', 'IINV', 'EPROD' or 'IPROD' in the amount for:
|
||||
<br />
|
||||
- 'MAX' to export maximum amount possible.
|
||||
<br />
|
||||
- 'EINV' export city's inventory of the material.
|
||||
<br />
|
||||
- 'IINV' import city's inventory of the material.
|
||||
<br />
|
||||
- 'EPROD' export city's per second production of the material
|
||||
<br />
|
||||
- 'IPROD' import city's per second production of the material
|
||||
<br />
|
||||
Note: Consumption is negative production.
|
||||
<br />
|
||||
<br />
|
||||
For example: setting the amount "(EINV-20)/10" would try to export all except 20 of the material.
|
||||
</Typography>
|
||||
<Select onChange={onIndustryChange} value={industry}>
|
||||
{corp.divisions
|
||||
|
@ -55,11 +55,11 @@ export function GoPublicModal(props: IProps): React.ReactElement {
|
||||
be deposited directly into your Corporation's funds).
|
||||
<br />
|
||||
<br />
|
||||
You have a total of {formatShares(corp.numShares)} shares that you can issue.
|
||||
You have a total of {formatShares(corp.numShares)}-1 shares that you can issue. You cannot sell all your shares.
|
||||
</Typography>
|
||||
<Box display="flex" alignItems="center">
|
||||
<NumberInput onChange={setShares} autoFocus placeholder="Shares to issue" onKeyDown={onKeyDown} />
|
||||
<Button disabled={shares < 0 || shares > corp.numShares} sx={{ mx: 1 }} onClick={goPublic}>
|
||||
<Button disabled={shares < 0 || shares >= corp.numShares} sx={{ mx: 1 }} onClick={goPublic}>
|
||||
Go Public
|
||||
</Button>
|
||||
</Box>
|
||||
|
@ -20,7 +20,7 @@ interface IProps {
|
||||
}
|
||||
|
||||
function productPlaceholder(type: string): string {
|
||||
if (type === IndustryType.Food) {
|
||||
if (type === IndustryType.Restaurant) {
|
||||
return "Restaurant Name";
|
||||
} else if (type === IndustryType.Healthcare) {
|
||||
return "Hospital Name";
|
||||
|
@ -1,13 +1,11 @@
|
||||
import React, { useState } from "react";
|
||||
import { formatMoney, formatPreciseMultiplier } from "../../../ui/formatNumber";
|
||||
import { formatMoney } from "../../../ui/formatNumber";
|
||||
import { Material } from "../../Material";
|
||||
import { Modal } from "../../../ui/React/Modal";
|
||||
import { useDivision } from "../Context";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
||||
import Switch from "@mui/material/Switch";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import { useRerender } from "../../../ui/React/hooks";
|
||||
|
||||
interface IMarketTA2Props {
|
||||
@ -17,30 +15,7 @@ interface IMarketTA2Props {
|
||||
function MarketTA2(props: IMarketTA2Props): React.ReactElement {
|
||||
const division = useDivision();
|
||||
if (!division.hasResearch("Market-TA.II")) return <></>;
|
||||
const [newCost, setNewCost] = useState<number>(props.mat.bCost);
|
||||
const rerender = useRerender();
|
||||
const markupLimit = props.mat.getMarkupLimit();
|
||||
|
||||
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
if (event.target.value === "") setNewCost(0);
|
||||
else setNewCost(parseFloat(event.target.value));
|
||||
}
|
||||
|
||||
const sCost = newCost;
|
||||
let markup = 1;
|
||||
if (sCost > props.mat.bCost) {
|
||||
//Penalty if difference between sCost and bCost is greater than markup limit
|
||||
if (sCost - props.mat.bCost > markupLimit) {
|
||||
markup = Math.pow(markupLimit / (sCost - props.mat.bCost), 2);
|
||||
}
|
||||
} else if (sCost < props.mat.bCost) {
|
||||
if (sCost <= 0) {
|
||||
markup = 1e12; //Sell everything, essentially discard
|
||||
} else {
|
||||
//Lower prices than market increases sales
|
||||
markup = props.mat.bCost / sCost;
|
||||
}
|
||||
}
|
||||
|
||||
function onMarketTA2(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
props.mat.marketTa2 = event.target.checked;
|
||||
@ -50,28 +25,15 @@ function MarketTA2(props: IMarketTA2Props): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
<Typography variant="h4">Market-TA.II</Typography>
|
||||
<br />
|
||||
<Typography>
|
||||
If you sell at {formatMoney(sCost)}, then you will sell x{formatPreciseMultiplier(markup)} as much compared to
|
||||
if you sold at market price.
|
||||
If this is enabled, then this Material will automatically be sold at the optimal price such that the amount sold
|
||||
matches the amount produced. (i.e. the highest possible price, while still ensuring that all produced materials
|
||||
will be sold)
|
||||
</Typography>
|
||||
<TextField type="number" onChange={onChange} value={newCost} />
|
||||
<br />
|
||||
<FormControlLabel
|
||||
control={<Switch checked={props.mat.marketTa2} onChange={onMarketTA2} />}
|
||||
label={
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
If this is enabled, then this Material will automatically be sold at the optimal price such that the
|
||||
amount sold matches the amount produced. (i.e. the highest possible price, while still ensuring that all
|
||||
produced materials will be sold)
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<Typography>Use Market-TA.II for Auto-Sale Price</Typography>
|
||||
</Tooltip>
|
||||
}
|
||||
label={<Typography>Use Market-TA.II for Auto-Sale Price</Typography>}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
@ -103,22 +65,15 @@ export function MaterialMarketTaModal(props: IProps): React.ReactElement {
|
||||
<Typography>
|
||||
The maximum sale price you can mark this up to is {formatMoney(props.mat.bCost + markupLimit)}. This means
|
||||
that if you set the sale price higher than this, you will begin to experience a loss in number of sales
|
||||
<br></br>
|
||||
<br></br>
|
||||
If this is enabled, then this Material will automatically be sold at the price identified by Market-TA.I (i.e.
|
||||
the price shown above)
|
||||
</Typography>
|
||||
|
||||
<FormControlLabel
|
||||
control={<Switch checked={props.mat.marketTa1} onChange={onMarketTA1} />}
|
||||
label={
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
If this is enabled, then this Material will automatically be sold at the price identified by
|
||||
Market-TA.I (i.e. the price shown above)
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<Typography>Use Market-TA.I for Auto-Sale Price</Typography>
|
||||
</Tooltip>
|
||||
}
|
||||
label={<Typography>Use Market-TA.I for Auto-Sale Price</Typography>}
|
||||
/>
|
||||
</>
|
||||
|
||||
|
@ -1,13 +1,11 @@
|
||||
import React, { useState } from "react";
|
||||
import { formatMoney, formatPreciseMultiplier } from "../../../ui/formatNumber";
|
||||
import { formatMoney } from "../../../ui/formatNumber";
|
||||
import { Product } from "../../Product";
|
||||
import { Modal } from "../../../ui/React/Modal";
|
||||
import { useDivision } from "../Context";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
||||
import Switch from "@mui/material/Switch";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import { useRerender } from "../../../ui/React/hooks";
|
||||
|
||||
interface ITa2Props {
|
||||
@ -17,52 +15,26 @@ interface ITa2Props {
|
||||
function MarketTA2(props: ITa2Props): React.ReactElement {
|
||||
const division = useDivision();
|
||||
if (!division.hasResearch("Market-TA.II")) return <></>;
|
||||
const markupLimit = props.product.rat / props.product.mku;
|
||||
const [value, setValue] = useState(props.product.pCost);
|
||||
const rerender = useRerender();
|
||||
|
||||
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
setValue(parseFloat(event.target.value));
|
||||
}
|
||||
|
||||
function onCheckedChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
props.product.marketTa2 = event.target.checked;
|
||||
rerender();
|
||||
}
|
||||
|
||||
const sCost = value;
|
||||
let markup = 1;
|
||||
if (sCost > props.product.pCost) {
|
||||
if (sCost - props.product.pCost > markupLimit) {
|
||||
markup = markupLimit / (sCost - props.product.pCost);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography variant="h4">Market-TA.II</Typography>
|
||||
<br />
|
||||
<Typography>
|
||||
If you sell at {formatMoney(sCost)}, then you will sell x{formatPreciseMultiplier(markup)} as much compared to
|
||||
if you sold at market price.
|
||||
If this is enabled, then this product will automatically be sold at the optimal price such that the amount sold
|
||||
matches the amount produced. (i.e. the highest possible price, while still ensuring that all produced materials
|
||||
will be sold)
|
||||
</Typography>
|
||||
<TextField type="number" onChange={onChange} value={value} />
|
||||
<br />
|
||||
<FormControlLabel
|
||||
control={<Switch checked={props.product.marketTa2} onChange={onCheckedChange} />}
|
||||
label={
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
If this is enabled, then this Material will automatically be sold at the optimal price such that the
|
||||
amount sold matches the amount produced. (i.e. the highest possible price, while still ensuring that all
|
||||
produced materials will be sold)
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<Typography>Use Market-TA.II for Auto-Sale Price</Typography>
|
||||
</Tooltip>
|
||||
}
|
||||
label={<Typography>Use Market-TA.II for Auto-Sale Price</Typography>}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
@ -94,22 +66,15 @@ export function ProductMarketTaModal(props: IProps): React.ReactElement {
|
||||
<Typography>
|
||||
The maximum sale price you can mark this up to is {formatMoney(props.product.pCost + markupLimit)}. This means
|
||||
that if you set the sale price higher than this, you will begin to experience a loss in number of sales
|
||||
<br></br>
|
||||
<br></br>
|
||||
If this is enabled, then this product will automatically be sold at the price identified by Market-TA.I (i.e.
|
||||
the price shown above)
|
||||
</Typography>
|
||||
|
||||
<FormControlLabel
|
||||
control={<Switch checked={props.product.marketTa1} onChange={onChange} />}
|
||||
label={
|
||||
<Tooltip
|
||||
title={
|
||||
<Typography>
|
||||
If this is enabled, then this Material will automatically be sold at the price identified by
|
||||
Market-TA.I (i.e. the price shown above)
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<Typography>Use Market-TA.I for Auto-Sale Price</Typography>
|
||||
</Tooltip>
|
||||
}
|
||||
label={<Typography>Use Market-TA.I for Auto-Sale Price</Typography>}
|
||||
/>
|
||||
</>
|
||||
|
||||
|
@ -6,7 +6,7 @@ import { Material } from "../../Material";
|
||||
import { formatMatPurchaseAmount, formatMoney } from "../../../ui/formatNumber";
|
||||
import { BulkPurchase, BuyMaterial } from "../../Actions";
|
||||
import { Modal } from "../../../ui/React/Modal";
|
||||
import { useCorporation, useDivision } from "../Context";
|
||||
import { useCorporation } from "../Context";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import Button from "@mui/material/Button";
|
||||
@ -110,7 +110,6 @@ interface IProps {
|
||||
|
||||
// Create a popup that lets the player purchase a Material
|
||||
export function PurchaseMaterialModal(props: IProps): React.ReactElement {
|
||||
const division = useDivision();
|
||||
const [buyAmt, setBuyAmt] = useState(props.mat.buy ? props.mat.buy : 0);
|
||||
|
||||
function purchaseMaterial(): void {
|
||||
@ -160,9 +159,7 @@ export function PurchaseMaterialModal(props: IProps): React.ReactElement {
|
||||
<Button disabled={props.disablePurchaseLimit} onClick={clearPurchase}>
|
||||
Clear Purchase
|
||||
</Button>
|
||||
{division.hasResearch("Bulk Purchasing") && (
|
||||
<BulkPurchaseSection onClose={props.onClose} mat={props.mat} warehouse={props.warehouse} />
|
||||
)}
|
||||
{<BulkPurchaseSection onClose={props.onClose} mat={props.mat} warehouse={props.warehouse} />}
|
||||
</>
|
||||
</Modal>
|
||||
);
|
||||
|
71
src/Corporation/ui/modals/SellCorporationModal.tsx
Normal file
71
src/Corporation/ui/modals/SellCorporationModal.tsx
Normal file
@ -0,0 +1,71 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { Money } from "../../../ui/React/Money";
|
||||
import { Modal } from "../../../ui/React/Modal";
|
||||
import { Router } from "../../../ui/GameRoot";
|
||||
import { Page } from "../../../ui/Router";
|
||||
import { Player } from "@player";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import TextField from "@mui/material/TextField";
|
||||
|
||||
interface IProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export function SellCorporationModal(props: IProps): React.ReactElement {
|
||||
let cost = 150e9;
|
||||
if (!Player.corporation?.seedFunded) {
|
||||
cost /= 3;
|
||||
}
|
||||
const canSelfFund = Player.canAfford(cost);
|
||||
|
||||
const [name, setName] = useState("");
|
||||
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
setName(event.target.value);
|
||||
}
|
||||
|
||||
function selfFund(): void {
|
||||
if (!canSelfFund) return;
|
||||
if (name == "") return;
|
||||
|
||||
Player.startCorporation(name, false);
|
||||
Player.loseMoney(cost, "corporation");
|
||||
|
||||
props.onClose();
|
||||
Router.toPage(Page.Corporation);
|
||||
}
|
||||
|
||||
function seed(): void {
|
||||
if (name == "") {
|
||||
return;
|
||||
}
|
||||
|
||||
Player.startCorporation(name, true);
|
||||
|
||||
props.onClose();
|
||||
Router.toPage(Page.Corporation);
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal open={props.open} onClose={props.onClose}>
|
||||
<Typography>
|
||||
Would you like to sell your position as CEO and start a new corporation? Everything from your current
|
||||
corporation will be gone and you start fresh.
|
||||
<br />
|
||||
<br />
|
||||
If you would like to start new one, please enter a name for your corporation below:
|
||||
</Typography>
|
||||
<TextField autoFocus={true} placeholder="Corporation Name" onChange={onChange} value={name} />
|
||||
{Player.bitNodeN === 3 && (
|
||||
<Button onClick={seed} disabled={name == ""}>
|
||||
Use seed money
|
||||
</Button>
|
||||
)}
|
||||
<Button onClick={selfFund} disabled={name == "" || !canSelfFund}>
|
||||
Self-Fund (<Money money={cost} forPurchase={true} />)
|
||||
</Button>
|
||||
</Modal>
|
||||
);
|
||||
}
|
100
src/Corporation/ui/modals/SellDivisionModal.tsx
Normal file
100
src/Corporation/ui/modals/SellDivisionModal.tsx
Normal file
@ -0,0 +1,100 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { Modal } from "../../../ui/React/Modal";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Button from "@mui/material/Button";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||
import { useCorporation } from "../../ui/Context";
|
||||
import { Industry } from "src/Corporation/Industry";
|
||||
import { CityName } from "@nsdefs";
|
||||
import * as corpConstants from "../../data/Constants";
|
||||
import { formatMoney, formatNumber } from "../../../ui/formatNumber";
|
||||
import { removeIndustry } from "../../Actions";
|
||||
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||
|
||||
interface IProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export function SellDivisionModal(props: IProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const allIndustries = Object.values(corp.divisions).sort();
|
||||
const [industry, setIndustry] = useState(allIndustries[0]);
|
||||
const price = calculatePrice();
|
||||
|
||||
function calculatePrice() {
|
||||
let price = industry.startingCost;
|
||||
for (const city in industry.offices) {
|
||||
if (industry.offices[city as CityName] === 0) continue;
|
||||
if (city === "Sector-12") continue;
|
||||
price += corpConstants.officeInitialCost;
|
||||
if (industry.warehouses[city as CityName] !== 0) price += corpConstants.warehouseInitialCost;
|
||||
}
|
||||
price /= 2;
|
||||
return price;
|
||||
}
|
||||
|
||||
function onIndustryChange(event: SelectChangeEvent<string>): void {
|
||||
setIndustry(corp.divisions.find((div) => div.name === event.target.value) as Industry);
|
||||
}
|
||||
|
||||
function sum(total: number, num: number) {
|
||||
return total + num;
|
||||
}
|
||||
|
||||
function sellDivision() {
|
||||
removeIndustry(corp, industry.name);
|
||||
corp.funds += price;
|
||||
props.onClose();
|
||||
dialogBoxCreate(
|
||||
<>
|
||||
Sold {industry.name} for {formatMoney(price)}, you now have space for{" "}
|
||||
{corp.maxDivisions - corp.divisions.length} more divisions.
|
||||
</>,
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal open={props.open} onClose={props.onClose}>
|
||||
<Typography>
|
||||
Would you like to sell a division?
|
||||
<br></br>
|
||||
You'll get back half the money you've spent on starting the division and expanding to offices and warehouses.
|
||||
</Typography>
|
||||
|
||||
<Select value={industry.name} onChange={onIndustryChange}>
|
||||
{allIndustries.map((industry) => (
|
||||
<MenuItem key={industry.name} value={industry.name}>
|
||||
{industry.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
<Typography>
|
||||
Division {industry.name} has:
|
||||
<br></br>- Profit: ${formatNumber((industry.lastCycleRevenue - industry.lastCycleExpenses) / 10)} / sec
|
||||
<br></br>- Cities:{" "}
|
||||
{Object.keys(industry.offices)
|
||||
.map((city) => (!!industry.offices[city as CityName] ? 1 : 0))
|
||||
.reduce(sum, 0)}
|
||||
<br></br>- Warehouses:{" "}
|
||||
{Object.keys(industry.warehouses)
|
||||
.map((city) => (!!industry.warehouses[city as CityName] ? 1 : 0))
|
||||
.reduce(sum, 0)}
|
||||
{industry.makesProducts ?? (
|
||||
<Typography>
|
||||
{" "}
|
||||
<br></br>- Products: {industry.products.length}{" "}
|
||||
</Typography>
|
||||
)}
|
||||
<br></br>
|
||||
<br></br>
|
||||
Sell price: {formatNumber(price)}
|
||||
</Typography>
|
||||
<Button disabled={false} onClick={sellDivision}>
|
||||
Sell division
|
||||
</Button>
|
||||
</Modal>
|
||||
);
|
||||
}
|
@ -11,8 +11,8 @@ import FormControlLabel from "@mui/material/FormControlLabel";
|
||||
import Switch from "@mui/material/Switch";
|
||||
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||
|
||||
function initialPrice(product: Product): string {
|
||||
let val = product.sCost ? product.sCost + "" : "";
|
||||
function initialPrice(product: Product, city: string): string {
|
||||
let val = product.sCost[city] ? product.sCost[city] + "" : "";
|
||||
if (product.marketTa2) {
|
||||
val += " (Market-TA.II)";
|
||||
} else if (product.marketTa1) {
|
||||
@ -34,7 +34,7 @@ export function SellProductModal(props: IProps): React.ReactElement {
|
||||
const [iQty, setQty] = useState<string>(
|
||||
props.product.sllman[props.city][1] ? props.product.sllman[props.city][1] : "",
|
||||
);
|
||||
const [px, setPx] = useState<string>(initialPrice(props.product));
|
||||
const [px, setPx] = useState<string>(initialPrice(props.product, props.city));
|
||||
|
||||
function onCheckedChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
setChecked(event.target.checked);
|
||||
|
@ -10,6 +10,7 @@ import { Money } from "../../../ui/React/Money";
|
||||
import { SellShares } from "../../Actions";
|
||||
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||
import { NumberInput } from "../../../ui/React/NumberInput";
|
||||
import { isInteger } from "lodash";
|
||||
interface IProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
@ -22,15 +23,19 @@ export function SellSharesModal(props: IProps): React.ReactElement {
|
||||
const corp = useCorporation();
|
||||
const [shares, setShares] = useState<number>(NaN);
|
||||
|
||||
const disabled = isNaN(shares) || shares <= 0 || shares > corp.numShares;
|
||||
const disabled = isNaN(shares) || shares <= 0 || shares >= corp.numShares;
|
||||
|
||||
function ProfitIndicator(props: { shares: number | null; corp: Corporation }): React.ReactElement {
|
||||
if (props.shares === null) return <></>;
|
||||
let text = "";
|
||||
if (isNaN(props.shares) || props.shares <= 0) {
|
||||
if (isNaN(props.shares) || props.shares <= 0 || !isInteger(props.shares)) {
|
||||
text = `ERROR: Invalid value entered for number of shares to sell`;
|
||||
} else if (props.shares > corp.numShares) {
|
||||
text = `You don't have this many shares to sell!`;
|
||||
} else if (props.shares === corp.numShares) {
|
||||
text = `You can not sell all your shares!`;
|
||||
} else if (props.shares > 1e14) {
|
||||
text = `You can't sell more than 100t shares at once!`;
|
||||
} else {
|
||||
const stockSaleResults = corp.calculateShareSale(props.shares);
|
||||
const profit = stockSaleResults[0];
|
||||
@ -74,6 +79,9 @@ export function SellSharesModal(props: IProps): React.ReactElement {
|
||||
(NOT your Corporation).
|
||||
<br />
|
||||
<br />
|
||||
The amount sold must be an integer between 1 and 100t.
|
||||
<br />
|
||||
<br />
|
||||
Selling your shares will cause your corporation's stock price to fall due to dilution. Furthermore, selling a
|
||||
large number of shares all at once will have an immediate effect in reducing your stock price.
|
||||
<br />
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { Warehouse } from "../../Warehouse";
|
||||
import { SetSmartSupply, SetSmartSupplyUseLeftovers } from "../../Actions";
|
||||
import { SetSmartSupply, SetSmartSupplyOption } from "../../Actions";
|
||||
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||
import { Modal } from "../../../ui/React/Modal";
|
||||
import { useDivision } from "../Context";
|
||||
@ -12,30 +12,50 @@ import { CorpMaterialName } from "@nsdefs";
|
||||
import { materialNames } from "../../data/Constants";
|
||||
import { useRerender } from "../../../ui/React/hooks";
|
||||
|
||||
interface ILeftoverProps {
|
||||
interface ISSoptionProps {
|
||||
matName: CorpMaterialName;
|
||||
warehouse: Warehouse;
|
||||
}
|
||||
|
||||
function Leftover(props: ILeftoverProps): React.ReactElement {
|
||||
const [checked, setChecked] = useState(!!props.warehouse.smartSupplyUseLeftovers[props.matName]);
|
||||
function SSoption(props: ISSoptionProps): React.ReactElement {
|
||||
const [value, setChecked] = useState(props.warehouse.smartSupplyOptions[props.matName]);
|
||||
|
||||
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
|
||||
//leftover switch
|
||||
function onLOChange(): void {
|
||||
const newValue = value != "leftovers" ? "leftovers" : "none";
|
||||
try {
|
||||
const matName = props.matName;
|
||||
const material = props.warehouse.materials[matName];
|
||||
SetSmartSupplyUseLeftovers(props.warehouse, material, event.target.checked);
|
||||
SetSmartSupplyOption(props.warehouse, material, newValue);
|
||||
} catch (err) {
|
||||
dialogBoxCreate(err + "");
|
||||
}
|
||||
setChecked(event.target.checked);
|
||||
setChecked(newValue);
|
||||
}
|
||||
|
||||
//imports switch
|
||||
function onIChange(): void {
|
||||
const newValue = value != "imports" ? "imports" : "none";
|
||||
try {
|
||||
const matName = props.matName;
|
||||
const material = props.warehouse.materials[matName];
|
||||
SetSmartSupplyOption(props.warehouse, material, newValue);
|
||||
} catch (err) {
|
||||
dialogBoxCreate(err + "");
|
||||
}
|
||||
setChecked(newValue);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
label={<Typography>{props.warehouse.materials[props.matName].name}</Typography>}
|
||||
<FormControlLabel
|
||||
control={<Switch checked={checked} onChange={onChange} />}
|
||||
label={<Typography>{props.warehouse.materials[props.matName].name}</Typography>}
|
||||
control={<Switch checked={value == "leftovers"} onChange={onLOChange} />}
|
||||
label={<Typography>{"Use leftovers"}</Typography>}
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={<Switch checked={value == "imports"} onChange={onIChange} />}
|
||||
label={<Typography>{"Use imported"}</Typography>}
|
||||
/>
|
||||
<br />
|
||||
</>
|
||||
@ -63,18 +83,29 @@ export function SmartSupplyModal(props: IProps): React.ReactElement {
|
||||
for (const matName of Object.values(materialNames)) {
|
||||
if (!props.warehouse.materials[matName]) continue;
|
||||
if (!Object.keys(division.reqMats).includes(matName)) continue;
|
||||
mats.push(<Leftover key={matName} warehouse={props.warehouse} matName={matName} />);
|
||||
mats.push(<SSoption key={matName} warehouse={props.warehouse} matName={matName} />);
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal open={props.open} onClose={props.onClose}>
|
||||
<>
|
||||
<Typography>Smart Supply purchases the exact amount of materials needed for maximal production.</Typography>
|
||||
<br />
|
||||
<FormControlLabel
|
||||
control={<Switch checked={props.warehouse.smartSupplyEnabled} onChange={smartSupplyOnChange} />}
|
||||
label={<Typography>Enable Smart Supply</Typography>}
|
||||
/>
|
||||
<br />
|
||||
<Typography>Use materials already in the warehouse instead of buying new ones, if available:</Typography>
|
||||
<Typography>
|
||||
Options:
|
||||
<br />
|
||||
- Use leftovers takes the amount of that material already in storage into account when purchasing new ones.
|
||||
<br />
|
||||
- Use imported takes the amount of that materials that was imported in previous cycle into account.
|
||||
<br />
|
||||
if neither is toggled on, Smart Supply will ignore any materials in store and attempts to buy as much as is
|
||||
needed for production.
|
||||
</Typography>
|
||||
{mats}
|
||||
</>
|
||||
</Modal>
|
||||
|
@ -38,12 +38,12 @@ export function ThrowPartyModal(props: IProps): React.ReactElement {
|
||||
dialogBoxCreate("You don't have enough company funds to throw a party!");
|
||||
} else {
|
||||
const mult = ThrowParty(corp, props.office, cost);
|
||||
// Each 5% multiplier gives an extra flat +1 to morale and happiness 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 = mult > 1 ? (mult - 1) * 0.2 : 0;
|
||||
|
||||
if (mult > 0) {
|
||||
dialogBoxCreate(
|
||||
"You threw a party for the office! The morale and happiness of each employee increased by " +
|
||||
"You threw a party for the office! The morale of each employee increased by " +
|
||||
formatPercent(increase) +
|
||||
" and was multiplied by " +
|
||||
formatMultiplier(mult),
|
||||
|
@ -37,7 +37,7 @@ export function General(): React.ReactElement {
|
||||
|
||||
// Corp functions
|
||||
const createCorporation = () => {
|
||||
Player.startCorporation(corporationName);
|
||||
Player.startCorporation(corporationName, false);
|
||||
// Rerender so the corp menu option will show up immediately on the devmenu page selection
|
||||
ThemeEvents.emit();
|
||||
};
|
||||
|
@ -34,49 +34,54 @@ export const Literatures: Record<string, Literature> = {};
|
||||
fn = LiteratureNames.CorporationManagementHandbook;
|
||||
txt =
|
||||
"<u>Getting Started with Corporations</u><br>" +
|
||||
"To get started, visit the City Hall in Sector-12 in order to create a Corporation. This requires " +
|
||||
"$150b of your own money, but this $150b will get put into your Corporation's funds. " +
|
||||
"Your Corporation can have many different divisions, each in a different Industry. There are many different " +
|
||||
"types of Industries, each with different properties. To create your first division, click the " +
|
||||
"'Expand into new Industry' button at the top of the management UI. The Agriculture " +
|
||||
"and Software industries are recommended for your first division.<br><br>" +
|
||||
"The first thing you'll need to do is hire some employees. Employees can be assigned to five different positions. " +
|
||||
"Each position has a different effect on various aspects of your Corporation. It is recommended to have at least " +
|
||||
"one employee at each position.<br><br>" +
|
||||
"Each industry uses some combination of Materials in order to produce other Materials and/or create Products. " +
|
||||
"Specific information about this is displayed in each of your divisions' UI.<br><br>" +
|
||||
"Products are special, industry-specific objects. They are different than Materials because you " +
|
||||
"must manually choose to develop them, and you can choose to develop any number of Products. Developing " +
|
||||
"a Product takes time, but a Product typically generates significantly more revenue than any Material. " +
|
||||
"Not all industries allow you to create Products. To create a Product, look for a button " +
|
||||
"in the top-left panel of the division UI (e.g. For the Software Industry, the button says 'Develop Software').<br><br>" +
|
||||
"To get your supply chain system started, " +
|
||||
"purchase the Materials that your industry needs to produce other Materials/Products. This can be done " +
|
||||
"by clicking the 'Buy' button next to the corresponding Material(s). After you have the required Materials, " +
|
||||
"you will immediately start production. The amount of Materials/Products you produce is based on a variety of factors, " +
|
||||
"one of which is your employees and their productivity.<br><br>" +
|
||||
"Once you start producing Materials/Products, you can sell them in order to start earning revenue. This can be done " +
|
||||
"by clicking the 'Sell' button next to the corresponding Material or Product. The amount of Material/Product you sell is dependent " +
|
||||
"on a wide variety of different factors.<br><br>" +
|
||||
"These are the basics of getting your Corporation up and running! Now, you can start purchasing upgrades to improve " +
|
||||
"your bottom line. If you need money, consider looking for seed investors, who will give you money in exchange for stock shares. " +
|
||||
"Otherwise, once you feel you are ready, take your Corporation public! Once your Corporation goes public, you can no longer " +
|
||||
"find investors. Instead, your Corporation will be publicly traded and its stock price will change based on how well " +
|
||||
"it's performing financially. You can then sell your stock shares in order to make money.<br><br>" +
|
||||
"To get started, visit the City Hall in Sector-12 in order to create a Corporation. This requires $150b of your own money, " +
|
||||
"but this $150b will get put into your Corporation's funds. If you're in BitNode 3 you also have option to get seed money from " +
|
||||
"the government in exchange for 500m shares. Your Corporation can have many different divisions, each in a different Industry. " +
|
||||
"There are many different types of Industries, each with different properties. To create your first division, click the 'Expand' " +
|
||||
"(into new Industry) button at the top of the management UI. The Agriculture industry is recommended for your first division.<br><br>" +
|
||||
"The first thing you'll need to do is hire some employees. Employees can be assigned to five different positions. Each position has a " +
|
||||
"different effect on various aspects of your Corporation. It is recommended to have at least one employee at each position.<br><br>" +
|
||||
"Each industry uses some combination of Materials in order to produce other Materials and/or create Products. Specific information " +
|
||||
"about this is displayed in each of your divisions' UI.<br><br>" +
|
||||
"Products are special, industry-specific objects. They are different than Materials because you must manually choose to develop them, " +
|
||||
"and you can choose to develop any number of Products. Developing a Product takes time, but a Product typically generates significantly " +
|
||||
"more revenue than any Material. Not all industries allow you to create Products. To create a Product, look for a button in the top-left " +
|
||||
"panel of the division UI (e.g. For the Software Industry, the button says 'Develop Software').<br><br>" +
|
||||
"To get your supply chain system started, purchase the Materials that your industry needs to produce other Materials/Products. This can be " +
|
||||
"done by clicking the 'Buy' button next to the corresponding Material(s). After you have the required Materials, you will immediately start " +
|
||||
"production. The amount and quality/effective rating of Materials/Products you produce is based on a variety of factors, such as your employees " +
|
||||
"and their productivity and the quality of materials used for production.<br><br>" +
|
||||
"Once you start producing Materials/Products, you can sell them in order to start earning revenue. This can be done by clicking the 'Sell' " +
|
||||
"button next to the corresponding Material or Product. The amount of Material/Product you sell is dependent on a wide variety of different factors. " +
|
||||
"In order to produce and sell a Product you'll have to fully develop it first.<br><br>" +
|
||||
"These are the basics of getting your Corporation up and running! Now, you can start purchasing upgrades to improve your bottom line. " +
|
||||
"If you need money, consider looking for seed investors, who will give you money in exchange for stock shares. Otherwise, once you feel " +
|
||||
"you are ready, take your Corporation public! Once your Corporation goes public, you can no longer find investors. Instead, your Corporation " +
|
||||
"will be publicly traded and its stock price will change based on how well it's performing financially. In order to make money for yourself you " +
|
||||
"can set dividends for a solid reliable income or you can sell your stock shares in order to make quick money.<br><br>" +
|
||||
"<u>Tips/Pointers</u><br>" +
|
||||
"-Start with one division, such as Agriculture. Get it profitable on it's own, then expand to a division that consumes/produces " +
|
||||
"a material that the division you selected produces/consumes.<br><br>" +
|
||||
"-Materials are profitable, but Products are where the real money is, although if the product had a low development budget or is " +
|
||||
"produced with low quality materials it won't sell well.<br><br>" +
|
||||
"-The 'Smart Supply' upgrade is extremely useful. Consider purchasing it as soon as possible.<br><br>" +
|
||||
"-Purchasing Hardware, Robots, AI Cores, and Real Estate can potentially increase your production. " +
|
||||
"The effects of these depend on what industry you are in.<br><br>" +
|
||||
"-In order to optimize your production, you will need a good balance of Operators, Managers, and Engineers<br><br>" +
|
||||
"-Different employees excel in different jobs. For example, the highly intelligent employees will probably do best " +
|
||||
"if they are assigned to do Engineering work or Research & Development.<br><br>" +
|
||||
"-If your employees have low morale, energy, or happiness, their production will greatly suffer.<br><br>" +
|
||||
"-Tech is important, but don't neglect sales! Having several Businessmen can boost your sales and your bottom line.<br><br>" +
|
||||
"-Purchasing Hardware, Robots, AI Cores, and Real Estate can potentially increase your production. The effects of these depend on " +
|
||||
"what industry you are in.<br><br>" +
|
||||
"-In order to optimize your production, you will need a good balance of all employee positions, about 1/9 should be interning<br><br>" +
|
||||
"-Quality of materials used for production affects the quality/effective rating of materials/products produced, so vertical integration " +
|
||||
"is important for high profits.<br><br>" +
|
||||
"-Materials purchased from the open market are always of quality 1.<br><br>" +
|
||||
"-The price at which you can sell your Materials/Products is highly affected by the quality/effective rating<br><br>" +
|
||||
"-When developing a product, different employee positions affect the development process differently, " +
|
||||
"some improve the development speed, some improve the rating of the finished product.<br><br>" +
|
||||
"-If your employees have low morale or energy, their production will greatly suffer. Having enough interns will make sure those stats get " +
|
||||
"high and stay high.<br><br>" +
|
||||
"-Don't forget to advertise your company. You won't have any business if nobody knows you.<br><br>" +
|
||||
"-Having company awareness is great, but what's really important is your company's popularity. Try to keep " +
|
||||
"your popularity as high as possible to see the biggest benefit for your sales<br><br>" +
|
||||
"-Having company awareness is great, but what's really important is your company's popularity. Try to keep your popularity as high as " +
|
||||
"possible to see the biggest benefit for your sales<br><br>" +
|
||||
"-Remember, you need to spend money to make money!<br><br>" +
|
||||
"-Corporations do not reset when installing Augmentations, but they do reset when destroying a BitNode";
|
||||
|
||||
Literatures[fn] = new Literature(title, fn, txt);
|
||||
|
||||
title = "A Brief History of Synthoids";
|
||||
|
@ -373,7 +373,7 @@ const corporation = {
|
||||
sellProduct: RamCostConstants.Corporation,
|
||||
discontinueProduct: RamCostConstants.Corporation,
|
||||
setSmartSupply: RamCostConstants.Corporation,
|
||||
setSmartSupplyUseLeftovers: RamCostConstants.Corporation,
|
||||
setSmartSupplyOption: RamCostConstants.Corporation,
|
||||
buyMaterial: RamCostConstants.Corporation,
|
||||
bulkPurchase: RamCostConstants.Corporation,
|
||||
getWarehouse: RamCostConstants.Corporation,
|
||||
@ -395,7 +395,7 @@ const corporation = {
|
||||
hireEmployee: RamCostConstants.Corporation,
|
||||
upgradeOfficeSize: RamCostConstants.Corporation,
|
||||
throwParty: RamCostConstants.Corporation,
|
||||
buyCoffee: RamCostConstants.Corporation,
|
||||
buyTea: RamCostConstants.Corporation,
|
||||
hireAdVert: RamCostConstants.Corporation,
|
||||
research: RamCostConstants.Corporation,
|
||||
getOffice: RamCostConstants.Corporation,
|
||||
|
@ -32,7 +32,7 @@ import {
|
||||
UpgradeOfficeSize,
|
||||
PurchaseWarehouse,
|
||||
UpgradeWarehouse,
|
||||
BuyCoffee,
|
||||
BuyTea,
|
||||
ThrowParty,
|
||||
HireAdVert,
|
||||
MakeProduct,
|
||||
@ -46,7 +46,7 @@ import {
|
||||
BulkPurchase,
|
||||
SellShares,
|
||||
BuyBackShares,
|
||||
SetSmartSupplyUseLeftovers,
|
||||
SetSmartSupplyOption,
|
||||
LimitMaterialProduction,
|
||||
LimitProductProduction,
|
||||
UpgradeWarehouseCost,
|
||||
@ -76,10 +76,10 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
if (selfFund) {
|
||||
if (!player.canAfford(150e9)) return false;
|
||||
|
||||
player.startCorporation(corporationName);
|
||||
player.startCorporation(corporationName, false);
|
||||
player.loseMoney(150e9, "corporation");
|
||||
} else {
|
||||
player.startCorporation(corporationName, 500e6);
|
||||
player.startCorporation(corporationName, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -243,7 +243,7 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
return material;
|
||||
}
|
||||
|
||||
function getProduct(divisionName: string, productName: string): Product {
|
||||
function getProduct(divisionName: string, cityName: string, productName: string): Product {
|
||||
const division = getDivision(divisionName);
|
||||
const product = division.products[productName];
|
||||
if (product === undefined) throw new Error(`Invalid product name: '${productName}'`);
|
||||
@ -331,6 +331,7 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
return {
|
||||
cost: material.bCost,
|
||||
sCost: material.sCost,
|
||||
sAmt: material.sllman[1],
|
||||
name: material.name,
|
||||
qty: material.qty,
|
||||
qlt: material.qlt,
|
||||
@ -341,17 +342,19 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
exp: exports,
|
||||
};
|
||||
},
|
||||
getProduct: (ctx) => (_divisionName, _productName) => {
|
||||
getProduct: (ctx) => (_divisionName, _cityName, _productName) => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const productName = helpers.string(ctx, "productName", _productName);
|
||||
const product = getProduct(divisionName, productName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const product = getProduct(divisionName, cityName, productName);
|
||||
const corporation = getCorporation();
|
||||
return {
|
||||
name: product.name,
|
||||
dmd: corporation.unlockUpgrades[2] ? product.dmd : undefined,
|
||||
cmp: corporation.unlockUpgrades[3] ? product.cmp : undefined,
|
||||
rat: product.rat,
|
||||
effRat: product.data[cityName][3],
|
||||
properties: {
|
||||
qlt: product.qlt,
|
||||
per: product.per,
|
||||
@ -361,8 +364,11 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
fea: product.fea,
|
||||
},
|
||||
pCost: product.pCost,
|
||||
sCost: product.sCost,
|
||||
cityData: product.data,
|
||||
sCost: product.sCost[cityName],
|
||||
sAmt: product.sllman[cityName][1],
|
||||
qty: product.data[cityName][0],
|
||||
prod: product.data[cityName][1],
|
||||
sell: product.data[cityName][2],
|
||||
developmentProgress: product.prog,
|
||||
};
|
||||
},
|
||||
@ -406,14 +412,14 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
const amt = helpers.string(ctx, "amt", _amt);
|
||||
const price = helpers.string(ctx, "price", _price);
|
||||
const all = !!_all;
|
||||
const product = getProduct(divisionName, productName);
|
||||
const product = getProduct(divisionName, cityName, productName);
|
||||
SellProduct(product, cityName, amt, price, all);
|
||||
},
|
||||
discontinueProduct: (ctx) => (_divisionName, _productName) => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const productName = helpers.string(ctx, "productName", _productName);
|
||||
getDivision(divisionName).discontinueProduct(getProduct(divisionName, productName));
|
||||
getDivision(divisionName).discontinueProduct(getProduct(divisionName, "Sector-12", productName));
|
||||
},
|
||||
setSmartSupply: (ctx) => (_divisionName, _cityName, _enabled) => {
|
||||
checkAccess(ctx, 7);
|
||||
@ -425,17 +431,17 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `You have not purchased the Smart Supply upgrade!`);
|
||||
SetSmartSupply(warehouse, enabled);
|
||||
},
|
||||
setSmartSupplyUseLeftovers: (ctx) => (_divisionName, _cityName, materialName, _enabled) => {
|
||||
setSmartSupplyOption: (ctx) => (_divisionName, _cityName, materialName, _option) => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
assertMember(ctx, corpConstants.materialNames, "Material Name", "materialName", materialName);
|
||||
const enabled = !!_enabled;
|
||||
const warehouse = getWarehouse(divisionName, cityName);
|
||||
const material = getMaterial(divisionName, cityName, materialName);
|
||||
const option = helpers.string(ctx, "option", _option);
|
||||
if (!hasUnlockUpgrade("Smart Supply"))
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `You have not purchased the Smart Supply upgrade!`);
|
||||
SetSmartSupplyUseLeftovers(warehouse, material, enabled);
|
||||
SetSmartSupplyOption(warehouse, material, option);
|
||||
},
|
||||
buyMaterial: (ctx) => (_divisionName, _cityName, materialName, _amt) => {
|
||||
checkAccess(ctx, 7);
|
||||
@ -451,8 +457,6 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
bulkPurchase: (ctx) => (_divisionName, _cityName, materialName, _amt) => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
if (!hasResearched(getDivision(divisionName), "Bulk Purchasing"))
|
||||
throw new Error(`You have not researched Bulk Purchasing in ${divisionName}`);
|
||||
const corporation = getCorporation();
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
assertMember(ctx, corpConstants.materialNames, "Material Name", "materialName", materialName);
|
||||
@ -479,7 +483,7 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const productName = helpers.string(ctx, "productName", _productName);
|
||||
const qty = helpers.number(ctx, "qty", _qty);
|
||||
LimitProductProduction(getProduct(divisionName, productName), cityName, qty);
|
||||
LimitProductProduction(getProduct(divisionName, cityName, productName), cityName, qty);
|
||||
},
|
||||
exportMaterial:
|
||||
(ctx) =>
|
||||
@ -539,23 +543,25 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `You have not researched MarketTA.II for division: ${divisionName}`);
|
||||
SetMaterialMarketTA2(getMaterial(divisionName, cityName, materialName), on);
|
||||
},
|
||||
setProductMarketTA1: (ctx) => (_divisionName, _productName, _on) => {
|
||||
setProductMarketTA1: (ctx) => (_divisionName, _cityName, _productName, _on) => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const productName = helpers.string(ctx, "productName", _productName);
|
||||
const on = !!_on;
|
||||
if (!getDivision(divisionName).hasResearch("Market-TA.I"))
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `You have not researched MarketTA.I for division: ${divisionName}`);
|
||||
SetProductMarketTA1(getProduct(divisionName, productName), on);
|
||||
SetProductMarketTA1(getProduct(divisionName, cityName, productName), on);
|
||||
},
|
||||
setProductMarketTA2: (ctx) => (_divisionName, _productName, _on) => {
|
||||
setProductMarketTA2: (ctx) => (_divisionName, _cityName, _productName, _on) => {
|
||||
checkAccess(ctx, 7);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
const productName = helpers.string(ctx, "productName", _productName);
|
||||
const on = !!_on;
|
||||
if (!getDivision(divisionName).hasResearch("Market-TA.II"))
|
||||
throw helpers.makeRuntimeErrorMsg(ctx, `You have not researched MarketTA.II for division: ${divisionName}`);
|
||||
SetProductMarketTA2(getProduct(divisionName, productName), on);
|
||||
SetProductMarketTA2(getProduct(divisionName, cityName, productName), on);
|
||||
},
|
||||
};
|
||||
|
||||
@ -660,14 +666,14 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
|
||||
return ThrowParty(corporation, office, costPerEmployee);
|
||||
},
|
||||
buyCoffee: (ctx) => (_divisionName, _cityName) => {
|
||||
buyTea: (ctx) => (_divisionName, _cityName) => {
|
||||
checkAccess(ctx, 8);
|
||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||
const cityName = helpers.city(ctx, "cityName", _cityName);
|
||||
|
||||
const corporation = getCorporation();
|
||||
const office = getOffice(divisionName, cityName);
|
||||
return BuyCoffee(corporation, office);
|
||||
return BuyTea(corporation, office);
|
||||
},
|
||||
hireAdVert: (ctx) => (_divisionName) => {
|
||||
checkAccess(ctx, 8);
|
||||
@ -690,11 +696,9 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
loc: office.loc,
|
||||
size: office.size,
|
||||
maxEne: office.maxEne,
|
||||
maxHap: office.maxHap,
|
||||
maxMor: office.maxMor,
|
||||
employees: office.totalEmployees,
|
||||
avgEne: office.avgEne,
|
||||
avgHap: office.avgHap,
|
||||
avgMor: office.avgMor,
|
||||
totalExperience: office.totalExp,
|
||||
employeeProd: Object.assign({}, office.employeeProd),
|
||||
@ -761,7 +765,7 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
||||
const corporation = getCorporation();
|
||||
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade.name === upgradeName);
|
||||
if (upgrade === undefined) throw new Error(`No upgrade named '${upgradeName}'`);
|
||||
LevelUpgrade(corporation, upgrade);
|
||||
LevelUpgrade(corporation, upgrade, 1);
|
||||
},
|
||||
issueDividends: (ctx) => (_rate) => {
|
||||
checkAccess(ctx);
|
||||
|
@ -4,15 +4,19 @@ import {
|
||||
CorporationUnlockUpgrades,
|
||||
} from "../../Corporation/data/CorporationUnlockUpgrades";
|
||||
import { PlayerObject } from "./PlayerObject";
|
||||
import { resetIndustryResearchTrees } from "../../Corporation/IndustryData";
|
||||
|
||||
export function canAccessCorporation(this: PlayerObject): boolean {
|
||||
return this.bitNodeN === 3 || this.sourceFileLvl(3) > 0;
|
||||
}
|
||||
|
||||
export function startCorporation(this: PlayerObject, corpName: string, additionalShares = 0): void {
|
||||
export function startCorporation(this: PlayerObject, corpName: string, seedFunded: boolean): void {
|
||||
this.corporation = new Corporation({
|
||||
name: corpName,
|
||||
seedFunded: seedFunded,
|
||||
});
|
||||
//reset the research tree in case the corporation was restarted
|
||||
resetIndustryResearchTrees();
|
||||
|
||||
if (this.bitNodeN === 3 || this.sourceFileLvl(3) === 3) {
|
||||
const warehouseApi = CorporationUnlockUpgrades[CorporationUnlockUpgradeIndex.WarehouseAPI].index;
|
||||
@ -22,5 +26,5 @@ export function startCorporation(this: PlayerObject, corpName: string, additiona
|
||||
this.corporation.unlockUpgrades[OfficeApi] = 1;
|
||||
}
|
||||
|
||||
this.corporation.totalShares += additionalShares;
|
||||
this.corporation.totalShares += seedFunded ? 500_000_000 : 0;
|
||||
}
|
||||
|
@ -248,8 +248,11 @@ export function prestigeSourceFile(flume: boolean): void {
|
||||
homeComp.programs.push(Programs.Formulas.name);
|
||||
}
|
||||
|
||||
console.log(Player.bitNodeN);
|
||||
dialogBoxCreate("hello");
|
||||
// BitNode 3: Corporatocracy
|
||||
if (Player.bitNodeN === 3) {
|
||||
console.log("why isn't the dialogbox happening?");
|
||||
homeComp.messages.push(LiteratureNames.CorporationManagementHandbook);
|
||||
dialogBoxCreate(
|
||||
"You received a copy of the Corporation Management Handbook on your home computer. " +
|
||||
|
63
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
63
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -6887,17 +6887,18 @@ type CorpEmployeePosition =
|
||||
| "Business"
|
||||
| "Management"
|
||||
| "Research & Development"
|
||||
| "Training"
|
||||
| "Intern"
|
||||
| "Unassigned";
|
||||
|
||||
/** @public */
|
||||
type CorpIndustryName =
|
||||
| "Energy"
|
||||
| "Spring Water"
|
||||
| "Water Utilities"
|
||||
| "Agriculture"
|
||||
| "Fishing"
|
||||
| "Mining"
|
||||
| "Food"
|
||||
| "Refinery"
|
||||
| "Restaurant"
|
||||
| "Tobacco"
|
||||
| "Chemical"
|
||||
| "Pharmaceutical"
|
||||
@ -7026,16 +7027,16 @@ export interface OfficeAPI {
|
||||
* @param divisionName - Name of the division
|
||||
* @param city - Name of the city
|
||||
* @param costPerEmployee - Amount to spend per employee.
|
||||
* @returns Multiplier for happiness and morale, or zero on failure
|
||||
* @returns Multiplier for morale, or zero on failure
|
||||
*/
|
||||
throwParty(divisionName: string, city: CityName | `${CityName}`, costPerEmployee: number): number;
|
||||
/**
|
||||
* Buy coffee for your employees
|
||||
* Buy tea for your employees
|
||||
* @param divisionName - Name of the division
|
||||
* @param city - Name of the city
|
||||
* @returns true if buying coffee was successful, false otherwise
|
||||
* @returns true if buying tea was successful, false otherwise
|
||||
*/
|
||||
buyCoffee(divisionName: string, city: CityName | `${CityName}`): boolean;
|
||||
buyTea(divisionName: string, city: CityName | `${CityName}`): boolean;
|
||||
/**
|
||||
* Hire AdVert.
|
||||
* @param divisionName - Name of the division
|
||||
@ -7156,13 +7157,13 @@ export interface WarehouseAPI {
|
||||
* @param divisionName - Name of the division
|
||||
* @param city - Name of the city
|
||||
* @param materialName - Name of the material
|
||||
* @param enabled - smart supply use leftovers enabled
|
||||
* @param option - smart supply option, "leftovers" to use leftovers, "imports" to use only imported materials, "none" to not use materials from store
|
||||
*/
|
||||
setSmartSupplyUseLeftovers(
|
||||
setSmartSupplyOption(
|
||||
divisionName: string,
|
||||
city: CityName | `${CityName}`,
|
||||
materialName: string,
|
||||
enabled: boolean,
|
||||
option: string,
|
||||
): void;
|
||||
/**
|
||||
* Set material buy data
|
||||
@ -7190,10 +7191,11 @@ export interface WarehouseAPI {
|
||||
/**
|
||||
* Get product data
|
||||
* @param divisionName - Name of the division
|
||||
* @param city - Name of the city
|
||||
* @param productName - Name of the product
|
||||
* @returns product data
|
||||
*/
|
||||
getProduct(divisionName: string, productName: string): Product;
|
||||
getProduct(divisionName: string, city: CityName | `${CityName}`, productName: string): Product;
|
||||
/**
|
||||
* Get material data
|
||||
* @param divisionName - Name of the division
|
||||
@ -7221,17 +7223,19 @@ export interface WarehouseAPI {
|
||||
/**
|
||||
* Set market TA 1 for a product.
|
||||
* @param divisionName - Name of the division
|
||||
* @param city - Name of the city
|
||||
* @param productName - Name of the product
|
||||
* @param on - market ta enabled
|
||||
*/
|
||||
setProductMarketTA1(divisionName: string, productName: string, on: boolean): void;
|
||||
setProductMarketTA1(divisionName: string, city: CityName | `${CityName}`, productName: string, on: boolean): void;
|
||||
/**
|
||||
* Set market TA 2 for a product.
|
||||
* @param divisionName - Name of the division
|
||||
* @param city - Name of the city
|
||||
* @param productName - Name of the product
|
||||
* @param on - market ta enabled
|
||||
*/
|
||||
setProductMarketTA2(divisionName: string, productName: string, on: boolean): void;
|
||||
setProductMarketTA2(divisionName: string, city: CityName | `${CityName}`, productName: string, on: boolean): void;
|
||||
/**
|
||||
* Set material export data
|
||||
* @param sourceDivision - Source division
|
||||
@ -7433,11 +7437,11 @@ export interface Corporation extends WarehouseAPI, OfficeAPI {
|
||||
issueNewShares(amount?: number): number;
|
||||
|
||||
/** Buyback Shares
|
||||
* @param amount - Amount of shares to buy back. */
|
||||
* @param amount - Amount of shares to buy back, must be integer and larger than 0 */
|
||||
buyBackShares(amount: number): void;
|
||||
|
||||
/** Sell Shares
|
||||
* @param amount - Amount of shares to sell. */
|
||||
* @param amount - Amount of shares to sell, must be integer between 1 and 100t */
|
||||
sellShares(amount: number): void;
|
||||
|
||||
/** Get bonus time.
|
||||
@ -7555,7 +7559,7 @@ interface CorpConstants {
|
||||
issueNewSharesCooldown: number;
|
||||
/** Cooldown for selling shares in game cycles (1 game cycle = 200ms) */
|
||||
sellSharesCooldown: number;
|
||||
coffeeCostPerEmployee: number;
|
||||
teaCostPerEmployee: number;
|
||||
gameCyclesPerMarketCycle: number;
|
||||
gameCyclesPerCorpStateCycle: number;
|
||||
secondsPerMarketCycle: number;
|
||||
@ -7575,7 +7579,7 @@ interface CorpConstants {
|
||||
employeeRaiseAmount: number;
|
||||
/** Max products for a division without upgrades */
|
||||
maxProductsBase: number;
|
||||
/** The minimum decay value for happiness/morale/energy */
|
||||
/** The minimum decay value for morale/energy */
|
||||
minEmployeeDecay: number;
|
||||
}
|
||||
/** @public */
|
||||
@ -7583,8 +7587,9 @@ type CorpStateName = "START" | "PURCHASE" | "PRODUCTION" | "EXPORT" | "SALE";
|
||||
|
||||
/** @public */
|
||||
type CorpMaterialName =
|
||||
| "Minerals"
|
||||
| "Ore"
|
||||
| "Water"
|
||||
| "Energy"
|
||||
| "Food"
|
||||
| "Plants"
|
||||
| "Metal"
|
||||
@ -7699,16 +7704,22 @@ interface Product {
|
||||
cmp: number | undefined;
|
||||
/** Product Rating */
|
||||
rat: number;
|
||||
/** Effective rating */
|
||||
effRat: number;
|
||||
/** Product Properties. The data is \{qlt, per, dur, rel, aes, fea\} */
|
||||
properties: { [key: string]: number };
|
||||
/** Production cost */
|
||||
pCost: number;
|
||||
/** Sell cost, can be "MP+5" */
|
||||
sCost: string | number;
|
||||
/** Data refers to the production, sale, and quantity of the products
|
||||
* These values are specific to a city
|
||||
* For each city, the data is [qty, prod, sell] */
|
||||
cityData: Record<CityName | `${CityName}`, number[]>;
|
||||
sCost: string;
|
||||
/** Sell amount, can be "PROD/2" */
|
||||
sAmt: string;
|
||||
/** Amount of product */
|
||||
qty: number;
|
||||
/** Amount of product produced */
|
||||
prod: number;
|
||||
/** Amount of product sold */
|
||||
sell: number;
|
||||
/** Creation progress - A number between 0-100 representing percentage */
|
||||
developmentProgress: number;
|
||||
}
|
||||
@ -7736,6 +7747,8 @@ interface Material {
|
||||
cost: number;
|
||||
/** Sell cost, can be "MP+5" */
|
||||
sCost: string | number;
|
||||
/** Sell amount, can be "PROD/2" */
|
||||
sAmt: string | number;
|
||||
/** Export orders */
|
||||
exp: Export[];
|
||||
}
|
||||
@ -7781,16 +7794,12 @@ export interface Office {
|
||||
size: number;
|
||||
/** Maximum amount of energy of the employees */
|
||||
maxEne: number;
|
||||
/** Maximum happiness of the employees */
|
||||
maxHap: number;
|
||||
/** Maximum morale of the employees */
|
||||
maxMor: number;
|
||||
/** Amount of employees */
|
||||
employees: number;
|
||||
/** Average energy of the employees */
|
||||
avgEne: number;
|
||||
/** Average happiness of the employees */
|
||||
avgHap: number;
|
||||
/** Average morale of the employees */
|
||||
avgMor: number;
|
||||
/** Total experience of all employees */
|
||||
|
Loading…
Reference in New Issue
Block a user