From 8d474a7610febe574478a1739d68590b04f260d7 Mon Sep 17 00:00:00 2001
From: Staszek Welsh <stalefishies@gmail.com>
Date: Mon, 30 May 2022 21:45:36 +0100
Subject: [PATCH 1/7] Change corporation.dividendPercentage to
 corporation.dividendRate

---
 src/Corporation/Actions.ts                    |  8 +++----
 src/Corporation/Corporation.tsx               | 22 +++++++++----------
 src/Corporation/ICorporation.ts               |  2 +-
 src/Corporation/data/Constants.ts             |  4 ++--
 src/Corporation/ui/Overview.tsx               |  6 ++---
 .../ui/modals/IssueDividendsModal.tsx         |  2 +-
 6 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/src/Corporation/Actions.ts b/src/Corporation/Actions.ts
index 1ec820037..acd211467 100644
--- a/src/Corporation/Actions.ts
+++ b/src/Corporation/Actions.ts
@@ -84,12 +84,12 @@ export function LevelUpgrade(corporation: ICorporation, upgrade: CorporationUpgr
   }
 }
 
-export function IssueDividends(corporation: ICorporation, percent: number): void {
-  if (isNaN(percent) || percent < 0 || percent > CorporationConstants.DividendMaxPercentage) {
-    throw new Error(`Invalid value. Must be an integer between 0 and ${CorporationConstants.DividendMaxPercentage}`);
+export function IssueDividends(corporation: ICorporation, rate: number): void {
+  if (isNaN(rate) || rate < 0 || rate > CorporationConstants.DividendMaxRate) {
+    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 {
diff --git a/src/Corporation/Corporation.tsx b/src/Corporation/Corporation.tsx
index ace40ae72..787e22569 100644
--- a/src/Corporation/Corporation.tsx
+++ b/src/Corporation/Corporation.tsx
@@ -35,8 +35,8 @@ export class Corporation {
   shareSalesUntilPriceUpdate = CorporationConstants.SHARESPERPRICEUPDATE;
   shareSaleCooldown = 0; // Game cycles until player can sell shares again
   issueNewSharesCooldown = 0; // Game cycles until player can issue shares again
-  dividendPercentage = 0;
-  dividendTaxPercentage = 50;
+  dividendRate = 0;
+  dividendTaxPercentage = 100 - 100 * BitNodeMultipliers.CorporationSoftcap;
   issuedShares = 0;
   sharePrice = 0;
   storedCycles = 0;
@@ -121,16 +121,16 @@ export class Corporation {
         }
 
         // Process dividends
-        if (this.dividendPercentage > 0 && cycleProfit > 0) {
+        if (this.dividendRate > 0 && cycleProfit > 0) {
           // Validate input again, just to be safe
           if (
-            isNaN(this.dividendPercentage) ||
-            this.dividendPercentage < 0 ||
-            this.dividendPercentage > CorporationConstants.DividendMaxPercentage * 100
+            isNaN(this.dividendRate) ||
+            this.dividendRate < 0 ||
+            this.dividendRate > CorporationConstants.DividendMaxRate
           ) {
-            console.error(`Invalid Corporation dividend percentage: ${this.dividendPercentage}`);
+            console.error(`Invalid Corporation dividend rate: ${this.dividendRate}`);
           } else {
-            const totalDividends = (this.dividendPercentage / 100) * cycleProfit;
+            const totalDividends = this.dividendRate * cycleProfit;
             const retainedEarnings = cycleProfit - totalDividends;
             player.gainMoney(this.getDividends(), "corporation");
             this.addFunds(retainedEarnings);
@@ -149,7 +149,7 @@ export class Corporation {
   getDividends(): number {
     const profit = this.revenue - this.expenses;
     const cycleProfit = profit * CorporationConstants.SecsPerMarketCycle;
-    const totalDividends = (this.dividendPercentage / 100) * cycleProfit;
+    const totalDividends = this.dividendRate * cycleProfit;
     const dividendsPerShare = totalDividends / this.totalShares;
     const dividends = this.numShares * dividendsPerShare;
     let upgrades = -0.15;
@@ -167,8 +167,8 @@ export class Corporation {
       profit = this.avgProfit;
     if (this.public) {
       // Account for dividends
-      if (this.dividendPercentage > 0) {
-        profit *= (100 - this.dividendPercentage) / 100;
+      if (this.dividendRate > 0) {
+        profit *= 1 - this.dividendRate;
       }
 
       val = this.funds + profit * 85e3;
diff --git a/src/Corporation/ICorporation.ts b/src/Corporation/ICorporation.ts
index 609204fee..ebb51cad6 100644
--- a/src/Corporation/ICorporation.ts
+++ b/src/Corporation/ICorporation.ts
@@ -19,7 +19,7 @@ export interface ICorporation {
   shareSalesUntilPriceUpdate: number;
   shareSaleCooldown: number;
   issueNewSharesCooldown: number;
-  dividendPercentage: number;
+  dividendRate: number;
   dividendTaxPercentage: number;
   issuedShares: number;
   sharePrice: number;
diff --git a/src/Corporation/data/Constants.ts b/src/Corporation/data/Constants.ts
index d6b53f3d1..c83e3e0d7 100644
--- a/src/Corporation/data/Constants.ts
+++ b/src/Corporation/data/Constants.ts
@@ -19,7 +19,7 @@ export const CorporationConstants: {
   BribeThreshold: number;
   BribeToRepRatio: number;
   ProductProductionCostRatio: number;
-  DividendMaxPercentage: number;
+  DividendMaxRate: number;
   EmployeeSalaryMultiplier: number;
   CyclesPerEmployeeRaise: number;
   EmployeeRaiseAmount: number;
@@ -61,7 +61,7 @@ export const CorporationConstants: {
 
   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
   CyclesPerEmployeeRaise: 400, // All employees get a raise every X market cycles
diff --git a/src/Corporation/ui/Overview.tsx b/src/Corporation/ui/Overview.tsx
index e2856867a..a873f9a92 100644
--- a/src/Corporation/ui/Overview.tsx
+++ b/src/Corporation/ui/Overview.tsx
@@ -275,15 +275,15 @@ interface IDividendsStatsProps {
 }
 function DividendsStats({ profit }: IDividendsStatsProps): React.ReactElement {
   const corp = useCorporation();
-  if (corp.dividendPercentage <= 0 || profit <= 0) return <></>;
-  const totalDividends = (corp.dividendPercentage / 100) * profit;
+  if (corp.dividendRate <= 0 || profit <= 0) return <></>;
+  const totalDividends = corp.dividendRate * profit;
   const retainedEarnings = profit - totalDividends;
   const dividendsPerShare = totalDividends / corp.totalShares;
   return (
     <StatsTable
       rows={[
         ["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} />],
         ["Your earnings as a shareholder:", <MoneyRate money={corp.getDividends()} />],
       ]}
diff --git a/src/Corporation/ui/modals/IssueDividendsModal.tsx b/src/Corporation/ui/modals/IssueDividendsModal.tsx
index 4531faedf..110e21cc5 100644
--- a/src/Corporation/ui/modals/IssueDividendsModal.tsx
+++ b/src/Corporation/ui/modals/IssueDividendsModal.tsx
@@ -19,7 +19,7 @@ export function IssueDividendsModal(props: IProps): React.ReactElement {
   const corp = useCorporation();
   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 {
     if (!canIssue) return;
     if (percent === null) return;

From e28fe3e31d07d7a4b410c30760a4d40fb017c20c Mon Sep 17 00:00:00 2001
From: Staszek Welsh <stalefishies@gmail.com>
Date: Mon, 30 May 2022 22:05:05 +0100
Subject: [PATCH 2/7] Use stored corporation.dividendTax in the dividend tax
 calculation

---
 src/Corporation/Corporation.tsx | 28 +++++++++++++++-------------
 src/Corporation/ICorporation.ts |  5 +++--
 2 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/src/Corporation/Corporation.tsx b/src/Corporation/Corporation.tsx
index 787e22569..a41185372 100644
--- a/src/Corporation/Corporation.tsx
+++ b/src/Corporation/Corporation.tsx
@@ -36,7 +36,7 @@ export class Corporation {
   shareSaleCooldown = 0; // Game cycles until player can sell shares again
   issueNewSharesCooldown = 0; // Game cycles until player can issue shares again
   dividendRate = 0;
-  dividendTaxPercentage = 100 - 100 * BitNodeMultipliers.CorporationSoftcap;
+  dividendTax = 1 - BitNodeMultipliers.CorporationSoftcap + 0.15;
   issuedShares = 0;
   sharePrice = 0;
   storedCycles = 0;
@@ -121,6 +121,7 @@ export class Corporation {
         }
 
         // Process dividends
+        this.updateDividendTax();
         if (this.dividendRate > 0 && cycleProfit > 0) {
           // Validate input again, just to be safe
           if (
@@ -146,20 +147,23 @@ export class Corporation {
     }
   }
 
+  updateDividendTax(): void {
+    this.dividendTax = 1 - BitNodeMultipliers.CorporationSoftcap + 0.15;
+    if (this.unlockUpgrades[5] === 1) {
+      this.dividendTax -= 0.05;
+    }
+    if (this.unlockUpgrades[6] === 1) {
+      this.dividendTax -= 0.1;
+    }
+  }
+
   getDividends(): 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;
-    let upgrades = -0.15;
-    if (this.unlockUpgrades[5] === 1) {
-      upgrades += 0.05;
-    }
-    if (this.unlockUpgrades[6] === 1) {
-      upgrades += 0.1;
-    }
-    return Math.pow(dividends, BitNodeMultipliers.CorporationSoftcap + upgrades);
+    return Math.pow(dividends, 1 - this.dividendTax);
   }
 
   determineValuation(): number {
@@ -277,10 +281,8 @@ export class Corporation {
     this.funds = this.funds - price;
 
     // Apply effects for one-time upgrades
-    if (upgN === 5) {
-      this.dividendTaxPercentage -= 5;
-    } else if (upgN === 6) {
-      this.dividendTaxPercentage -= 10;
+    if (upgN === 5 || upgN === 6) {
+      this.updateDividendTax();
     }
   }
 
diff --git a/src/Corporation/ICorporation.ts b/src/Corporation/ICorporation.ts
index ebb51cad6..457f09061 100644
--- a/src/Corporation/ICorporation.ts
+++ b/src/Corporation/ICorporation.ts
@@ -20,7 +20,7 @@ export interface ICorporation {
   shareSaleCooldown: number;
   issueNewSharesCooldown: number;
   dividendRate: number;
-  dividendTaxPercentage: number;
+  dividendTax: number;
   issuedShares: number;
   sharePrice: number;
   storedCycles: number;
@@ -54,6 +54,7 @@ export interface ICorporation {
   getSalesMultiplier(): number;
   getScientificResearchMultiplier(): number;
   getStarterGuide(player: IPlayer): void;
-  toJSON(): any;
+  updateDividendTax(): void;
   getDividends(): number;
+  toJSON(): any;
 }

From c117b55df902f948770426efec9cb7eb3971ef56 Mon Sep 17 00:00:00 2001
From: Staszek Welsh <stalefishies@gmail.com>
Date: Mon, 30 May 2022 22:21:27 +0100
Subject: [PATCH 3/7] Expose dividend info through
 ns.corporation.getCorporation()

---
 src/NetscriptFunctions/Corporation.ts      | 3 +++
 src/ScriptEditor/NetscriptDefinitions.d.ts | 6 ++++++
 2 files changed, 9 insertions(+)

diff --git a/src/NetscriptFunctions/Corporation.ts b/src/NetscriptFunctions/Corporation.ts
index 9ed771625..1303151cc 100644
--- a/src/NetscriptFunctions/Corporation.ts
+++ b/src/NetscriptFunctions/Corporation.ts
@@ -952,6 +952,9 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript
         shareSaleCooldown: corporation.shareSaleCooldown,
         issuedShares: corporation.issuedShares,
         sharePrice: corporation.sharePrice,
+        dividendRate: corporation.dividendRate,
+        dividendTax: corporation.dividendTax,
+        dividendEarnings: corporation.getDividends() / CorporationConstants.SecsPerMarketCycle,
         state: corporation.state.getState(),
         divisions: corporation.divisions.map((division): NSDivision => getSafeDivision(division)),
       };
diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts
index 01432f441..b9bda8ce9 100644
--- a/src/ScriptEditor/NetscriptDefinitions.d.ts
+++ b/src/ScriptEditor/NetscriptDefinitions.d.ts
@@ -7100,6 +7100,12 @@ interface CorporationInfo {
   issuedShares: number;
   /** Price of the shares */
   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: string;
   /** Array of all divisions */

From 74e4a32f1396b248b06d3635292939b4d9b6bd99 Mon Sep 17 00:00:00 2001
From: Staszek Welsh <stalefishies@gmail.com>
Date: Mon, 30 May 2022 22:24:52 +0100
Subject: [PATCH 4/7] Fix shareholder earnings in UI being per cycle instead of
 per sec

---
 src/Corporation/ui/Overview.tsx | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/Corporation/ui/Overview.tsx b/src/Corporation/ui/Overview.tsx
index a873f9a92..126408257 100644
--- a/src/Corporation/ui/Overview.tsx
+++ b/src/Corporation/ui/Overview.tsx
@@ -279,13 +279,14 @@ function DividendsStats({ profit }: IDividendsStatsProps): React.ReactElement {
   const totalDividends = corp.dividendRate * profit;
   const retainedEarnings = profit - totalDividends;
   const dividendsPerShare = totalDividends / corp.totalShares;
+  const playerEarnings = corp.getDividends() / CorporationConstants.SecsPerMarketCycle;
   return (
     <StatsTable
       rows={[
         ["Retained Profits (after dividends):", <MoneyRate money={retainedEarnings} />],
         ["Dividend Percentage:", numeralWrapper.format(corp.dividendRate, "0%")],
         ["Dividends per share:", <MoneyRate money={dividendsPerShare} />],
-        ["Your earnings as a shareholder:", <MoneyRate money={corp.getDividends()} />],
+        ["Your earnings as a shareholder:", <MoneyRate money={playerEarnings} />],
       ]}
     />
   );

From 4a3558098ce26b8c6fd95051eddc59d874d184e4 Mon Sep 17 00:00:00 2001
From: Staszek Welsh <stalefishies@gmail.com>
Date: Mon, 30 May 2022 22:31:51 +0100
Subject: [PATCH 5/7] Fix error check in issueDividends expecting 0-100 when it
 actually takes 0-1

---
 src/NetscriptFunctions/Corporation.ts      | 11 ++++++-----
 src/ScriptEditor/NetscriptDefinitions.d.ts |  4 ++--
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/src/NetscriptFunctions/Corporation.ts b/src/NetscriptFunctions/Corporation.ts
index 1303151cc..18bab912b 100644
--- a/src/NetscriptFunctions/Corporation.ts
+++ b/src/NetscriptFunctions/Corporation.ts
@@ -918,14 +918,15 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript
       },
     issueDividends:
       (ctx: NetscriptContext) =>
-      (_percent: unknown): void => {
+      (_rate: unknown): void => {
         checkAccess(ctx);
-        const percent = ctx.helper.number("percent", _percent);
-        if (percent < 0 || percent > 100)
-          throw new Error("Invalid value for percent field! Must be numeric, greater than 0, and less than 100");
+        const rate = ctx.helper.number("rate", _rate);
+        const max = CorporationConstants.DividendMaxRate;
+        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();
         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
diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts
index b9bda8ce9..a1b01a9ca 100644
--- a/src/ScriptEditor/NetscriptDefinitions.d.ts
+++ b/src/ScriptEditor/NetscriptDefinitions.d.ts
@@ -7048,9 +7048,9 @@ export interface Corporation extends WarehouseAPI, OfficeAPI {
   levelUpgrade(upgradeName: string): void;
   /**
    * 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
    * @param amount - Amount of shares to buy back.

From eb46e4d15695d70ae5818ec9901a5e95f88071bd Mon Sep 17 00:00:00 2001
From: Staszek Welsh <stalefishies@gmail.com>
Date: Wed, 1 Jun 2022 12:59:45 +0100
Subject: [PATCH 6/7] Rename getDividends to getCycleDividends for clarity

---
 src/Corporation/Corporation.tsx       | 4 ++--
 src/Corporation/ICorporation.ts       | 2 +-
 src/Corporation/ui/Overview.tsx       | 2 +-
 src/NetscriptFunctions/Corporation.ts | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/Corporation/Corporation.tsx b/src/Corporation/Corporation.tsx
index a41185372..eae2692a5 100644
--- a/src/Corporation/Corporation.tsx
+++ b/src/Corporation/Corporation.tsx
@@ -133,7 +133,7 @@ export class Corporation {
           } else {
             const totalDividends = this.dividendRate * cycleProfit;
             const retainedEarnings = cycleProfit - totalDividends;
-            player.gainMoney(this.getDividends(), "corporation");
+            player.gainMoney(this.getCycleDividends(), "corporation");
             this.addFunds(retainedEarnings);
           }
         } else {
@@ -157,7 +157,7 @@ export class Corporation {
     }
   }
 
-  getDividends(): number {
+  getCycleDividends(): number {
     const profit = this.revenue - this.expenses;
     const cycleProfit = profit * CorporationConstants.SecsPerMarketCycle;
     const totalDividends = this.dividendRate * cycleProfit;
diff --git a/src/Corporation/ICorporation.ts b/src/Corporation/ICorporation.ts
index 457f09061..b2ea08648 100644
--- a/src/Corporation/ICorporation.ts
+++ b/src/Corporation/ICorporation.ts
@@ -55,6 +55,6 @@ export interface ICorporation {
   getScientificResearchMultiplier(): number;
   getStarterGuide(player: IPlayer): void;
   updateDividendTax(): void;
-  getDividends(): number;
+  getCycleDividends(): number;
   toJSON(): any;
 }
diff --git a/src/Corporation/ui/Overview.tsx b/src/Corporation/ui/Overview.tsx
index 126408257..b6390aad3 100644
--- a/src/Corporation/ui/Overview.tsx
+++ b/src/Corporation/ui/Overview.tsx
@@ -279,7 +279,7 @@ function DividendsStats({ profit }: IDividendsStatsProps): React.ReactElement {
   const totalDividends = corp.dividendRate * profit;
   const retainedEarnings = profit - totalDividends;
   const dividendsPerShare = totalDividends / corp.totalShares;
-  const playerEarnings = corp.getDividends() / CorporationConstants.SecsPerMarketCycle;
+  const playerEarnings = corp.getCycleDividends() / CorporationConstants.SecsPerMarketCycle;
   return (
     <StatsTable
       rows={[
diff --git a/src/NetscriptFunctions/Corporation.ts b/src/NetscriptFunctions/Corporation.ts
index 18bab912b..6a8b55ec2 100644
--- a/src/NetscriptFunctions/Corporation.ts
+++ b/src/NetscriptFunctions/Corporation.ts
@@ -955,7 +955,7 @@ export function NetscriptCorporation(player: IPlayer, workerScript: WorkerScript
         sharePrice: corporation.sharePrice,
         dividendRate: corporation.dividendRate,
         dividendTax: corporation.dividendTax,
-        dividendEarnings: corporation.getDividends() / CorporationConstants.SecsPerMarketCycle,
+        dividendEarnings: corporation.getCycleDividends() / CorporationConstants.SecsPerMarketCycle,
         state: corporation.state.getState(),
         divisions: corporation.divisions.map((division): NSDivision => getSafeDivision(division)),
       };

From df98bcc748ffe77784a4c1a3f3780ebc69af15ca Mon Sep 17 00:00:00 2001
From: Staszek Welsh <stalefishies@gmail.com>
Date: Wed, 1 Jun 2022 13:03:32 +0100
Subject: [PATCH 7/7] Remove unnecessary check in corporation.unlock

---
 src/Corporation/Corporation.tsx | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/Corporation/Corporation.tsx b/src/Corporation/Corporation.tsx
index eae2692a5..e493ccf31 100644
--- a/src/Corporation/Corporation.tsx
+++ b/src/Corporation/Corporation.tsx
@@ -281,9 +281,7 @@ export class Corporation {
     this.funds = this.funds - price;
 
     // Apply effects for one-time upgrades
-    if (upgN === 5 || upgN === 6) {
-      this.updateDividendTax();
-    }
+    this.updateDividendTax();
   }
 
   //Levelable upgrades