sneak in corp API.

This commit is contained in:
Olivier Gagnon 2021-09-10 02:17:55 -04:00
parent e906a6331f
commit e5dcb424a2
13 changed files with 388 additions and 157 deletions

File diff suppressed because one or more lines are too long

20
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

@ -13,6 +13,8 @@ import { Cities } from "../Locations/Cities";
import { EmployeePositions } from "./EmployeePositions";
import { Employee } from "./Employee";
import { IndustryUpgrades } from "./IndustryUpgrades";
import { IndustryResearchTrees } from "./IndustryData";
import { ResearchMap } from "./ResearchMap";
export function NewIndustry(corporation: ICorporation, industry: string, name: string): void {
for (let i = 0; i < corporation.divisions.length; ++i) {
@ -229,6 +231,12 @@ export function SetSmartSupply(warehouse: Warehouse, smartSupply: boolean): void
warehouse.smartSupplyEnabled = smartSupply;
}
export function SetSmartSupplyUseLeftovers(warehouse: Warehouse, material: Material, useLeftover: boolean): void {
if (!Object.keys(warehouse.smartSupplyUseLeftovers).includes(material.name))
throw new Error(`Invalid material '${material.name}'`);
warehouse.smartSupplyUseLeftovers[material.name] = useLeftover;
}
export function BuyMaterial(material: Material, amt: number): void {
if (isNaN(amt)) {
throw new Error(`Invalid amount '${amt}' to buy material '${material.name}'`);
@ -250,7 +258,6 @@ export function UpgradeOfficeSize(corp: ICorporation, office: OfficeSpace, size:
mult += Math.pow(costMultiplier, initialPriceMult + i);
}
const cost = CorporationConstants.OfficeInitialCost * mult;
console.log(cost);
if (corp.funds.lt(cost)) return;
office.size += size;
corp.funds = corp.funds.minus(cost);
@ -347,3 +354,73 @@ export function MakeProduct(
corp.funds = corp.funds.minus(designInvest + marketingInvest);
division.products[product.name] = product;
}
export function Research(division: IIndustry, researchName: string): void {
const researchTree = IndustryResearchTrees[division.type];
if (researchTree === undefined) throw new Error(`No research tree for industry '${division.type}'`);
const allResearch = researchTree.getAllNodes();
if (!allResearch.includes(researchName)) throw new Error(`No research named '${researchName}'`);
const research = ResearchMap[researchName];
if (division.sciResearch.qty < research.cost)
throw new Error(`You do not have enough Scientific Research for ${research.name}`);
division.sciResearch.qty -= research.cost;
// Get the Node from the Research Tree and set its 'researched' property
researchTree.research(researchName);
division.researched[researchName] = true;
}
export function ExportMaterial(divisionName: string, cityName: string, material: Material, amt: string): void {
// Sanitize amt
let sanitizedAmt = amt.replace(/\s+/g, "");
sanitizedAmt = sanitizedAmt.replace(/[^-()\d/*+.MAX]/g, "");
let temp = sanitizedAmt.replace(/MAX/g, "1");
try {
temp = eval(temp);
} catch (e) {
throw new Error("Invalid expression entered for export amount: " + e);
}
const n = parseFloat(temp);
if (n == null || isNaN(n) || n < 0) {
throw new Error("Invalid amount entered for export");
}
const exportObj = { ind: divisionName, city: cityName, amt: sanitizedAmt };
material.exp.push(exportObj);
}
export function CancelExportMaterial(divisionName: string, cityName: string, material: Material, amt: string): void {
for (let i = 0; i < material.exp.length; ++i) {
if (material.exp[i].ind !== divisionName || material.exp[i].city !== cityName || material.exp[i].amt !== amt)
continue;
material.exp.splice(i, 1);
break;
}
}
export function LimitProductProduction(product: Product, cityName: string, qty: number): void {
if (qty < 0 || isNaN(qty)) {
product.prdman[cityName][0] = false;
} else {
product.prdman[cityName][0] = true;
product.prdman[cityName][1] = qty;
}
}
export function SetMaterialMarketTA1(material: Material, on: boolean): void {
material.marketTa1 = on;
}
export function SetMaterialMarketTA2(material: Material, on: boolean): void {
material.marketTa2 = on;
}
export function SetProductMarketTA1(product: Product, on: boolean): void {
product.marketTa1 = on;
}
export function SetProductMarketTA2(product: Product, on: boolean): void {
product.marketTa2 = on;
}

@ -207,6 +207,25 @@ export class Employee {
panel.appendChild(selector);
}
copy(): Employee {
const employee = new Employee();
employee.name = this.name;
employee.mor = this.mor;
employee.hap = this.hap;
employee.ene = this.ene;
employee.int = this.int;
employee.cha = this.cha;
employee.exp = this.exp;
employee.cre = this.cre;
employee.eff = this.eff;
employee.sal = this.sal;
employee.pro = this.pro;
employee.cyclesUntilRaise = this.cyclesUntilRaise;
employee.loc = this.loc;
employee.pos = this.pos;
return employee;
}
toJSON(): any {
return Generic_toJSON("Employee", this);
}

@ -1439,6 +1439,59 @@ export class Industry implements IIndustry {
return researchTree.getStorageMultiplier();
}
copy(): Industry {
// products: { [key: string]: Product | undefined } = {};
// //Maps locations to warehouses. 0 if no warehouse at that location
// warehouses: { [key: string]: Warehouse | 0 };
// //Maps locations to offices. 0 if no office at that location
// offices: { [key: string]: OfficeSpace | 0 } = {
// [CityName.Aevum]: 0,
// [CityName.Chongqing]: 0,
// [CityName.Sector12]: new OfficeSpace({
// loc: CityName.Sector12,
// size: CorporationConstants.OfficeInitialSize,
// }),
// [CityName.NewTokyo]: 0,
// [CityName.Ishima]: 0,
// [CityName.Volhaven]: 0,
// };
const division = new Industry();
division.sciResearch = this.sciResearch.copy();
division.researched = {};
for (const x of Object.keys(this.researched)) {
division.researched[x] = this.researched[x];
}
division.reqMats = {};
for (const x of Object.keys(this.reqMats)) {
division.reqMats[x] = this.reqMats[x];
}
division.name = this.name;
division.type = this.type;
division.makesProducts = this.makesProducts;
division.awareness = this.awareness;
division.popularity = this.popularity;
division.startingCost = this.startingCost;
division.reFac = this.reFac;
division.sciFac = this.sciFac;
division.hwFac = this.hwFac;
division.robFac = this.robFac;
division.aiFac = this.aiFac;
division.advFac = this.advFac;
division.prodMult = this.prodMult;
division.state = this.state;
division.newInd = this.newInd;
division.lastCycleRevenue = this.lastCycleRevenue.plus(0);
division.lastCycleExpenses = this.lastCycleExpenses.plus(0);
division.thisCycleRevenue = this.thisCycleRevenue.plus(0);
division.thisCycleExpenses = this.thisCycleExpenses.plus(0);
division.upgrades = this.upgrades.slice();
division.prodMats = this.prodMats.slice();
return division;
}
/**
* Serialize the current object to a JSON save state.
*/

@ -225,6 +225,38 @@ export class Material {
}
}
copy(): Material {
const material = new Material();
material.name = this.name;
material.qty = this.qty;
material.qlt = this.qlt;
material.dmd = this.dmd;
material.cmp = this.cmp;
material.mv = this.mv;
material.mku = this.mku;
material.buy = this.buy;
material.sll = this.sll;
material.prd = this.prd;
material.imp = this.imp;
material.totalExp = this.totalExp;
material.bCost = this.bCost;
material.marketTa1 = this.marketTa1;
material.marketTa2 = this.marketTa2;
material.marketTa2Price = this.marketTa2Price;
material.sCost = this.sCost;
material.prdman = [this.prdman[0], this.prdman[1]];
material.sllman = [this.sllman[0], this.sllman[1]];
material.dmdR = this.dmdR.slice();
material.cmpR = this.cmpR.slice();
material.exp = this.exp.slice().map((e) => {
return { ind: e.ind, city: e.city, amt: e.amt };
});
return material;
}
// Serialize the current object to a JSON save state.
toJSON(): any {
return Generic_toJSON("Material", this);

@ -9,19 +9,12 @@ import { ICorporation } from "./ICorporation";
interface IParams {
loc?: string;
cost?: number;
size?: number;
comfort?: number;
beauty?: number;
}
export class OfficeSpace {
loc: string;
cost: number;
size: number;
comf: number;
beau: number;
tier = "Basic";
minEne = 0;
maxEne = 100;
minHap = 0;
@ -39,10 +32,7 @@ export class OfficeSpace {
constructor(params: IParams = {}) {
this.loc = params.loc ? params.loc : "";
this.cost = params.cost ? params.cost : 1;
this.size = params.size ? params.size : 1;
this.comf = params.comfort ? params.comfort : 1;
this.beau = params.beauty ? params.beauty : 1;
}
atCapacity(): boolean {
@ -184,6 +174,30 @@ export class OfficeSpace {
return false;
}
copy(): OfficeSpace {
const office = new OfficeSpace();
office.loc = this.loc;
office.size = this.size;
office.minEne = this.minEne;
office.maxEne = this.maxEne;
office.minHap = this.minHap;
office.maxHap = this.maxHap;
office.maxMor = this.maxMor;
office.employeeProd = {
[EmployeePositions.Operations]: this.employeeProd[EmployeePositions.Operations],
[EmployeePositions.Engineer]: this.employeeProd[EmployeePositions.Engineer],
[EmployeePositions.Business]: this.employeeProd[EmployeePositions.Business],
[EmployeePositions.Management]: this.employeeProd[EmployeePositions.Management],
[EmployeePositions.RandD]: this.employeeProd[EmployeePositions.RandD],
total: this.employeeProd["total"],
};
office.employees = [];
for (const employee of this.employees) {
office.employees.push(employee.copy());
}
return office;
}
toJSON(): any {
return Generic_toJSON("OfficeSpace", this);
}

@ -5,6 +5,7 @@ import { ICorporation } from "../ICorporation";
import { Material } from "../Material";
import { Export } from "../Export";
import { IIndustry } from "../IIndustry";
import { ExportMaterial } from "../Actions";
interface IProps {
mat: Material;
@ -39,28 +40,11 @@ export function ExportPopup(props: IProps): React.ReactElement {
}
function exportMaterial(): void {
const industryName = industry;
const cityName = city;
// Sanitize amt
let sanitizedAmt = amt.replace(/\s+/g, "");
sanitizedAmt = sanitizedAmt.replace(/[^-()\d/*+.MAX]/g, "");
let temp = sanitizedAmt.replace(/MAX/g, "1");
try {
temp = eval(temp);
} catch (e) {
dialogBoxCreate("Invalid expression entered for export amount: " + e);
return;
ExportMaterial(industry, city, props.mat, amt);
} catch (err) {
dialogBoxCreate(err + "");
}
const n = parseFloat(temp);
if (n == null || isNaN(n) || n < 0) {
dialogBoxCreate("Invalid amount entered for export");
return;
}
const exportObj = { ind: industryName, city: cityName, amt: sanitizedAmt };
props.mat.exp.push(exportObj);
removePopup(props.popupId);
}

@ -2,6 +2,7 @@ import React, { useState } from "react";
import { dialogBoxCreate } from "../../../utils/DialogBox";
import { removePopup } from "../../ui/React/createPopup";
import { Product } from "../Product";
import { LimitProductProduction } from "../Actions";
interface IProps {
product: Product;
@ -14,22 +15,9 @@ export function LimitProductProductionPopup(props: IProps): React.ReactElement {
const [limit, setLimit] = useState<number | null>(null);
function limitProductProduction(): void {
if (limit === null) {
props.product.prdman[props.city][0] = false;
removePopup(props.popupId);
return;
}
const qty = limit;
if (isNaN(qty)) {
dialogBoxCreate("Invalid value entered");
return;
}
if (qty < 0) {
props.product.prdman[props.city][0] = false;
} else {
props.product.prdman[props.city][0] = true;
props.product.prdman[props.city][1] = qty;
}
let qty = limit;
if (qty === null) qty = -1;
LimitProductProduction(props.product, props.city, qty);
removePopup(props.popupId);
}

@ -6,6 +6,7 @@ import { CorporationConstants } from "../data/Constants";
import { ResearchMap } from "../ResearchMap";
import { Treant } from "treant-js";
import { IIndustry } from "../IIndustry";
import { Research } from "../Actions";
interface IProps {
industry: IIndustry;
@ -61,22 +62,18 @@ export function ResearchPopup(props: IProps): React.ReactElement {
}
div.addEventListener("click", () => {
if (props.industry.sciResearch.qty >= research.cost) {
props.industry.sciResearch.qty -= research.cost;
// Get the Node from the Research Tree and set its 'researched' property
researchTree.research(allResearch[i]);
props.industry.researched[allResearch[i]] = true;
dialogBoxCreate(
`Researched ${allResearch[i]}. It may take a market cycle ` +
`(~${CorporationConstants.SecsPerMarketCycle} seconds) before the effects of ` +
`the Research apply.`,
);
removePopup(props.popupId);
} else {
dialogBoxCreate(`You do not have enough Scientific Research for ${research.name}`);
try {
Research(props.industry, allResearch[i]);
} catch (err) {
dialogBoxCreate(err + "");
}
dialogBoxCreate(
`Researched ${allResearch[i]}. It may take a market cycle ` +
`(~${CorporationConstants.SecsPerMarketCycle} seconds) before the effects of ` +
`the Research apply.`,
);
removePopup(props.popupId);
});
}
});

@ -3,9 +3,10 @@ import React, { useState } from "react";
import { Warehouse } from "../Warehouse";
import { ICorporation } from "../ICorporation";
import { IIndustry } from "../IIndustry";
import { SetSmartSupply } from "../Actions";
import { SetSmartSupply, SetSmartSupplyUseLeftovers } from "../Actions";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { Material } from "../Material";
import { dialogBoxCreate } from "../../../utils/DialogBox";
interface ILeftoverProps {
matName: string;
@ -16,7 +17,12 @@ function Leftover(props: ILeftoverProps): React.ReactElement {
const [checked, setChecked] = useState(!!props.warehouse.smartSupplyUseLeftovers[props.matName]);
function onChange(event: React.ChangeEvent<HTMLInputElement>): void {
props.warehouse.smartSupplyUseLeftovers[props.matName] = event.target.checked;
try {
const material = props.warehouse.materials[props.matName];
SetSmartSupplyUseLeftovers(props.warehouse, material, event.target.checked);
} catch (err) {
dialogBoxCreate(err + "");
}
setChecked(event.target.checked);
}

@ -35,7 +35,15 @@ import {
BuyCoffee,
HireAdVert,
MakeProduct,
Research,
ExportMaterial,
CancelExportMaterial,
SetMaterialMarketTA1,
SetMaterialMarketTA2,
SetProductMarketTA1,
SetProductMarketTA2,
} from "./Corporation/Actions";
import { Reviver } from "../utils/JSONReviver";
import { CorporationUnlockUpgrades } from "./Corporation/data/CorporationUnlockUpgrades";
import { CorporationUpgrades } from "./Corporation/data/CorporationUpgrades";
import {
@ -4502,86 +4510,139 @@ function NetscriptFunctions(workerScript) {
},
}, // End Bladeburner
// corporation: {
// expandIndustry: function (industryName, divisionName) {
// NewIndustry(Player.corporation, industryName, divisionName);
// },
// expandCity: function (divisionName, cityName) {
// const division = getDivision(divisionName);
// NewCity(Player.corporation, division, cityName);
// },
// unlockUpgrade: function (upgradeName) {
// const upgrade = Object.values(CorporationUnlockUpgrades).find((upgrade) => upgrade[2] === upgradeName);
// if (upgrade === undefined) throw new Error("No upgrade named '${upgradeName}'");
// UnlockUpgrade(Player.corporation, upgrade);
// },
// levelUpgrade: function (upgradeName) {
// const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade[4] === upgradeName);
// if (upgrade === undefined) throw new Error("No upgrade named '${upgradeName}'");
// LevelUpgrade(Player.corporation, upgrade);
// },
// issueDividends: function (percent) {
// IssueDividends(Player.corporation, percent);
// },
// sellMaterial: function (divisionName, cityName, materialName, amt, price) {
// const material = getMaterial(divisionName, cityName, materialName);
// SellMaterial(material, amt, price);
// },
// sellProduct: function (divisionName, cityName, productName, amt, price, all) {
// const product = getProduct(divisionName, productName);
// SellProduct(product, cityName, amt, price, all);
// },
// setSmartSupply: function (divisionName, cityName, enabled) {
// const warehouse = getWarehouse(divisionName, cityName);
// SetSmartSupply(warehouse, enabled);
// },
// buyMaterial: function (divisionName, cityName, materialName, amt) {
// const material = getMaterial(divisionName, cityName, materialName);
// BuyMaterial(material, amt);
// },
// employees: function (divisionName, cityName) {
// const office = getOffice(divisionName, cityName);
// return office.employees.map((e) => Object.assign({}, e));
// },
// assignJob: function (divisionName, cityName, employeeName, job) {
// const employee = getEmployee(divisionName, cityName, employeeName);
// AssignJob(employee, job);
// },
// hireEmployee: function (divisionName, cityName) {
// const office = getOffice(divisionName, cityName);
// office.hireRandomEmployee();
// },
// upgradeOfficeSize: function (divisionName, cityName, size) {
// const office = getOffice(divisionName, cityName);
// UpgradeOfficeSize(Player.corporation, office, size);
// },
// throwParty: function (divisionName, cityName, costPerEmployee) {
// const office = getOffice(divisionName, cityName);
// ThrowParty(Player.corporation, office, costPerEmployee);
// },
// purchaseWarehouse: function (divisionName, cityName) {
// PurchaseWarehouse(Player.corporation, getDivision(divisionName), cityName);
// },
// upgradeWarehouse: function (divisionName, cityName) {
// UpgradeWarehouse(Player.corporation, getDivision(divisionName), getWarehouse(divisionName, cityName));
// },
// buyCoffee: function (divisionName, cityName) {
// BuyCoffee(Player.corporation, getDivision(divisionName), getOffice(divisionName, cityName));
// },
// hireAdVert: function (divisionName) {
// HireAdVert(Player.corporation, getDivision(divisionName), getOffice(divisionName, "Sector-12"));
// },
// makeProduct: function (divisionName, cityName, productName, designInvest, marketingInvest) {
// MakeProduct(
// Player.corporation,
// getDivision(divisionName),
// cityName,
// productName,
// designInvest,
// marketingInvest,
// );
// },
// }, // End Corporation API
// Hi, if you're reading this you're a bit nosy.
// There's a corporation API but it's very imbalanced right now.
// It's here so players can test with if they want.
corporation: {
expandIndustry: function (industryName, divisionName) {
NewIndustry(Player.corporation, industryName, divisionName);
},
expandCity: function (divisionName, cityName) {
const division = getDivision(divisionName);
NewCity(Player.corporation, division, cityName);
},
unlockUpgrade: function (upgradeName) {
const upgrade = Object.values(CorporationUnlockUpgrades).find((upgrade) => upgrade[2] === upgradeName);
if (upgrade === undefined) throw new Error("No upgrade named '${upgradeName}'");
UnlockUpgrade(Player.corporation, upgrade);
},
levelUpgrade: function (upgradeName) {
const upgrade = Object.values(CorporationUpgrades).find((upgrade) => upgrade[4] === upgradeName);
if (upgrade === undefined) throw new Error("No upgrade named '${upgradeName}'");
LevelUpgrade(Player.corporation, upgrade);
},
issueDividends: function (percent) {
IssueDividends(Player.corporation, percent);
},
sellMaterial: function (divisionName, cityName, materialName, amt, price) {
const material = getMaterial(divisionName, cityName, materialName);
SellMaterial(material, amt, price);
},
sellProduct: function (divisionName, cityName, productName, amt, price, all) {
const product = getProduct(divisionName, productName);
SellProduct(product, cityName, amt, price, all);
},
discontinueProduct: function (divisionName, productName) {
getDivision(divisionName).discontinueProduct(getProduct(divisionName, productName));
},
setSmartSupply: function (divisionName, cityName, enabled) {
const warehouse = getWarehouse(divisionName, cityName);
SetSmartSupply(warehouse, enabled);
},
setSmartSupplyUseLeftovers: function () {},
buyMaterial: function (divisionName, cityName, materialName, amt) {
const material = getMaterial(divisionName, cityName, materialName);
BuyMaterial(material, amt);
},
employees: function (divisionName, cityName) {
const office = getOffice(divisionName, cityName);
return office.employees.map((e) => Object.assign({}, e));
},
assignJob: function (divisionName, cityName, employeeName, job) {
const employee = getEmployee(divisionName, cityName, employeeName);
AssignJob(employee, job);
},
hireEmployee: function (divisionName, cityName) {
const office = getOffice(divisionName, cityName);
office.hireRandomEmployee();
},
upgradeOfficeSize: function (divisionName, cityName, size) {
const office = getOffice(divisionName, cityName);
UpgradeOfficeSize(Player.corporation, office, size);
},
throwParty: function (divisionName, cityName, costPerEmployee) {
const office = getOffice(divisionName, cityName);
ThrowParty(Player.corporation, office, costPerEmployee);
},
purchaseWarehouse: function (divisionName, cityName) {
PurchaseWarehouse(Player.corporation, getDivision(divisionName), cityName);
},
upgradeWarehouse: function (divisionName, cityName) {
UpgradeWarehouse(Player.corporation, getDivision(divisionName), getWarehouse(divisionName, cityName));
},
buyCoffee: function (divisionName, cityName) {
BuyCoffee(Player.corporation, getDivision(divisionName), getOffice(divisionName, cityName));
},
hireAdVert: function (divisionName) {
HireAdVert(Player.corporation, getDivision(divisionName), getOffice(divisionName, "Sector-12"));
},
makeProduct: function (divisionName, cityName, productName, designInvest, marketingInvest) {
MakeProduct(
Player.corporation,
getDivision(divisionName),
cityName,
productName,
designInvest,
marketingInvest,
);
},
research: function (divisionName, researchName) {
Research(getDivision(divisionName), researchName);
},
exportMaterial: function (sourceDivision, sourceCity, targetDivision, targetCity, materialName, amt) {
ExportMaterial(targetDivision, targetCity, getMaterial(sourceDivision, sourceCity, materialName), amt + "");
},
cancelExportMaterial: function (sourceDivision, sourceCity, targetDivision, targetCity, materialName, amt) {
CancelExportMaterial(
targetDivision,
targetCity,
getMaterial(sourceDivision, sourceCity, materialName),
amt + "",
);
},
setMaterialMarketTA1: function (divisionName, cityName, materialName, on) {
SetMaterialMarketTA1(getMaterial(divisionName, cityName, materialName), on);
},
setMaterialMarketTA2: function (divisionName, cityName, materialName, on) {
SetMaterialMarketTA2(getMaterial(divisionName, cityName, materialName), on);
},
setProductMarketTA1: function (divisionName, productName, on) {
SetProductMarketTA1(getProduct(divisionName, productName), on);
},
setProductMarketTA2: function (divisionName, productName, on) {
SetProductMarketTA2(getProduct(divisionName, productName), on);
},
// If you modify these objects you will affect them for real, it's not
// copies.
getDivision: function (divisionName) {
return getDivision(divisionName);
},
getOffice: function (divisionName, cityName) {
return getOffice(divisionName, cityName);
},
getWarehouse: function (divisionName, cityName) {
return getWarehouse(divisionName, cityName);
},
getMaterial: function (divisionName, cityName, materialName) {
return getMaterial(divisionName, cityName, materialName);
},
getProduct: function (divisionName, productName) {
return getProduct(divisionName, productName);
},
getEmployee: function (divisionName, cityName, employeeName) {
return getEmployee(divisionName, cityName, employeeName);
},
}, // End Corporation API
// Coding Contract API
codingcontract: {

@ -45,7 +45,7 @@ let symbols: string[] = [];
}
symbols = populate(ns);
const exclude = ["heart", "break", "exploit", "bypass"];
const exclude = ["heart", "break", "exploit", "bypass", "corporation"];
symbols = symbols.filter((symbol: string) => !exclude.includes(symbol));
})();