mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-22 23:53:48 +01:00
NETSCRIPT: Added ns.corporation.issueNewShares function (#261)
This commit is contained in:
parent
556fe8dd33
commit
5c80655d62
@ -16,6 +16,7 @@ import { ResearchMap } from "./ResearchMap";
|
|||||||
import { isRelevantMaterial } from "./ui/Helpers";
|
import { isRelevantMaterial } from "./ui/Helpers";
|
||||||
import { checkEnum } from "../utils/helpers/enum";
|
import { checkEnum } from "../utils/helpers/enum";
|
||||||
import { CityName } from "../Locations/data/CityNames";
|
import { CityName } from "../Locations/data/CityNames";
|
||||||
|
import { getRandomInt } from "../utils/helpers/getRandomInt";
|
||||||
|
|
||||||
export function NewIndustry(corporation: Corporation, industry: IndustryType, name: string): void {
|
export function NewIndustry(corporation: Corporation, industry: IndustryType, name: string): void {
|
||||||
if (corporation.divisions.find(({ type }) => industry == type))
|
if (corporation.divisions.find(({ type }) => industry == type))
|
||||||
@ -90,6 +91,33 @@ export function IssueDividends(corporation: Corporation, rate: number): void {
|
|||||||
corporation.dividendRate = rate;
|
corporation.dividendRate = rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function IssueNewShares(corporation: Corporation, amount: number): [number, number, number] {
|
||||||
|
const max = corporation.calculateMaxNewShares();
|
||||||
|
|
||||||
|
// Round to nearest ten-millionth
|
||||||
|
amount = Math.round(amount / 10e6) * 10e6;
|
||||||
|
|
||||||
|
if (isNaN(amount) || amount < 10e6 || amount > max) {
|
||||||
|
throw new Error(`Invalid value. Must be an number between 10m and ${max} (20% of total shares)`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const newSharePrice = Math.round(corporation.sharePrice * 0.9);
|
||||||
|
|
||||||
|
const profit = amount * newSharePrice;
|
||||||
|
corporation.issueNewSharesCooldown = CorporationConstants.IssueNewSharesCooldown;
|
||||||
|
|
||||||
|
const privateOwnedRatio = 1 - (corporation.numShares + corporation.issuedShares) / corporation.totalShares;
|
||||||
|
const maxPrivateShares = Math.round((amount / 2) * privateOwnedRatio);
|
||||||
|
const privateShares = Math.round(getRandomInt(0, maxPrivateShares) / 10e6) * 10e6;
|
||||||
|
|
||||||
|
corporation.issuedShares += amount - privateShares;
|
||||||
|
corporation.totalShares += amount;
|
||||||
|
corporation.funds = corporation.funds + profit;
|
||||||
|
corporation.immediatelyUpdateSharePrice();
|
||||||
|
|
||||||
|
return [profit, amount, privateShares];
|
||||||
|
}
|
||||||
|
|
||||||
export function SellMaterial(mat: Material, amt: string, price: string): void {
|
export function SellMaterial(mat: Material, amt: string, price: string): void {
|
||||||
if (price === "") price = "0";
|
if (price === "") price = "0";
|
||||||
if (amt === "") amt = "0";
|
if (amt === "") amt = "0";
|
||||||
|
@ -225,6 +225,12 @@ export class Corporation {
|
|||||||
this.sharePrice = this.getTargetSharePrice();
|
this.sharePrice = this.getTargetSharePrice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
calculateMaxNewShares(): number {
|
||||||
|
const maxNewSharesUnrounded = Math.round(this.totalShares * 0.2);
|
||||||
|
const maxNewShares = maxNewSharesUnrounded - (maxNewSharesUnrounded % 10e6);
|
||||||
|
return maxNewShares;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculates how much money will be made and what the resulting stock price
|
// Calculates how much money will be made and what the resulting stock price
|
||||||
// will be when the player sells his/her shares
|
// will be when the player sells his/her shares
|
||||||
// @return - [Player profit, final stock price, end shareSalesUntilPriceUpdate property]
|
// @return - [Player profit, final stock price, end shareSalesUntilPriceUpdate property]
|
||||||
|
@ -2,13 +2,12 @@ import React, { useState } from "react";
|
|||||||
import { numeralWrapper } from "../../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
import { Modal } from "../../../ui/React/Modal";
|
import { Modal } from "../../../ui/React/Modal";
|
||||||
import { getRandomInt } from "../../../utils/helpers/getRandomInt";
|
|
||||||
import { CorporationConstants } from "../../data/Constants";
|
|
||||||
import { useCorporation } from "../Context";
|
import { useCorporation } from "../Context";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import { NumberInput } from "../../../ui/React/NumberInput";
|
import { NumberInput } from "../../../ui/React/NumberInput";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import { KEY } from "../../../utils/helpers/keyCodes";
|
import { KEY } from "../../../utils/helpers/keyCodes";
|
||||||
|
import { IssueNewShares } from "../../Actions";
|
||||||
|
|
||||||
interface IEffectTextProps {
|
interface IEffectTextProps {
|
||||||
shares: number | null;
|
shares: number | null;
|
||||||
@ -18,8 +17,7 @@ function EffectText(props: IEffectTextProps): React.ReactElement {
|
|||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
if (props.shares === null) return <></>;
|
if (props.shares === null) return <></>;
|
||||||
const newSharePrice = Math.round(corp.sharePrice * 0.9);
|
const newSharePrice = Math.round(corp.sharePrice * 0.9);
|
||||||
const maxNewSharesUnrounded = Math.round(corp.totalShares * 0.2);
|
const maxNewShares = corp.calculateMaxNewShares();
|
||||||
const maxNewShares = maxNewSharesUnrounded - (maxNewSharesUnrounded % 1e6);
|
|
||||||
let newShares = props.shares;
|
let newShares = props.shares;
|
||||||
if (isNaN(newShares)) {
|
if (isNaN(newShares)) {
|
||||||
return <Typography>Invalid input</Typography>;
|
return <Typography>Invalid input</Typography>;
|
||||||
@ -55,8 +53,7 @@ interface IProps {
|
|||||||
export function IssueNewSharesModal(props: IProps): React.ReactElement {
|
export function IssueNewSharesModal(props: IProps): React.ReactElement {
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const [shares, setShares] = useState<number>(NaN);
|
const [shares, setShares] = useState<number>(NaN);
|
||||||
const maxNewSharesUnrounded = Math.round(corp.totalShares * 0.2);
|
const maxNewShares = corp.calculateMaxNewShares();
|
||||||
const maxNewShares = maxNewSharesUnrounded - (maxNewSharesUnrounded % 1e6);
|
|
||||||
|
|
||||||
const newShares = Math.round((shares || 0) / 10e6) * 10e6;
|
const newShares = Math.round((shares || 0) / 10e6) * 10e6;
|
||||||
const disabled = isNaN(shares) || isNaN(newShares) || newShares < 10e6 || newShares > maxNewShares;
|
const disabled = isNaN(shares) || isNaN(newShares) || newShares < 10e6 || newShares > maxNewShares;
|
||||||
@ -64,27 +61,8 @@ export function IssueNewSharesModal(props: IProps): React.ReactElement {
|
|||||||
function issueNewShares(): void {
|
function issueNewShares(): void {
|
||||||
if (isNaN(shares)) return;
|
if (isNaN(shares)) return;
|
||||||
if (disabled) return;
|
if (disabled) return;
|
||||||
|
const [profit, newShares, privateShares] = IssueNewShares(corp, shares);
|
||||||
|
|
||||||
const newSharePrice = Math.round(corp.sharePrice * 0.9);
|
|
||||||
let newShares = shares;
|
|
||||||
|
|
||||||
// Round to nearest ten-millionth
|
|
||||||
newShares = Math.round(newShares / 10e6) * 10e6;
|
|
||||||
|
|
||||||
const profit = newShares * newSharePrice;
|
|
||||||
corp.issueNewSharesCooldown = CorporationConstants.IssueNewSharesCooldown;
|
|
||||||
|
|
||||||
// Determine how many are bought by private investors
|
|
||||||
// If private investors own n% of the company, private investors get up to 0.5n% at most
|
|
||||||
// Round # of private shares to the nearest million
|
|
||||||
const privateOwnedRatio = 1 - (corp.numShares + corp.issuedShares) / corp.totalShares;
|
|
||||||
const maxPrivateShares = Math.round((newShares / 2) * privateOwnedRatio);
|
|
||||||
const privateShares = Math.round(getRandomInt(0, maxPrivateShares) / 1e6) * 1e6;
|
|
||||||
|
|
||||||
corp.issuedShares += newShares - privateShares;
|
|
||||||
corp.totalShares += newShares;
|
|
||||||
corp.funds = corp.funds + profit;
|
|
||||||
corp.immediatelyUpdateSharePrice();
|
|
||||||
props.onClose();
|
props.onClose();
|
||||||
|
|
||||||
let dialogContents =
|
let dialogContents =
|
||||||
|
@ -373,6 +373,7 @@ const corporation = {
|
|||||||
unlockUpgrade: 0,
|
unlockUpgrade: 0,
|
||||||
levelUpgrade: 0,
|
levelUpgrade: 0,
|
||||||
issueDividends: 0,
|
issueDividends: 0,
|
||||||
|
issueNewShares: 0,
|
||||||
buyBackShares: 0,
|
buyBackShares: 0,
|
||||||
sellShares: 0,
|
sellShares: 0,
|
||||||
getBonusTime: 0,
|
getBonusTime: 0,
|
||||||
|
@ -24,6 +24,7 @@ import {
|
|||||||
UnlockUpgrade,
|
UnlockUpgrade,
|
||||||
LevelUpgrade,
|
LevelUpgrade,
|
||||||
IssueDividends,
|
IssueDividends,
|
||||||
|
IssueNewShares,
|
||||||
SellMaterial,
|
SellMaterial,
|
||||||
SellProduct,
|
SellProduct,
|
||||||
SetSmartSupply,
|
SetSmartSupply,
|
||||||
@ -820,6 +821,21 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
|
|||||||
if (!corporation.public) throw helpers.makeRuntimeErrorMsg(ctx, `Your company has not gone public!`);
|
if (!corporation.public) throw helpers.makeRuntimeErrorMsg(ctx, `Your company has not gone public!`);
|
||||||
IssueDividends(corporation, rate);
|
IssueDividends(corporation, rate);
|
||||||
},
|
},
|
||||||
|
issueNewShares: (ctx) => (_amount) => {
|
||||||
|
checkAccess(ctx);
|
||||||
|
const corporation = getCorporation();
|
||||||
|
const maxNewShares = corporation.calculateMaxNewShares();
|
||||||
|
if (_amount == undefined) _amount = maxNewShares;
|
||||||
|
const amount = helpers.number(ctx, "amount", _amount);
|
||||||
|
if (corporation.issueNewSharesCooldown > 0) throw new Error(`Can't issue new shares, action on cooldown.`);
|
||||||
|
if (amount < 10e6 || amount > maxNewShares)
|
||||||
|
throw new Error(
|
||||||
|
`Invalid value for amount field! Must be numeric, greater than 10m, and less than ${maxNewShares} (20% of total shares)`,
|
||||||
|
);
|
||||||
|
if (!corporation.public) throw helpers.makeRuntimeErrorMsg(ctx, `Your company has not gone public!`);
|
||||||
|
const [funds] = IssueNewShares(corporation, amount);
|
||||||
|
return funds;
|
||||||
|
},
|
||||||
getDivision: (ctx) => (_divisionName) => {
|
getDivision: (ctx) => (_divisionName) => {
|
||||||
checkAccess(ctx);
|
checkAccess(ctx);
|
||||||
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
|
||||||
|
5
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
5
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -7545,6 +7545,11 @@ export interface Corporation extends WarehouseAPI, OfficeAPI {
|
|||||||
* @param rate - Fraction of profit to issue as dividends. */
|
* @param rate - Fraction of profit to issue as dividends. */
|
||||||
issueDividends(rate: number): void;
|
issueDividends(rate: number): void;
|
||||||
|
|
||||||
|
/** Issue new shares
|
||||||
|
* @param amount - Number of new shares to issue, will be rounded to nearest 10m. Defaults to max amount.
|
||||||
|
* @returns Amount of funds generated for the corporation. */
|
||||||
|
issueNewShares(amount?: number): number;
|
||||||
|
|
||||||
/** Buyback Shares
|
/** Buyback Shares
|
||||||
* @param amount - Amount of shares to buy back. */
|
* @param amount - Amount of shares to buy back. */
|
||||||
buyBackShares(amount: number): void;
|
buyBackShares(amount: number): void;
|
||||||
|
Loading…
Reference in New Issue
Block a user