Skip to content

Commit

Permalink
CORPORATION: Add a new API to sell a division (#1210)
Browse files Browse the repository at this point in the history
Also refactoring around use of "player" variable (whether it is capitalized or not).
  • Loading branch information
catloversg authored Apr 16, 2024
1 parent dd3975a commit 216500e
Show file tree
Hide file tree
Showing 13 changed files with 111 additions and 152 deletions.
32 changes: 32 additions & 0 deletions src/Corporation/Actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,40 @@ import {
sellSharesFailureReason,
buybackSharesFailureReason,
issueNewSharesFailureReason,
costOfCreatingCorporation,
} from "./helpers";
import { PositiveInteger } from "../types";
import { currentNodeMults } from "../BitNode/BitNodeMultipliers";

export function createCorporation(corporationName: string, selfFund: boolean, restart: boolean): boolean {
if (!Player.canAccessCorporation()) {
return false;
}
if (Player.corporation && !restart) {
return false;
}
if (!corporationName) {
return false;
}
if (Player.bitNodeN !== 3 && !selfFund) {
throw new Error("Cannot use seed funds outside of BitNode 3");
}
if (currentNodeMults.CorporationSoftcap < 0.15) {
throw new Error(`You cannot create a corporation in BitNode ${Player.bitNodeN}`);
}

if (selfFund) {
const cost = costOfCreatingCorporation(restart);
if (!Player.canAfford(cost)) {
return false;
}
Player.startCorporation(corporationName, false);
Player.loseMoney(cost, "corporation");
} else {
Player.startCorporation(corporationName, true);
}
return true;
}

export function NewDivision(corporation: Corporation, industry: IndustryType, name: string): void {
if (corporation.divisions.size >= corporation.maxDivisions)
Expand Down
7 changes: 7 additions & 0 deletions src/Corporation/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ import { Corporation } from "./Corporation";
import { CorpUpgrade } from "./data/CorporationUpgrades";
import * as corpConstants from "./data/Constants";

export function costOfCreatingCorporation(restart: boolean): number {
if (restart && !Player.corporation?.seedFunded) {
return 50e9;
}
return 150e9;
}

export function calculateUpgradeCost(corporation: Corporation, upgrade: CorpUpgrade, amount: PositiveInteger): number {
const priceMult = upgrade.priceMult;
const level = corporation.upgrades[upgrade.name].level;
Expand Down
10 changes: 3 additions & 7 deletions src/Corporation/ui/Overview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ import Box from "@mui/material/Box";
import Paper from "@mui/material/Paper";
import Grid from "@mui/material/Grid";
import { MultiplierButtons } from "./MultiplierButtons";
import { SellCorporationModal } from "./modals/SellCorporationModal";
import { SellDivisionModal } from "./modals/SellDivisionModal";
import { getRecordKeys } from "../../Types/Record";
import { PositiveInteger } from "../../types";
import { ButtonWithTooltip } from "../../ui/Components/ButtonWithTooltip";
import { CreateCorporationModal } from "./modals/CreateCorporationModal";

interface IProps {
rerender: () => void;
Expand Down Expand Up @@ -319,16 +319,12 @@ function SellDivisionButton(): React.ReactElement {
function RestartButton(): React.ReactElement {
const [open, setOpen] = useState(false);

function restart(): void {
setOpen(true);
}

return (
<>
<ButtonWithTooltip normalTooltip={"Sell corporation and start over"} onClick={restart}>
<ButtonWithTooltip normalTooltip={"Sell corporation and start over"} onClick={() => setOpen(true)}>
Sell CEO position
</ButtonWithTooltip>
<SellCorporationModal open={open} onClose={() => setOpen(false)} />
<CreateCorporationModal open={open} onClose={() => setOpen(false)} restart={true} />
</>
);
}
Expand Down
54 changes: 26 additions & 28 deletions src/Corporation/ui/modals/CreateCorporationModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,21 @@ import { Player } from "@player";
import Typography from "@mui/material/Typography";
import { ButtonWithTooltip } from "../../../ui/Components/ButtonWithTooltip";
import TextField from "@mui/material/TextField";
import { createCorporation } from "../../Actions";
import { costOfCreatingCorporation } from "../../helpers";

interface IProps {
open: boolean;
onClose: () => void;
restart: boolean;
}

export function CreateCorporationModal(props: IProps): React.ReactElement {
const canSelfFund = Player.canAfford(150e9);
const cost = costOfCreatingCorporation(props.restart);
const canSelfFund = Player.canAfford(cost);
const [name, setName] = useState("");

if (!Player.canAccessCorporation() || Player.corporation) {
props.onClose();
if (!Player.canAccessCorporation() || (Player.corporation && !props.restart)) {
return <></>;
}

Expand All @@ -30,55 +33,50 @@ export function CreateCorporationModal(props: IProps): React.ReactElement {
setName(event.target.value);
}

function selfFund(): void {
if (!canSelfFund) return;
if (name == "") return;

Player.startCorporation(name, false);
Player.loseMoney(150e9, "corporation");

props.onClose();
Router.toPage(Page.Corporation);
}

function seed(): void {
if (name == "") {
function createCorporationWithUI(corporationName: string, selfFund: boolean): void {
if (!createCorporation(corporationName, selfFund, props.restart)) {
return;
}

Player.startCorporation(name, true);

props.onClose();
Router.toPage(Page.Corporation);
}

return (
<Modal open={props.open} onClose={props.onClose}>
<Typography>
Would you like to start a corporation? This will require <Money money={150e9} forPurchase={true} /> for
registration and initial funding.{" "}
{Player.bitNodeN === 3 && (
{!props.restart ? (
<>
Would you like to start a corporation? This will require <Money money={cost} forPurchase={true} /> for
registration and initial funding.{" "}
{Player.bitNodeN === 3 && (
<>
This <Money money={cost} /> can either be self-funded, or you can obtain the seed money from the
government in exchange for {formatShares(500e6)} shares (a <b>33.3%</b> stake in the company).
</>
)}
</>
) : (
<>
This <Money money={150e9} /> can either be self-funded, or you can obtain the seed money from the government
in exchange for {formatShares(500e6)} shares (a <b>33.3%</b> stake in the company).
Would you like to sell your position as CEO and start a new corporation? Everything from your current
corporation will be gone and you start fresh.
</>
)}
<br />
<br />
If you would like to start one, please enter a name for your corporation below:
If you would like to start {props.restart ? "a new" : ""} one, please enter a name for your corporation below:
</Typography>
<br />
<TextField autoFocus={true} placeholder="Corporation Name" onChange={onChange} value={name} />
{Player.bitNodeN === 3 && (
<ButtonWithTooltip onClick={seed} disabledTooltip={disabledTextForNoName}>
<ButtonWithTooltip onClick={() => createCorporationWithUI(name, false)} disabledTooltip={disabledTextForNoName}>
Use seed money
</ButtonWithTooltip>
)}
<ButtonWithTooltip
onClick={selfFund}
onClick={() => createCorporationWithUI(name, true)}
disabledTooltip={disabledTextForNoName || (canSelfFund ? "" : "Insufficient player funds")}
>
Self-Fund (<Money money={150e9} forPurchase={true} />)
Self-Fund (<Money money={cost} forPurchase={true} />)
</ButtonWithTooltip>
</Modal>
);
Expand Down
72 changes: 0 additions & 72 deletions src/Corporation/ui/modals/SellCorporationModal.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/Locations/ui/SpecialLocation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ export function SpecialLocation(props: SpecialLocationProps): React.ReactElement
<Button disabled={!Player.canAccessCorporation() || !!Player.corporation} onClick={() => setOpen(true)}>
Create a Corporation
</Button>
<CreateCorporationModal open={open} onClose={() => setOpen(false)} />
<CreateCorporationModal open={open} onClose={() => setOpen(false)} restart={false} />
</>
);
}
Expand Down
1 change: 1 addition & 0 deletions src/Netscript/RamCostGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ const corporation = {
hasResearched: RamCostConstants.CorporationInfo,
setAutoJobAssignment: RamCostConstants.CorporationAction,
getOfficeSizeUpgradeCost: RamCostConstants.CorporationInfo,
sellDivision: RamCostConstants.CorporationAction,
} as const;

/** RamCosts guaranteed to match ns structure 1:1 (aside from args and enums).
Expand Down
39 changes: 14 additions & 25 deletions src/NetscriptFunctions/Corporation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Player, Player as player } from "../Player";
import { Player } from "@player";

import { OfficeSpace } from "../Corporation/OfficeSpace";
import { Product } from "../Corporation/Product";
Expand Down Expand Up @@ -50,6 +50,8 @@ import {
LimitMaterialProduction,
LimitProductProduction,
UpgradeWarehouseCost,
createCorporation,
removeDivision,
} from "../Corporation/Actions";
import { CorpUnlocks } from "../Corporation/data/CorporationUnlocks";
import { CorpUpgrades } from "../Corporation/data/CorporationUpgrades";
Expand All @@ -58,7 +60,6 @@ import { IndustriesData, IndustryResearchTrees } from "../Corporation/data/Indus
import * as corpConstants from "../Corporation/data/Constants";
import { ResearchMap } from "../Corporation/ResearchMap";
import { Factions } from "../Faction/Factions";
import { currentNodeMults } from "../BitNode/BitNodeMultipliers";
import { InternalAPI, NetscriptContext, setRemovedFunctions } from "../Netscript/APIWrapper";
import { helpers } from "../Netscript/NetscriptHelpers";
import { getEnumHelper } from "../utils/EnumHelper";
Expand All @@ -68,24 +69,6 @@ import { PositiveInteger } from "../types";
import { getRecordKeys } from "../Types/Record";

export function NetscriptCorporation(): InternalAPI<NSCorporation> {
function createCorporation(corporationName: string, selfFund = true): boolean {
if (!player.canAccessCorporation() || player.corporation) return false;
if (!corporationName) return false;
if (player.bitNodeN !== 3 && !selfFund) throw new Error("cannot use seed funds outside of BitNode 3");
if (currentNodeMults.CorporationSoftcap < 0.15)
throw new Error(`You cannot create a corporation in Bitnode ${player.bitNodeN}`);

if (selfFund) {
if (!player.canAfford(150e9)) return false;

player.startCorporation(corporationName, false);
player.loseMoney(150e9, "corporation");
} else {
player.startCorporation(corporationName, true);
}
return true;
}

function hasUnlock(unlockName: CorpUnlockName): boolean {
const corporation = getCorporation();
return corporation.unlocks.has(unlockName);
Expand Down Expand Up @@ -128,7 +111,7 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
const faction = Factions[factionName];
const info = faction.getInfo();
if (!info.offersWork()) return false;
if (player.hasGangWith(factionName)) return false;
if (Player.hasGangWith(factionName)) return false;

const repGain = amountCash / corpConstants.bribeAmountPerReputation;
faction.playerReputation += repGain;
Expand All @@ -138,7 +121,7 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
}

function getCorporation(): Corporation {
const corporation = player.corporation;
const corporation = Player.corporation;
if (corporation === null) throw new Error("cannot be called without a corporation");
return corporation;
}
Expand Down Expand Up @@ -178,9 +161,9 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
}

function checkAccess(ctx: NetscriptContext, api?: CorpUnlockName): void {
if (!player.corporation) throw helpers.errorMessage(ctx, "Must own a corporation.");
if (!Player.corporation) throw helpers.errorMessage(ctx, "Must own a corporation.");
if (!api) return;
if (!player.corporation.unlocks.has(api)) {
if (!Player.corporation.unlocks.has(api)) {
throw helpers.errorMessage(ctx, "You do not have access to this API.");
}
}
Expand Down Expand Up @@ -732,7 +715,7 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
(_corporationName, _selfFund = true): boolean => {
const corporationName = helpers.string(ctx, "corporationName", _corporationName);
const selfFund = !!_selfFund;
return createCorporation(corporationName, selfFund);
return createCorporation(corporationName, selfFund, false);
},
hasUnlock: (ctx) => (_unlockName) => {
checkAccess(ctx);
Expand Down Expand Up @@ -803,6 +786,12 @@ export function NetscriptCorporation(): InternalAPI<NSCorporation> {
CorporationPromise.promise = new Promise<CorpStateName>((res) => (CorporationPromise.resolve = res));
return CorporationPromise.promise;
},
sellDivision: (ctx) => (_divisionName) => {
checkAccess(ctx);
const corporation = getCorporation();
const divisionName = helpers.string(ctx, "divisionName", _divisionName);
removeDivision(corporation, divisionName);
},
};

// Removed functions
Expand Down
2 changes: 1 addition & 1 deletion src/NetscriptFunctions/Extra.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Player } from "../Player";
import { Player } from "@player";
import { Exploit } from "../Exploits/Exploit";
import * as bcrypt from "bcryptjs";
import { Apr1Events as devMenu } from "../ui/Apr1";
Expand Down
Loading

0 comments on commit 216500e

Please sign in to comment.