Merge pull request #2955 from phyzical/bugfix/corp-api-fixes

Bugfix/corp api fixes
This commit is contained in:
hydroflame 2022-03-07 17:43:39 -05:00 committed by GitHub
commit 89316be477
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 96 additions and 63 deletions

@ -14,12 +14,12 @@ import { EmployeePositions } from "./EmployeePositions";
import { Employee } from "./Employee"; import { Employee } from "./Employee";
import { IndustryUpgrades } from "./IndustryUpgrades"; import { IndustryUpgrades } from "./IndustryUpgrades";
import { ResearchMap } from "./ResearchMap"; import { ResearchMap } from "./ResearchMap";
import { isRelevantMaterial } from "./ui/Helpers";
export function NewIndustry(corporation: ICorporation, industry: string, name: string): void { export function NewIndustry(corporation: ICorporation, industry: string, name: string): void {
for (let i = 0; i < corporation.divisions.length; ++i) { for (let i = 0; i < corporation.divisions.length; ++i) {
if (corporation.divisions[i].name === name) { if (corporation.divisions[i].name === name) {
throw new Error("This division name is already in use!"); throw new Error("This division name is already in use!");
return;
} }
} }
@ -290,6 +290,7 @@ export function PurchaseWarehouse(corp: ICorporation, division: IIndustry, city:
export function UpgradeWarehouse(corp: ICorporation, division: IIndustry, warehouse: Warehouse): void { export function UpgradeWarehouse(corp: ICorporation, division: IIndustry, warehouse: Warehouse): void {
const sizeUpgradeCost = CorporationConstants.WarehouseUpgradeBaseCost * Math.pow(1.07, warehouse.level + 1); const sizeUpgradeCost = CorporationConstants.WarehouseUpgradeBaseCost * Math.pow(1.07, warehouse.level + 1);
if (corp.funds < sizeUpgradeCost) return;
++warehouse.level; ++warehouse.level;
warehouse.updateSize(corp, division); warehouse.updateSize(corp, division);
corp.funds = corp.funds - sizeUpgradeCost; corp.funds = corp.funds - sizeUpgradeCost;
@ -343,17 +344,29 @@ export function MakeProduct(
if (corp.funds < designInvest + marketingInvest) { if (corp.funds < designInvest + marketingInvest) {
throw new Error("You don't have enough company funds to make this large of an investment"); throw new Error("You don't have enough company funds to make this large of an investment");
} }
let maxProducts = 3
if (division.hasResearch("uPgrade: Capacity.II")) {
maxProducts = 5
} else if (division.hasResearch("uPgrade: Capacity.I")) {
maxProducts = 4
}
const products = division.products
if (Object.keys(products).length >= maxProducts) {
throw new Error(`You are already at the max products (${maxProducts}) for division: ${division.name}!`);
}
const product = new Product({ const product = new Product({
name: productName.replace(/[<>]/g, ""), //Sanitize for HTMl elements name: productName.replace(/[<>]/g, ""), //Sanitize for HTMl elements
createCity: city, createCity: city,
designCost: designInvest, designCost: designInvest,
advCost: marketingInvest, advCost: marketingInvest,
}); });
if (division.products[product.name] instanceof Product) { if (products[product.name] instanceof Product) {
throw new Error(`You already have a product with this name!`); throw new Error(`You already have a product with this name!`);
} }
corp.funds = corp.funds - (designInvest + marketingInvest); corp.funds = corp.funds - (designInvest + marketingInvest);
division.products[product.name] = product; products[product.name] = product;
} }
export function Research(division: IIndustry, researchName: string): void { export function Research(division: IIndustry, researchName: string): void {
@ -372,7 +385,7 @@ export function Research(division: IIndustry, researchName: string): void {
division.researched[researchName] = true; division.researched[researchName] = true;
} }
export function ExportMaterial(divisionName: string, cityName: string, material: Material, amt: string): void { export function ExportMaterial(divisionName: string, cityName: string, material: Material, amt: string, division?: Industry): void {
// Sanitize amt // Sanitize amt
let sanitizedAmt = amt.replace(/\s+/g, "").toUpperCase(); let sanitizedAmt = amt.replace(/\s+/g, "").toUpperCase();
sanitizedAmt = sanitizedAmt.replace(/[^-()\d/*+.MAX]/g, ""); sanitizedAmt = sanitizedAmt.replace(/[^-()\d/*+.MAX]/g, "");
@ -388,6 +401,11 @@ export function ExportMaterial(divisionName: string, cityName: string, material:
if (n == null || isNaN(n) || n < 0) { if (n == null || isNaN(n) || n < 0) {
throw new Error("Invalid amount entered for export"); throw new Error("Invalid amount entered for export");
} }
if (!division || !isRelevantMaterial(material.name, division)) {
throw new Error(`You cannot export material: ${material.name} to division: ${divisionName}!`);
}
const exportObj = { ind: divisionName, city: cityName, amt: sanitizedAmt }; const exportObj = { ind: divisionName, city: cityName, amt: sanitizedAmt };
material.exp.push(exportObj); material.exp.push(exportObj);
} }

@ -174,33 +174,16 @@ export class OfficeSpace {
} }
setEmployeeToJob(job: string, amount: number): boolean { setEmployeeToJob(job: string, amount: number): boolean {
let unassignedCount = 0; let jobCount = this.employees.reduce((acc, employee) => (employee.pos === job ? acc + 1 : acc), 0);
let jobCount = 0;
for (let i = 0; i < this.employees.length; ++i) { for (const employee of this.employees) {
if (this.employees[i].pos === EmployeePositions.Unassigned) { if (jobCount == amount) return true
unassignedCount++; if (employee.pos === EmployeePositions.Unassigned && jobCount <= amount) {
} else if (this.employees[i].pos === job) { employee.pos = job;
jobCount++; jobCount++;
} } else if (employee.pos === job && jobCount >= amount) {
} employee.pos = EmployeePositions.Unassigned;
jobCount--;
if ((jobCount + unassignedCount) < amount) return false;
for (let i = 0; i < this.employees.length; ++i) {
if (this.employees[i].pos === EmployeePositions.Unassigned) {
if (jobCount <= amount) {
this.employees[i].pos = job;
jobCount++;
unassignedCount--;
}
if (jobCount === amount) break;
} else if (this.employees[i].pos === job) {
if (jobCount >= amount) {
this.employees[i].pos = EmployeePositions.Unassigned;
jobCount--;
unassignedCount++;
}
if (jobCount === amount) break;
} }
} }
if (jobCount !== amount) return false; if (jobCount !== amount) return false;

@ -50,7 +50,7 @@ export function ExportModal(props: IProps): React.ReactElement {
function exportMaterial(): void { function exportMaterial(): void {
try { try {
ExportMaterial(industry, city, props.mat, amt); ExportMaterial(industry, city, props.mat, amt, currentDivision);
} catch (err) { } catch (err) {
dialogBoxCreate(err + ""); dialogBoxCreate(err + "");
} }

@ -19,10 +19,18 @@ interface IProps {
export function Corporation(props: IProps): React.ReactElement { export function Corporation(props: IProps): React.ReactElement {
function addTonsCorporationFunds(): void { function addTonsCorporationFunds(): void {
if (props.player.corporation) { if (props.player.corporation) {
props.player.corporation.funds = props.player.corporation.funds + 1e99; props.player.corporation.funds = props.player.corporation.funds + bigNumber;
} }
} }
function modifyCorporationFunds(modify: number): (x: number) => void {
return function (funds: number): void {
if (props.player.corporation) {
props.player.corporation.funds += funds * modify;
}
};
}
function resetCorporationFunds(): void { function resetCorporationFunds(): void {
if (props.player.corporation) { if (props.player.corporation) {
props.player.corporation.funds = props.player.corporation.funds - props.player.corporation.funds; props.player.corporation.funds = props.player.corporation.funds - props.player.corporation.funds;
@ -77,8 +85,17 @@ export function Corporation(props: IProps): React.ReactElement {
<tbody> <tbody>
<tr> <tr>
<td> <td>
<Button onClick={addTonsCorporationFunds}>Tons of funds</Button> <Typography>Funds:</Typography>
<Button onClick={resetCorporationFunds}>Reset funds</Button> </td>
<td>
<Adjuster
label="set funds"
placeholder="amt"
tons={addTonsCorporationFunds}
add={modifyCorporationFunds(1)}
subtract={modifyCorporationFunds(-1)}
reset={resetCorporationFunds}
/>
</td> </td>
</tr> </tr>
<tr> <tr>

@ -132,11 +132,11 @@ export function NetscriptCorporation(
function getInvestmentOffer(): InvestmentOffer { function getInvestmentOffer(): InvestmentOffer {
const corporation = getCorporation(); const corporation = getCorporation();
if (corporation.fundingRound >= CorporationConstants.FundingRoundShares.length || corporation.fundingRound >= CorporationConstants.FundingRoundMultiplier.length || corporation.public) if (corporation.fundingRound >= CorporationConstants.FundingRoundShares.length || corporation.fundingRound >= CorporationConstants.FundingRoundMultiplier.length || corporation.public)
return { return {
funds: 0, funds: 0,
shares: 0, shares: 0,
round: corporation.fundingRound + 1 // Make more readable round: corporation.fundingRound + 1 // Make more readable
}; // Don't throw an error here, no reason to have a second function to check if you can get investment. }; // Don't throw an error here, no reason to have a second function to check if you can get investment.
const val = corporation.determineValuation(); const val = corporation.determineValuation();
const percShares = CorporationConstants.FundingRoundShares[corporation.fundingRound]; const percShares = CorporationConstants.FundingRoundShares[corporation.fundingRound];
@ -146,7 +146,7 @@ export function NetscriptCorporation(
return { return {
funds: funding, funds: funding,
shares: investShares, shares: investShares,
round: corporation.fundingRound + 1 // Make more readable round: corporation.fundingRound + 1 // Make more readable
}; };
} }
@ -193,7 +193,8 @@ export function NetscriptCorporation(
function bribe(factionName: string, amountCash: number, amountShares: number): boolean { function bribe(factionName: string, amountCash: number, amountShares: number): boolean {
if (!player.factions.includes(factionName)) throw new Error("Invalid faction name"); if (!player.factions.includes(factionName)) throw new Error("Invalid faction name");
if (isNaN(amountCash) || amountCash < 0 || isNaN(amountShares) || amountShares < 0) throw new Error("Invalid value for amount field! Must be numeric, greater than 0."); if (isNaN(amountCash) || amountCash < 0 || isNaN(amountShares) || amountShares < 0) throw new Error("Invalid value for amount field! Must be numeric, grater than 0.");
const corporation = getCorporation(); const corporation = getCorporation();
if (corporation.funds < amountCash) return false; if (corporation.funds < amountCash) return false;
if (corporation.numShares < amountShares) return false; if (corporation.numShares < amountShares) return false;
@ -271,25 +272,25 @@ export function NetscriptCorporation(
function getSafeDivision(division: Industry): NSDivision { function getSafeDivision(division: Industry): NSDivision {
const cities: string[] = []; const cities: string[] = [];
for (const office of Object.values(division.offices)) { for (const office of Object.values(division.offices)) {
if (office === 0) continue; if (office === 0) continue;
cities.push(office.loc); cities.push(office.loc);
} }
return { return {
name: division.name, name: division.name,
type: division.type, type: division.type,
awareness: division.awareness, awareness: division.awareness,
popularity: division.popularity, popularity: division.popularity,
prodMult: division.prodMult, prodMult: division.prodMult,
research: division.sciResearch.qty, research: division.sciResearch.qty,
lastCycleRevenue: division.lastCycleRevenue, lastCycleRevenue: division.lastCycleRevenue,
lastCycleExpenses: division.lastCycleExpenses, lastCycleExpenses: division.lastCycleExpenses,
thisCycleRevenue: division.thisCycleRevenue, thisCycleRevenue: division.thisCycleRevenue,
thisCycleExpenses: division.thisCycleExpenses, thisCycleExpenses: division.thisCycleExpenses,
upgrades: division.upgrades, upgrades: division.upgrades,
cities: cities, cities: cities,
products: division.products === undefined ? [] : Object.keys(division.products), products: division.products === undefined ? [] : Object.keys(division.products),
}; };
} }
const warehouseAPI: WarehouseAPI = { const warehouseAPI: WarehouseAPI = {
@ -409,6 +410,8 @@ export function NetscriptCorporation(
const cityName = helper.string("sellProduct", "cityName", acityName); const cityName = helper.string("sellProduct", "cityName", acityName);
const enabled = helper.boolean(aenabled); const enabled = helper.boolean(aenabled);
const warehouse = getWarehouse(divisionName, cityName); const warehouse = getWarehouse(divisionName, cityName);
if (!hasUnlockUpgrade("SmartSupply"))
throw helper.makeRuntimeErrorMsg(`corporation.setSmartSupply`, `You have not purchased the SmartSupply upgrade!`);
SetSmartSupply(warehouse, enabled); SetSmartSupply(warehouse, enabled);
}, },
setSmartSupplyUseLeftovers: function (adivisionName: any, acityName: any, amaterialName: any, aenabled: any): void { setSmartSupplyUseLeftovers: function (adivisionName: any, acityName: any, amaterialName: any, aenabled: any): void {
@ -419,6 +422,8 @@ export function NetscriptCorporation(
const enabled = helper.boolean(aenabled); const enabled = helper.boolean(aenabled);
const warehouse = getWarehouse(divisionName, cityName); const warehouse = getWarehouse(divisionName, cityName);
const material = getMaterial(divisionName, cityName, materialName); const material = getMaterial(divisionName, cityName, materialName);
if (!hasUnlockUpgrade("SmartSupply"))
throw helper.makeRuntimeErrorMsg(`corporation.setSmartSupply`, `You have not purchased the SmartSupply upgrade!`);
SetSmartSupplyUseLeftovers(warehouse, material, enabled); SetSmartSupplyUseLeftovers(warehouse, material, enabled);
}, },
buyMaterial: function (adivisionName: any, acityName: any, amaterialName: any, aamt: any): void { buyMaterial: function (adivisionName: any, acityName: any, amaterialName: any, aamt: any): void {
@ -462,7 +467,7 @@ export function NetscriptCorporation(
const targetCity = helper.string("exportMaterial", "targetCity", atargetCity); const targetCity = helper.string("exportMaterial", "targetCity", atargetCity);
const materialName = helper.string("exportMaterial", "materialName", amaterialName); const materialName = helper.string("exportMaterial", "materialName", amaterialName);
const amt = helper.string("exportMaterial", "amt", aamt); const amt = helper.string("exportMaterial", "amt", aamt);
ExportMaterial(targetDivision, targetCity, getMaterial(sourceDivision, sourceCity, materialName), amt + ""); ExportMaterial(targetDivision, targetCity, getMaterial(sourceDivision, sourceCity, materialName), amt + "", getDivision(targetDivision));
}, },
cancelExportMaterial: function ( cancelExportMaterial: function (
asourceDivision: any, asourceDivision: any,
@ -487,6 +492,8 @@ export function NetscriptCorporation(
const cityName = helper.string("setMaterialMarketTA1", "cityName", acityName); const cityName = helper.string("setMaterialMarketTA1", "cityName", acityName);
const materialName = helper.string("setMaterialMarketTA1", "materialName", amaterialName); const materialName = helper.string("setMaterialMarketTA1", "materialName", amaterialName);
const on = helper.boolean(aon); const on = helper.boolean(aon);
if (!getDivision(divisionName).hasResearch("Market-TA.I"))
throw helper.makeRuntimeErrorMsg(`corporation.setMaterialMarketTA1`, `You have not researched MarketTA.I for division: ${divisionName}`);
SetMaterialMarketTA1(getMaterial(divisionName, cityName, materialName), on); SetMaterialMarketTA1(getMaterial(divisionName, cityName, materialName), on);
}, },
setMaterialMarketTA2: function (adivisionName: any, acityName: any, amaterialName: any, aon: any): void { setMaterialMarketTA2: function (adivisionName: any, acityName: any, amaterialName: any, aon: any): void {
@ -495,6 +502,8 @@ export function NetscriptCorporation(
const cityName = helper.string("setMaterialMarketTA2", "cityName", acityName); const cityName = helper.string("setMaterialMarketTA2", "cityName", acityName);
const materialName = helper.string("setMaterialMarketTA2", "materialName", amaterialName); const materialName = helper.string("setMaterialMarketTA2", "materialName", amaterialName);
const on = helper.boolean(aon); const on = helper.boolean(aon);
if (!getDivision(divisionName).hasResearch("Market-TA.II"))
throw helper.makeRuntimeErrorMsg(`corporation.setMaterialMarketTA2`, `You have not researched MarketTA.II for division: ${divisionName}`);
SetMaterialMarketTA2(getMaterial(divisionName, cityName, materialName), on); SetMaterialMarketTA2(getMaterial(divisionName, cityName, materialName), on);
}, },
setProductMarketTA1: function (adivisionName: any, aproductName: any, aon: any): void { setProductMarketTA1: function (adivisionName: any, aproductName: any, aon: any): void {
@ -502,6 +511,8 @@ export function NetscriptCorporation(
const divisionName = helper.string("setProductMarketTA1", "divisionName", adivisionName); const divisionName = helper.string("setProductMarketTA1", "divisionName", adivisionName);
const productName = helper.string("setProductMarketTA1", "productName", aproductName); const productName = helper.string("setProductMarketTA1", "productName", aproductName);
const on = helper.boolean(aon); const on = helper.boolean(aon);
if (!getDivision(divisionName).hasResearch("Market-TA.I"))
throw helper.makeRuntimeErrorMsg(`corporation.setProductMarketTA1`, `You have not researched MarketTA.I for division: ${divisionName}`);
SetProductMarketTA1(getProduct(divisionName, productName), on); SetProductMarketTA1(getProduct(divisionName, productName), on);
}, },
setProductMarketTA2: function (adivisionName: any, aproductName: any, aon: any): void { setProductMarketTA2: function (adivisionName: any, aproductName: any, aon: any): void {
@ -509,6 +520,8 @@ export function NetscriptCorporation(
const divisionName = helper.string("setProductMarketTA2", "divisionName", adivisionName); const divisionName = helper.string("setProductMarketTA2", "divisionName", adivisionName);
const productName = helper.string("setProductMarketTA2", "productName", aproductName); const productName = helper.string("setProductMarketTA2", "productName", aproductName);
const on = helper.boolean(aon); const on = helper.boolean(aon);
if (!getDivision(divisionName).hasResearch("Market-TA.II"))
throw helper.makeRuntimeErrorMsg(`corporation.setProductMarketTA2`, `You have not researched MarketTA.II for division: ${divisionName}`);
SetProductMarketTA2(getProduct(divisionName, productName), on); SetProductMarketTA2(getProduct(divisionName, productName), on);
}, },
}; };
@ -723,6 +736,8 @@ export function NetscriptCorporation(
const percent = helper.number("issueDividends", "percent", apercent); const percent = helper.number("issueDividends", "percent", apercent);
if (percent < 0 || percent > 100) throw new Error("Invalid value for percent field! Must be numeric, greater than 0, and less than 100"); if (percent < 0 || percent > 100) throw new Error("Invalid value for percent field! Must be numeric, greater than 0, and less than 100");
const corporation = getCorporation(); const corporation = getCorporation();
if (!corporation.public)
throw helper.makeRuntimeErrorMsg(`corporation.issueDividends`, `Your company has not gone public!`);
IssueDividends(corporation, percent); IssueDividends(corporation, percent);
}, },
@ -781,24 +796,24 @@ export function NetscriptCorporation(
const industryName = helper.string("getExpandIndustryCost", "industryName", aindustryName); const industryName = helper.string("getExpandIndustryCost", "industryName", aindustryName);
return getExpandIndustryCost(industryName); return getExpandIndustryCost(industryName);
}, },
getExpandCityCost: function(): number { getExpandCityCost: function (): number {
checkAccess("getExpandCityCost"); checkAccess("getExpandCityCost");
return getExpandCityCost(); return getExpandCityCost();
}, },
getInvestmentOffer: function(): InvestmentOffer { getInvestmentOffer: function (): InvestmentOffer {
checkAccess("getInvestmentOffer"); checkAccess("getInvestmentOffer");
return getInvestmentOffer(); return getInvestmentOffer();
}, },
acceptInvestmentOffer: function(): boolean { acceptInvestmentOffer: function (): boolean {
checkAccess("acceptInvestmentOffer"); checkAccess("acceptInvestmentOffer");
return acceptInvestmentOffer(); return acceptInvestmentOffer();
}, },
goPublic: function(anumShares: any): boolean { goPublic: function (anumShares: any): boolean {
checkAccess("acceptInvestmentOffer"); checkAccess("acceptInvestmentOffer");
const numShares = helper.number("goPublic", "numShares", anumShares); const numShares = helper.number("goPublic", "numShares", anumShares);
return goPublic(numShares); return goPublic(numShares);
}, },
bribe: function(afactionName: string, aamountCash: any, aamountShares: any): boolean { bribe: function (afactionName: string, aamountCash: any, aamountShares: any): boolean {
checkAccess("bribe"); checkAccess("bribe");
const factionName = helper.string("bribe", "factionName", afactionName); const factionName = helper.string("bribe", "factionName", afactionName);
const amountCash = helper.number("bribe", "amountCash", aamountCash); const amountCash = helper.number("bribe", "amountCash", aamountCash);