mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-23 22:52:29 +01:00
Merge pull request #3802 from stalefishies/corp-dividends
CORPORATION: (BREAKING) Dividend fixes and exposing dividends info via scripts
This commit is contained in:
commit
17c2f06ae0
@ -84,12 +84,12 @@ export function LevelUpgrade(corporation: ICorporation, upgrade: CorporationUpgr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function IssueDividends(corporation: ICorporation, percent: number): void {
|
export function IssueDividends(corporation: ICorporation, rate: number): void {
|
||||||
if (isNaN(percent) || percent < 0 || percent > CorporationConstants.DividendMaxPercentage) {
|
if (isNaN(rate) || rate < 0 || rate > CorporationConstants.DividendMaxRate) {
|
||||||
throw new Error(`Invalid value. Must be an integer between 0 and ${CorporationConstants.DividendMaxPercentage}`);
|
throw new Error(`Invalid value. Must be an number between 0 and ${CorporationConstants.DividendMaxRate}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
corporation.dividendPercentage = percent * 100;
|
corporation.dividendRate = rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SellMaterial(mat: Material, amt: string, price: string): void {
|
export function SellMaterial(mat: Material, amt: string, price: string): void {
|
||||||
|
@ -35,8 +35,8 @@ export class Corporation {
|
|||||||
shareSalesUntilPriceUpdate = CorporationConstants.SHARESPERPRICEUPDATE;
|
shareSalesUntilPriceUpdate = CorporationConstants.SHARESPERPRICEUPDATE;
|
||||||
shareSaleCooldown = 0; // Game cycles until player can sell shares again
|
shareSaleCooldown = 0; // Game cycles until player can sell shares again
|
||||||
issueNewSharesCooldown = 0; // Game cycles until player can issue shares again
|
issueNewSharesCooldown = 0; // Game cycles until player can issue shares again
|
||||||
dividendPercentage = 0;
|
dividendRate = 0;
|
||||||
dividendTaxPercentage = 50;
|
dividendTax = 1 - BitNodeMultipliers.CorporationSoftcap + 0.15;
|
||||||
issuedShares = 0;
|
issuedShares = 0;
|
||||||
sharePrice = 0;
|
sharePrice = 0;
|
||||||
storedCycles = 0;
|
storedCycles = 0;
|
||||||
@ -121,18 +121,19 @@ export class Corporation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process dividends
|
// Process dividends
|
||||||
if (this.dividendPercentage > 0 && cycleProfit > 0) {
|
this.updateDividendTax();
|
||||||
|
if (this.dividendRate > 0 && cycleProfit > 0) {
|
||||||
// Validate input again, just to be safe
|
// Validate input again, just to be safe
|
||||||
if (
|
if (
|
||||||
isNaN(this.dividendPercentage) ||
|
isNaN(this.dividendRate) ||
|
||||||
this.dividendPercentage < 0 ||
|
this.dividendRate < 0 ||
|
||||||
this.dividendPercentage > CorporationConstants.DividendMaxPercentage * 100
|
this.dividendRate > CorporationConstants.DividendMaxRate
|
||||||
) {
|
) {
|
||||||
console.error(`Invalid Corporation dividend percentage: ${this.dividendPercentage}`);
|
console.error(`Invalid Corporation dividend rate: ${this.dividendRate}`);
|
||||||
} else {
|
} else {
|
||||||
const totalDividends = (this.dividendPercentage / 100) * cycleProfit;
|
const totalDividends = this.dividendRate * cycleProfit;
|
||||||
const retainedEarnings = cycleProfit - totalDividends;
|
const retainedEarnings = cycleProfit - totalDividends;
|
||||||
player.gainMoney(this.getDividends(), "corporation");
|
player.gainMoney(this.getCycleDividends(), "corporation");
|
||||||
this.addFunds(retainedEarnings);
|
this.addFunds(retainedEarnings);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -146,20 +147,23 @@ export class Corporation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getDividends(): number {
|
updateDividendTax(): void {
|
||||||
const profit = this.revenue - this.expenses;
|
this.dividendTax = 1 - BitNodeMultipliers.CorporationSoftcap + 0.15;
|
||||||
const cycleProfit = profit * CorporationConstants.SecsPerMarketCycle;
|
|
||||||
const totalDividends = (this.dividendPercentage / 100) * cycleProfit;
|
|
||||||
const dividendsPerShare = totalDividends / this.totalShares;
|
|
||||||
const dividends = this.numShares * dividendsPerShare;
|
|
||||||
let upgrades = -0.15;
|
|
||||||
if (this.unlockUpgrades[5] === 1) {
|
if (this.unlockUpgrades[5] === 1) {
|
||||||
upgrades += 0.05;
|
this.dividendTax -= 0.05;
|
||||||
}
|
}
|
||||||
if (this.unlockUpgrades[6] === 1) {
|
if (this.unlockUpgrades[6] === 1) {
|
||||||
upgrades += 0.1;
|
this.dividendTax -= 0.1;
|
||||||
}
|
}
|
||||||
return Math.pow(dividends, BitNodeMultipliers.CorporationSoftcap + upgrades);
|
}
|
||||||
|
|
||||||
|
getCycleDividends(): number {
|
||||||
|
const profit = this.revenue - this.expenses;
|
||||||
|
const cycleProfit = profit * CorporationConstants.SecsPerMarketCycle;
|
||||||
|
const totalDividends = this.dividendRate * cycleProfit;
|
||||||
|
const dividendsPerShare = totalDividends / this.totalShares;
|
||||||
|
const dividends = this.numShares * dividendsPerShare;
|
||||||
|
return Math.pow(dividends, 1 - this.dividendTax);
|
||||||
}
|
}
|
||||||
|
|
||||||
determineValuation(): number {
|
determineValuation(): number {
|
||||||
@ -167,8 +171,8 @@ export class Corporation {
|
|||||||
profit = this.avgProfit;
|
profit = this.avgProfit;
|
||||||
if (this.public) {
|
if (this.public) {
|
||||||
// Account for dividends
|
// Account for dividends
|
||||||
if (this.dividendPercentage > 0) {
|
if (this.dividendRate > 0) {
|
||||||
profit *= (100 - this.dividendPercentage) / 100;
|
profit *= 1 - this.dividendRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
val = this.funds + profit * 85e3;
|
val = this.funds + profit * 85e3;
|
||||||
@ -277,11 +281,7 @@ export class Corporation {
|
|||||||
this.funds = this.funds - price;
|
this.funds = this.funds - price;
|
||||||
|
|
||||||
// Apply effects for one-time upgrades
|
// Apply effects for one-time upgrades
|
||||||
if (upgN === 5) {
|
this.updateDividendTax();
|
||||||
this.dividendTaxPercentage -= 5;
|
|
||||||
} else if (upgN === 6) {
|
|
||||||
this.dividendTaxPercentage -= 10;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Levelable upgrades
|
//Levelable upgrades
|
||||||
|
@ -19,8 +19,8 @@ export interface ICorporation {
|
|||||||
shareSalesUntilPriceUpdate: number;
|
shareSalesUntilPriceUpdate: number;
|
||||||
shareSaleCooldown: number;
|
shareSaleCooldown: number;
|
||||||
issueNewSharesCooldown: number;
|
issueNewSharesCooldown: number;
|
||||||
dividendPercentage: number;
|
dividendRate: number;
|
||||||
dividendTaxPercentage: number;
|
dividendTax: number;
|
||||||
issuedShares: number;
|
issuedShares: number;
|
||||||
sharePrice: number;
|
sharePrice: number;
|
||||||
storedCycles: number;
|
storedCycles: number;
|
||||||
@ -54,6 +54,7 @@ export interface ICorporation {
|
|||||||
getSalesMultiplier(): number;
|
getSalesMultiplier(): number;
|
||||||
getScientificResearchMultiplier(): number;
|
getScientificResearchMultiplier(): number;
|
||||||
getStarterGuide(player: IPlayer): void;
|
getStarterGuide(player: IPlayer): void;
|
||||||
|
updateDividendTax(): void;
|
||||||
|
getCycleDividends(): number;
|
||||||
toJSON(): any;
|
toJSON(): any;
|
||||||
getDividends(): number;
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ export const CorporationConstants: {
|
|||||||
BribeThreshold: number;
|
BribeThreshold: number;
|
||||||
BribeToRepRatio: number;
|
BribeToRepRatio: number;
|
||||||
ProductProductionCostRatio: number;
|
ProductProductionCostRatio: number;
|
||||||
DividendMaxPercentage: number;
|
DividendMaxRate: number;
|
||||||
EmployeeSalaryMultiplier: number;
|
EmployeeSalaryMultiplier: number;
|
||||||
CyclesPerEmployeeRaise: number;
|
CyclesPerEmployeeRaise: number;
|
||||||
EmployeeRaiseAmount: number;
|
EmployeeRaiseAmount: number;
|
||||||
@ -61,7 +61,7 @@ export const CorporationConstants: {
|
|||||||
|
|
||||||
ProductProductionCostRatio: 5, //Ratio of material cost of a product to its production cost
|
ProductProductionCostRatio: 5, //Ratio of material cost of a product to its production cost
|
||||||
|
|
||||||
DividendMaxPercentage: 1,
|
DividendMaxRate: 1,
|
||||||
|
|
||||||
EmployeeSalaryMultiplier: 3, // Employee stats multiplied by this to determine initial salary
|
EmployeeSalaryMultiplier: 3, // Employee stats multiplied by this to determine initial salary
|
||||||
CyclesPerEmployeeRaise: 400, // All employees get a raise every X market cycles
|
CyclesPerEmployeeRaise: 400, // All employees get a raise every X market cycles
|
||||||
|
@ -275,17 +275,18 @@ interface IDividendsStatsProps {
|
|||||||
}
|
}
|
||||||
function DividendsStats({ profit }: IDividendsStatsProps): React.ReactElement {
|
function DividendsStats({ profit }: IDividendsStatsProps): React.ReactElement {
|
||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
if (corp.dividendPercentage <= 0 || profit <= 0) return <></>;
|
if (corp.dividendRate <= 0 || profit <= 0) return <></>;
|
||||||
const totalDividends = (corp.dividendPercentage / 100) * profit;
|
const totalDividends = corp.dividendRate * profit;
|
||||||
const retainedEarnings = profit - totalDividends;
|
const retainedEarnings = profit - totalDividends;
|
||||||
const dividendsPerShare = totalDividends / corp.totalShares;
|
const dividendsPerShare = totalDividends / corp.totalShares;
|
||||||
|
const playerEarnings = corp.getCycleDividends() / CorporationConstants.SecsPerMarketCycle;
|
||||||
return (
|
return (
|
||||||
<StatsTable
|
<StatsTable
|
||||||
rows={[
|
rows={[
|
||||||
["Retained Profits (after dividends):", <MoneyRate money={retainedEarnings} />],
|
["Retained Profits (after dividends):", <MoneyRate money={retainedEarnings} />],
|
||||||
["Dividend Percentage:", numeralWrapper.format(corp.dividendPercentage / 100, "0%")],
|
["Dividend Percentage:", numeralWrapper.format(corp.dividendRate, "0%")],
|
||||||
["Dividends per share:", <MoneyRate money={dividendsPerShare} />],
|
["Dividends per share:", <MoneyRate money={dividendsPerShare} />],
|
||||||
["Your earnings as a shareholder:", <MoneyRate money={corp.getDividends()} />],
|
["Your earnings as a shareholder:", <MoneyRate money={playerEarnings} />],
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -19,7 +19,7 @@ export function IssueDividendsModal(props: IProps): React.ReactElement {
|
|||||||
const corp = useCorporation();
|
const corp = useCorporation();
|
||||||
const [percent, setPercent] = useState(0);
|
const [percent, setPercent] = useState(0);
|
||||||
|
|
||||||
const canIssue = !isNaN(percent) && percent >= 0 && percent <= CorporationConstants.DividendMaxPercentage * 100;
|
const canIssue = !isNaN(percent) && percent >= 0 && percent <= CorporationConstants.DividendMaxRate * 100;
|
||||||
function issueDividends(): void {
|
function issueDividends(): void {
|
||||||
if (!canIssue) return;
|
if (!canIssue) return;
|
||||||
if (percent === null) return;
|
if (percent === null) return;
|
||||||
|
@ -920,14 +920,15 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript
|
|||||||
},
|
},
|
||||||
issueDividends:
|
issueDividends:
|
||||||
(ctx: NetscriptContext) =>
|
(ctx: NetscriptContext) =>
|
||||||
(_percent: unknown): void => {
|
(_rate: unknown): void => {
|
||||||
checkAccess(ctx);
|
checkAccess(ctx);
|
||||||
const percent = ctx.helper.number("percent", _percent);
|
const rate = ctx.helper.number("rate", _rate);
|
||||||
if (percent < 0 || percent > 100)
|
const max = CorporationConstants.DividendMaxRate;
|
||||||
throw new Error("Invalid value for percent field! Must be numeric, greater than 0, and less than 100");
|
if (rate < 0 || rate > max)
|
||||||
|
throw new Error(`Invalid value for rate field! Must be numeric, greater than 0, and less than ${max}`);
|
||||||
const corporation = getCorporation();
|
const corporation = getCorporation();
|
||||||
if (!corporation.public) throw ctx.makeRuntimeErrorMsg(`Your company has not gone public!`);
|
if (!corporation.public) throw ctx.makeRuntimeErrorMsg(`Your company has not gone public!`);
|
||||||
IssueDividends(corporation, percent);
|
IssueDividends(corporation, rate);
|
||||||
},
|
},
|
||||||
|
|
||||||
// If you modify these objects you will affect them for real, it's not
|
// If you modify these objects you will affect them for real, it's not
|
||||||
@ -954,6 +955,9 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript
|
|||||||
shareSaleCooldown: corporation.shareSaleCooldown,
|
shareSaleCooldown: corporation.shareSaleCooldown,
|
||||||
issuedShares: corporation.issuedShares,
|
issuedShares: corporation.issuedShares,
|
||||||
sharePrice: corporation.sharePrice,
|
sharePrice: corporation.sharePrice,
|
||||||
|
dividendRate: corporation.dividendRate,
|
||||||
|
dividendTax: corporation.dividendTax,
|
||||||
|
dividendEarnings: corporation.getCycleDividends() / CorporationConstants.SecsPerMarketCycle,
|
||||||
state: corporation.state.getState(),
|
state: corporation.state.getState(),
|
||||||
divisions: corporation.divisions.map((division): NSDivision => getSafeDivision(division)),
|
divisions: corporation.divisions.map((division): NSDivision => getSafeDivision(division)),
|
||||||
};
|
};
|
||||||
|
10
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
10
src/ScriptEditor/NetscriptDefinitions.d.ts
vendored
@ -7053,9 +7053,9 @@ export interface Corporation extends WarehouseAPI, OfficeAPI {
|
|||||||
levelUpgrade(upgradeName: string): void;
|
levelUpgrade(upgradeName: string): void;
|
||||||
/**
|
/**
|
||||||
* Issue dividends
|
* Issue dividends
|
||||||
* @param percent - Percent of profit to issue as dividends.
|
* @param rate - Fraction of profit to issue as dividends.
|
||||||
*/
|
*/
|
||||||
issueDividends(percent: number): void;
|
issueDividends(rate: number): void;
|
||||||
/**
|
/**
|
||||||
* Buyback Shares
|
* Buyback Shares
|
||||||
* @param amount - Amount of shares to buy back.
|
* @param amount - Amount of shares to buy back.
|
||||||
@ -7105,6 +7105,12 @@ interface CorporationInfo {
|
|||||||
issuedShares: number;
|
issuedShares: number;
|
||||||
/** Price of the shares */
|
/** Price of the shares */
|
||||||
sharePrice: number;
|
sharePrice: number;
|
||||||
|
/** Fraction of profits issued as dividends */
|
||||||
|
dividendRate: number;
|
||||||
|
/** Tax applied on your earnings as a shareholder */
|
||||||
|
dividendTax: number;
|
||||||
|
/** Your earnings as a shareholder per second this cycle */
|
||||||
|
dividendEarnings: number;
|
||||||
/** State of the corporation. Possible states are START, PURCHASE, PRODUCTION, SALE, EXPORT. */
|
/** State of the corporation. Possible states are START, PURCHASE, PRODUCTION, SALE, EXPORT. */
|
||||||
state: string;
|
state: string;
|
||||||
/** Array of all divisions */
|
/** Array of all divisions */
|
||||||
|
Loading…
Reference in New Issue
Block a user