mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-26 09:33:49 +01:00
Fixed more bugs with new Corporation UI. Minor rebalancing on Corp UI. Changed the Market TA researches to allow you to automatically set price
This commit is contained in:
parent
a28fe7ab9f
commit
e6c5ff7ab7
@ -10,7 +10,8 @@
|
|||||||
|
|
||||||
#cmpy-mgmt-container p,
|
#cmpy-mgmt-container p,
|
||||||
#cmpy-mgmt-container a,
|
#cmpy-mgmt-container a,
|
||||||
#cmpy-mgmt-container div {
|
#cmpy-mgmt-container div,
|
||||||
|
#cmpy-mgmt-container br {
|
||||||
font-size: $defaultFontSize * 0.8125;
|
font-size: $defaultFontSize * 0.8125;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,9 +297,11 @@ export let CONSTANTS: IMap<any> = {
|
|||||||
** Significantly changed the effects of the different employee positions. See updated descriptions
|
** Significantly changed the effects of the different employee positions. See updated descriptions
|
||||||
** Reduced the amount of money you gain from private investors
|
** Reduced the amount of money you gain from private investors
|
||||||
** Training employees is now 3x more effective
|
** Training employees is now 3x more effective
|
||||||
|
** Bug Fix: An industry's products are now properly separated between different cities
|
||||||
|
|
||||||
* Rebalanced BitNode-3 to make it slightly harder
|
* Rebalanced BitNode-3 to make it slightly harder
|
||||||
* Bug Fix: Bladeburner's Hyperbolic Regeneration Chamber should no longer instantly refill all stamina
|
* Bug Fix: Bladeburner's Hyperbolic Regeneration Chamber should no longer instantly refill all stamina
|
||||||
|
* Bug Fix: The cost of purchasing Augmentations for Duplicate Sleeves no longer scales with how many Augs you've purchased for yourself
|
||||||
`
|
`
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ import { CONSTANTS } from "../Constants";
|
|||||||
import { Factions } from "../Faction/Factions";
|
import { Factions } from "../Faction/Factions";
|
||||||
import { showLiterature } from "../Literature";
|
import { showLiterature } from "../Literature";
|
||||||
import { Locations } from "../Locations";
|
import { Locations } from "../Locations";
|
||||||
|
import { createCityMap } from "../Locations/Cities";
|
||||||
import { Player } from "../Player";
|
import { Player } from "../Player";
|
||||||
|
|
||||||
import { numeralWrapper } from "../ui/numeralFormat";
|
import { numeralWrapper } from "../ui/numeralFormat";
|
||||||
@ -590,7 +591,7 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
|
|||||||
|
|
||||||
//At the start of the export state, set the imports of everything to 0
|
//At the start of the export state, set the imports of everything to 0
|
||||||
if (this.state === "EXPORT") {
|
if (this.state === "EXPORT") {
|
||||||
for (var i = 0; i < Cities.length; ++i) {
|
for (let i = 0; i < Cities.length; ++i) {
|
||||||
var city = Cities[i], office = this.offices[city];
|
var city = Cities[i], office = this.offices[city];
|
||||||
if (!(this.warehouses[city] instanceof Warehouse)) {
|
if (!(this.warehouses[city] instanceof Warehouse)) {
|
||||||
continue;
|
continue;
|
||||||
@ -605,7 +606,7 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < Cities.length; ++i) {
|
for (let i = 0; i < Cities.length; ++i) {
|
||||||
var city = Cities[i], office = this.offices[city];
|
var city = Cities[i], office = this.offices[city];
|
||||||
|
|
||||||
if (this.warehouses[city] instanceof Warehouse) {
|
if (this.warehouses[city] instanceof Warehouse) {
|
||||||
@ -665,19 +666,17 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
|
|||||||
prod = maxProd;
|
prod = maxProd;
|
||||||
}
|
}
|
||||||
prod *= (SecsPerMarketCycle * marketCycles); //Convert production from per second to per market cycle
|
prod *= (SecsPerMarketCycle * marketCycles); //Convert production from per second to per market cycle
|
||||||
//Calculate net change in warehouse storage making
|
|
||||||
//the produced materials will cost
|
// Calculate net change in warehouse storage making the produced materials will cost
|
||||||
var totalMatSize = 0;
|
var totalMatSize = 0;
|
||||||
for (var tmp = 0; tmp < this.prodMats.length; ++tmp) {
|
for (let tmp = 0; tmp < this.prodMats.length; ++tmp) {
|
||||||
totalMatSize += (MaterialSizes[this.prodMats[tmp]]);
|
totalMatSize += (MaterialSizes[this.prodMats[tmp]]);
|
||||||
}
|
}
|
||||||
for (var reqMatName in this.reqMats) {
|
for (const reqMatName in this.reqMats) {
|
||||||
if (this.reqMats.hasOwnProperty(reqMatName)) {
|
var normQty = this.reqMats[reqMatName];
|
||||||
var normQty = this.reqMats[reqMatName];
|
totalMatSize -= (MaterialSizes[reqMatName] * normQty);
|
||||||
totalMatSize -= (MaterialSizes[reqMatName] * normQty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//If not enough space in warehouse, limit the amount of produced materials
|
// If not enough space in warehouse, limit the amount of produced materials
|
||||||
if (totalMatSize > 0) {
|
if (totalMatSize > 0) {
|
||||||
var maxAmt = Math.floor((warehouse.size - warehouse.sizeUsed) / totalMatSize);
|
var maxAmt = Math.floor((warehouse.size - warehouse.sizeUsed) / totalMatSize);
|
||||||
prod = Math.min(maxAmt, prod);
|
prod = Math.min(maxAmt, prod);
|
||||||
@ -685,10 +684,10 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
|
|||||||
|
|
||||||
if (prod < 0) {prod = 0;}
|
if (prod < 0) {prod = 0;}
|
||||||
|
|
||||||
//Keep track of production for smart supply (/s)
|
// Keep track of production for smart supply (/s)
|
||||||
warehouse.smartSupplyStore += (prod / (SecsPerMarketCycle * marketCycles));
|
warehouse.smartSupplyStore += (prod / (SecsPerMarketCycle * marketCycles));
|
||||||
|
|
||||||
//Make sure we have enough resource to make our materials
|
// Make sure we have enough resource to make our materials
|
||||||
var producableFrac = 1;
|
var producableFrac = 1;
|
||||||
for (var reqMatName in this.reqMats) {
|
for (var reqMatName in this.reqMats) {
|
||||||
if (this.reqMats.hasOwnProperty(reqMatName)) {
|
if (this.reqMats.hasOwnProperty(reqMatName)) {
|
||||||
@ -700,17 +699,15 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
|
|||||||
}
|
}
|
||||||
if (producableFrac <= 0) {producableFrac = 0; prod = 0;}
|
if (producableFrac <= 0) {producableFrac = 0; prod = 0;}
|
||||||
|
|
||||||
//Make our materials if they are producable
|
// Make our materials if they are producable
|
||||||
if (producableFrac > 0 && prod > 0) {
|
if (producableFrac > 0 && prod > 0) {
|
||||||
for (var reqMatName in this.reqMats) {
|
for (const reqMatName in this.reqMats) {
|
||||||
if (this.reqMats.hasOwnProperty(reqMatName)) {
|
var reqMatQtyNeeded = (this.reqMats[reqMatName] * prod * producableFrac);
|
||||||
var reqMatQtyNeeded = (this.reqMats[reqMatName] * prod * producableFrac);
|
warehouse.materials[reqMatName].qty -= reqMatQtyNeeded;
|
||||||
warehouse.materials[reqMatName].qty -= reqMatQtyNeeded;
|
warehouse.materials[reqMatName].prd = 0;
|
||||||
warehouse.materials[reqMatName].prd = 0;
|
warehouse.materials[reqMatName].prd -= reqMatQtyNeeded / (SecsPerMarketCycle * marketCycles);
|
||||||
warehouse.materials[reqMatName].prd -= reqMatQtyNeeded / (SecsPerMarketCycle * marketCycles);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (var j = 0; j < this.prodMats.length; ++j) {
|
for (let j = 0; j < this.prodMats.length; ++j) {
|
||||||
warehouse.materials[this.prodMats[j]].qty += (prod * producableFrac);
|
warehouse.materials[this.prodMats[j]].qty += (prod * producableFrac);
|
||||||
warehouse.materials[this.prodMats[j]].qlt =
|
warehouse.materials[this.prodMats[j]].qlt =
|
||||||
(office.employeeProd[EmployeePositions.Engineer] / 90 +
|
(office.employeeProd[EmployeePositions.Engineer] / 90 +
|
||||||
@ -718,7 +715,7 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
|
|||||||
Math.pow(warehouse.materials["AICores"].qty, this.aiFac) / 10e3);
|
Math.pow(warehouse.materials["AICores"].qty, this.aiFac) / 10e3);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (var reqMatName in this.reqMats) {
|
for (const reqMatName in this.reqMats) {
|
||||||
if (this.reqMats.hasOwnProperty(reqMatName)) {
|
if (this.reqMats.hasOwnProperty(reqMatName)) {
|
||||||
warehouse.materials[reqMatName].prd = 0;
|
warehouse.materials[reqMatName].prd = 0;
|
||||||
}
|
}
|
||||||
@ -726,18 +723,16 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Per second
|
//Per second
|
||||||
var fooProd = prod * producableFrac / (SecsPerMarketCycle * marketCycles);
|
const fooProd = prod * producableFrac / (SecsPerMarketCycle * marketCycles);
|
||||||
for (var fooI = 0; fooI < this.prodMats.length; ++fooI) {
|
for (let fooI = 0; fooI < this.prodMats.length; ++fooI) {
|
||||||
warehouse.materials[this.prodMats[fooI]].prd = fooProd;
|
warehouse.materials[this.prodMats[fooI]].prd = fooProd;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//If this doesn't produce any materials, then it only creates
|
//If this doesn't produce any materials, then it only creates
|
||||||
//Products. Creating products will consume materials. The
|
//Products. Creating products will consume materials. The
|
||||||
//Production of all consumed materials must be set to 0
|
//Production of all consumed materials must be set to 0
|
||||||
for (var reqMatName in this.reqMats) {
|
for (const reqMatName in this.reqMats) {
|
||||||
if (this.reqMats.hasOwnProperty(reqMatName)) {
|
warehouse.materials[reqMatName].prd = 0;
|
||||||
warehouse.materials[reqMatName].prd = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -751,12 +746,39 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
|
|||||||
mat.sll = 0;
|
mat.sll = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var mat = warehouse.materials[matName];
|
|
||||||
|
|
||||||
// Calculate sale cost
|
// Sale multipliers
|
||||||
|
const businessFactor = this.getBusinessFactor(office); //Business employee productivity
|
||||||
|
const advertisingFactor = this.getAdvertisingFactors()[0]; //Awareness + popularity
|
||||||
|
const marketFactor = this.getMarketFactor(mat); //Competition + demand
|
||||||
|
|
||||||
|
// Determine the cost that the material will be sold at
|
||||||
const markupLimit = mat.getMarkupLimit();
|
const markupLimit = mat.getMarkupLimit();
|
||||||
var sCost;
|
var sCost;
|
||||||
if (mat.marketTa1) {
|
if (mat.marketTa2) {
|
||||||
|
const prod = mat.prd;
|
||||||
|
|
||||||
|
// Reverse engineer the 'maxSell' formula
|
||||||
|
// 1. Set 'maxSell' = prod
|
||||||
|
// 2. Substitute formula for 'markup'
|
||||||
|
// 3. Solve for 'sCost'
|
||||||
|
const numerator = markupLimit;
|
||||||
|
const sqrtNumerator = prod;
|
||||||
|
const sqrtDenominator = ((mat.qlt + .001)
|
||||||
|
* marketFactor
|
||||||
|
* businessFactor
|
||||||
|
* company.getSalesMultiplier()
|
||||||
|
* advertisingFactor
|
||||||
|
* this.getSalesMultiplier());
|
||||||
|
const denominator = Math.sqrt(sqrtNumerator / sqrtDenominator);
|
||||||
|
const optimalPrice = (numerator / denominator) + mat.bCost;
|
||||||
|
|
||||||
|
// We'll store this "Optimal Price" in a property so that we don't have
|
||||||
|
// to re-calculate it for the UI
|
||||||
|
mat.marketTa2Price = optimalPrice;
|
||||||
|
|
||||||
|
sCost = optimalPrice;
|
||||||
|
} else if (mat.marketTa1) {
|
||||||
sCost = mat.bCost + markupLimit;
|
sCost = mat.bCost + markupLimit;
|
||||||
} else if (isString(mat.sCost)) {
|
} else if (isString(mat.sCost)) {
|
||||||
sCost = mat.sCost.replace(/MP/g, mat.bCost);
|
sCost = mat.sCost.replace(/MP/g, mat.bCost);
|
||||||
@ -780,9 +802,7 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
|
|||||||
markup = mat.bCost / sCost;
|
markup = mat.bCost / sCost;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var businessFactor = this.getBusinessFactor(office); //Business employee productivity
|
|
||||||
var advertisingFactor = this.getAdvertisingFactors()[0]; //Awareness + popularity
|
|
||||||
var marketFactor = this.getMarketFactor(mat); //Competition + demand
|
|
||||||
var maxSell = (mat.qlt + .001)
|
var maxSell = (mat.qlt + .001)
|
||||||
* marketFactor
|
* marketFactor
|
||||||
* markup
|
* markup
|
||||||
@ -905,8 +925,8 @@ Industry.prototype.processMaterials = function(marketCycles=1, company) {
|
|||||||
//Produce Scientific Research based on R&D employees
|
//Produce Scientific Research based on R&D employees
|
||||||
//Scientific Research can be produced without a warehouse
|
//Scientific Research can be produced without a warehouse
|
||||||
if (office instanceof OfficeSpace) {
|
if (office instanceof OfficeSpace) {
|
||||||
this.sciResearch.qty += (.005
|
this.sciResearch.qty += (.004
|
||||||
* Math.pow(office.employeeProd[EmployeePositions.RandD], 0.55)
|
* Math.pow(office.employeeProd[EmployeePositions.RandD], 0.5)
|
||||||
* company.getScientificResearchMultiplier()
|
* company.getScientificResearchMultiplier()
|
||||||
* this.getScientificResearchMultiplier());
|
* this.getScientificResearchMultiplier());
|
||||||
}
|
}
|
||||||
@ -962,9 +982,9 @@ Industry.prototype.processProducts = function(marketCycles=1, corporation) {
|
|||||||
|
|
||||||
//Processes FINISHED products
|
//Processes FINISHED products
|
||||||
Industry.prototype.processProduct = function(marketCycles=1, product, corporation) {
|
Industry.prototype.processProduct = function(marketCycles=1, product, corporation) {
|
||||||
var totalProfit = 0;
|
let totalProfit = 0;
|
||||||
for (var i = 0; i < Cities.length; ++i) {
|
for (let i = 0; i < Cities.length; ++i) {
|
||||||
var city = Cities[i], office = this.offices[city], warehouse = this.warehouses[city];
|
let city = Cities[i], office = this.offices[city], warehouse = this.warehouses[city];
|
||||||
if (warehouse instanceof Warehouse) {
|
if (warehouse instanceof Warehouse) {
|
||||||
switch(this.state) {
|
switch(this.state) {
|
||||||
|
|
||||||
@ -1040,27 +1060,60 @@ Industry.prototype.processProduct = function(marketCycles=1, product, corporatio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Since its a product, its production cost is increased for labor
|
// Since its a product, its production cost is increased for labor
|
||||||
product.pCost *= ProductProductionCostRatio;
|
product.pCost *= ProductProductionCostRatio;
|
||||||
|
|
||||||
//Calculate Sale Cost (sCost), which could be dynamically evaluated
|
// Sale multipliers
|
||||||
|
const businessFactor = this.getBusinessFactor(office); //Business employee productivity
|
||||||
|
const advertisingFactor = this.getAdvertisingFactors()[0]; //Awareness + popularity
|
||||||
|
const marketFactor = this.getMarketFactor(product); //Competition + demand
|
||||||
|
|
||||||
|
// Calculate Sale Cost (sCost), which could be dynamically evaluated
|
||||||
|
const markupLimit = product.rat / product.mku;
|
||||||
var sCost;
|
var sCost;
|
||||||
if (isString(product.sCost)) {
|
if (product.marketTa2) {
|
||||||
|
const prod = product.data[city][1];
|
||||||
|
|
||||||
|
// Reverse engineer the 'maxSell' formula
|
||||||
|
// 1. Set 'maxSell' = prod
|
||||||
|
// 2. Substitute formula for 'markup'
|
||||||
|
// 3. Solve for 'sCost'roduct.pCost = sCost
|
||||||
|
const numerator = markupLimit;
|
||||||
|
const sqrtNumerator = prod;
|
||||||
|
const sqrtDenominator = (0.5
|
||||||
|
* Math.pow(product.rat, 0.65)
|
||||||
|
* marketFactor
|
||||||
|
* corporation.getSalesMultiplier()
|
||||||
|
* businessFactor
|
||||||
|
* advertisingFactor
|
||||||
|
* this.getSalesMultiplier());
|
||||||
|
const denominator = Math.sqrt(sqrtNumerator / sqrtDenominator);
|
||||||
|
let optimalPrice;
|
||||||
|
if (sqrtDenominator === 0 || denominator === 0) {
|
||||||
|
optimalPrice = 0;
|
||||||
|
} else {
|
||||||
|
optimalPrice = (numerator / denominator) + product.pCost;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store this "optimal Price" in a property so we don't have to re-calculate for UI
|
||||||
|
product.marketTa2Price[city] = optimalPrice;
|
||||||
|
sCost = optimalPrice;
|
||||||
|
} else if (product.marketTa1) {
|
||||||
|
sCost = product.pCost + markupLimit;
|
||||||
|
} else if (isString(product.sCost)) {
|
||||||
sCost = product.sCost.replace(/MP/g, product.pCost + product.rat / product.mku);
|
sCost = product.sCost.replace(/MP/g, product.pCost + product.rat / product.mku);
|
||||||
sCost = eval(sCost);
|
sCost = eval(sCost);
|
||||||
} else {
|
} else {
|
||||||
sCost = product.sCost;
|
sCost = product.sCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
var markup = 1, markupLimit = product.rat / product.mku;
|
var markup = 1;
|
||||||
if (sCost > product.pCost) {
|
if (sCost > product.pCost) {
|
||||||
if ((sCost - product.pCost) > markupLimit) {
|
if ((sCost - product.pCost) > markupLimit) {
|
||||||
markup = markupLimit / (sCost - product.pCost);
|
markup = markupLimit / (sCost - product.pCost);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var businessFactor = this.getBusinessFactor(office); //Business employee productivity
|
|
||||||
var advertisingFactor = this.getAdvertisingFactors()[0]; //Awareness + popularity
|
|
||||||
var marketFactor = this.getMarketFactor(product); //Competition + demand
|
|
||||||
var maxSell = 0.5
|
var maxSell = 0.5
|
||||||
* Math.pow(product.rat, 0.65)
|
* Math.pow(product.rat, 0.65)
|
||||||
* marketFactor
|
* marketFactor
|
||||||
@ -1085,8 +1138,9 @@ Industry.prototype.processProduct = function(marketCycles=1, product, corporatio
|
|||||||
} else if (product.sllman[city][0] && product.sllman[city][1] > 0) {
|
} else if (product.sllman[city][0] && product.sllman[city][1] > 0) {
|
||||||
//Sell amount is manually limited
|
//Sell amount is manually limited
|
||||||
sellAmt = Math.min(maxSell, product.sllman[city][1]);
|
sellAmt = Math.min(maxSell, product.sllman[city][1]);
|
||||||
|
} else if (product.sllman[city][0] === false){
|
||||||
|
sellAmt = 0;
|
||||||
} else {
|
} else {
|
||||||
//Backwards compatibility, -1 = 0
|
|
||||||
sellAmt = maxSell;
|
sellAmt = maxSell;
|
||||||
}
|
}
|
||||||
if (sellAmt < 0) { sellAmt = 0; }
|
if (sellAmt < 0) { sellAmt = 0; }
|
||||||
@ -1114,8 +1168,7 @@ Industry.prototype.processProduct = function(marketCycles=1, product, corporatio
|
|||||||
return totalProfit;
|
return totalProfit;
|
||||||
}
|
}
|
||||||
|
|
||||||
Industry.prototype.discontinueProduct = function(product, parentRefs) {
|
Industry.prototype.discontinueProduct = function(product) {
|
||||||
var company = parentRefs.company, industry = parentRefs.industry;
|
|
||||||
for (var productName in this.products) {
|
for (var productName in this.products) {
|
||||||
if (this.products.hasOwnProperty(productName)) {
|
if (this.products.hasOwnProperty(productName)) {
|
||||||
if (product === this.products[productName]) {
|
if (product === this.products[productName]) {
|
||||||
|
@ -66,6 +66,7 @@ export class Material {
|
|||||||
// Flags that signal whether automatic sale pricing through Market TA is enabled
|
// Flags that signal whether automatic sale pricing through Market TA is enabled
|
||||||
marketTa1: boolean = false;
|
marketTa1: boolean = false;
|
||||||
marketTa2: boolean = false;
|
marketTa2: boolean = false;
|
||||||
|
marketTa2Price: number = 0;
|
||||||
|
|
||||||
constructor(params: IConstructorParams = {}) {
|
constructor(params: IConstructorParams = {}) {
|
||||||
if (params.name) { this.name = params.name; }
|
if (params.name) { this.name = params.name; }
|
||||||
|
@ -2,15 +2,17 @@ import { IMap } from "../types";
|
|||||||
|
|
||||||
// Map of material (by name) to their sizes (how much space it takes in warehouse)
|
// Map of material (by name) to their sizes (how much space it takes in warehouse)
|
||||||
export const MaterialSizes: IMap<number> = {
|
export const MaterialSizes: IMap<number> = {
|
||||||
Water: 0.05,
|
Water: 0.05,
|
||||||
Energy: 0.01,
|
Energy: 0.01,
|
||||||
Food: 0.03,
|
Food: 0.03,
|
||||||
Plants: 0.05,
|
Plants: 0.05,
|
||||||
Metal: 0.1,
|
Metal: 0.1,
|
||||||
Hardware: 0.06,
|
Hardware: 0.06,
|
||||||
Chemicals: 0.05,
|
Chemicals: 0.05,
|
||||||
Drugs: 0.02,
|
Drugs: 0.02,
|
||||||
Robots: 0.5,
|
Robots: 0.5,
|
||||||
AICores: 0.1,
|
AICores: 0.1,
|
||||||
RealEstate: 0,
|
RealEstate: 0,
|
||||||
|
"Real Estate": 0,
|
||||||
|
"AI Cores": 0,
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,10 @@ import { ProductRatingWeights,
|
|||||||
IProductRatingWeight } from "./ProductRatingWeights";
|
IProductRatingWeight } from "./ProductRatingWeights";
|
||||||
|
|
||||||
import { Cities } from "../Locations/Cities";
|
import { Cities } from "../Locations/Cities";
|
||||||
|
import { createCityMap } from "../Locations/createCityMap";
|
||||||
import { IMap } from "../types";
|
import { IMap } from "../types";
|
||||||
|
|
||||||
|
|
||||||
import { Generic_fromJSON,
|
import { Generic_fromJSON,
|
||||||
Generic_toJSON,
|
Generic_toJSON,
|
||||||
Reviver } from "../../utils/JSONReviver";
|
Reviver } from "../../utils/JSONReviver";
|
||||||
@ -89,14 +91,7 @@ export class Product {
|
|||||||
// Data refers to the production, sale, and quantity of the products
|
// Data refers to the production, sale, and quantity of the products
|
||||||
// These values are specific to a city
|
// These values are specific to a city
|
||||||
// For each city, the data is [qty, prod, sell]
|
// For each city, the data is [qty, prod, sell]
|
||||||
data: IMap<number[]> = {
|
data: IMap<number[]> = createCityMap<number[]>([0, 0, 0]);
|
||||||
[Cities.Aevum]: [0, 0, 0],
|
|
||||||
[Cities.Chongqing]: [0, 0, 0],
|
|
||||||
[Cities.Sector12]: [0, 0, 0],
|
|
||||||
[Cities.NewTokyo]: [0, 0, 0],
|
|
||||||
[Cities.Ishima]: [0, 0, 0],
|
|
||||||
[Cities.Volhaven]: [0, 0, 0],
|
|
||||||
}
|
|
||||||
|
|
||||||
// Location of this Product
|
// Location of this Product
|
||||||
// Only applies for location-based products like restaurants/hospitals
|
// Only applies for location-based products like restaurants/hospitals
|
||||||
@ -113,23 +108,13 @@ export class Product {
|
|||||||
// Data to keep track of whether production/sale of this Product is
|
// Data to keep track of whether production/sale of this Product is
|
||||||
// manually limited. These values are specific to a city
|
// manually limited. These values are specific to a city
|
||||||
// [Whether production/sale is limited, limit amount]
|
// [Whether production/sale is limited, limit amount]
|
||||||
prdman: IMap<any[]> = {
|
prdman: IMap<any[]> = createCityMap<any[]>([false, 0]);
|
||||||
[Cities.Aevum]: [false, 0],
|
sllman: IMap<any[]> = createCityMap<any[]>([false, 0]);
|
||||||
[Cities.Chongqing]: [false, 0],
|
|
||||||
[Cities.Sector12]: [false, 0],
|
|
||||||
[Cities.NewTokyo]: [false, 0],
|
|
||||||
[Cities.Ishima]: [false, 0],
|
|
||||||
[Cities.Volhaven]: [false, 0],
|
|
||||||
}
|
|
||||||
|
|
||||||
sllman: IMap<any[]> = {
|
// Flags that signal whether automatic sale pricing through Market TA is enabled
|
||||||
[Cities.Aevum]: [false, 0],
|
marketTa1: boolean = false;
|
||||||
[Cities.Chongqing]: [false, 0],
|
marketTa2: boolean = false;
|
||||||
[Cities.Sector12]: [false, 0],
|
marketTa2Price: IMap<number> = createCityMap<number>(0);
|
||||||
[Cities.NewTokyo]: [false, 0],
|
|
||||||
[Cities.Ishima]: [false, 0],
|
|
||||||
[Cities.Volhaven]: [false, 0],
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(params: IConstructorParams={}) {
|
constructor(params: IConstructorParams={}) {
|
||||||
this.name = params.name ? params.name : "";
|
this.name = params.name ? params.name : "";
|
||||||
|
@ -46,6 +46,10 @@ export class Warehouse {
|
|||||||
// Whether Smart Supply is enabled for this Industry (the Industry that this Warehouse is for)
|
// Whether Smart Supply is enabled for this Industry (the Industry that this Warehouse is for)
|
||||||
smartSupplyEnabled: boolean = false;
|
smartSupplyEnabled: boolean = false;
|
||||||
|
|
||||||
|
// Flag that indicates whether Smart Supply accounts for imports when calculating
|
||||||
|
// the amount fo purchase
|
||||||
|
smartSupplyConsiderExports: boolean = false;
|
||||||
|
|
||||||
// Stores the amount of product to be produced. Used for Smart Supply unlock.
|
// Stores the amount of product to be produced. Used for Smart Supply unlock.
|
||||||
// The production tracked by smart supply is always based on the previous cycle,
|
// The production tracked by smart supply is always based on the previous cycle,
|
||||||
// so it will always trail the "true" production by 1 cycle
|
// so it will always trail the "true" production by 1 cycle
|
||||||
|
@ -94,11 +94,13 @@ export const researchMetadata: IConstructorParams[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Market-TA.II",
|
name: "Market-TA.II",
|
||||||
cost: 40e3,
|
cost: 50e3,
|
||||||
desc: "Develop double-advanced AI software that uses technical analysis to " +
|
desc: "Develop double-advanced AI software that uses technical analysis to " +
|
||||||
"help you understand and exploit the market. This research " +
|
"help you understand and exploit the market. This research " +
|
||||||
"allows you to know how many sales of a Material/Product you lose or gain " +
|
"allows you to know how many sales of a Material/Product you lose or gain " +
|
||||||
"from having too high or too low or a sale price.",
|
"from having too high or too low or a sale price. It also lets you automatically " +
|
||||||
|
"set the sale price of your Materials/Products at the optimal price such that " +
|
||||||
|
"the amount sold matches the amount produced.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Overclock",
|
name: "Overclock",
|
||||||
|
@ -17,10 +17,14 @@ import { Industries,
|
|||||||
IndustryDescriptions,
|
IndustryDescriptions,
|
||||||
IndustryResearchTrees } from "../IndustryData";
|
IndustryResearchTrees } from "../IndustryData";
|
||||||
|
|
||||||
|
import { MaterialSizes } from "../MaterialSizes";
|
||||||
|
|
||||||
import { Product } from "../Product";
|
import { Product } from "../Product";
|
||||||
|
|
||||||
import { Player } from "../../Player";
|
import { Player } from "../../Player";
|
||||||
|
|
||||||
|
import { Cities } from "../../Locations/Cities";
|
||||||
|
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
import { dialogBoxCreate } from "../../../utils/DialogBox";
|
||||||
@ -81,7 +85,7 @@ export class CorporationEventHandler {
|
|||||||
|
|
||||||
var totalAmount = Number(money) + (stockShares * stockPrice);
|
var totalAmount = Number(money) + (stockShares * stockPrice);
|
||||||
var repGain = totalAmount / BribeToRepRatio;
|
var repGain = totalAmount / BribeToRepRatio;
|
||||||
repGainText.innerText = "You will gain " + numeralWrapper.formatNumber(repGain, "0,0") +
|
repGainText.innerText = "You will gain " + numeralWrapper.format(repGain, "0,0") +
|
||||||
" reputation with " +
|
" reputation with " +
|
||||||
factionSelector.options[factionSelector.selectedIndex].value +
|
factionSelector.options[factionSelector.selectedIndex].value +
|
||||||
" with this bribe";
|
" with this bribe";
|
||||||
@ -104,7 +108,7 @@ export class CorporationEventHandler {
|
|||||||
var totalAmount = money + (stockShares * stockPrice);
|
var totalAmount = money + (stockShares * stockPrice);
|
||||||
var repGain = totalAmount / BribeToRepRatio;
|
var repGain = totalAmount / BribeToRepRatio;
|
||||||
console.log("repGain: " + repGain);
|
console.log("repGain: " + repGain);
|
||||||
repGainText.innerText = "You will gain " + numeralWrapper.formatNumber(repGain, "0,0") +
|
repGainText.innerText = "You will gain " + numeralWrapper.format(repGain, "0,0") +
|
||||||
" reputation with " +
|
" reputation with " +
|
||||||
factionSelector.options[factionSelector.selectedIndex].value +
|
factionSelector.options[factionSelector.selectedIndex].value +
|
||||||
" with this bribe";
|
" with this bribe";
|
||||||
@ -131,7 +135,7 @@ export class CorporationEventHandler {
|
|||||||
} else {
|
} else {
|
||||||
var totalAmount = money + (stockShares * stockPrice);
|
var totalAmount = money + (stockShares * stockPrice);
|
||||||
var repGain = totalAmount / BribeToRepRatio;
|
var repGain = totalAmount / BribeToRepRatio;
|
||||||
dialogBoxCreate("You gained " + formatNumber(repGain, 0) +
|
dialogBoxCreate("You gained " + numeralWrapper.format(repGain, "0,0") +
|
||||||
" reputation with " + fac.name + " by bribing them.");
|
" reputation with " + fac.name + " by bribing them.");
|
||||||
fac.playerReputation += repGain;
|
fac.playerReputation += repGain;
|
||||||
this.corp.funds = this.corp.funds.minus(money);
|
this.corp.funds = this.corp.funds.minus(money);
|
||||||
@ -170,7 +174,6 @@ export class CorporationEventHandler {
|
|||||||
type:"number", placeholder:"Shares to buyback", margin:"5px",
|
type:"number", placeholder:"Shares to buyback", margin:"5px",
|
||||||
inputListener: ()=> {
|
inputListener: ()=> {
|
||||||
var numShares = Math.round(input.value);
|
var numShares = Math.round(input.value);
|
||||||
//TODO add conditional for if player doesn't have enough money
|
|
||||||
if (isNaN(numShares) || numShares <= 0) {
|
if (isNaN(numShares) || numShares <= 0) {
|
||||||
costIndicator.innerText = "ERROR: Invalid value entered for number of shares to buyback"
|
costIndicator.innerText = "ERROR: Invalid value entered for number of shares to buyback"
|
||||||
} else if (numShares > this.corp.issuedShares) {
|
} else if (numShares > this.corp.issuedShares) {
|
||||||
@ -228,7 +231,7 @@ export class CorporationEventHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a popup that lets the player discontinue a product
|
// Create a popup that lets the player discontinue a product
|
||||||
createDiscontinueProductPopup(product) {
|
createDiscontinueProductPopup(product, industry) {
|
||||||
const popupId = "cmpy-mgmt-discontinue-product-popup";
|
const popupId = "cmpy-mgmt-discontinue-product-popup";
|
||||||
const txt = createElement("p", {
|
const txt = createElement("p", {
|
||||||
innerText:"Are you sure you want to do this? Discontinuing a product " +
|
innerText:"Are you sure you want to do this? Discontinuing a product " +
|
||||||
@ -237,9 +240,9 @@ export class CorporationEventHandler {
|
|||||||
"removed and left unsold",
|
"removed and left unsold",
|
||||||
});
|
});
|
||||||
const confirmBtn = createElement("button", {
|
const confirmBtn = createElement("button", {
|
||||||
class:"a-link-button",innerText:"Discontinue",
|
class:"popup-box-button",innerText:"Discontinue",
|
||||||
clickListener: () => {
|
clickListener: () => {
|
||||||
industry.discontinueProduct(product, parentRefs);
|
industry.discontinueProduct(product);
|
||||||
removeElementById(popupId);
|
removeElementById(popupId);
|
||||||
this.rerender();
|
this.rerender();
|
||||||
return false;
|
return false;
|
||||||
@ -247,7 +250,7 @@ export class CorporationEventHandler {
|
|||||||
});
|
});
|
||||||
const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" });
|
const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" });
|
||||||
|
|
||||||
createPopup(popupId, [txt, confirmBtn, cancelBtn]);
|
createPopup(popupId, [txt, cancelBtn, confirmBtn]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a popup that lets the player manage exports
|
// Create a popup that lets the player manage exports
|
||||||
@ -669,8 +672,8 @@ export class CorporationEventHandler {
|
|||||||
productNameInput.focus();
|
productNameInput.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a popup that lets the player use the Market TA research
|
// Create a popup that lets the player use the Market TA research for Materials
|
||||||
createMarketTaPopup(mat, industry) {
|
createMaterialMarketTaPopup(mat, industry) {
|
||||||
const corp = this.corp;
|
const corp = this.corp;
|
||||||
|
|
||||||
const popupId = "cmpy-mgmt-marketta-popup";
|
const popupId = "cmpy-mgmt-marketta-popup";
|
||||||
@ -694,19 +697,21 @@ export class CorporationEventHandler {
|
|||||||
"be sold at the price identified by Market-TA.I (i.e. the price shown above)"
|
"be sold at the price identified by Market-TA.I (i.e. the price shown above)"
|
||||||
})
|
})
|
||||||
const useTa1AutoSaleCheckbox = createElement("input", {
|
const useTa1AutoSaleCheckbox = createElement("input", {
|
||||||
|
checked: mat.marketTa1,
|
||||||
id: useTa1AutoSaleId,
|
id: useTa1AutoSaleId,
|
||||||
|
margin: "3px",
|
||||||
type: "checkbox",
|
type: "checkbox",
|
||||||
value: mat.marketTa1,
|
|
||||||
changeListener: (e) => {
|
changeListener: (e) => {
|
||||||
mat.marketTa1 = e.target.value;
|
mat.marketTa1 = e.target.checked;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox);
|
useTa1AutoSaleDiv.appendChild(useTa1AutoSaleLabel);
|
||||||
useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox);
|
useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox);
|
||||||
|
|
||||||
const closeBtn = createPopupCloseButton(popupId, {
|
const closeBtn = createPopupCloseButton(popupId, {
|
||||||
class: "std-button",
|
class: "std-button",
|
||||||
display: "block",
|
display: "block",
|
||||||
|
innerText: "Close",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (industry.hasResearch("Market-TA.II")) {
|
if (industry.hasResearch("Market-TA.II")) {
|
||||||
@ -741,11 +746,36 @@ export class CorporationEventHandler {
|
|||||||
}
|
}
|
||||||
ta2Text.innerHTML = `<br><u><strong>Market-TA.II</strong></u><br>` +
|
ta2Text.innerHTML = `<br><u><strong>Market-TA.II</strong></u><br>` +
|
||||||
`If you sell at ${numeralWrapper.formatMoney(sCost)}, ` +
|
`If you sell at ${numeralWrapper.formatMoney(sCost)}, ` +
|
||||||
`then you will sell ${formatNumber(markup, 5)}x as much compared ` +
|
`then you will sell ${numeralWrapper.format(markup, "0.00000")}x as much compared ` +
|
||||||
`to if you sold at market price.`;
|
`to if you sold at market price.`;
|
||||||
}
|
}
|
||||||
updateTa2Text();
|
updateTa2Text();
|
||||||
createPopup(popupId, [ta1, ta2Text, ta2Input, closeBtn]);
|
|
||||||
|
// Enable using Market-TA2 for automatically setting sale price
|
||||||
|
const useTa2AutoSaleId = "cmpy-mgmt-marketa2-checkbox";
|
||||||
|
const useTa2AutoSaleDiv = createElement("div", { display: "block" });
|
||||||
|
const useTa2AutoSaleLabel = createElement("label", {
|
||||||
|
color: "white",
|
||||||
|
for: useTa2AutoSaleId,
|
||||||
|
innerText: "Use Market-TA.II for Auto-Sale Price",
|
||||||
|
tooltip: "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)"
|
||||||
|
})
|
||||||
|
const useTa2AutoSaleCheckbox = createElement("input", {
|
||||||
|
checked: mat.marketTa2,
|
||||||
|
id: useTa2AutoSaleId,
|
||||||
|
margin: "3px",
|
||||||
|
type: "checkbox",
|
||||||
|
changeListener: (e) => {
|
||||||
|
mat.marketTa2 = e.target.checked;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
useTa2AutoSaleDiv.appendChild(useTa2AutoSaleLabel);
|
||||||
|
useTa2AutoSaleDiv.appendChild(useTa2AutoSaleCheckbox);
|
||||||
|
|
||||||
|
createPopup(popupId, [ta1, useTa1AutoSaleDiv, ta2Text, ta2Input, useTa2AutoSaleDiv, closeBtn]);
|
||||||
} else {
|
} else {
|
||||||
// Market-TA.I only
|
// Market-TA.I only
|
||||||
createPopup(popupId, [ta1, useTa1AutoSaleDiv, closeBtn]);
|
createPopup(popupId, [ta1, useTa1AutoSaleDiv, closeBtn]);
|
||||||
@ -775,6 +805,7 @@ export class CorporationEventHandler {
|
|||||||
display:"inline-block",
|
display:"inline-block",
|
||||||
innerText: "Confirm",
|
innerText: "Confirm",
|
||||||
clickListener: () => {
|
clickListener: () => {
|
||||||
|
if (citySelector.length <= 0) { return false; }
|
||||||
let city = citySelector.options[citySelector.selectedIndex].value;
|
let city = citySelector.options[citySelector.selectedIndex].value;
|
||||||
if (this.corp.funds.lt(OfficeInitialCost)) {
|
if (this.corp.funds.lt(OfficeInitialCost)) {
|
||||||
dialogBoxCreate("You don't have enough company funds to open a new office!");
|
dialogBoxCreate("You don't have enough company funds to open a new office!");
|
||||||
@ -921,8 +952,110 @@ export class CorporationEventHandler {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a popup that lets the player use the Market TA research for Products
|
||||||
|
createProductMarketTaPopup(product, industry) {
|
||||||
|
const corp = this.corp;
|
||||||
|
|
||||||
|
const popupId = "cmpy-mgmt-marketta-popup";
|
||||||
|
const markupLimit = product.rat / product.mku;
|
||||||
|
const ta1 = createElement("p", {
|
||||||
|
innerHTML: "<u><strong>Market-TA.I</strong></u><br>" +
|
||||||
|
"The maximum sale price you can mark this up to is " +
|
||||||
|
numeralWrapper.formatMoney(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",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Enable using Market-TA1 for automatically setting sale price
|
||||||
|
const useTa1AutoSaleId = "cmpy-mgmt-marketa1-checkbox";
|
||||||
|
const useTa1AutoSaleDiv = createElement("div", { display: "block" });
|
||||||
|
const useTa1AutoSaleLabel = createElement("label", {
|
||||||
|
color: "white",
|
||||||
|
for: useTa1AutoSaleId,
|
||||||
|
innerText: "Use Market-TA.I for Auto-Sale Price",
|
||||||
|
tooltip: "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)"
|
||||||
|
})
|
||||||
|
const useTa1AutoSaleCheckbox = createElement("input", {
|
||||||
|
checked: product.marketTa1,
|
||||||
|
id: useTa1AutoSaleId,
|
||||||
|
margin: "3px",
|
||||||
|
type: "checkbox",
|
||||||
|
changeListener: (e) => {
|
||||||
|
product.marketTa1 = e.target.checked;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
useTa1AutoSaleDiv.appendChild(useTa1AutoSaleLabel);
|
||||||
|
useTa1AutoSaleDiv.appendChild(useTa1AutoSaleCheckbox);
|
||||||
|
|
||||||
|
const closeBtn = createPopupCloseButton(popupId, {
|
||||||
|
class: "std-button",
|
||||||
|
display: "block",
|
||||||
|
innerText: "Close",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (industry.hasResearch("Market-TA.II")) {
|
||||||
|
let updateTa2Text;
|
||||||
|
const ta2Text = createElement("p");
|
||||||
|
const ta2Input = createElement("input", {
|
||||||
|
marginTop: "4px",
|
||||||
|
onkeyup: (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
updateTa2Text();
|
||||||
|
},
|
||||||
|
type: "number",
|
||||||
|
value: product.pCost,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Function that updates the text in ta2Text element
|
||||||
|
updateTa2Text = function() {
|
||||||
|
const sCost = parseFloat(ta2Input.value);
|
||||||
|
let markup = 1;
|
||||||
|
if (sCost > product.pCost) {
|
||||||
|
if ((sCost - product.pCost) > markupLimit) {
|
||||||
|
markup = markupLimit / (sCost - product.pCost);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ta2Text.innerHTML = `<br><u><strong>Market-TA.II</strong></u><br>` +
|
||||||
|
`If you sell at ${numeralWrapper.formatMoney(sCost)}, ` +
|
||||||
|
`then you will sell ${numeralWrapper.format(markup, "0.00000")}x as much compared ` +
|
||||||
|
`to if you sold at market price.`;
|
||||||
|
}
|
||||||
|
updateTa2Text();
|
||||||
|
|
||||||
|
// Enable using Market-TA2 for automatically setting sale price
|
||||||
|
const useTa2AutoSaleId = "cmpy-mgmt-marketa2-checkbox";
|
||||||
|
const useTa2AutoSaleDiv = createElement("div", { display: "block" });
|
||||||
|
const useTa2AutoSaleLabel = createElement("label", {
|
||||||
|
color: "white",
|
||||||
|
for: useTa2AutoSaleId,
|
||||||
|
innerText: "Use Market-TA.II for Auto-Sale Price",
|
||||||
|
tooltip: "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)"
|
||||||
|
})
|
||||||
|
const useTa2AutoSaleCheckbox = createElement("input", {
|
||||||
|
checked: product.marketTa2,
|
||||||
|
id: useTa2AutoSaleId,
|
||||||
|
margin: "3px",
|
||||||
|
type: "checkbox",
|
||||||
|
changeListener: (e) => {
|
||||||
|
product.marketTa2 = e.target.checked;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
useTa2AutoSaleDiv.appendChild(useTa2AutoSaleLabel);
|
||||||
|
useTa2AutoSaleDiv.appendChild(useTa2AutoSaleCheckbox);
|
||||||
|
|
||||||
|
createPopup(popupId, [ta1, useTa1AutoSaleDiv, ta2Text, ta2Input, useTa2AutoSaleDiv, closeBtn]);
|
||||||
|
} else {
|
||||||
|
// Market-TA.I only
|
||||||
|
createPopup(popupId, [ta1, useTa1AutoSaleDiv, closeBtn]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create a popup that lets the player purchase a Material
|
// Create a popup that lets the player purchase a Material
|
||||||
createPurchaseMaterialPopup(mat, industry) {
|
createPurchaseMaterialPopup(mat, industry, warehouse) {
|
||||||
const corp = this.corp;
|
const corp = this.corp;
|
||||||
|
|
||||||
const purchasePopupId = "cmpy-mgmt-material-purchase-popup";
|
const purchasePopupId = "cmpy-mgmt-material-purchase-popup";
|
||||||
@ -980,15 +1113,20 @@ export class CorporationEventHandler {
|
|||||||
|
|
||||||
let bulkPurchaseCostTxt = createElement("p");
|
let bulkPurchaseCostTxt = createElement("p");
|
||||||
function updateBulkPurchaseText(amount) {
|
function updateBulkPurchaseText(amount) {
|
||||||
const cost = parseFloat(amount) * mat.bCost;
|
const parsedAmt = parseFloat(amount);
|
||||||
if (isNaN(cost)) {
|
const cost = parsedAmt * mat.bCost;
|
||||||
dialogBoxCreate(`Bulk Purchase Cost calculated to be NaN. This is either due to ` +
|
|
||||||
`invalid input, or it is a bug (in which case you should report to dev)`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bulkPurchaseCostTxt.innerText = `Purchasing ${numeralWrapper.format(amt, "0,0.00")} of ` +
|
const matSize = MaterialSizes[mat.name];
|
||||||
`${mat.name} will cost ${numeralWrapper.formatMoney(cost)}`;
|
const maxAmount = ((warehouse.size - warehouse.sizeUsed) / matSize);
|
||||||
|
|
||||||
|
if (parsedAmt * matSize > maxAmount) {
|
||||||
|
bulkPurchaseCostTxt.innerText = "Not enough warehouse space to purchase this amount";
|
||||||
|
} else if (isNaN(cost)) {
|
||||||
|
bulkPurchaseCostTxt.innerText = "Invalid put for Bulk Purchase amount";
|
||||||
|
} else {
|
||||||
|
bulkPurchaseCostTxt.innerText = `Purchasing ${numeralWrapper.format(parsedAmt, "0,0.00")} of ` +
|
||||||
|
`${mat.name} will cost ${numeralWrapper.formatMoney(cost)}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let bulkPurchaseConfirmBtn;
|
let bulkPurchaseConfirmBtn;
|
||||||
@ -998,7 +1136,7 @@ export class CorporationEventHandler {
|
|||||||
type: "number",
|
type: "number",
|
||||||
onkeyup: (e) => {
|
onkeyup: (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
updateBulkPurchaseText();
|
updateBulkPurchaseText(e.target.value);
|
||||||
if (e.keyCode === KEY.ENTER) {bulkPurchaseConfirmBtn.click();}
|
if (e.keyCode === KEY.ENTER) {bulkPurchaseConfirmBtn.click();}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -1007,7 +1145,15 @@ export class CorporationEventHandler {
|
|||||||
class: "std-button",
|
class: "std-button",
|
||||||
innerText: "Confirm Bulk Purchase",
|
innerText: "Confirm Bulk Purchase",
|
||||||
clickListener: () => {
|
clickListener: () => {
|
||||||
const amount = parseFloat(input.value);
|
const amount = parseFloat(bulkPurchaseInput.value);
|
||||||
|
|
||||||
|
const matSize = MaterialSizes[mat.name];
|
||||||
|
const maxAmount = ((warehouse.size - warehouse.sizeUsed) / matSize);
|
||||||
|
if (amount * matSize > maxAmount) {
|
||||||
|
dialogBoxCreate(`You do not have enough warehouse size to fit this purchase`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (isNaN(amount)) {
|
if (isNaN(amount)) {
|
||||||
dialogBoxCreate("Invalid input amount");
|
dialogBoxCreate("Invalid input amount");
|
||||||
} else {
|
} else {
|
||||||
@ -1065,9 +1211,18 @@ export class CorporationEventHandler {
|
|||||||
if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
|
if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let inputButtonInitValue = mat.sCost ? mat.sCost : null;
|
||||||
|
if (mat.marketTa2) {
|
||||||
|
inputButtonInitValue += " (Market-TA.II)";
|
||||||
|
} else if (mat.marketTa1) {
|
||||||
|
inputButtonInitValue += " (Market-TA.I)";
|
||||||
|
}
|
||||||
|
|
||||||
const inputPx = createElement("input", {
|
const inputPx = createElement("input", {
|
||||||
type: "text", marginTop: "4px",
|
type: "text", marginTop: "4px",
|
||||||
value: mat.sCost ? mat.sCost : null, placeholder: "Sell price",
|
value: inputButtonInitValue,
|
||||||
|
placeholder: "Sell price",
|
||||||
onkeyup: (e) => {
|
onkeyup: (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
|
if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
|
||||||
@ -1179,16 +1334,41 @@ export class CorporationEventHandler {
|
|||||||
if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
|
if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let inputButtonInitValue = product.sCost ? product.sCost : null;
|
||||||
|
if (product.marketTa2) {
|
||||||
|
inputButtonInitValue += " (Market-TA.II)";
|
||||||
|
} else if (product.marketTa1) {
|
||||||
|
inputButtonInitValue += " (Market-TA.I)";
|
||||||
|
}
|
||||||
|
|
||||||
const inputPx = createElement("input", {
|
const inputPx = createElement("input", {
|
||||||
margin: "5px 0px 5px 0px",
|
margin: "5px 0px 5px 0px",
|
||||||
placeholder: "Sell price",
|
placeholder: "Sell price",
|
||||||
type: "text",
|
type: "text",
|
||||||
value: product.sCost ? product.sCost : null,
|
value: inputButtonInitValue,
|
||||||
onkeyup: (e) => {
|
onkeyup: (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
|
if (e.keyCode === KEY.ENTER) {confirmBtn.click();}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
const checkboxDiv = createElement("div", {
|
||||||
|
border: "1px solid white",
|
||||||
|
display: "inline-block",
|
||||||
|
})
|
||||||
|
const checkboxLabel = createElement("label", {
|
||||||
|
for: popupId + "-checkbox",
|
||||||
|
innerText: "Use same 'Sell Amount' for all cities",
|
||||||
|
});
|
||||||
|
const checkbox = createElement("input", {
|
||||||
|
checked: true,
|
||||||
|
id: popupId + "-checkbox",
|
||||||
|
margin: "2px",
|
||||||
|
type: "checkbox",
|
||||||
|
});
|
||||||
|
checkboxDiv.appendChild(checkboxLabel);
|
||||||
|
checkboxDiv.appendChild(checkbox);
|
||||||
|
|
||||||
confirmBtn = createElement("button", {
|
confirmBtn = createElement("button", {
|
||||||
class: "std-button",
|
class: "std-button",
|
||||||
innerText: "Confirm",
|
innerText: "Confirm",
|
||||||
@ -1220,7 +1400,10 @@ export class CorporationEventHandler {
|
|||||||
product.sCost = cost;
|
product.sCost = cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Parse quantity
|
// Array of all cities. Used later
|
||||||
|
const cities = Object.values(Cities);
|
||||||
|
|
||||||
|
// Parse quantity
|
||||||
if (inputQty.value.includes("MAX") || inputQty.value.includes("PROD")) {
|
if (inputQty.value.includes("MAX") || inputQty.value.includes("PROD")) {
|
||||||
//Dynamically evaluated quantity. First test to make sure its valid
|
//Dynamically evaluated quantity. First test to make sure its valid
|
||||||
var qty = inputQty.value.replace(/\s+/g, '');
|
var qty = inputQty.value.replace(/\s+/g, '');
|
||||||
@ -1238,8 +1421,16 @@ export class CorporationEventHandler {
|
|||||||
dialogBoxCreate("Invalid value or expression for sell price field");
|
dialogBoxCreate("Invalid value or expression for sell price field");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
product.sllman[city][0] = true;
|
if (checkbox.checked) {
|
||||||
product.sllman[city][1] = qty; //Use sanitized input
|
for (let i = 0; i < cities.length; ++i) {
|
||||||
|
const tempCity = cities[i];
|
||||||
|
product.sllman[tempCity][0] = true;
|
||||||
|
product.sllman[tempCity][1] = qty; //Use sanitized input
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
product.sllman[city][0] = true;
|
||||||
|
product.sllman[city][1] = qty; //Use sanitized input
|
||||||
|
}
|
||||||
} else if (isNaN(inputQty.value)) {
|
} else if (isNaN(inputQty.value)) {
|
||||||
dialogBoxCreate("Invalid value for sell quantity field! Must be numeric");
|
dialogBoxCreate("Invalid value for sell quantity field! Must be numeric");
|
||||||
return false;
|
return false;
|
||||||
@ -1247,10 +1438,25 @@ export class CorporationEventHandler {
|
|||||||
var qty = parseFloat(inputQty.value);
|
var qty = parseFloat(inputQty.value);
|
||||||
if (isNaN(qty)) {qty = 0;}
|
if (isNaN(qty)) {qty = 0;}
|
||||||
if (qty === 0) {
|
if (qty === 0) {
|
||||||
product.sllman[city][0] = false;
|
if (checkbox.checked) {
|
||||||
|
for (let i = 0; i < cities.length; ++i) {
|
||||||
|
const tempCity = cities[i];
|
||||||
|
product.sllman[tempCity][0] = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
product.sllman[city][0] = false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
product.sllman[city][0] = true;
|
if (checkbox.checked) {
|
||||||
product.sllman[city][1] = qty;
|
for (let i = 0; i < cities.length; ++i) {
|
||||||
|
const tempCity = cities[i];
|
||||||
|
product.sllman[tempCity][0] = true;
|
||||||
|
product.sllman[tempCity][1] = qty;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
product.sllman[city][0] = true;
|
||||||
|
product.sllman[city][1] = qty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1259,9 +1465,12 @@ export class CorporationEventHandler {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const cancelBtn = createPopupCloseButton(popupId, { innerText: "Cancel" });
|
const cancelBtn = createPopupCloseButton(popupId, { class: "std-button" });
|
||||||
|
|
||||||
createPopup(popupId, [txt, inputQty, inputPx, confirmBtn, cancelBtn]);
|
const linebreak1 = createElement("br");
|
||||||
|
|
||||||
|
createPopup(popupId, [txt, inputQty, inputPx, confirmBtn, cancelBtn, linebreak1,
|
||||||
|
checkboxDiv]);
|
||||||
inputQty.focus();
|
inputQty.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,7 +305,7 @@ export class IndustryOffice extends BaseReactComponent {
|
|||||||
<p>Total Employee Salary: {numeralWrapper.formatMoney(totalSalary)}</p>
|
<p>Total Employee Salary: {numeralWrapper.formatMoney(totalSalary)}</p>
|
||||||
{
|
{
|
||||||
vechain &&
|
vechain &&
|
||||||
<p className={"tooltip"} style={{display: "block"}}>
|
<p className={"tooltip"} style={{display: "inline-block"}}>
|
||||||
Material Production: {numeralWrapper.format(division.getOfficeProductivity(office), "0.000")}
|
Material Production: {numeralWrapper.format(division.getOfficeProductivity(office), "0.000")}
|
||||||
<span className={"tooltiptext"}>
|
<span className={"tooltiptext"}>
|
||||||
The base amount of material this office can produce. Does not include
|
The base amount of material this office can produce. Does not include
|
||||||
@ -314,9 +314,12 @@ export class IndustryOffice extends BaseReactComponent {
|
|||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
vechain && <br />
|
||||||
|
}
|
||||||
{
|
{
|
||||||
vechain &&
|
vechain &&
|
||||||
<p className={"tooltip"} style={{display: "block"}}>
|
<p className={"tooltip"} style={{display: "inline-block"}}>
|
||||||
Product Production: {numeralWrapper.format(division.getOfficeProductivity(office, {forProduct:true}), "0.000")}
|
Product Production: {numeralWrapper.format(division.getOfficeProductivity(office, {forProduct:true}), "0.000")}
|
||||||
<span className={"tooltiptext"}>
|
<span className={"tooltiptext"}>
|
||||||
The base amount of any given Product this office can produce. Does not include
|
The base amount of any given Product this office can produce. Does not include
|
||||||
@ -325,15 +328,21 @@ export class IndustryOffice extends BaseReactComponent {
|
|||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
vechain && <br />
|
||||||
|
}
|
||||||
{
|
{
|
||||||
vechain &&
|
vechain &&
|
||||||
<p className={"tooltip"} style={{display: "block"}}>
|
<p className={"tooltip"} style={{display: "inline-block"}}>
|
||||||
Business Multiplier: x{numeralWrapper.format(division.getBusinessFactor(office), "0.000")}
|
Business Multiplier: x{numeralWrapper.format(division.getBusinessFactor(office), "0.000")}
|
||||||
<span className={"tooltiptext"}>
|
<span className={"tooltiptext"}>
|
||||||
The effect this office's 'Business' employees has on boosting sales
|
The effect this office's 'Business' employees has on boosting sales
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
vechain && <br />
|
||||||
|
}
|
||||||
|
|
||||||
<h2 className={"tooltip"} style={positionHeaderStyle}>
|
<h2 className={"tooltip"} style={positionHeaderStyle}>
|
||||||
{EmployeePositions.Operations} ({this.state.numOperations})
|
{EmployeePositions.Operations} ({this.state.numOperations})
|
||||||
|
@ -3,13 +3,13 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { BaseReactComponent } from "./BaseReactComponent";
|
import { BaseReactComponent } from "./BaseReactComponent";
|
||||||
|
|
||||||
import { Material } from "../Material";
|
import { OfficeSpace,
|
||||||
import { Product } from "../Product";
|
|
||||||
|
|
||||||
import { Warehouse,
|
|
||||||
WarehouseInitialCost,
|
WarehouseInitialCost,
|
||||||
WarehouseUpgradeBaseCost,
|
WarehouseUpgradeBaseCost,
|
||||||
ProductProductionCostRatio } from "../Corporation";
|
ProductProductionCostRatio } from "../Corporation";
|
||||||
|
import { Material } from "../Material";
|
||||||
|
import { Product } from "../Product";
|
||||||
|
import { Warehouse } from "../Warehouse";
|
||||||
|
|
||||||
import { numeralWrapper } from "../../ui/numeralFormat";
|
import { numeralWrapper } from "../../ui/numeralFormat";
|
||||||
|
|
||||||
@ -45,7 +45,12 @@ function ProductComponent(props) {
|
|||||||
sellButtonText = "Sell (0.000/0.000)";
|
sellButtonText = "Sell (0.000/0.000)";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (product.sCost) {
|
if (product.marketTa2) {
|
||||||
|
sellButtonText += (" @ " + numeralWrapper.formatMoney(product.marketTa2Price[city]));
|
||||||
|
} else if (product.marketTa1) {
|
||||||
|
const markupLimit = product.rat / product.mku;
|
||||||
|
sellButtonText += (" @ " + numeralWrapper.formatMoney(product.pCost + markupLimit));
|
||||||
|
} else if (product.sCost) {
|
||||||
if (isString(product.sCost)) {
|
if (isString(product.sCost)) {
|
||||||
sellButtonText += (" @ " + product.sCost);
|
sellButtonText += (" @ " + product.sCost);
|
||||||
} else {
|
} else {
|
||||||
@ -55,14 +60,17 @@ function ProductComponent(props) {
|
|||||||
const sellButtonOnClick = eventHandler.createSellProductPopup.bind(eventHandler, product, city);
|
const sellButtonOnClick = eventHandler.createSellProductPopup.bind(eventHandler, product, city);
|
||||||
|
|
||||||
// Limit Production button
|
// Limit Production button
|
||||||
const limitProductionButtonText = "Limit Production";
|
let limitProductionButtonText = "Limit Production";
|
||||||
if (product.prdman[city][0]) {
|
if (product.prdman[city][0]) {
|
||||||
limitProductionButtonText += " (" + numeralWrapper.format(product.prdman[city][1], nf) + ")";
|
limitProductionButtonText += " (" + numeralWrapper.format(product.prdman[city][1], nf) + ")";
|
||||||
}
|
}
|
||||||
const limitProductionButtonOnClick = eventHandler.createLimitProductProdutionPopup.bind(eventHandler, product, city);
|
const limitProductionButtonOnClick = eventHandler.createLimitProductProdutionPopup.bind(eventHandler, product, city);
|
||||||
|
|
||||||
// Discontinue Button
|
// Discontinue Button
|
||||||
const discontinueButtonOnClick = eventHandler.createDiscontinueProductPopup.bind(eventHandler, product);
|
const discontinueButtonOnClick = eventHandler.createDiscontinueProductPopup.bind(eventHandler, product, division);
|
||||||
|
|
||||||
|
// Market TA button
|
||||||
|
const marketTaButtonOnClick = eventHandler.createProductMarketTaPopup.bind(eventHandler, product, division);
|
||||||
|
|
||||||
// Unfinished Product
|
// Unfinished Product
|
||||||
if (!product.fin) {
|
if (!product.fin) {
|
||||||
@ -83,6 +91,12 @@ function ProductComponent(props) {
|
|||||||
<button className={"std-button"} onClick={discontinueButtonOnClick}>
|
<button className={"std-button"} onClick={discontinueButtonOnClick}>
|
||||||
Discontinue
|
Discontinue
|
||||||
</button>
|
</button>
|
||||||
|
{
|
||||||
|
division.hasResearch("Market-TA.I") &&
|
||||||
|
<button className={"std-button"} onClick={marketTaButtonOnClick}>
|
||||||
|
Market-TA
|
||||||
|
</button>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@ -139,7 +153,7 @@ function ProductComponent(props) {
|
|||||||
</span>
|
</span>
|
||||||
</p><br />
|
</p><br />
|
||||||
<p className={"tooltip"}>
|
<p className={"tooltip"}>
|
||||||
Est. Market Price: {numeralWrapper.formatMoney(product.pCost + product.rat / product.mku)}
|
Est. Market Price: {numeralWrapper.formatMoney(product.pCost)}
|
||||||
<span className={"tooltiptext"}>
|
<span className={"tooltiptext"}>
|
||||||
An estimate of how much consumers are willing to pay for this product.
|
An estimate of how much consumers are willing to pay for this product.
|
||||||
Setting the sale price above this may result in less sales. Setting the sale price below this may result
|
Setting the sale price above this may result in less sales. Setting the sale price below this may result
|
||||||
@ -157,6 +171,12 @@ function ProductComponent(props) {
|
|||||||
<button className={"std-button"} onClick={discontinueButtonOnClick}>
|
<button className={"std-button"} onClick={discontinueButtonOnClick}>
|
||||||
Discontinue
|
Discontinue
|
||||||
</button>
|
</button>
|
||||||
|
{
|
||||||
|
division.hasResearch("Market-TA.I") &&
|
||||||
|
<button className={"std-button"} onClick={marketTaButtonOnClick}>
|
||||||
|
Market-TA
|
||||||
|
</button>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@ -167,9 +187,14 @@ function MaterialComponent(props) {
|
|||||||
const corp = props.corp;
|
const corp = props.corp;
|
||||||
const division = props.division;
|
const division = props.division;
|
||||||
const warehouse = props.warehouse;
|
const warehouse = props.warehouse;
|
||||||
|
const city = props.city;
|
||||||
const mat = props.mat;
|
const mat = props.mat;
|
||||||
const eventHandler = props.eventHandler;
|
const eventHandler = props.eventHandler;
|
||||||
const markupLimit = mat.getMarkupLimit();
|
const markupLimit = mat.getMarkupLimit();
|
||||||
|
const office = division.offices[city];
|
||||||
|
if (!(office instanceof OfficeSpace)) {
|
||||||
|
throw new Error(`Could not get OfficeSpace object for this city (${city})`);
|
||||||
|
}
|
||||||
|
|
||||||
// Numeraljs formatter
|
// Numeraljs formatter
|
||||||
const nf = "0.000";
|
const nf = "0.000";
|
||||||
@ -195,7 +220,7 @@ function MaterialComponent(props) {
|
|||||||
// Purchase material button
|
// Purchase material button
|
||||||
const purchaseButtonText = `Buy (${numeralWrapper.format(mat.buy, nf)})`;
|
const purchaseButtonText = `Buy (${numeralWrapper.format(mat.buy, nf)})`;
|
||||||
const purchaseButtonClass = tutorial ? "std-button flashing-button tooltip" : "std-button";
|
const purchaseButtonClass = tutorial ? "std-button flashing-button tooltip" : "std-button";
|
||||||
const purchaseButtonOnClick = eventHandler.createPurchaseMaterialPopup.bind(eventHandler, mat, division);
|
const purchaseButtonOnClick = eventHandler.createPurchaseMaterialPopup.bind(eventHandler, mat, division, warehouse);
|
||||||
|
|
||||||
// Export material button
|
// Export material button
|
||||||
const exportButtonOnClick = eventHandler.createExportMaterialPopup.bind(eventHandler, mat);
|
const exportButtonOnClick = eventHandler.createExportMaterialPopup.bind(eventHandler, mat);
|
||||||
@ -209,10 +234,12 @@ function MaterialComponent(props) {
|
|||||||
sellButtonText = `Sell (${numeralWrapper.format(mat.sll, nf)}/${numeralWrapper.format(mat.sllman[1], nf)})`;
|
sellButtonText = `Sell (${numeralWrapper.format(mat.sll, nf)}/${numeralWrapper.format(mat.sllman[1], nf)})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mat.sCost) {
|
if (mat.marketTa2) {
|
||||||
if (mat.marketTa1) {
|
sellButtonText += " @ " + numeralWrapper.formatMoney(mat.marketTa2Price);
|
||||||
sellButtonText += " @ " + numeralWrapper.formatMoney(mat.bCost + markupLimit);
|
} else if (mat.marketTa1) {
|
||||||
} else if (isString(mat.sCost)) {
|
sellButtonText += " @ " + numeralWrapper.formatMoney(mat.bCost + markupLimit);
|
||||||
|
} else if (mat.sCost) {
|
||||||
|
if (isString(mat.sCost)) {
|
||||||
var sCost = mat.sCost.replace(/MP/g, mat.bCost);
|
var sCost = mat.sCost.replace(/MP/g, mat.bCost);
|
||||||
sellButtonText += " @ " + numeralWrapper.formatMoney(eval(sCost));
|
sellButtonText += " @ " + numeralWrapper.formatMoney(eval(sCost));
|
||||||
} else {
|
} else {
|
||||||
@ -225,7 +252,7 @@ function MaterialComponent(props) {
|
|||||||
const sellButtonOnClick = eventHandler.createSellMaterialPopup.bind(eventHandler, mat);
|
const sellButtonOnClick = eventHandler.createSellMaterialPopup.bind(eventHandler, mat);
|
||||||
|
|
||||||
// Market TA button
|
// Market TA button
|
||||||
const marketTaButtonOnClick = eventHandler.createMarketTaPopup.bind(eventHandler, mat, division);
|
const marketTaButtonOnClick = eventHandler.createMaterialMarketTaPopup.bind(eventHandler, mat, division);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={"cmpy-mgmt-warehouse-material-div"} key={props.key}>
|
<div className={"cmpy-mgmt-warehouse-material-div"} key={props.key}>
|
||||||
@ -411,6 +438,7 @@ export class IndustryWarehouse extends BaseReactComponent {
|
|||||||
// Only create UI for materials that are relevant for the industry
|
// Only create UI for materials that are relevant for the industry
|
||||||
if (isRelevantMaterial(matName)) {
|
if (isRelevantMaterial(matName)) {
|
||||||
mats.push(MaterialComponent({
|
mats.push(MaterialComponent({
|
||||||
|
city: this.props.currentCity,
|
||||||
corp: corp,
|
corp: corp,
|
||||||
division: division,
|
division: division,
|
||||||
eventHandler: this.eventHandler(),
|
eventHandler: this.eventHandler(),
|
||||||
|
18
src/Locations/createCityMap.ts
Normal file
18
src/Locations/createCityMap.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* Utility function that creates a "city map", which is an object where
|
||||||
|
* each city is a key (property).
|
||||||
|
*
|
||||||
|
* This map uses the official name of the city, NOT its key in the 'Cities' object
|
||||||
|
*/
|
||||||
|
import { Cities } from "./Cities";
|
||||||
|
import { IMap } from "../types";
|
||||||
|
|
||||||
|
export function createCityMap<T>(initValue: T): IMap<T> {
|
||||||
|
const map: IMap<any> = {};
|
||||||
|
const cities = Object.values(Cities);
|
||||||
|
for (let i = 0; i < cities.length; ++i) {
|
||||||
|
map[cities[i]] = initValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
@ -105,13 +105,13 @@ export function createSleevePurchaseAugsPopup(sleeve: Sleeve, p: IPlayer) {
|
|||||||
innerHTML:
|
innerHTML:
|
||||||
[
|
[
|
||||||
`<h2>${aug.name}</h2><br>`,
|
`<h2>${aug.name}</h2><br>`,
|
||||||
`Cost: ${numeralWrapper.formatMoney(aug.baseCost)}<br><br>`,
|
`Cost: ${numeralWrapper.formatMoney(aug.startingCost)}<br><br>`,
|
||||||
`${aug.info}`
|
`${aug.info}`
|
||||||
].join(" "),
|
].join(" "),
|
||||||
padding: "2px",
|
padding: "2px",
|
||||||
clickListener: () => {
|
clickListener: () => {
|
||||||
if (p.canAfford(aug.baseCost)) {
|
if (p.canAfford(aug.startingCost)) {
|
||||||
p.loseMoney(aug.baseCost);
|
p.loseMoney(aug.startingCost);
|
||||||
sleeve.installAugmentation(aug);
|
sleeve.installAugmentation(aug);
|
||||||
dialogBoxCreate(`Installed ${aug.name} on Duplicate Sleeve!`, false)
|
dialogBoxCreate(`Installed ${aug.name} on Duplicate Sleeve!`, false)
|
||||||
removeElementById(popupId);
|
removeElementById(popupId);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl" : ".",
|
"baseUrl" : ".",
|
||||||
"jsx": "react",
|
"jsx": "react",
|
||||||
"lib" : ["es2016", "dom"],
|
"lib" : ["es2016", "dom", "es2017.object"],
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
|
Loading…
Reference in New Issue
Block a user