Merge branch 'dev' of github.com:danielyxie/bitburner into dev

This commit is contained in:
Olivier Gagnon 2021-09-13 14:02:17 -04:00
commit acc215cc61
6 changed files with 330 additions and 309 deletions

@ -63,7 +63,6 @@ module.exports = {
"id-blacklist": ["error"], "id-blacklist": ["error"],
"id-length": ["off"], "id-length": ["off"],
"id-match": ["error"], "id-match": ["error"],
"implicit-arrow-linebreak": ["error", "beside"],
indent: ["off"], indent: ["off"],
"indent-legacy": ["off"], "indent-legacy": ["off"],
"init-declarations": ["off"], "init-declarations": ["off"],

@ -133,6 +133,7 @@
} }
.cmpy-mgmt-upgrade-div { .cmpy-mgmt-upgrade-div {
text-align: left;
display: inline-block; display: inline-block;
border: 1px solid #fff; border: 1px solid #fff;
margin: 2px; margin: 2px;

@ -40,9 +40,9 @@ export function LevelableUpgrade(props: IProps): React.ReactElement {
} }
return ( return (
<div className={"cmpy-mgmt-upgrade-div tooltip"} style={{ width: "45%" }} onClick={onClick}> <button className={"cmpy-mgmt-upgrade-div tooltip"} style={{ width: "45%" }} onClick={onClick}>
{text} {text}
<span className={"tooltiptext"}>{tooltip}</span> <span className={"tooltiptext"}>{tooltip}</span>
</div> </button>
); );
} }

@ -27,330 +27,52 @@ interface IProps {
player: IPlayer; player: IPlayer;
rerender: () => void; rerender: () => void;
} }
export function Overview({ corp, player, rerender }: IProps): React.ReactElement {
export function Overview(props: IProps): React.ReactElement { const profit: number = corp.revenue.minus(corp.expenses).toNumber();
// Generic Function for Creating a button
interface ICreateButtonProps {
text: string;
class?: string;
className?: string;
display?: string;
tooltip?: string;
onClick?: (event: React.MouseEvent) => void;
}
function Button(props: ICreateButtonProps): React.ReactElement {
let className = props.className ? props.className : "std-button";
const hasTooltip = props.tooltip != null;
if (hasTooltip) className += " tooltip";
return (
<a className={className} onClick={props.onClick} style={{ display: props.display ? props.display : "block" }}>
{props.text}
{hasTooltip && <span className={"tooltiptext"}>{props.tooltip}</span>}
</a>
);
}
function openBribeFactionPopup(): void {
const popupId = "corp-bribe-popup";
createPopup(popupId, BribeFactionPopup, {
player: props.player,
popupId: popupId,
corp: props.corp,
});
}
const profit: number = props.corp.revenue.minus(props.corp.expenses).toNumber();
function DividendsStats(): React.ReactElement {
if (props.corp.dividendPercentage <= 0 || profit <= 0) return <></>;
const totalDividends = (props.corp.dividendPercentage / 100) * profit;
const retainedEarnings = profit - totalDividends;
const dividendsPerShare = totalDividends / props.corp.totalShares;
const playerEarnings = props.corp.numShares * dividendsPerShare;
return (
<>
Retained Profits (after dividends): <Money money={retainedEarnings} /> / s<br />
<br />
Dividend Percentage: {numeralWrapper.format(props.corp.dividendPercentage / 100, "0%")}
<br />
Dividends per share: <Money money={dividendsPerShare} /> / s<br />
Your earnings as a shareholder (Pre-Tax): <Money money={playerEarnings} /> / s<br />
Dividend Tax Rate: {props.corp.dividendTaxPercentage}%<br />
Your earnings as a shareholder (Post-Tax):{" "}
<Money money={playerEarnings * (1 - props.corp.dividendTaxPercentage / 100)} /> / s<br />
<br />
</>
);
}
function Mult(props: { name: string; mult: number }): React.ReactElement {
if (props.mult <= 1) return <></>;
return (
<p>
{props.name}
{numeralWrapper.format(props.mult, "0.000")}
<br />
</p>
);
}
// Returns a string with general information about Corporation
function BonusTime(): React.ReactElement {
const storedTime = props.corp.storedCycles * CONSTANTS.MilliPerCycle;
if (storedTime <= 15000) return <></>;
return (
<p>
Bonus time: {convertTimeMsToTimeElapsedString(storedTime)}
<br />
<br />
</p>
);
}
function BribeButton(): React.ReactElement {
const canBribe = props.corp.determineValuation() >= CorporationConstants.BribeThreshold || true;
const bribeFactionsClass = canBribe ? "a-link-button" : "a-link-button-inactive";
return (
<Button
className={bribeFactionsClass}
display="inline-block"
onClick={openBribeFactionPopup}
text="Bribe Factions"
tooltip={
canBribe
? "Use your Corporations power and influence to bribe Faction leaders in exchange for reputation"
: "Your Corporation is not powerful enough to bribe Faction leaders"
}
/>
);
}
function openFindInvestorsPopup(): void {
const popupId = "cmpy-mgmt-find-investors-popup";
createPopup(popupId, FindInvestorsPopup, {
rerender: props.rerender,
player: props.player,
popupId: popupId,
corp: props.corp,
});
}
function openGoPublicPopup(): void {
const popupId = "cmpy-mgmt-go-public-popup";
createPopup(popupId, GoPublicPopup, {
rerender: props.rerender,
player: props.player,
popupId: popupId,
corp: props.corp,
});
}
// Render the buttons for when your Corporation is still private
function PrivateButtons(): React.ReactElement {
const fundingAvailable = props.corp.fundingRound < 4;
const findInvestorsClassName = fundingAvailable ? "std-button" : "a-link-button-inactive";
const findInvestorsTooltip = fundingAvailable
? "Search for private investors who will give you startup funding in exchangefor equity (stock shares) in your company"
: undefined;
return (
<>
<Button
className={findInvestorsClassName}
onClick={openFindInvestorsPopup}
text="Find Investors"
tooltip={findInvestorsTooltip}
display="inline-block"
/>
<Button
className="std-button"
onClick={openGoPublicPopup}
display="inline-block"
text="Go Public"
tooltip={
"Become a publicly traded and owned entity. Going public " +
"involves issuing shares for an IPO. Once you are a public " +
"company, your shares will be traded on the stock market."
}
/>
<br />
</>
);
}
function openSellSharesPopup(): void {
const popupId = "cmpy-mgmt-sell-shares-popup";
createPopup(popupId, SellSharesPopup, {
corp: props.corp,
player: props.player,
popupId: popupId,
rerender: props.rerender,
});
}
function openBuybackSharesPopup(): void {
const popupId = "corp-buyback-shares-popup";
createPopup(popupId, BuybackSharesPopup, {
rerender: props.rerender,
player: props.player,
popupId: popupId,
corp: props.corp,
});
}
function openIssueNewSharesPopup(): void {
const popupId = "cmpy-mgmt-issue-new-shares-popup";
createPopup(popupId, IssueNewSharesPopup, {
popupId: popupId,
corp: props.corp,
});
}
function openIssueDividendsPopup(): void {
const popupId = "cmpy-mgmt-issue-dividends-popup";
createPopup(popupId, IssueDividendsPopup, {
popupId: popupId,
corp: props.corp,
});
}
// Render the buttons for when your Corporation has gone public
function PublicButtons(): React.ReactElement {
const corp = props.corp;
const sellSharesOnCd = corp.shareSaleCooldown > 0;
const sellSharesClass = sellSharesOnCd ? "a-link-button-inactive" : "std-button";
const sellSharesTooltip = sellSharesOnCd
? "Cannot sell shares for " + corp.convertCooldownToString(corp.shareSaleCooldown)
: "Sell your shares in the company. The money earned from selling your " +
"shares goes into your personal account, not the Corporation's. " +
"This is one of the only ways to profit from your business venture.";
const issueNewSharesOnCd = corp.issueNewSharesCooldown > 0;
const issueNewSharesClass = issueNewSharesOnCd ? "a-link-button-inactive" : "std-button";
const issueNewSharesTooltip = issueNewSharesOnCd
? "Cannot issue new shares for " + corp.convertCooldownToString(corp.issueNewSharesCooldown)
: "Issue new equity shares to raise capital.";
return (
<>
<Button
className={sellSharesClass}
display="inline-block"
onClick={openSellSharesPopup}
text="Sell Shares"
tooltip={sellSharesTooltip}
/>
<Button
className="std-button"
display="inline-block"
onClick={openBuybackSharesPopup}
text="Buyback shares"
tooltip="Buy back shares you that previously issued or sold at market price."
/>
<br />
<Button
className={issueNewSharesClass}
display="inline-block"
onClick={openIssueNewSharesPopup}
text="Issue New Shares"
tooltip={issueNewSharesTooltip}
/>
<Button
className="std-button"
display="inline-block"
onClick={openIssueDividendsPopup}
text="Issue Dividends"
tooltip="Manage the dividends that are paid out to shareholders (including yourself)"
/>
<br />
</>
);
}
// Render the UI for Corporation upgrades
function Upgrades(): React.ReactElement {
// Don't show upgrades
if (props.corp.divisions.length <= 0) {
return <h1>Unlock upgrades after creating your first division</h1>;
}
return (
<div className={"cmpy-mgmt-upgrade-container"}>
<h1 className={"cmpy-mgmt-upgrade-header"}> Unlocks </h1>
{Object.values(CorporationUnlockUpgrades)
.filter((upgrade: CorporationUnlockUpgrade) => props.corp.unlockUpgrades[upgrade[0]] === 0)
.map((upgrade: CorporationUnlockUpgrade) => (
<UnlockUpgrade
rerender={props.rerender}
player={props.player}
corp={props.corp}
upgradeData={upgrade}
key={upgrade[0]}
/>
))}
<h1 className={"cmpy-mgmt-upgrade-header"}> Upgrades </h1>
{props.corp.upgrades
.map((level: number, i: number) => CorporationUpgrades[i])
.map((upgrade: CorporationUpgrade) => (
<LevelableUpgrade
rerender={props.rerender}
player={props.player}
corp={props.corp}
upgrade={upgrade}
key={upgrade[0]}
/>
))}
</div>
);
}
return ( return (
<div> <div>
<p> <p>
Total Funds: <Money money={props.corp.funds.toNumber()} /> Total Funds: <Money money={corp.funds.toNumber()} />
<br /> <br />
Total Revenue: <Money money={props.corp.revenue.toNumber()} /> / s<br /> Total Revenue: <Money money={corp.revenue.toNumber()} /> / s<br />
Total Expenses: <Money money={props.corp.expenses.toNumber()} /> / s Total Expenses: <Money money={corp.expenses.toNumber()} /> / s
<br /> <br />
Total Profits: <Money money={profit} /> / s<br /> Total Profits: <Money money={profit} /> / s<br />
<DividendsStats /> <DividendsStats corp={corp} profit={profit} />
Publicly Traded: {props.corp.public ? "Yes" : "No"} Publicly Traded: {corp.public ? "Yes" : "No"}
<br /> <br />
Owned Stock Shares: {numeralWrapper.format(props.corp.numShares, "0.000a")} Owned Stock Shares: {numeralWrapper.format(corp.numShares, "0.000a")}
<br /> <br />
Stock Price: {props.corp.public ? <Money money={props.corp.sharePrice} /> : "N/A"} Stock Price: {corp.public ? <Money money={corp.sharePrice} /> : "N/A"}
<br /> <br />
</p> </p>
<p className="tooltip"> <p className="tooltip">
Total Stock Shares: {numeralWrapper.format(props.corp.totalShares, "0.000a")} Total Stock Shares: {numeralWrapper.format(corp.totalShares, "0.000a")}
<span className="tooltiptext"> <span className="tooltiptext">
Outstanding Shares: {numeralWrapper.format(props.corp.issuedShares, "0.000a")} Outstanding Shares: {numeralWrapper.format(corp.issuedShares, "0.000a")}
<br /> <br />
Private Shares:{" "} Private Shares: {numeralWrapper.format(corp.totalShares - corp.issuedShares - corp.numShares, "0.000a")}
{numeralWrapper.format(props.corp.totalShares - props.corp.issuedShares - props.corp.numShares, "0.000a")}
</span> </span>
</p> </p>
<br /> <br />
<br /> <br />
<Mult name="Production Multiplier: " mult={props.corp.getProductionMultiplier()} /> <Mult name="Production Multiplier: " mult={corp.getProductionMultiplier()} />
<Mult name="Storage Multiplier: " mult={props.corp.getStorageMultiplier()} /> <Mult name="Storage Multiplier: " mult={corp.getStorageMultiplier()} />
<Mult name="Advertising Multiplier: " mult={props.corp.getAdvertisingMultiplier()} /> <Mult name="Advertising Multiplier: " mult={corp.getAdvertisingMultiplier()} />
<Mult name="Empl. Creativity Multiplier: " mult={props.corp.getEmployeeCreMultiplier()} /> <Mult name="Empl. Creativity Multiplier: " mult={corp.getEmployeeCreMultiplier()} />
<Mult name="Empl. Charisma Multiplier: " mult={props.corp.getEmployeeChaMultiplier()} /> <Mult name="Empl. Charisma Multiplier: " mult={corp.getEmployeeChaMultiplier()} />
<Mult name="Empl. Intelligence Multiplier: " mult={props.corp.getEmployeeIntMultiplier()} /> <Mult name="Empl. Intelligence Multiplier: " mult={corp.getEmployeeIntMultiplier()} />
<Mult name="Empl. Efficiency Multiplier: " mult={props.corp.getEmployeeEffMultiplier()} /> <Mult name="Empl. Efficiency Multiplier: " mult={corp.getEmployeeEffMultiplier()} />
<Mult name="Sales Multiplier: " mult={props.corp.getSalesMultiplier()} /> <Mult name="Sales Multiplier: " mult={corp.getSalesMultiplier()} />
<Mult name="Scientific Research Multiplier: " mult={props.corp.getScientificResearchMultiplier()} /> <Mult name="Scientific Research Multiplier: " mult={corp.getScientificResearchMultiplier()} />
<br /> <br />
<BonusTime /> <BonusTime corp={corp} />
<div> <div>
<Button <Button
className="a-link-button" className="a-link-button"
display="inline-block" display="inline-block"
onClick={() => props.corp.getStarterGuide(props.player)} onClick={() => corp.getStarterGuide(player)}
text="Getting Started Guide" text="Getting Started Guide"
tooltip={ tooltip={
"Get a copy of and read 'The Complete Handbook for Creating a Successful Corporation.' " + "Get a copy of and read 'The Complete Handbook for Creating a Successful Corporation.' " +
@ -358,11 +80,307 @@ export function Overview(props: IProps): React.ReactElement {
"provides some tips/pointers for helping you get started with managing it." "provides some tips/pointers for helping you get started with managing it."
} }
/> />
{props.corp.public ? <PublicButtons /> : <PrivateButtons />} {corp.public ? (
<BribeButton /> <PublicButtons corp={corp} player={player} rerender={rerender} />
) : (
<PrivateButtons corp={corp} player={player} rerender={rerender} />
)}
<BribeButton corp={corp} player={player} />
</div> </div>
<br /> <br />
<Upgrades /> <Upgrades corp={corp} player={player} rerender={rerender} />
</div> </div>
); );
} }
interface IPrivateButtonsProps {
corp: ICorporation;
player: IPlayer;
rerender: () => void;
}
// Render the buttons for when your Corporation is still private
function PrivateButtons({ corp, player, rerender }: IPrivateButtonsProps): React.ReactElement {
function openFindInvestorsPopup(): void {
const popupId = "cmpy-mgmt-find-investors-popup";
createPopup(popupId, FindInvestorsPopup, {
rerender,
player,
popupId,
corp: corp,
});
}
function openGoPublicPopup(): void {
const popupId = "cmpy-mgmt-go-public-popup";
createPopup(popupId, GoPublicPopup, {
rerender,
player,
popupId,
corp: corp,
});
}
const fundingAvailable = corp.fundingRound < 4;
const findInvestorsClassName = fundingAvailable ? "std-button" : "a-link-button-inactive";
const findInvestorsTooltip = fundingAvailable
? "Search for private investors who will give you startup funding in exchangefor equity (stock shares) in your company"
: undefined;
return (
<>
<Button
className={findInvestorsClassName}
onClick={openFindInvestorsPopup}
text="Find Investors"
tooltip={findInvestorsTooltip}
display="inline-block"
/>
<Button
className="std-button"
onClick={openGoPublicPopup}
display="inline-block"
text="Go Public"
tooltip={
"Become a publicly traded and owned entity. Going public " +
"involves issuing shares for an IPO. Once you are a public " +
"company, your shares will be traded on the stock market."
}
/>
<br />
</>
);
}
interface IUpgradeProps {
corp: ICorporation;
player: IPlayer;
rerender: () => void;
}
// Render the UI for Corporation upgrades
function Upgrades({ corp, player, rerender }: IUpgradeProps): React.ReactElement {
// Don't show upgrades
if (corp.divisions.length <= 0) {
return <h1>Unlock upgrades after creating your first division</h1>;
}
return (
<div className={"cmpy-mgmt-upgrade-container"}>
<h1 className={"cmpy-mgmt-upgrade-header"}> Unlocks </h1>
{Object.values(CorporationUnlockUpgrades)
.filter((upgrade: CorporationUnlockUpgrade) => corp.unlockUpgrades[upgrade[0]] === 0)
.map((upgrade: CorporationUnlockUpgrade) => (
<UnlockUpgrade rerender={rerender} player={player} corp={corp} upgradeData={upgrade} key={upgrade[0]} />
))}
<h1 className={"cmpy-mgmt-upgrade-header"}> Upgrades </h1>
{corp.upgrades
.map((level: number, i: number) => CorporationUpgrades[i])
.map((upgrade: CorporationUpgrade) => (
<LevelableUpgrade rerender={rerender} player={player} corp={corp} upgrade={upgrade} key={upgrade[0]} />
))}
</div>
);
}
interface IPublicButtonsProps {
corp: ICorporation;
player: IPlayer;
rerender: () => void;
}
// Render the buttons for when your Corporation has gone public
function PublicButtons({ corp, player, rerender }: IPublicButtonsProps): React.ReactElement {
const sellSharesOnCd = corp.shareSaleCooldown > 0;
const sellSharesClass = sellSharesOnCd ? "a-link-button-inactive" : "std-button";
const sellSharesTooltip = sellSharesOnCd
? "Cannot sell shares for " + corp.convertCooldownToString(corp.shareSaleCooldown)
: "Sell your shares in the company. The money earned from selling your " +
"shares goes into your personal account, not the Corporation's. " +
"This is one of the only ways to profit from your business venture.";
const issueNewSharesOnCd = corp.issueNewSharesCooldown > 0;
const issueNewSharesClass = issueNewSharesOnCd ? "a-link-button-inactive" : "std-button";
const issueNewSharesTooltip = issueNewSharesOnCd
? "Cannot issue new shares for " + corp.convertCooldownToString(corp.issueNewSharesCooldown)
: "Issue new equity shares to raise capital.";
function openSellSharesPopup(): void {
const popupId = "cmpy-mgmt-sell-shares-popup";
createPopup(popupId, SellSharesPopup, {
corp: corp,
player,
popupId,
rerender,
});
}
function openBuybackSharesPopup(): void {
const popupId = "corp-buyback-shares-popup";
createPopup(popupId, BuybackSharesPopup, {
rerender,
player,
popupId,
corp: corp,
});
}
function openIssueNewSharesPopup(): void {
const popupId = "cmpy-mgmt-issue-new-shares-popup";
createPopup(popupId, IssueNewSharesPopup, {
popupId,
corp: corp,
});
}
function openIssueDividendsPopup(): void {
const popupId = "cmpy-mgmt-issue-dividends-popup";
createPopup(popupId, IssueDividendsPopup, {
popupId,
corp: corp,
});
}
return (
<>
<Button
className={sellSharesClass}
display="inline-block"
onClick={openSellSharesPopup}
text="Sell Shares"
tooltip={sellSharesTooltip}
/>
<Button
className="std-button"
display="inline-block"
onClick={openBuybackSharesPopup}
text="Buyback shares"
tooltip="Buy back shares you that previously issued or sold at market price."
/>
<br />
<Button
className={issueNewSharesClass}
display="inline-block"
onClick={openIssueNewSharesPopup}
text="Issue New Shares"
tooltip={issueNewSharesTooltip}
/>
<Button
className="std-button"
display="inline-block"
onClick={openIssueDividendsPopup}
text="Issue Dividends"
tooltip="Manage the dividends that are paid out to shareholders (including yourself)"
/>
<br />
</>
);
}
// Generic Function for Creating a button
interface ICreateButtonProps {
text: string;
className?: string;
display?: string;
tooltip?: string;
onClick?: (event: React.MouseEvent) => void;
}
function Button({ className = "std-button", text, display, tooltip, onClick }: ICreateButtonProps): React.ReactElement {
const hasTooltip = tooltip != null;
if (hasTooltip) className += " tooltip";
return (
<button className={className} onClick={onClick} style={{ display: display ? display : "block" }}>
{text}
{hasTooltip && <span className={"tooltiptext"}>{tooltip}</span>}
</button>
);
}
interface IBribeButtonProps {
player: IPlayer;
corp: ICorporation;
}
function BribeButton({ player, corp }: IBribeButtonProps): React.ReactElement {
function openBribeFactionPopup(): void {
const popupId = "corp-bribe-popup";
createPopup(popupId, BribeFactionPopup, {
player,
popupId,
corp: corp,
});
}
const canBribe = corp.determineValuation() >= CorporationConstants.BribeThreshold || true;
const bribeFactionsClass = canBribe ? "a-link-button" : "a-link-button-inactive";
return (
<Button
className={bribeFactionsClass}
display="inline-block"
onClick={openBribeFactionPopup}
text="Bribe Factions"
tooltip={
canBribe
? "Use your Corporations power and influence to bribe Faction leaders in exchange for reputation"
: "Your Corporation is not powerful enough to bribe Faction leaders"
}
/>
);
}
interface IDividendsStatsProps {
corp: ICorporation;
profit: number;
}
function DividendsStats({ corp, profit }: IDividendsStatsProps): React.ReactElement {
if (corp.dividendPercentage <= 0 || profit <= 0) return <></>;
const totalDividends = (corp.dividendPercentage / 100) * profit;
const retainedEarnings = profit - totalDividends;
const dividendsPerShare = totalDividends / corp.totalShares;
const playerEarnings = corp.numShares * dividendsPerShare;
return (
<>
Retained Profits (after dividends): <Money money={retainedEarnings} /> / s
<br />
<br />
Dividend Percentage: {numeralWrapper.format(corp.dividendPercentage / 100, "0%")}
<br />
Dividends per share: <Money money={dividendsPerShare} /> / s<br />
Your earnings as a shareholder (Pre-Tax): <Money money={playerEarnings} /> / s<br />
Dividend Tax Rate: {corp.dividendTaxPercentage}%<br />
Your earnings as a shareholder (Post-Tax):{" "}
<Money money={playerEarnings * (1 - corp.dividendTaxPercentage / 100)} /> / s<br />
<br />
</>
);
}
interface IMultProps {
name: string;
mult: number;
}
function Mult({ name, mult }: IMultProps): React.ReactElement {
if (mult <= 1) return <></>;
return (
<p>
{name}
{numeralWrapper.format(mult, "0.000")}
<br />
</p>
);
}
interface IBonusTimeProps {
corp: ICorporation;
}
// Returns a string with general information about Corporation
function BonusTime({ corp }: IBonusTimeProps): React.ReactElement {
const storedTime = corp.storedCycles * CONSTANTS.MilliPerCycle;
if (storedTime <= 15000) return <></>;
return (
<p>
Bonus time: {convertTimeMsToTimeElapsedString(storedTime)}
<br />
<br />
</p>
);
}

@ -34,9 +34,9 @@ export function UnlockUpgrade(props: IProps): React.ReactElement {
} }
return ( return (
<div className={"cmpy-mgmt-upgrade-div tooltip"} style={{ width: "45%" }} onClick={onClick}> <button className={"cmpy-mgmt-upgrade-div tooltip"} style={{ width: "45%" }} onClick={onClick}>
{text} {text}
<span className={"tooltiptext"}>{tooltip}</span> <span className={"tooltiptext"}>{tooltip}</span>
</div> </button>
); );
} }

@ -174,6 +174,9 @@ export function prestigeAugmentation() {
this.hacknetNodes.length = 0; this.hacknetNodes.length = 0;
this.hashManager.prestige(); this.hashManager.prestige();
// Reset player multipliers
this.resetMultipliers();
// Re-calculate skills and reset HP // Re-calculate skills and reset HP
this.updateSkillLevels(); this.updateSkillLevels();
this.hp = this.max_hp; this.hp = this.max_hp;