diff --git a/dist/bitburner.d.ts b/dist/bitburner.d.ts
index dc45e4693..56fc6734c 100644
--- a/dist/bitburner.d.ts
+++ b/dist/bitburner.d.ts
@@ -958,6 +958,16 @@ export declare interface Corporation extends WarehouseAPI, OfficeAPI {
* @param percent - Percent of profit to issue as dividends.
*/
issueDividends(percent: number): void;
+ /**
+ * Buyback Shares
+ * @param amt - Number of shares to attempt to buyback.
+ */
+ buyBackShares(amt: number): void;
+ /**
+ * Sell Shares
+ * @param amt - Number of shares to attempt to sell.
+ */
+ sellShares(amt: number): void;
}
/**
@@ -6635,6 +6645,14 @@ export declare interface WarehouseAPI {
* @param amt - Amount of material to buy
*/
buyMaterial(divisionName: string, cityName: string, materialName: string, amt: number): void;
+ /**
+ * Set material to bulk buy
+ * @param divisionName - Name of the division
+ * @param cityName - Name of the city
+ * @param materialName - Name of the material
+ * @param amt - Amount of material to buy
+ */
+ bulkPurchase(divisionName: string, cityName: string, materialName: string, amt: number): void;
/**
* Get warehouse data
* @param divisionName - Name of the division
diff --git a/markdown/bitburner.corporation.buybackshares.md b/markdown/bitburner.corporation.buybackshares.md
new file mode 100644
index 000000000..ccc0a787b
--- /dev/null
+++ b/markdown/bitburner.corporation.buybackshares.md
@@ -0,0 +1,24 @@
+
+
+[Home](./index.md) > [bitburner](./bitburner.md) > [Corporation](./bitburner.corporation.md) > [buyBackShares](./bitburner.corporation.buybackshares.md)
+
+## Corporation.buyBackShares() method
+
+Buyback Shares
+
+Signature:
+
+```typescript
+buyBackShares(amount: number): void;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| amount | number | Amount of shares to buy back. |
+
+Returns:
+
+void
+
diff --git a/markdown/bitburner.corporation.md b/markdown/bitburner.corporation.md
index 68d553b6f..d41b84ba2 100644
--- a/markdown/bitburner.corporation.md
+++ b/markdown/bitburner.corporation.md
@@ -19,6 +19,7 @@ export interface Corporation extends WarehouseAPI, OfficeAPI
| --- | --- |
| [acceptInvestmentOffer()](./bitburner.corporation.acceptinvestmentoffer.md) | Accept investment based on you companies current valuation |
| [bribe(factionName, amountCash, amountShares)](./bitburner.corporation.bribe.md) | Bribe a faction |
+| [buyBackShares(amount)](./bitburner.corporation.buybackshares.md) | Buyback Shares |
| [createCorporation(corporationName, selfFund)](./bitburner.corporation.createcorporation.md) | Create a Corporation |
| [expandCity(divisionName, cityName)](./bitburner.corporation.expandcity.md) | Expand to a new city |
| [expandIndustry(industryType, divisionName)](./bitburner.corporation.expandindustry.md) | Expand to a new industry |
@@ -34,5 +35,6 @@ export interface Corporation extends WarehouseAPI, OfficeAPI
| [hasUnlockUpgrade(upgradeName)](./bitburner.corporation.hasunlockupgrade.md) | Check if you have a one time unlockable upgrade |
| [issueDividends(percent)](./bitburner.corporation.issuedividends.md) | Issue dividends |
| [levelUpgrade(upgradeName)](./bitburner.corporation.levelupgrade.md) | Level an upgrade. |
+| [sellShares(amount)](./bitburner.corporation.sellshares.md) | Sell Shares |
| [unlockUpgrade(upgradeName)](./bitburner.corporation.unlockupgrade.md) | Unlock an upgrade |
diff --git a/markdown/bitburner.corporation.sellshares.md b/markdown/bitburner.corporation.sellshares.md
new file mode 100644
index 000000000..6ee2b480a
--- /dev/null
+++ b/markdown/bitburner.corporation.sellshares.md
@@ -0,0 +1,24 @@
+
+
+[Home](./index.md) > [bitburner](./bitburner.md) > [Corporation](./bitburner.corporation.md) > [sellShares](./bitburner.corporation.sellshares.md)
+
+## Corporation.sellShares() method
+
+Sell Shares
+
+Signature:
+
+```typescript
+sellShares(amount: number): void;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| amount | number | Amount of shares to sell. |
+
+Returns:
+
+void
+
diff --git a/markdown/bitburner.warehouseapi.bulkpurchase.md b/markdown/bitburner.warehouseapi.bulkpurchase.md
new file mode 100644
index 000000000..3f55a3cac
--- /dev/null
+++ b/markdown/bitburner.warehouseapi.bulkpurchase.md
@@ -0,0 +1,27 @@
+
+
+[Home](./index.md) > [bitburner](./bitburner.md) > [WarehouseAPI](./bitburner.warehouseapi.md) > [bulkPurchase](./bitburner.warehouseapi.bulkpurchase.md)
+
+## WarehouseAPI.bulkPurchase() method
+
+Set material to bulk buy
+
+Signature:
+
+```typescript
+bulkPurchase(divisionName: string, cityName: string, materialName: string, amt: number): void;
+```
+
+## Parameters
+
+| Parameter | Type | Description |
+| --- | --- | --- |
+| divisionName | string | Name of the division |
+| cityName | string | Name of the city |
+| materialName | string | Name of the material |
+| amt | number | Amount of material to buy |
+
+Returns:
+
+void
+
diff --git a/src/Corporation/Actions.ts b/src/Corporation/Actions.ts
index c7ef42687..1b648e2b0 100644
--- a/src/Corporation/Actions.ts
+++ b/src/Corporation/Actions.ts
@@ -1,3 +1,5 @@
+import { IPlayer } from 'src/PersonObjects/IPlayer';
+import { MaterialSizes } from './MaterialSizes';
import { ICorporation } from "./ICorporation";
import { IIndustry } from "./IIndustry";
import { IndustryStartingCosts, IndustryResearchTrees } from "./IndustryData";
@@ -245,6 +247,57 @@ export function BuyMaterial(material: Material, amt: number): void {
material.buy = amt;
}
+export function BulkPurchase(corp: ICorporation, warehouse: Warehouse, material: Material, amt: number): void {
+ const matSize = MaterialSizes[material.name];
+ const maxAmount = (warehouse.size - warehouse.sizeUsed) / matSize;
+ if (isNaN(amt) || amt < 0) {
+ throw new Error(`Invalid input amount`);
+ }
+ if (amt * matSize > maxAmount) {
+ throw new Error(`You do not have enough warehouse size to fit this purchase`);
+ }
+ const cost = amt * material.bCost;
+ if (corp.funds >= cost) {
+ corp.funds = corp.funds - cost;
+ material.qty += amt;
+ } else {
+ throw new Error(`You cannot afford this purchase.`);
+ }
+}
+
+export function SellShares(corporation: ICorporation, player: IPlayer, numShares: number): number {
+ if (isNaN(numShares)) throw new Error("Invalid value for number of shares");
+ if (numShares < 0) throw new Error("Invalid value for number of shares");
+ if (numShares > corporation.numShares) throw new Error("You don't have that many shares to sell!");
+ if (!corporation.public) throw new Error("You haven't gone public!");
+ if (corporation.shareSaleCooldown) throw new Error("Share sale on cooldown!");
+ const stockSaleResults = corporation.calculateShareSale(numShares);
+ const profit = stockSaleResults[0];
+ const newSharePrice = stockSaleResults[1];
+ const newSharesUntilUpdate = stockSaleResults[2];
+
+ corporation.numShares -= numShares;
+ corporation.issuedShares += numShares;
+ corporation.sharePrice = newSharePrice;
+ corporation.shareSalesUntilPriceUpdate = newSharesUntilUpdate;
+ corporation.shareSaleCooldown = CorporationConstants.SellSharesCooldown;
+ player.gainMoney(profit, "corporation");
+ return profit;
+}
+
+export function BuyBackShares(corporation: ICorporation, player: IPlayer, numShares: number): boolean {
+ if (isNaN(numShares)) throw new Error("Invalid value for number of shares");
+ if (numShares < 0) throw new Error("Invalid value for number of shares");
+ if (numShares > corporation.issuedShares) throw new Error("You don't have that many shares to buy!");
+ if (!corporation.public) throw new Error("You haven't gone public!");
+ const buybackPrice = corporation.sharePrice * 1.1;
+ if (corporation.funds < (numShares * buybackPrice)) throw new Error("You cant afford that many shares!");
+ corporation.numShares += numShares;
+ corporation.issuedShares -= numShares;
+ player.loseMoney(numShares * buybackPrice, "corporation");
+ return true;
+}
+
export function AssignJob(employee: Employee, job: string): void {
if (!Object.values(EmployeePositions).includes(job)) throw new Error(`'${job}' is not a valid job.`);
employee.pos = job;
@@ -335,6 +388,9 @@ export function MakeProduct(
if (productName == null || productName === "") {
throw new Error("You must specify a name for your product!");
}
+ if (!division.makesProducts) {
+ throw new Error("You cannot create products for this industry!");
+ }
if (isNaN(designInvest)) {
throw new Error("Invalid value for design investment");
}
diff --git a/src/Corporation/ui/BuybackSharesModal.tsx b/src/Corporation/ui/BuybackSharesModal.tsx
index d58b01842..4d6568af7 100644
--- a/src/Corporation/ui/BuybackSharesModal.tsx
+++ b/src/Corporation/ui/BuybackSharesModal.tsx
@@ -6,6 +6,8 @@ import { useCorporation } from "./Context";
import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
import TextField from "@mui/material/TextField";
+import { BuyBackShares } from '../Actions';
+import { dialogBoxCreate } from '../../ui/React/DialogBox';
interface IProps {
open: boolean;
@@ -36,20 +38,12 @@ export function BuybackSharesModal(props: IProps): React.ReactElement {
function buy(): void {
if (disabled) return;
- if (shares === null) return;
- corp.numShares += shares;
- if (isNaN(corp.issuedShares)) {
- console.warn("Corporation issuedShares is NaN: " + corp.issuedShares);
- console.warn("Converting to number now");
- const res = corp.issuedShares;
- if (isNaN(res)) {
- corp.issuedShares = 0;
- } else {
- corp.issuedShares = res;
- }
+ try {
+ BuyBackShares(corp, player, shares)
+ }
+ catch (err) {
+ dialogBoxCreate(err + "");
}
- corp.issuedShares -= shares;
- player.loseMoney(shares * buybackPrice, "corporation");
props.onClose();
props.rerender();
}
diff --git a/src/Corporation/ui/PurchaseMaterialModal.tsx b/src/Corporation/ui/PurchaseMaterialModal.tsx
index 114e53940..5c6f6bda8 100644
--- a/src/Corporation/ui/PurchaseMaterialModal.tsx
+++ b/src/Corporation/ui/PurchaseMaterialModal.tsx
@@ -4,7 +4,7 @@ import { MaterialSizes } from "../MaterialSizes";
import { Warehouse } from "../Warehouse";
import { Material } from "../Material";
import { numeralWrapper } from "../../ui/numeralFormat";
-import { BuyMaterial } from "../Actions";
+import { BulkPurchase, BuyMaterial } from "../Actions";
import { Modal } from "../../ui/React/Modal";
import { useCorporation, useDivision } from "./Context";
import Typography from "@mui/material/Typography";
@@ -54,33 +54,17 @@ interface IBPProps {
warehouse: Warehouse;
}
-function BulkPurchase(props: IBPProps): React.ReactElement {
+function BulkPurchaseSection(props: IBPProps): React.ReactElement {
const corp = useCorporation();
const [buyAmt, setBuyAmt] = useState("");
function bulkPurchase(): void {
- const amount = parseFloat(buyAmt);
-
- const matSize = MaterialSizes[props.mat.name];
- const maxAmount = (props.warehouse.size - props.warehouse.sizeUsed) / matSize;
- if (amount * matSize > maxAmount) {
- dialogBoxCreate(`You do not have enough warehouse size to fit this purchase`);
- return;
- }
-
- if (isNaN(amount) || amount < 0) {
- dialogBoxCreate("Invalid input amount");
- } else {
- const cost = amount * props.mat.bCost;
- if (corp.funds >= cost) {
- corp.funds = corp.funds - cost;
- props.mat.qty += amount;
- } else {
- dialogBoxCreate(`You cannot afford this purchase.`);
- return;
- }
- props.onClose();
+ try {
+ BulkPurchase(corp, props.warehouse, props.mat, parseFloat(buyAmt));
+ } catch (err) {
+ dialogBoxCreate(err + "");
}
+ props.onClose();
}
function onKeyDown(event: React.KeyboardEvent): void {
@@ -164,7 +148,7 @@ export function PurchaseMaterialModal(props: IProps): React.ReactElement {
{division.hasResearch("Bulk Purchasing") && (
-
+
)}
>
diff --git a/src/Corporation/ui/SellSharesModal.tsx b/src/Corporation/ui/SellSharesModal.tsx
index f17f564ea..e96fa9959 100644
--- a/src/Corporation/ui/SellSharesModal.tsx
+++ b/src/Corporation/ui/SellSharesModal.tsx
@@ -4,12 +4,12 @@ import { dialogBoxCreate } from "../../ui/React/DialogBox";
import { Modal } from "../../ui/React/Modal";
import { use } from "../../ui/Context";
import { useCorporation } from "./Context";
-import { CorporationConstants } from "../data/Constants";
import { ICorporation } from "../ICorporation";
import Typography from "@mui/material/Typography";
import TextField from "@mui/material/TextField";
import Button from "@mui/material/Button";
import { Money } from "../../ui/React/Money";
+import { SellShares } from "../Actions";
interface IProps {
open: boolean;
onClose: () => void;
@@ -48,38 +48,23 @@ export function SellSharesModal(props: IProps): React.ReactElement {
}
function sell(): void {
- if (shares === null) return;
if (disabled) return;
- const stockSaleResults = corp.calculateShareSale(shares);
- const profit = stockSaleResults[0];
- const newSharePrice = stockSaleResults[1];
- const newSharesUntilUpdate = stockSaleResults[2];
+ try {
+ const profit = SellShares(corp, player, shares)
+ props.onClose();
+ dialogBoxCreate(
+ <>
+ Sold {numeralWrapper.formatMoney(shares)} shares for
+ . The corporation's stock price fell to
+ as a result of dilution.
+ >,
+ );
- corp.numShares -= shares;
- if (isNaN(corp.issuedShares)) {
- console.error(`Corporation issuedShares is NaN: ${corp.issuedShares}`);
- const res = corp.issuedShares;
- if (isNaN(res)) {
- corp.issuedShares = 0;
- } else {
- corp.issuedShares = res;
- }
+ props.rerender();
+ } catch (err) {
+ dialogBoxCreate(err + "");
}
- corp.issuedShares += shares;
- corp.sharePrice = newSharePrice;
- corp.shareSalesUntilPriceUpdate = newSharesUntilUpdate;
- corp.shareSaleCooldown = CorporationConstants.SellSharesCooldown;
- player.gainMoney(profit, "corporation");
- props.onClose();
- dialogBoxCreate(
- <>
- Sold {numeralWrapper.formatMoney(shares)} shares for
- . The corporation's stock price fell to
- as a result of dilution.
- >,
- );
- props.rerender();
}
function onKeyDown(event: React.KeyboardEvent): void {
diff --git a/src/NetscriptFunctions/Corporation.ts b/src/NetscriptFunctions/Corporation.ts
index 8ca4a4d48..365cd2aec 100644
--- a/src/NetscriptFunctions/Corporation.ts
+++ b/src/NetscriptFunctions/Corporation.ts
@@ -49,6 +49,9 @@ import {
SetMaterialMarketTA2,
SetProductMarketTA1,
SetProductMarketTA2,
+ BulkPurchase,
+ SellShares,
+ BuyBackShares,
SetSmartSupplyUseLeftovers,
} from "../Corporation/Actions";
import { CorporationUnlockUpgrades } from "../Corporation/data/CorporationUnlockUpgrades";
@@ -178,6 +181,7 @@ export function NetscriptCorporation(
return true;
}
+
function getResearchCost(division: IIndustry, researchName: string): number {
const researchTree = IndustryResearchTrees[division.type];
if (researchTree === undefined) throw new Error(`No research tree for industry '${division.type}'`);
@@ -436,6 +440,18 @@ export function NetscriptCorporation(
const material = getMaterial(divisionName, cityName, materialName);
BuyMaterial(material, amt);
},
+ bulkPurchase: function (adivisionName: any, acityName: any, amaterialName: any, aamt: any): void {
+ checkAccess("bulkPurchase", 7);
+ const divisionName = helper.string("bulkPurchase", "divisionName", adivisionName);
+ if (!hasResearched(getDivision(adivisionName), "Bulk Purchasing")) throw new Error(`You have not researched Bulk Purchasing in ${divisionName}`)
+ const corporation = getCorporation();
+ const cityName = helper.string("bulkPurchase", "cityName", acityName);
+ const materialName = helper.string("bulkPurchase", "materialName", amaterialName);
+ const amt = helper.number("bulkPurchase", "amt", aamt);
+ const warehouse = getWarehouse(divisionName, cityName)
+ const material = getMaterial(divisionName, cityName, materialName);
+ BulkPurchase(corporation, warehouse, material, amt);
+ },
makeProduct: function (
adivisionName: any,
acityName: any,
@@ -813,6 +829,16 @@ export function NetscriptCorporation(
const numShares = helper.number("goPublic", "numShares", anumShares);
return goPublic(numShares);
},
+ sellShares: function (anumShares: any): number {
+ checkAccess("acceptInvestmentOffer");
+ const numShares = helper.number("sellStock", "numShares", anumShares);
+ return SellShares(getCorporation(), player, numShares);
+ },
+ buyBackShares: function (anumShares: any): boolean {
+ checkAccess("acceptInvestmentOffer");
+ const numShares = helper.number("buyStock", "numShares", anumShares);
+ return BuyBackShares(getCorporation(), player, numShares);
+ },
bribe: function (afactionName: string, aamountCash: any, aamountShares: any): boolean {
checkAccess("bribe");
const factionName = helper.string("bribe", "factionName", afactionName);
diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts
index 661a1f230..25cd9eaa8 100644
--- a/src/ScriptEditor/NetscriptDefinitions.d.ts
+++ b/src/ScriptEditor/NetscriptDefinitions.d.ts
@@ -6382,6 +6382,14 @@ export interface WarehouseAPI {
* @param amt - Amount of material to buy
*/
buyMaterial(divisionName: string, cityName: string, materialName: string, amt: number): void;
+ /**
+ * Set material to bulk buy
+ * @param divisionName - Name of the division
+ * @param cityName - Name of the city
+ * @param materialName - Name of the material
+ * @param amt - Amount of material to buy
+ */
+ bulkPurchase(divisionName: string, cityName: string, materialName: string, amt: number): void;
/**
* Get warehouse data
* @param divisionName - Name of the division
@@ -6622,6 +6630,18 @@ export interface Corporation extends WarehouseAPI, OfficeAPI {
* @param percent - Percent of profit to issue as dividends.
*/
issueDividends(percent: number): void;
+ /**
+ * Buyback Shares
+ * @param amount - Amount of shares to buy back.
+ *
+ */
+ buyBackShares(amount: number): void;
+ /**
+ * Sell Shares
+ * @param amount - Amount of shares to sell.
+ *
+ */
+ sellShares(amount: number): void;
}
/**