Merge pull request #1356 from danielyxie/dev

can buy trp
This commit is contained in:
hydroflame 2021-09-22 11:00:31 -04:00 committed by GitHub
commit 1ba0332c53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 450 additions and 376 deletions

24
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -13,6 +13,7 @@ export interface IConstructorParams {
expMultiplier: number; expMultiplier: number;
salaryMultiplier: number; salaryMultiplier: number;
jobStatReqOffset: number; jobStatReqOffset: number;
isMegacorp?: boolean;
} }
const DefaultConstructorParams: IConstructorParams = { const DefaultConstructorParams: IConstructorParams = {
@ -35,6 +36,11 @@ export class Company {
*/ */
info: string; info: string;
/**
* Has faction associated.
*/
isMegacorp: boolean;
/** /**
* Object that holds all available positions in this Company. * Object that holds all available positions in this Company.
* Position names are held in keys. * Position names are held in keys.
@ -79,6 +85,8 @@ export class Company {
this.playerReputation = 1; this.playerReputation = 1;
this.favor = 0; this.favor = 0;
this.rolloverRep = 0; this.rolloverRep = 0;
this.isMegacorp = false;
if (p.isMegacorp) this.isMegacorp = true;
} }
hasPosition(pos: CompanyPosition | string): boolean { hasPosition(pos: CompanyPosition | string): boolean {

@ -45,6 +45,11 @@ export class FactionInfo {
*/ */
offerSecurityWork: boolean; offerSecurityWork: boolean;
/**
* Keep faction on install.
*/
keep: boolean;
constructor( constructor(
infoText: JSX.Element, infoText: JSX.Element,
enemies: string[], enemies: string[],
@ -52,6 +57,7 @@ export class FactionInfo {
offerHackingWork: boolean, offerHackingWork: boolean,
offerFieldWork: boolean, offerFieldWork: boolean,
offerSecurityWork: boolean, offerSecurityWork: boolean,
keep: boolean,
) { ) {
this.infoText = infoText; this.infoText = infoText;
this.enemies = enemies; this.enemies = enemies;
@ -63,6 +69,7 @@ export class FactionInfo {
// These are always all 1 for now. // These are always all 1 for now.
this.augmentationPriceMult = 1; this.augmentationPriceMult = 1;
this.augmentationRepRequirementMult = 1; this.augmentationRepRequirementMult = 1;
this.keep = keep;
} }
offersWork(): boolean { offersWork(): boolean {
@ -88,6 +95,7 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
false, false,
false,
), ),
Daedalus: new FactionInfo( Daedalus: new FactionInfo(
@ -97,6 +105,7 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
false, false,
false,
), ),
"The Covenant": new FactionInfo( "The Covenant": new FactionInfo(
@ -114,6 +123,7 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
false, false,
false,
), ),
// Megacorporations, each forms its own faction // Megacorporations, each forms its own faction
@ -129,6 +139,7 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
true, true,
true,
), ),
MegaCorp: new FactionInfo( MegaCorp: new FactionInfo(
@ -147,6 +158,7 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
true, true,
true,
), ),
"Bachman & Associates": new FactionInfo( "Bachman & Associates": new FactionInfo(
@ -163,9 +175,10 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
true, true,
true,
), ),
"Blade Industries": new FactionInfo(<>Augmentation is Salvation.</>, [], true, true, true, true), "Blade Industries": new FactionInfo(<>Augmentation is Salvation.</>, [], true, true, true, true, true),
NWO: new FactionInfo( NWO: new FactionInfo(
( (
@ -180,9 +193,10 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
true, true,
true,
), ),
"Clarke Incorporated": new FactionInfo(<>The Power of the Genome - Unlocked.</>, [], true, true, true, true), "Clarke Incorporated": new FactionInfo(<>The Power of the Genome - Unlocked.</>, [], true, true, true, true, true),
"OmniTek Incorporated": new FactionInfo( "OmniTek Incorporated": new FactionInfo(
<>Simply put, our mission is to design and build robots that make a difference.</>, <>Simply put, our mission is to design and build robots that make a difference.</>,
@ -191,6 +205,7 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
true, true,
true,
), ),
"Four Sigma": new FactionInfo( "Four Sigma": new FactionInfo(
@ -205,9 +220,10 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
true, true,
true,
), ),
"KuaiGong International": new FactionInfo(<>Dream big. Work hard. Make history.</>, [], true, true, true, true), "KuaiGong International": new FactionInfo(<>Dream big. Work hard. Make history.</>, [], true, true, true, true, true),
// Other Corporations // Other Corporations
"Fulcrum Secret Technologies": new FactionInfo( "Fulcrum Secret Technologies": new FactionInfo(
@ -222,6 +238,7 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
false, false,
true, true,
true,
), ),
// Hacker groups // Hacker groups
@ -243,6 +260,7 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
false, false,
false, false,
false,
), ),
"The Black Hand": new FactionInfo( "The Black Hand": new FactionInfo(
@ -261,6 +279,7 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
false, false,
false,
), ),
// prettier-ignore // prettier-ignore
@ -305,6 +324,7 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
false, false,
false, false,
false,
), ),
// City factions, essentially governments // City factions, essentially governments
@ -315,8 +335,9 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
true, true,
false,
), ),
Chongqing: new FactionInfo(<>Serve the People.</>, ["Sector-12", "Aevum", "Volhaven"], true, true, true, true), Chongqing: new FactionInfo(<>Serve the People.</>, ["Sector-12", "Aevum", "Volhaven"], true, true, true, true, false),
Ishima: new FactionInfo( Ishima: new FactionInfo(
<>The East Asian Order of the Future.</>, <>The East Asian Order of the Future.</>,
["Sector-12", "Aevum", "Volhaven"], ["Sector-12", "Aevum", "Volhaven"],
@ -324,8 +345,17 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
true, true,
false,
),
"New Tokyo": new FactionInfo(
<>Asia's World City.</>,
["Sector-12", "Aevum", "Volhaven"],
true,
true,
true,
true,
false,
), ),
"New Tokyo": new FactionInfo(<>Asia's World City.</>, ["Sector-12", "Aevum", "Volhaven"], true, true, true, true),
"Sector-12": new FactionInfo( "Sector-12": new FactionInfo(
<>The City of the Future.</>, <>The City of the Future.</>,
["Chongqing", "New Tokyo", "Ishima", "Volhaven"], ["Chongqing", "New Tokyo", "Ishima", "Volhaven"],
@ -333,6 +363,7 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
true, true,
false,
), ),
Volhaven: new FactionInfo( Volhaven: new FactionInfo(
<>Benefit, Honor, and Glory.</>, <>Benefit, Honor, and Glory.</>,
@ -341,6 +372,7 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
true, true,
false,
), ),
// Criminal Organizations/Gangs // Criminal Organizations/Gangs
@ -351,6 +383,7 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
true, true,
false,
), ),
"The Dark Army": new FactionInfo( "The Dark Army": new FactionInfo(
@ -360,9 +393,10 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
false, false,
false,
), ),
"The Syndicate": new FactionInfo(<>Honor holds you back.</>, [], true, true, true, true), "The Syndicate": new FactionInfo(<>Honor holds you back.</>, [], true, true, true, true, false),
Silhouette: new FactionInfo( Silhouette: new FactionInfo(
( (
@ -380,6 +414,7 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
true, true,
false, false,
false,
), ),
Tetrads: new FactionInfo( Tetrads: new FactionInfo(
@ -389,14 +424,15 @@ export const FactionInfos: IMap<FactionInfo> = {
false, false,
true, true,
true, true,
false,
), ),
"Slum Snakes": new FactionInfo(<>Slum Snakes rule!</>, [], false, false, true, true), "Slum Snakes": new FactionInfo(<>Slum Snakes rule!</>, [], false, false, true, true, false),
// Earlygame factions - factions the player will prestige with early on that don't belong in other categories. // Earlygame factions - factions the player will prestige with early on that don't belong in other categories.
Netburners: new FactionInfo(<>{"~~//*>H4CK||3T 8URN3R5**>?>\\~~"}</>, [], true, true, false, false), Netburners: new FactionInfo(<>{"~~//*>H4CK||3T 8URN3R5**>?>\\~~"}</>, [], true, true, false, false, false),
"Tian Di Hui": new FactionInfo(<>Obey Heaven and work righteously.</>, [], true, true, false, true), "Tian Di Hui": new FactionInfo(<>Obey Heaven and work righteously.</>, [], true, true, false, true, false),
CyberSec: new FactionInfo( CyberSec: new FactionInfo(
( (
@ -411,6 +447,7 @@ export const FactionInfos: IMap<FactionInfo> = {
true, true,
false, false,
false, false,
false,
), ),
// Special Factions // Special Factions
@ -429,5 +466,6 @@ export const FactionInfos: IMap<FactionInfo> = {
false, false,
false, false,
false, false,
false,
), ),
}; };

@ -10,6 +10,7 @@ import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Faction } from "../../Faction/Faction"; import { Faction } from "../../Faction/Faction";
import { PurchaseAugmentationsOrderSetting } from "../../Settings/SettingEnums"; import { PurchaseAugmentationsOrderSetting } from "../../Settings/SettingEnums";
import { Settings } from "../../Settings/Settings"; import { Settings } from "../../Settings/Settings";
import { hasAugmentationPrereqs } from "../FactionHelpers";
import { StdButton } from "../../ui/React/StdButton"; import { StdButton } from "../../ui/React/StdButton";
import { use } from "../../ui/Context"; import { use } from "../../ui/Context";
@ -59,6 +60,9 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
case PurchaseAugmentationsOrderSetting.Reputation: { case PurchaseAugmentationsOrderSetting.Reputation: {
return getAugsSortedByReputation(); return getAugsSortedByReputation();
} }
case PurchaseAugmentationsOrderSetting.Purchasable: {
return getAugsSortedByPurchasable();
}
default: default:
return getAugsSortedByDefault(); return getAugsSortedByDefault();
} }
@ -79,6 +83,41 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
return augs; return augs;
} }
function getAugsSortedByPurchasable(): string[] {
const augs = getAugs();
function canBuy(augName: string): boolean {
const aug = Augmentations[augName];
const moneyCost = aug.baseCost * props.faction.getInfo().augmentationPriceMult;
const repCost = aug.baseRepRequirement * props.faction.getInfo().augmentationRepRequirementMult;
const hasReq = props.faction.playerReputation >= repCost;
const hasRep = hasAugmentationPrereqs(aug);
const hasCost =
aug.baseCost !== 0 && player.money.gt(aug.baseCost * props.faction.getInfo().augmentationPriceMult);
return hasCost && hasReq && hasRep;
}
const buy = augs.filter(canBuy).sort((augName1, augName2) => {
const aug1 = Augmentations[augName1],
aug2 = Augmentations[augName2];
if (aug1 == null || aug2 == null) {
throw new Error("Invalid Augmentation Names");
}
return aug1.baseCost - aug2.baseCost;
});
const cantBuy = augs
.filter((aug) => !canBuy(aug))
.sort((augName1, augName2) => {
const aug1 = Augmentations[augName1],
aug2 = Augmentations[augName2];
if (aug1 == null || aug2 == null) {
throw new Error("Invalid Augmentation Names");
}
return aug1.baseRepRequirement - aug2.baseRepRequirement;
});
return buy.concat(cantBuy);
}
function getAugsSortedByReputation(): string[] { function getAugsSortedByReputation(): string[] {
const augs = getAugs(); const augs = getAugs();
augs.sort((augName1, augName2) => { augs.sort((augName1, augName2) => {
@ -148,6 +187,9 @@ export function AugmentationsPage(props: IProps): React.ReactElement {
<Button onClick={() => switchSortOrder(PurchaseAugmentationsOrderSetting.Cost)}>Sort by Cost</Button> <Button onClick={() => switchSortOrder(PurchaseAugmentationsOrderSetting.Cost)}>Sort by Cost</Button>
<Button onClick={() => switchSortOrder(PurchaseAugmentationsOrderSetting.Reputation)}>Sort by Reputation</Button> <Button onClick={() => switchSortOrder(PurchaseAugmentationsOrderSetting.Reputation)}>Sort by Reputation</Button>
<Button onClick={() => switchSortOrder(PurchaseAugmentationsOrderSetting.Default)}>Sort by Default Order</Button> <Button onClick={() => switchSortOrder(PurchaseAugmentationsOrderSetting.Default)}>Sort by Default Order</Button>
<Button onClick={() => switchSortOrder(PurchaseAugmentationsOrderSetting.Purchasable)}>
Sort by Purchasable
</Button>
<br /> <br />
<Table size="small" padding="none"> <Table size="small" padding="none">

@ -55,12 +55,14 @@ function Requirements(props: IReqProps): React.ReactElement {
return ( return (
<React.Fragment key="f"> <React.Fragment key="f">
<TableCell key={1}> <TableCell key={1}>
<Typography color={color}> <Typography>
<Money money={props.cost} player={props.p} /> <Money money={props.cost} player={props.p} />
</Typography> </Typography>
</TableCell> </TableCell>
<TableCell key={2}> <TableCell key={2}>
<Typography color={color}>Requires {Reputation(props.rep)} faction reputation</Typography> <Typography color={props.hasRep ? "primary" : "error"}>
Requires {Reputation(props.rep)} faction reputation
</Typography>
</TableCell> </TableCell>
</React.Fragment> </React.Fragment>
); );
@ -78,24 +80,6 @@ export function PurchaseableAugmentation(props: IProps): React.ReactElement {
const aug = Augmentations[props.augName]; const aug = Augmentations[props.augName];
if (aug == null) throw new Error(`aug ${props.augName} does not exists`); if (aug == null) throw new Error(`aug ${props.augName} does not exists`);
function getMoneyCost(): number {
return aug.baseCost * props.faction.getInfo().augmentationPriceMult;
}
function getRepCost(): number {
return aug.baseRepRequirement * props.faction.getInfo().augmentationRepRequirementMult;
}
// Whether the player has the prerequisite Augmentations
function hasPrereqs(): boolean {
return hasAugmentationPrereqs(aug);
}
// Whether the player has enough rep for this Augmentation
function hasReputation(): boolean {
return props.faction.playerReputation >= getRepCost();
}
// Whether the player has this augmentations (purchased OR installed) // Whether the player has this augmentations (purchased OR installed)
function owned(): boolean { function owned(): boolean {
let owned = false; let owned = false;
@ -123,11 +107,11 @@ export function PurchaseableAugmentation(props: IProps): React.ReactElement {
return <></>; return <></>;
} }
const moneyCost = getMoneyCost(); const moneyCost = aug.baseCost * props.faction.getInfo().augmentationPriceMult;
const repCost = getRepCost(); const repCost = aug.baseRepRequirement * props.faction.getInfo().augmentationRepRequirementMult;
const hasReq = hasPrereqs(); const hasReq = hasAugmentationPrereqs(aug);
const hasRep = hasReputation(); const hasRep = props.faction.playerReputation >= repCost;
const hasCost = aug.baseCost !== 0 && props.p.money.gt(aug.baseCost * props.faction.getInfo().augmentationPriceMult); const hasCost = aug.baseCost === 0 || props.p.money.gt(aug.baseCost * props.faction.getInfo().augmentationPriceMult);
// Determine UI properties // Determine UI properties
const color: "error" | "primary" = !hasReq || !hasRep || !hasCost ? "error" : "primary"; const color: "error" | "primary" = !hasReq || !hasRep || !hasCost ? "error" : "primary";

@ -3,6 +3,9 @@ import { Milestones } from "../Milestones";
import { Milestone } from "../Milestone"; import { Milestone } from "../Milestone";
import * as React from "react"; import * as React from "react";
import Typography from "@mui/material/Typography";
import Box from "@mui/material/Box";
interface IProps { interface IProps {
player: IPlayer; player: IPlayer;
} }
@ -21,25 +24,25 @@ export function MilestonesRoot(props: IProps): JSX.Element {
const milestones = Milestones.map((milestone: Milestone, i: number) => { const milestones = Milestones.map((milestone: Milestone, i: number) => {
if (i <= n + 1) { if (i <= n + 1) {
return ( return (
<ul key={i}> <Typography key={i}>
<p> [{milestone.fulfilled(props.player) ? "x" : " "}] {milestone.title}
[{milestone.fulfilled(props.player) ? "x" : " "}] {milestone.title} </Typography>
</p>
</ul>
); );
} }
}); });
return ( return (
<div className="milestones-container"> <>
<h1>Milestones</h1> <Typography variant="h4">Milestones</Typography>
<p> <Box mx={2}>
Milestones don't reward you for completing them. They are here to guide you if you're lost. They will reset when <Typography>
you install Augmentations. Milestones don't reward you for completing them. They are here to guide you if you're lost. They will reset
</p> when you install Augmentations.
<br /> </Typography>
<br />
<h2>Completing fl1ght.exe</h2> <Typography>Completing fl1ght.exe</Typography>
<li>{milestones}</li> {milestones}
</div> </Box>
</>
); );
} }

@ -34,21 +34,8 @@ const BitNode8StartingMoney = 250e6;
function prestigeAugmentation() { function prestigeAugmentation() {
initBitNodeMultipliers(Player); initBitNodeMultipliers(Player);
const megaCorpFactions = [
"ECorp",
"MegaCorp",
"Bachman & Associates",
"Blade Industries",
"NWO",
"Clarke Incorporated",
"OmniTek Incorporated",
"Four Sigma",
"KuaiGong International",
"Fulcrum Secret Technologies",
];
const maintainMembership = Player.factions.filter(function (faction) { const maintainMembership = Player.factions.filter(function (faction) {
return megaCorpFactions.includes(faction); return Factions[faction].getInfo().keep;
}); });
Player.prestigeAugmentation(); Player.prestigeAugmentation();

@ -96,6 +96,7 @@ export enum PurchaseAugmentationsOrderSetting {
Cost, Cost,
Default, Default,
Reputation, Reputation,
Purchasable,
} }
/** /**

@ -1,99 +1,93 @@
import React from "react"; import React from "react";
import Typography from "@mui/material/Typography";
import Link from "@mui/material/Link";
import Box from "@mui/material/Box";
export function TutorialRoot(): React.ReactElement { export function TutorialRoot(): React.ReactElement {
return ( return (
<> <>
<h1>Tutorial (AKA Links to Documentation)</h1> <Typography variant="h4">Tutorial (AKA Links to Documentation)</Typography>
<a <Box m={2}>
id="tutorial-getting-started-link" <Link
className="a-link-button" color="primary"
target="_blank" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/guidesandtips/gettingstartedguideforbeginnerprogrammers.html" href="https://bitburner.readthedocs.io/en/latest/guidesandtips/gettingstartedguideforbeginnerprogrammers.html"
> >
Getting Started <Typography>Getting Started</Typography>
</a> </Link>
<br /> <br />
<br /> <Link
<a color="primary"
className="a-link-button" target="_blank"
target="_blank" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/servers.html"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/servers.html" >
> <Typography>Servers & Networking</Typography>
Servers & Networking </Link>
</a> <br />
<br /> <Link
<br /> color="primary"
<a target="_blank"
className="a-link-button" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/hacking.html"
target="_blank" >
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/hacking.html" <Typography>Hacking</Typography>
> </Link>
Hacking <br />
</a> <Link
<br /> color="primary"
<br /> target="_blank"
<a href="https://bitburner.readthedocs.io/en/latest/basicgameplay/scripts.html"
className="a-link-button" >
target="_blank" <Typography>Scripts</Typography>
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/scripts.html" </Link>
> <br />
Scripts <Link color="primary" target="_blank" href="https://bitburner.readthedocs.io/en/latest/netscript.html">
</a> <Typography>Netscript Programming Language</Typography>
<br /> </Link>
<br /> <br />
<a className="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/netscript.html"> <Link
Netscript Programming Language color="primary"
</a> target="_blank"
<br /> href="https://bitburner.readthedocs.io/en/latest/basicgameplay/world.html"
<br /> >
<a <Typography>Traveling</Typography>
className="a-link-button" </Link>
target="_blank" <br />
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/world.html" <Link
> color="primary"
Traveling target="_blank"
</a> href="https://bitburner.readthedocs.io/en/latest/basicgameplay/companies.html"
<br /> >
<br /> <Typography>Companies</Typography>
<a </Link>
className="a-link-button" <br />
target="_blank" <Link
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/companies.html" color="primary"
> target="_blank"
Companies href="https://bitburner.readthedocs.io/en/latest/basicgameplay/infiltration.html"
</a> >
<br /> <Typography>Infiltration</Typography>
<br /> </Link>
<a <br />
className="a-link-button" <Link
target="_blank" color="primary"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/infiltration.html" target="_blank"
> href="https://bitburner.readthedocs.io/en/latest/basicgameplay/factions.html"
Infiltration >
</a> <Typography>Factions</Typography>
<br /> </Link>
<br /> <br />
<a <Link
className="a-link-button" color="primary"
target="_blank" target="_blank"
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/factions.html" href="https://bitburner.readthedocs.io/en/latest/basicgameplay/augmentations.html"
> >
Factions <Typography>Augmentations</Typography>
</a> </Link>
<br /> <br />
<br /> <Link color="primary" target="_blank" href="https://bitburner.readthedocs.io/en/latest/shortcuts.html">
<a <Typography>Keyboard Shortcuts</Typography>
className="a-link-button" </Link>
target="_blank" </Box>
href="https://bitburner.readthedocs.io/en/latest/basicgameplay/augmentations.html"
>
Augmentations
</a>
<br />
<br />
<a className="a-link-button" target="_blank" href="https://bitburner.readthedocs.io/en/latest/shortcuts.html">
Keyboard Shortcuts
</a>
</> </>
); );
} }

@ -13,6 +13,10 @@ import { Companies } from "../Company/Companies";
import { Locations } from "../Locations/Locations"; import { Locations } from "../Locations/Locations";
import { LocationName } from "../Locations/data/LocationNames"; import { LocationName } from "../Locations/data/LocationNames";
import Typography from "@mui/material/Typography";
import Grid from "@mui/material/Grid";
import Button from "@mui/material/Button";
import { createProgressBarText } from "../../utils/helpers/createProgressBarText"; import { createProgressBarText } from "../../utils/helpers/createProgressBarText";
const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle; const CYCLES_PER_SEC = 1000 / CONSTANTS.MilliPerCycle;
@ -40,49 +44,50 @@ export function WorkInProgressRoot(): React.ReactElement {
player.stopFocusing(); player.stopFocusing();
} }
return ( return (
<div> <Grid container direction="column" justifyContent="center" alignItems="center" style={{ minHeight: "100vh" }}>
<p> <Grid item>
You are currently {player.currentWorkFactionDescription} for your faction {faction.name} <Typography>
<br /> You are currently {player.currentWorkFactionDescription} for your faction {faction.name}
(Current Faction Reputation: {Reputation(faction.playerReputation)}). <br /> <br />
You have been doing this for {convertTimeMsToTimeElapsedString(player.timeWorked)} (Current Faction Reputation: {Reputation(faction.playerReputation)}). <br />
<br /> You have been doing this for {convertTimeMsToTimeElapsedString(player.timeWorked)}
<br /> <br />
You have earned: <br /> <br />
<br /> You have earned: <br />
<Money money={player.workMoneyGained} /> (<MoneyRate money={player.workMoneyGainRate * CYCLES_PER_SEC} />){" "} <br />
<br /> <Money money={player.workMoneyGained} /> (<MoneyRate money={player.workMoneyGainRate * CYCLES_PER_SEC} />){" "}
<br /> <br />
{Reputation(player.workRepGained)} ({ReputationRate(player.workRepGainRate * CYCLES_PER_SEC)}) reputation for <br />
this faction <br /> {Reputation(player.workRepGained)} ({ReputationRate(player.workRepGainRate * CYCLES_PER_SEC)}) reputation
<br /> for this faction <br />
{numeralWrapper.formatExp(player.workHackExpGained)} ( <br />
{numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp <br /> {numeralWrapper.formatExp(player.workHackExpGained)} (
<br /> {numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp <br />
{numeralWrapper.formatExp(player.workStrExpGained)} ( <br />
{numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec) strength exp <br /> {numeralWrapper.formatExp(player.workStrExpGained)} (
{numeralWrapper.formatExp(player.workDefExpGained)} ( {numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec) strength exp <br />
{numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec) defense exp <br /> {numeralWrapper.formatExp(player.workDefExpGained)} (
{numeralWrapper.formatExp(player.workDexExpGained)} ( {numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec) defense exp <br />
{numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec) dexterity exp <br /> {numeralWrapper.formatExp(player.workDexExpGained)} (
{numeralWrapper.formatExp(player.workAgiExpGained)} ( {numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec) dexterity exp <br />
{numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec) agility exp <br /> {numeralWrapper.formatExp(player.workAgiExpGained)} (
<br /> {numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec) agility exp <br />
{numeralWrapper.formatExp(player.workChaExpGained)} ( <br />
{numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec) charisma exp <br /> {numeralWrapper.formatExp(player.workChaExpGained)} (
<br /> {numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec) charisma exp <br />
You will automatically finish after working for 20 hours. You can cancel earlier if you wish. <br />
<br /> You will automatically finish after working for 20 hours. You can cancel earlier if you wish.
There is no penalty for cancelling earlier. <br />
</p> There is no penalty for cancelling earlier.
</Typography>
<button onClick={cancel} className="work-button"> </Grid>
Stop Faction Work <Grid item>
</button> <Button sx={{ mx: 2 }} onClick={cancel}>
<button onClick={unfocus} className="work-button"> Stop Faction Work
Do something else simultaneously </Button>
</button> <Button onClick={unfocus}>Do something else simultaneously</Button>
</div> </Grid>
</Grid>
); );
} }
@ -110,35 +115,36 @@ export function WorkInProgressRoot(): React.ReactElement {
} }
return ( return (
<div> <Grid container direction="column" justifyContent="center" alignItems="center" style={{ minHeight: "100vh" }}>
<p> <Grid item>
You have been {className} for {convertTimeMsToTimeElapsedString(player.timeWorked)} <Typography>
<br /> You have been {className} for {convertTimeMsToTimeElapsedString(player.timeWorked)}
<br /> <br />
This has cost you: <br /> <br />
<Money money={-player.workMoneyGained} /> (<MoneyRate money={player.workMoneyLossRate * CYCLES_PER_SEC} />){" "} This has cost you: <br />
<br /> <Money money={-player.workMoneyGained} /> (<MoneyRate money={player.workMoneyLossRate * CYCLES_PER_SEC} />){" "}
<br /> <br />
You have gained: <br /> <br />
{numeralWrapper.formatExp(player.workHackExpGained)} ( You have gained: <br />
{numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp <br /> {numeralWrapper.formatExp(player.workHackExpGained)} (
{numeralWrapper.formatExp(player.workStrExpGained)} ( {numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec) hacking exp <br />
{numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec) strength exp <br /> {numeralWrapper.formatExp(player.workStrExpGained)} (
{numeralWrapper.formatExp(player.workDefExpGained)} ( {numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec) strength exp <br />
{numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec) defense exp <br /> {numeralWrapper.formatExp(player.workDefExpGained)} (
{numeralWrapper.formatExp(player.workDexExpGained)} ( {numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec) defense exp <br />
{numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec) dexterity exp <br /> {numeralWrapper.formatExp(player.workDexExpGained)} (
{numeralWrapper.formatExp(player.workAgiExpGained)} ( {numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec) dexterity exp <br />
{numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec) agility exp <br /> {numeralWrapper.formatExp(player.workAgiExpGained)} (
{numeralWrapper.formatExp(player.workChaExpGained)} ( {numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec) agility exp <br />
{numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec) charisma exp <br /> {numeralWrapper.formatExp(player.workChaExpGained)} (
You may cancel at any time {numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec) charisma exp <br />
</p> You may cancel at any time
</Typography>
<button onClick={cancel} className="work-button"> </Grid>
{stopText} <Grid item>
</button> <Button onClick={cancel}>{stopText}</Button>
</div> </Grid>
</Grid>
); );
} }
@ -165,54 +171,55 @@ export function WorkInProgressRoot(): React.ReactElement {
const penaltyString = penalty === 0.5 ? "half" : "three-quarters"; const penaltyString = penalty === 0.5 ? "half" : "three-quarters";
return ( return (
<div> <Grid container direction="column" justifyContent="center" alignItems="center" style={{ minHeight: "100vh" }}>
<p> <Grid item>
You are currently working as a {position} at {player.companyName} (Current Company Reputation:{" "} <Typography>
{Reputation(companyRep)})<br /> You are currently working as a {position} at {player.companyName} (Current Company Reputation:{" "}
<br /> {Reputation(companyRep)})<br />
You have been working for {convertTimeMsToTimeElapsedString(player.timeWorked)} <br />
<br /> You have been working for {convertTimeMsToTimeElapsedString(player.timeWorked)}
<br /> <br />
You have earned: <br /> <br />
<br /> You have earned: <br />
<Money money={player.workMoneyGained} /> (<MoneyRate money={player.workMoneyGainRate * CYCLES_PER_SEC} />){" "} <br />
<br /> <Money money={player.workMoneyGained} /> (<MoneyRate money={player.workMoneyGainRate * CYCLES_PER_SEC} />){" "}
<br /> <br />
{Reputation(player.workRepGained)} ({ReputationRate(player.workRepGainRate * CYCLES_PER_SEC)}) reputation for <br />
this company <br /> {Reputation(player.workRepGained)} ({ReputationRate(player.workRepGainRate * CYCLES_PER_SEC)}) reputation
<br /> for this company <br />
{numeralWrapper.formatExp(player.workHackExpGained)} ( <br />
{`${numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec`} {numeralWrapper.formatExp(player.workHackExpGained)} (
) hacking exp <br /> {`${numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec`}
<br /> ) hacking exp <br />
{numeralWrapper.formatExp(player.workStrExpGained)} ( <br />
{`${numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec`} {numeralWrapper.formatExp(player.workStrExpGained)} (
) strength exp <br /> {`${numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec`}
{numeralWrapper.formatExp(player.workDefExpGained)} ( ) strength exp <br />
{`${numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec`} {numeralWrapper.formatExp(player.workDefExpGained)} (
) defense exp <br /> {`${numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec`}
{numeralWrapper.formatExp(player.workDexExpGained)} ( ) defense exp <br />
{`${numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec`} {numeralWrapper.formatExp(player.workDexExpGained)} (
) dexterity exp <br /> {`${numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec`}
{numeralWrapper.formatExp(player.workAgiExpGained)} ( ) dexterity exp <br />
{`${numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec`} {numeralWrapper.formatExp(player.workAgiExpGained)} (
) agility exp <br /> {`${numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec`}
<br /> ) agility exp <br />
{numeralWrapper.formatExp(player.workChaExpGained)} ( <br />
{`${numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec`} {numeralWrapper.formatExp(player.workChaExpGained)} (
) charisma exp <br /> {`${numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec`}
<br /> ) charisma exp <br />
You will automatically finish after working for 8 hours. You can cancel earlier if you wish, but you will only <br />
gain {penaltyString} of the reputation you've earned so far. You will automatically finish after working for 8 hours. You can cancel earlier if you wish, but you will
</p> only gain {penaltyString} of the reputation you've earned so far.
</Typography>
<button onClick={cancel} className="work-button"> </Grid>
Stop Working <Grid item>
</button> <Button sx={{ mx: 2 }} onClick={cancel}>
<button onClick={unfocus} className="work-button"> Stop Working
Do something else simultaneously </Button>
</button> <Button onClick={unfocus}>Do something else simultaneously</Button>
</div> </Grid>
</Grid>
); );
} }
@ -234,55 +241,56 @@ export function WorkInProgressRoot(): React.ReactElement {
const position = player.jobs[player.companyName]; const position = player.jobs[player.companyName];
return ( return (
<div> <Grid container direction="column" justifyContent="center" alignItems="center" style={{ minHeight: "100vh" }}>
<p> <Grid item>
You are currently working as a {position} at {player.companyName} (Current Company Reputation:{" "} <Typography>
{Reputation(companyRep)})<br /> You are currently working as a {position} at {player.companyName} (Current Company Reputation:{" "}
<br /> {Reputation(companyRep)})<br />
You have been working for {convertTimeMsToTimeElapsedString(player.timeWorked)} <br />
<br /> You have been working for {convertTimeMsToTimeElapsedString(player.timeWorked)}
<br /> <br />
You have earned: <br /> <br />
<br /> You have earned: <br />
<Money money={player.workMoneyGained} /> (<MoneyRate money={player.workMoneyGainRate * CYCLES_PER_SEC} />){" "} <br />
<br /> <Money money={player.workMoneyGained} /> (<MoneyRate money={player.workMoneyGainRate * CYCLES_PER_SEC} />){" "}
<br /> <br />
{Reputation(player.workRepGained)} ( <br />
{Reputation(`${numeralWrapper.formatExp(player.workRepGainRate * CYCLES_PER_SEC)} / sec`)} {Reputation(player.workRepGained)} (
) reputation for this company <br /> {Reputation(`${numeralWrapper.formatExp(player.workRepGainRate * CYCLES_PER_SEC)} / sec`)}
<br /> ) reputation for this company <br />
{numeralWrapper.formatExp(player.workHackExpGained)} ( <br />
{`${numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec`} {numeralWrapper.formatExp(player.workHackExpGained)} (
) hacking exp <br /> {`${numeralWrapper.formatExp(player.workHackExpGainRate * CYCLES_PER_SEC)} / sec`}
<br /> ) hacking exp <br />
{numeralWrapper.formatExp(player.workStrExpGained)} ( <br />
{`${numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec`} {numeralWrapper.formatExp(player.workStrExpGained)} (
) strength exp <br /> {`${numeralWrapper.formatExp(player.workStrExpGainRate * CYCLES_PER_SEC)} / sec`}
{numeralWrapper.formatExp(player.workDefExpGained)} ( ) strength exp <br />
{`${numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec`} {numeralWrapper.formatExp(player.workDefExpGained)} (
) defense exp <br /> {`${numeralWrapper.formatExp(player.workDefExpGainRate * CYCLES_PER_SEC)} / sec`}
{numeralWrapper.formatExp(player.workDexExpGained)} ( ) defense exp <br />
{`${numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec`} {numeralWrapper.formatExp(player.workDexExpGained)} (
) dexterity exp <br /> {`${numeralWrapper.formatExp(player.workDexExpGainRate * CYCLES_PER_SEC)} / sec`}
{numeralWrapper.formatExp(player.workAgiExpGained)} ( ) dexterity exp <br />
{`${numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec`} {numeralWrapper.formatExp(player.workAgiExpGained)} (
) agility exp <br /> {`${numeralWrapper.formatExp(player.workAgiExpGainRate * CYCLES_PER_SEC)} / sec`}
<br /> ) agility exp <br />
{numeralWrapper.formatExp(player.workChaExpGained)} ( <br />
{`${numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec`} {numeralWrapper.formatExp(player.workChaExpGained)} (
) charisma exp <br /> {`${numeralWrapper.formatExp(player.workChaExpGainRate * CYCLES_PER_SEC)} / sec`}
<br /> ) charisma exp <br />
You will automatically finish after working for 8 hours. You can cancel earlier if you wish, and there will be <br />
no penalty because this is a part-time job. You will automatically finish after working for 8 hours. You can cancel earlier if you wish, and there will
</p> be no penalty because this is a part-time job.
</Typography>
<button onClick={cancel} className="work-button"> </Grid>
Stop Working <Grid item>
</button> <Button sx={{ mx: 2 }} onClick={cancel}>
<button onClick={unfocus} className="work-button"> Stop Working
Do something else simultaneously </Button>
</button> <Button onClick={unfocus}>Do something else simultaneously</Button>
</div> </Grid>
</Grid>
); );
} }
@ -299,51 +307,60 @@ export function WorkInProgressRoot(): React.ReactElement {
const progressBar = createProgressBarText({ progress: (numBars + 1) / 20, totalTicks: 20 }); const progressBar = createProgressBarText({ progress: (numBars + 1) / 20, totalTicks: 20 });
return ( return (
<div> <Grid container direction="column" justifyContent="center" alignItems="center" style={{ minHeight: "100vh" }}>
<p>You are attempting to {player.crimeType}.</p> <Grid item>
<br /> <Typography>
<p>You are attempting to {player.crimeType}.</p>
<br />
<p>Time remaining: {convertTimeMsToTimeElapsedString(player.timeNeededToCompleteWork - player.timeWorked)}</p> <p>
Time remaining: {convertTimeMsToTimeElapsedString(player.timeNeededToCompleteWork - player.timeWorked)}
</p>
<br /> <br />
<pre>{progressBar}</pre> <pre>{progressBar}</pre>
</Typography>
<button </Grid>
className="work-button" <Grid item>
onClick={() => { <Button
router.toLocation(Locations[LocationName.Slums]); onClick={() => {
player.finishCrime(true); router.toLocation(Locations[LocationName.Slums]);
}} player.finishCrime(true);
> }}
Cancel crime >
</button> Cancel crime
</div> </Button>
</Grid>
</Grid>
); );
} }
if (player.createProgramName !== "") { if (player.createProgramName !== "") {
return ( return (
<div> <Grid container direction="column" justifyContent="center" alignItems="center" style={{ minHeight: "100vh" }}>
<p> <Grid item>
You are currently working on coding {player.createProgramName}.<br /> <Typography>
<br /> You are currently working on coding {player.createProgramName}.<br />
You have been working for {convertTimeMsToTimeElapsedString(player.timeWorked)} <br />
<br /> You have been working for {convertTimeMsToTimeElapsedString(player.timeWorked)}
<br /> <br />
The program is {((player.timeWorkedCreateProgram / player.timeNeededToCompleteWork) * 100).toFixed(2)} <br />
% complete. <br /> The program is {((player.timeWorkedCreateProgram / player.timeNeededToCompleteWork) * 100).toFixed(2)}
If you cancel, your work will be saved and you can come back to complete the program later. % complete. <br />
</p> If you cancel, your work will be saved and you can come back to complete the program later.
<button </Typography>
className="work-button" </Grid>
onClick={() => { <Grid item>
player.finishCreateProgramWork(true); <Button
router.toTerminal(); onClick={() => {
}} player.finishCreateProgramWork(true);
> router.toTerminal();
Cancel work on creating program }}
</button> >
</div> Cancel work on creating program
</Button>
</Grid>
</Grid>
); );
} }