Merge branch 'dev' into cityFix

This commit is contained in:
Snarling
2022-09-27 16:38:39 -04:00
committed by GitHub
362 changed files with 4082 additions and 6915 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ function constructLocation(p: IConstructorParams): Location {
throw new Error(`Invalid constructor parameters for Location. No 'name' property`);
}
if (Locations[p.name] instanceof Location) {
if (Locations[p.name]) {
console.warn(`Property with name ${p.name} already exists and is being overwritten`);
}
-40
View File
@@ -1,40 +0,0 @@
/**
* Location and traveling-related helper functions.
* Mostly used for UI
*/
import { SpecialServers } from "../Server/data/SpecialServers";
import { CONSTANTS } from "../Constants";
import { IPlayer } from "../PersonObjects/IPlayer";
import { GetServer } from "../Server/AllServers";
import { dialogBoxCreate } from "../ui/React/DialogBox";
/**
* Attempt to purchase a TOR router
* @param {IPlayer} p - Player object
*/
export function purchaseTorRouter(p: IPlayer): void {
if (p.hasTorRouter()) {
dialogBoxCreate(`You already have a TOR Router!`);
return;
}
if (!p.canAfford(CONSTANTS.TorRouterCost)) {
dialogBoxCreate("You cannot afford to purchase the TOR router!");
return;
}
p.loseMoney(CONSTANTS.TorRouterCost, "other");
const darkweb = GetServer(SpecialServers.DarkWeb);
if (!darkweb) {
throw new Error("Dark web is not a server.");
}
p.getHomeComputer().serversOnNetwork.push(darkweb.hostname);
darkweb.serversOnNetwork.push(p.getHomeComputer().hostname);
dialogBoxCreate(
"You have purchased a TOR router!<br>" +
"You now have access to the dark web from your home computer.<br>" +
"Use the scan/scan-analyze commands to search for the dark web connection.",
);
}
+2 -4
View File
@@ -7,7 +7,7 @@ import { Company } from "../../Company/Company";
import { CompanyPosition } from "../../Company/CompanyPosition";
import { getJobRequirementText } from "../../Company/GetJobRequirementText";
import { use } from "../../ui/Context";
import { Player } from "../../Player";
import Button from "@mui/material/Button";
import Tooltip from "@mui/material/Tooltip";
@@ -19,10 +19,8 @@ type IProps = {
};
export function ApplyToJobButton(props: IProps): React.ReactElement {
const player = use.Player();
function getJobRequirementTooltip(): string {
const pos = player.getNextCompanyPosition(props.company, props.entryPosType);
const pos = Player.getNextCompanyPosition(props.company, props.entryPosType);
if (pos == null) {
return "";
}
+5 -10
View File
@@ -9,7 +9,6 @@ import { Blackjack, DECK_COUNT } from "../../Casino/Blackjack";
import { CoinFlip } from "../../Casino/CoinFlip";
import { Roulette } from "../../Casino/Roulette";
import { SlotMachine } from "../../Casino/SlotMachine";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { Box } from "@mui/material";
enum GameType {
@@ -20,11 +19,7 @@ enum GameType {
Blackjack = "blackjack",
}
type IProps = {
p: IPlayer;
};
export function CasinoLocation(props: IProps): React.ReactElement {
export function CasinoLocation(): React.ReactElement {
const [game, setGame] = useState(GameType.None);
function updateGame(game: GameType): void {
@@ -44,10 +39,10 @@ export function CasinoLocation(props: IProps): React.ReactElement {
{game !== GameType.None && (
<>
<Button onClick={() => updateGame(GameType.None)}>Stop playing</Button>
{game === GameType.Coin && <CoinFlip p={props.p} />}
{game === GameType.Slots && <SlotMachine p={props.p} />}
{game === GameType.Roulette && <Roulette p={props.p} />}
{game === GameType.Blackjack && <Blackjack p={props.p} />}
{game === GameType.Coin && <CoinFlip />}
{game === GameType.Slots && <SlotMachine />}
{game === GameType.Roulette && <Roulette />}
{game === GameType.Blackjack && <Blackjack />}
</>
)}
</>
+1 -1
View File
@@ -12,8 +12,8 @@ import { Locations } from "../Locations";
import { Location } from "../Location";
import { Settings } from "../../Settings/Settings";
import { Router } from "../../ui/GameRoot";
import { Player } from "../../Player";
import { Router } from "../../ui/GameRoot";
import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
import { LocationType } from "../LocationTypeEnum";
+20 -22
View File
@@ -15,13 +15,13 @@ import { Locations } from "../Locations";
import { LocationName } from "../data/LocationNames";
import { Companies } from "../../Company/Companies";
import { CompanyPosition } from "../../Company/CompanyPosition";
import { CompanyPositions } from "../../Company/CompanyPositions";
import * as posNames from "../../Company/data/companypositionnames";
import { Reputation } from "../../ui/React/Reputation";
import { Favor } from "../../ui/React/Favor";
import { use } from "../../ui/Context";
import { Router } from "../../ui/GameRoot";
import { Player } from "../../Player";
import { QuitJobModal } from "../../Company/ui/QuitJobModal";
import { CompanyWork } from "../../Work/CompanyWork";
@@ -30,8 +30,6 @@ type IProps = {
};
export function CompanyLocation(props: IProps): React.ReactElement {
const p = use.Player();
const router = use.Router();
const [quitOpen, setQuitOpen] = useState(false);
const setRerender = useState(false)[1];
function rerender(): void {
@@ -60,7 +58,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
/**
* Name of company position that player holds, if applicable
*/
const jobTitle = p.jobs[props.locName] ? p.jobs[props.locName] : null;
const jobTitle = Player.jobs[props.locName] ? Player.jobs[props.locName] : null;
/**
* CompanyPosition object for the job that the player holds at this company
@@ -68,13 +66,13 @@ export function CompanyLocation(props: IProps): React.ReactElement {
*/
const companyPosition = jobTitle ? CompanyPositions[jobTitle] : null;
p.location = props.locName;
Player.location = props.locName;
function applyForAgentJob(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) {
return;
}
p.applyForAgentJob();
Player.applyForAgentJob();
rerender();
}
@@ -82,7 +80,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
if (!e.isTrusted) {
return;
}
p.applyForBusinessConsultantJob();
Player.applyForBusinessConsultantJob();
rerender();
}
@@ -90,7 +88,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
if (!e.isTrusted) {
return;
}
p.applyForBusinessJob();
Player.applyForBusinessJob();
rerender();
}
@@ -98,7 +96,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
if (!e.isTrusted) {
return;
}
p.applyForEmployeeJob();
Player.applyForEmployeeJob();
rerender();
}
@@ -106,7 +104,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
if (!e.isTrusted) {
return;
}
p.applyForItJob();
Player.applyForItJob();
rerender();
}
@@ -114,7 +112,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
if (!e.isTrusted) {
return;
}
p.applyForPartTimeEmployeeJob();
Player.applyForPartTimeEmployeeJob();
rerender();
}
@@ -122,7 +120,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
if (!e.isTrusted) {
return;
}
p.applyForPartTimeWaiterJob();
Player.applyForPartTimeWaiterJob();
rerender();
}
@@ -130,7 +128,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
if (!e.isTrusted) {
return;
}
p.applyForSecurityJob();
Player.applyForSecurityJob();
rerender();
}
@@ -138,7 +136,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
if (!e.isTrusted) {
return;
}
p.applyForSoftwareConsultantJob();
Player.applyForSoftwareConsultantJob();
rerender();
}
@@ -146,7 +144,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
if (!e.isTrusted) {
return;
}
p.applyForSoftwareJob();
Player.applyForSoftwareJob();
rerender();
}
@@ -154,7 +152,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
if (!e.isTrusted) {
return;
}
p.applyForWaiterJob();
Player.applyForWaiterJob();
rerender();
}
@@ -166,7 +164,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
if (!loc.infiltrationData)
throw new Error(`trying to start infiltration at ${props.locName} but the infiltrationData is null`);
router.toInfiltration(loc);
Router.toInfiltration(loc);
}
function work(e: React.MouseEvent<HTMLElement>): void {
@@ -175,15 +173,15 @@ export function CompanyLocation(props: IProps): React.ReactElement {
}
const pos = companyPosition;
if (pos instanceof CompanyPosition) {
p.startWork(
if (pos) {
Player.startWork(
new CompanyWork({
singularity: false,
companyName: props.locName,
}),
);
p.startFocusing();
router.toWork();
Player.startFocusing();
Router.toWork();
}
}
+7 -8
View File
@@ -3,29 +3,28 @@ import Button from "@mui/material/Button";
import Tooltip from "@mui/material/Tooltip";
import Typography from "@mui/material/Typography";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { Player } from "../../Player";
import { Money } from "../../ui/React/Money";
import { MathJaxWrapper } from "../../MathJaxWrapper";
type IProps = {
p: IPlayer;
rerender: () => void;
};
export function CoresButton(props: IProps): React.ReactElement {
const homeComputer = props.p.getHomeComputer();
const homeComputer = Player.getHomeComputer();
const maxCores = homeComputer.cpuCores >= 8;
if (maxCores) {
return <Button>Upgrade 'home' cores - MAX</Button>;
}
const cost = props.p.getUpgradeHomeCoresCost();
const cost = Player.getUpgradeHomeCoresCost();
function buy(): void {
if (maxCores) return;
if (!props.p.canAfford(cost)) return;
props.p.loseMoney(cost, "servers");
if (!Player.canAfford(cost)) return;
Player.loseMoney(cost, "servers");
homeComputer.cpuCores++;
props.rerender();
}
@@ -38,9 +37,9 @@ export function CoresButton(props: IProps): React.ReactElement {
<i>"Cores increase the effectiveness of grow() and weaken() on 'home'"</i>
</Typography>
<br />
<Button disabled={!props.p.canAfford(cost)} onClick={buy}>
<Button disabled={!Player.canAfford(cost)} onClick={buy}>
Upgrade 'home' cores ({homeComputer.cpuCores} -&gt; {homeComputer.cpuCores + 1}) -&nbsp;
<Money money={cost} player={props.p} />
<Money money={cost} forPurchase={true} />
</Button>
</span>
</Tooltip>
+11 -13
View File
@@ -27,7 +27,7 @@ import { isBackdoorInstalled } from "../../Server/ServerHelpers";
import { GetServer } from "../../Server/AllServers";
import { CorruptableText } from "../../ui/React/CorruptableText";
import { use } from "../../ui/Context";
import { Router } from "../../ui/GameRoot";
import { serverMetadata } from "../../Server/data/servers";
import { Tooltip } from "@mui/material";
@@ -36,8 +36,6 @@ type IProps = {
};
export function GenericLocation({ loc }: IProps): React.ReactElement {
const router = use.Router();
const player = use.Player();
/**
* Determine what needs to be rendered for this location based on the locations
* type. Returns an array of React components that should be rendered
@@ -46,39 +44,39 @@ export function GenericLocation({ loc }: IProps): React.ReactElement {
const content: React.ReactNode[] = [];
if (loc.types.includes(LocationType.Company)) {
content.push(<CompanyLocation key={"companylocation"} locName={loc.name} />);
content.push(<CompanyLocation locName={loc.name} />);
}
if (loc.types.includes(LocationType.Gym)) {
content.push(<GymLocation key={"gymlocation"} router={router} loc={loc} p={player} />);
content.push(<GymLocation loc={loc} />);
}
if (loc.types.includes(LocationType.Hospital)) {
content.push(<HospitalLocation key={"hospitallocation"} p={player} />);
content.push(<HospitalLocation />);
}
if (loc.types.includes(LocationType.Slums)) {
content.push(<SlumsLocation key={"slumslocation"} />);
content.push(<SlumsLocation />);
}
if (loc.types.includes(LocationType.Special)) {
content.push(<SpecialLocation key={"speciallocation"} loc={loc} />);
content.push(<SpecialLocation loc={loc} />);
}
if (loc.types.includes(LocationType.TechVendor)) {
content.push(<TechVendorLocation key={"techvendorlocation"} loc={loc} />);
content.push(<TechVendorLocation loc={loc} />);
}
if (loc.types.includes(LocationType.TravelAgency)) {
content.push(<TravelAgencyRoot key={"travelagencylocation"} p={player} router={router} />);
content.push(<TravelAgencyRoot />);
}
if (loc.types.includes(LocationType.University)) {
content.push(<UniversityLocation key={"universitylocation"} loc={loc} />);
content.push(<UniversityLocation loc={loc} />);
}
if (loc.types.includes(LocationType.Casino)) {
content.push(<CasinoLocation key={"casinoLocation"} p={player} />);
content.push(<CasinoLocation />);
}
return content;
@@ -92,7 +90,7 @@ export function GenericLocation({ loc }: IProps): React.ReactElement {
return (
<>
<Button onClick={() => router.toCity()}>Return to World</Button>
<Button onClick={() => Router.toCity()}>Return to World</Button>
<Typography variant="h4" sx={{ mt: 1 }}>
{backdoorInstalled && !Settings.DisableTextEffects ? (
<Tooltip title={`Backdoor installed on ${loc.name}.`}>
+9 -11
View File
@@ -8,31 +8,29 @@ import Button from "@mui/material/Button";
import { Location } from "../Location";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { Player } from "../../Player";
import { Money } from "../../ui/React/Money";
import { IRouter } from "../../ui/Router";
import { Router } from "../../ui/GameRoot";
import { Box } from "@mui/material";
import { ClassWork, ClassType, Classes } from "../../Work/ClassWork";
import { calculateCost } from "../../Work/formulas/Class";
type IProps = {
loc: Location;
p: IPlayer;
router: IRouter;
};
export function GymLocation(props: IProps): React.ReactElement {
function train(stat: ClassType): void {
props.p.startWork(
Player.startWork(
new ClassWork({
classType: stat,
location: props.loc.name,
singularity: false,
}),
);
props.p.startFocusing();
props.router.toWork();
Player.startFocusing();
Router.toWork();
}
const cost = calculateCost(Classes[ClassType.GymStrength], props.loc);
@@ -40,16 +38,16 @@ export function GymLocation(props: IProps): React.ReactElement {
return (
<Box sx={{ display: "grid", width: "fit-content" }}>
<Button onClick={() => train(ClassType.GymStrength)}>
Train Strength (<Money money={cost} player={props.p} /> / sec)
Train Strength (<Money money={cost} forPurchase={true} /> / sec)
</Button>
<Button onClick={() => train(ClassType.GymDefense)}>
Train Defense (<Money money={cost} player={props.p} /> / sec)
Train Defense (<Money money={cost} forPurchase={true} /> / sec)
</Button>
<Button onClick={() => train(ClassType.GymDexterity)}>
Train Dexterity (<Money money={cost} player={props.p} /> / sec)
Train Dexterity (<Money money={cost} forPurchase={true} /> / sec)
</Button>
<Button onClick={() => train(ClassType.GymAgility)}>
Train Agility (<Money money={cost} player={props.p} /> / sec)
Train Agility (<Money money={cost} forPurchase={true} /> / sec)
</Button>
</Box>
);
+14 -20
View File
@@ -6,40 +6,34 @@
import * as React from "react";
import Button from "@mui/material/Button";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { Player } from "../../Player";
import { getHospitalizationCost } from "../../Hospital/Hospital";
import { Money } from "../../ui/React/Money";
import { dialogBoxCreate } from "../../ui/React/DialogBox";
type IProps = {
p: IPlayer;
};
type IState = {
currHp: number;
};
export class HospitalLocation extends React.Component<IProps, IState> {
//Todo: Make this a functional component
export class HospitalLocation extends React.Component<Record<string, never>, IState> {
/**
* Stores button styling that sets them all to block display
*/
btnStyle = { display: "block" };
constructor(props: IProps) {
super(props);
this.getCost = this.getCost.bind(this);
this.getHealed = this.getHealed.bind(this);
constructor() {
super({});
this.state = {
currHp: this.props.p.hp.current,
currHp: Player.hp.current,
};
}
getCost(): number {
return getHospitalizationCost(this.props.p);
return getHospitalizationCost();
}
getHealed(e: React.MouseEvent<HTMLElement>): void {
@@ -47,20 +41,20 @@ export class HospitalLocation extends React.Component<IProps, IState> {
return;
}
if (this.props.p.hp.current < 0) {
this.props.p.hp.current = 0;
if (Player.hp.current < 0) {
Player.hp.current = 0;
}
if (this.props.p.hp.current >= this.props.p.hp.max) {
if (Player.hp.current >= Player.hp.max) {
return;
}
const cost = this.getCost();
this.props.p.loseMoney(cost, "hospitalization");
this.props.p.hp.current = this.props.p.hp.max;
Player.loseMoney(cost, "hospitalization");
Player.hp.current = Player.hp.max;
// This just forces a re-render to update the cost
this.setState({
currHp: this.props.p.hp.current,
currHp: Player.hp.current,
});
dialogBoxCreate(
@@ -75,7 +69,7 @@ export class HospitalLocation extends React.Component<IProps, IState> {
return (
<Button onClick={this.getHealed} style={this.btnStyle}>
Get treatment for wounds - <Money money={cost} player={this.props.p} />
Get treatment for wounds - <Money money={cost} forPurchase={true} />
</Button>
);
}
+4 -5
View File
@@ -6,7 +6,7 @@ import { purchaseServer } from "../../Server/ServerPurchases";
import { numeralWrapper } from "../../ui/numeralFormat";
import { Money } from "../../ui/React/Money";
import { Modal } from "../../ui/React/Modal";
import { use } from "../../ui/Context";
import { Player } from "../../Player";
import Typography from "@mui/material/Typography";
import TextField from "@mui/material/TextField";
import Button from "@mui/material/Button";
@@ -21,11 +21,10 @@ interface IProps {
}
export function PurchaseServerModal(props: IProps): React.ReactElement {
const player = use.Player();
const [hostname, setHostname] = useState("");
function tryToPurchaseServer(): void {
purchaseServer(hostname, props.ram, props.cost, player);
purchaseServer(hostname, props.ram, props.cost);
props.onClose();
}
@@ -41,7 +40,7 @@ export function PurchaseServerModal(props: IProps): React.ReactElement {
<Modal open={props.open} onClose={props.onClose}>
<Typography>
Would you like to purchase a new server with {numeralWrapper.formatRAM(props.ram)} of RAM for{" "}
<Money money={props.cost} player={player} />?
<Money money={props.cost} forPurchase={true} />?
</Typography>
<br />
<br />
@@ -56,7 +55,7 @@ export function PurchaseServerModal(props: IProps): React.ReactElement {
placeholder="Unique Hostname"
InputProps={{
endAdornment: (
<Button onClick={tryToPurchaseServer} disabled={!player.canAfford(props.cost) || hostname === ""}>
<Button onClick={tryToPurchaseServer} disabled={!Player.canAfford(props.cost) || hostname === ""}>
Buy
</Button>
),
+6 -7
View File
@@ -4,7 +4,7 @@ import Tooltip from "@mui/material/Tooltip";
import Typography from "@mui/material/Typography";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { Player } from "../../Player";
import { purchaseRamForHomeComputer } from "../../Server/ServerPurchases";
import { Money } from "../../ui/React/Money";
@@ -14,20 +14,19 @@ import { MathJaxWrapper } from "../../MathJaxWrapper";
import { BitNodeMultipliers } from "../../BitNode/BitNodeMultipliers";
type IProps = {
p: IPlayer;
rerender: () => void;
};
export function RamButton(props: IProps): React.ReactElement {
const homeComputer = props.p.getHomeComputer();
const homeComputer = Player.getHomeComputer();
if (homeComputer.maxRam >= CONSTANTS.HomeComputerMaxRam) {
return <Button>Upgrade 'home' RAM - MAX</Button>;
}
const cost = props.p.getUpgradeHomeRamCost();
const cost = Player.getUpgradeHomeRamCost();
function buy(): void {
purchaseRamForHomeComputer(props.p);
purchaseRamForHomeComputer();
props.rerender();
}
@@ -45,10 +44,10 @@ export function RamButton(props: IProps): React.ReactElement {
<i>"More RAM means more scripts on 'home'"</i>
</Typography>
<br />
<Button disabled={!props.p.canAfford(cost)} onClick={buy}>
<Button disabled={!Player.canAfford(cost)} onClick={buy}>
Upgrade 'home' RAM ({numeralWrapper.formatRAM(homeComputer.maxRam)} -&gt;&nbsp;
{numeralWrapper.formatRAM(homeComputer.maxRam * 2)}) -&nbsp;
<Money money={cost} player={props.p} />
<Money money={cost} forPurchase={true} />
</Button>
</span>
</Tooltip>
+50 -51
View File
@@ -10,132 +10,131 @@ import Tooltip from "@mui/material/Tooltip";
import { Crimes } from "../../Crime/Crimes";
import { numeralWrapper } from "../../ui/numeralFormat";
import { use } from "../../ui/Context";
import { Router } from "../../ui/GameRoot";
import { Player } from "../../Player";
import { Box } from "@mui/material";
export function SlumsLocation(): React.ReactElement {
const player = use.Player();
const router = use.Router();
function shoplift(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) {
return;
}
Crimes.Shoplift.commit(player);
router.toWork();
player.focus = true;
Crimes.Shoplift.commit();
Router.toWork();
Player.focus = true;
}
function robStore(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) {
return;
}
Crimes.RobStore.commit(player);
router.toWork();
player.focus = true;
Crimes.RobStore.commit();
Router.toWork();
Player.focus = true;
}
function mug(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) {
return;
}
Crimes.Mug.commit(player);
router.toWork();
player.focus = true;
Crimes.Mug.commit();
Router.toWork();
Player.focus = true;
}
function larceny(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) {
return;
}
Crimes.Larceny.commit(player);
router.toWork();
player.focus = true;
Crimes.Larceny.commit();
Router.toWork();
Player.focus = true;
}
function dealDrugs(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) {
return;
}
Crimes.DealDrugs.commit(player);
router.toWork();
player.focus = true;
Crimes.DealDrugs.commit();
Router.toWork();
Player.focus = true;
}
function bondForgery(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) {
return;
}
Crimes.BondForgery.commit(player);
router.toWork();
player.focus = true;
Crimes.BondForgery.commit();
Router.toWork();
Player.focus = true;
}
function traffickArms(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) {
return;
}
Crimes.TraffickArms.commit(player);
router.toWork();
player.focus = true;
Crimes.TraffickArms.commit();
Router.toWork();
Player.focus = true;
}
function homicide(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) {
return;
}
Crimes.Homicide.commit(player);
router.toWork();
player.focus = true;
Crimes.Homicide.commit();
Router.toWork();
Player.focus = true;
}
function grandTheftAuto(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) {
return;
}
Crimes.GrandTheftAuto.commit(player);
router.toWork();
player.focus = true;
Crimes.GrandTheftAuto.commit();
Router.toWork();
Player.focus = true;
}
function kidnap(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) {
return;
}
Crimes.Kidnap.commit(player);
router.toWork();
player.focus = true;
Crimes.Kidnap.commit();
Router.toWork();
Player.focus = true;
}
function assassinate(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) {
return;
}
Crimes.Assassination.commit(player);
router.toWork();
player.focus = true;
Crimes.Assassination.commit();
Router.toWork();
Player.focus = true;
}
function heist(e: React.MouseEvent<HTMLElement>): void {
if (!e.isTrusted) {
return;
}
Crimes.Heist.commit(player);
router.toWork();
player.focus = true;
Crimes.Heist.commit();
Router.toWork();
Player.focus = true;
}
const shopliftChance = Crimes.Shoplift.successRate(player);
const robStoreChance = Crimes.RobStore.successRate(player);
const mugChance = Crimes.Mug.successRate(player);
const larcenyChance = Crimes.Larceny.successRate(player);
const drugsChance = Crimes.DealDrugs.successRate(player);
const bondChance = Crimes.BondForgery.successRate(player);
const armsChance = Crimes.TraffickArms.successRate(player);
const homicideChance = Crimes.Homicide.successRate(player);
const gtaChance = Crimes.GrandTheftAuto.successRate(player);
const kidnapChance = Crimes.Kidnap.successRate(player);
const assassinateChance = Crimes.Assassination.successRate(player);
const heistChance = Crimes.Heist.successRate(player);
const shopliftChance = Crimes.Shoplift.successRate(Player);
const robStoreChance = Crimes.RobStore.successRate(Player);
const mugChance = Crimes.Mug.successRate(Player);
const larcenyChance = Crimes.Larceny.successRate(Player);
const drugsChance = Crimes.DealDrugs.successRate(Player);
const bondChance = Crimes.BondForgery.successRate(Player);
const armsChance = Crimes.TraffickArms.successRate(Player);
const homicideChance = Crimes.Homicide.successRate(Player);
const gtaChance = Crimes.GrandTheftAuto.successRate(Player);
const kidnapChance = Crimes.Kidnap.successRate(Player);
const assassinateChance = Crimes.Assassination.successRate(Player);
const heistChance = Crimes.Heist.successRate(Player);
return (
<Box sx={{ display: "grid", width: "fit-content" }}>
+42 -44
View File
@@ -21,7 +21,8 @@ import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Factions } from "../../Faction/Factions";
import { joinFaction } from "../../Faction/FactionHelpers";
import { use } from "../../ui/Context";
import { Router } from "../../ui/GameRoot";
import { Player } from "../../Player";
import { dialogBoxCreate } from "../../ui/React/DialogBox";
import { SnackbarEvents, ToastVariant } from "../../ui/React/Snackbar";
@@ -41,27 +42,24 @@ type IProps = {
};
export function SpecialLocation(props: IProps): React.ReactElement {
const player = use.Player();
const router = use.Router();
const setRerender = useState(false)[1];
const inBladeburner = player.inBladeburner();
const inBladeburner = Player.inBladeburner();
/**
* Click handler for Bladeburner button at Sector-12 NSA
*/
function handleBladeburner(): void {
const p = player;
if (p.inBladeburner()) {
if (Player.inBladeburner()) {
// Enter Bladeburner division
router.toBladeburner();
Router.toBladeburner();
} else if (
p.skills.strength >= 100 &&
p.skills.defense >= 100 &&
p.skills.dexterity >= 100 &&
p.skills.agility >= 100
Player.skills.strength >= 100 &&
Player.skills.defense >= 100 &&
Player.skills.dexterity >= 100 &&
Player.skills.agility >= 100
) {
// Apply for Bladeburner division
p.startBladeburner();
Player.startBladeburner();
dialogBoxCreate("You have been accepted into the Bladeburner division!");
setRerender((old) => !old);
@@ -79,11 +77,11 @@ export function SpecialLocation(props: IProps): React.ReactElement {
* Click handler for Resleeving button at New Tokyo VitaLife
*/
function handleGrafting(): void {
router.toGrafting();
Router.toGrafting();
}
function renderBladeburner(): React.ReactElement {
if (!player.canAccessBladeburner() || BitNodeMultipliers.BladeburnerRank === 0) {
if (!Player.canAccessBladeburner() || BitNodeMultipliers.BladeburnerRank === 0) {
return <></>;
}
const text = inBladeburner ? "Enter Bladeburner Headquarters" : "Apply to Bladeburner Division";
@@ -99,32 +97,32 @@ export function SpecialLocation(props: IProps): React.ReactElement {
function EatNoodles(): void {
SnackbarEvents.emit("You ate some delicious noodles and feel refreshed", ToastVariant.SUCCESS, 2000);
N00dles(); // This is the true power of the noodles.
if (player.sourceFiles.length > 0) player.giveExploit(Exploit.N00dles);
if (player.sourceFileLvl(5) > 0 || player.bitNodeN === 5) {
player.exp.intelligence *= 1.0000000000000002;
if (Player.sourceFiles.length > 0) Player.giveExploit(Exploit.N00dles);
if (Player.sourceFileLvl(5) > 0 || Player.bitNodeN === 5) {
Player.exp.intelligence *= 1.0000000000000002;
}
player.exp.hacking *= 1.0000000000000002;
player.exp.strength *= 1.0000000000000002;
player.exp.defense *= 1.0000000000000002;
player.exp.agility *= 1.0000000000000002;
player.exp.dexterity *= 1.0000000000000002;
player.exp.charisma *= 1.0000000000000002;
for (const node of player.hacknetNodes) {
Player.exp.hacking *= 1.0000000000000002;
Player.exp.strength *= 1.0000000000000002;
Player.exp.defense *= 1.0000000000000002;
Player.exp.agility *= 1.0000000000000002;
Player.exp.dexterity *= 1.0000000000000002;
Player.exp.charisma *= 1.0000000000000002;
for (const node of Player.hacknetNodes) {
if (node instanceof HacknetNode) {
player.gainMoney(node.moneyGainRatePerSecond * 0.001, "other");
Player.gainMoney(node.moneyGainRatePerSecond * 0.001, "other");
} else {
const server = GetServer(node);
if (!(server instanceof HacknetServer)) throw new Error(`Server ${node} is not a hacknet server.`);
player.hashManager.storeHashes(server.hashRate * 0.001);
Player.hashManager.storeHashes(server.hashRate * 0.001);
}
}
if (player.bladeburner) {
player.bladeburner.rank += 0.00001;
if (Player.bladeburner) {
Player.bladeburner.rank += 0.00001;
}
if (player.corporation) {
player.corporation.funds += player.corporation.revenue * 0.01;
if (Player.corporation) {
Player.corporation.funds += Player.corporation.revenue * 0.01;
}
}
@@ -138,7 +136,7 @@ export function SpecialLocation(props: IProps): React.ReactElement {
function CreateCorporation(): React.ReactElement {
const [open, setOpen] = useState(false);
if (!player.canAccessCorporation()) {
if (!Player.canAccessCorporation()) {
return (
<>
<Typography>
@@ -149,7 +147,7 @@ export function SpecialLocation(props: IProps): React.ReactElement {
}
return (
<>
<Button disabled={!player.canAccessCorporation() || player.hasCorporation()} onClick={() => setOpen(true)}>
<Button disabled={!Player.canAccessCorporation() || Player.hasCorporation()} onClick={() => setOpen(true)}>
Create a Corporation
</Button>
<CreateCorporationModal open={open} onClose={() => setOpen(false)} />
@@ -158,7 +156,7 @@ export function SpecialLocation(props: IProps): React.ReactElement {
}
function renderGrafting(): React.ReactElement {
if (!player.canAccessGrafting()) {
if (!Player.canAccessGrafting()) {
return <></>;
}
return (
@@ -170,21 +168,21 @@ export function SpecialLocation(props: IProps): React.ReactElement {
function handleCotMG(): void {
const faction = Factions[FactionNames.ChurchOfTheMachineGod];
if (!player.factions.includes(FactionNames.ChurchOfTheMachineGod)) {
if (!Player.factions.includes(FactionNames.ChurchOfTheMachineGod)) {
joinFaction(faction);
}
if (
!player.augmentations.some((a) => a.name === AugmentationNames.StaneksGift1) &&
!player.queuedAugmentations.some((a) => a.name === AugmentationNames.StaneksGift1)
!Player.augmentations.some((a) => a.name === AugmentationNames.StaneksGift1) &&
!Player.queuedAugmentations.some((a) => a.name === AugmentationNames.StaneksGift1)
) {
applyAugmentation({ name: AugmentationNames.StaneksGift1, level: 1 });
}
router.toStaneksGift();
Router.toStaneksGift();
}
function renderCotMG(): React.ReactElement {
const toStanek = <Button onClick={() => router.toStaneksGift()}>Open Stanek's Gift</Button>;
const toStanek = <Button onClick={() => Router.toStaneksGift()}>Open Stanek's Gift</Button>;
// prettier-ignore
const symbol = <Typography sx={{ lineHeight: '1em', whiteSpace: 'pre' }}>
{" `` "}<br />
@@ -215,7 +213,7 @@ export function SpecialLocation(props: IProps): React.ReactElement {
{" sNNo-.`.-omNy` "}<br />
{" -smNNNNmdo- "}<br />
{" `..` "}</Typography>
if (player.hasAugmentation(AugmentationNames.StaneksGift3, true)) {
if (Player.hasAugmentation(AugmentationNames.StaneksGift3, true)) {
return (
<>
<Typography>
@@ -232,7 +230,7 @@ export function SpecialLocation(props: IProps): React.ReactElement {
</>
);
}
if (player.hasAugmentation(AugmentationNames.StaneksGift2, true)) {
if (Player.hasAugmentation(AugmentationNames.StaneksGift2, true)) {
return (
<>
<Typography>
@@ -249,7 +247,7 @@ export function SpecialLocation(props: IProps): React.ReactElement {
</>
);
}
if (player.factions.includes(FactionNames.ChurchOfTheMachineGod)) {
if (Player.factions.includes(FactionNames.ChurchOfTheMachineGod)) {
return (
<>
<Typography>
@@ -263,7 +261,7 @@ export function SpecialLocation(props: IProps): React.ReactElement {
);
}
if (!player.canAccessCotMG()) {
if (!Player.canAccessCotMG()) {
return (
<>
<Typography>
@@ -278,8 +276,8 @@ export function SpecialLocation(props: IProps): React.ReactElement {
}
if (
player.augmentations.filter((a) => a.name !== AugmentationNames.NeuroFluxGovernor).length > 0 ||
player.queuedAugmentations.filter((a) => a.name !== AugmentationNames.NeuroFluxGovernor).length > 0
Player.augmentations.filter((a) => a.name !== AugmentationNames.NeuroFluxGovernor).length > 0 ||
Player.queuedAugmentations.filter((a) => a.name !== AugmentationNames.NeuroFluxGovernor).length > 0
) {
return (
<>
+6 -8
View File
@@ -15,7 +15,7 @@ import { CoresButton } from "./CoresButton";
import { getPurchaseServerCost } from "../../Server/ServerPurchases";
import { Money } from "../../ui/React/Money";
import { use } from "../../ui/Context";
import { Player } from "../../Player";
import { PurchaseServerModal } from "./PurchaseServerModal";
import { numeralWrapper } from "../../ui/numeralFormat";
import { Box } from "@mui/material";
@@ -27,13 +27,12 @@ interface IServerProps {
function ServerButton(props: IServerProps): React.ReactElement {
const [open, setOpen] = useState(false);
const player = use.Player();
const cost = getPurchaseServerCost(props.ram);
return (
<>
<Button onClick={() => setOpen(true)} disabled={!player.canAfford(cost)}>
<Button onClick={() => setOpen(true)} disabled={!Player.canAfford(cost)}>
Purchase {numeralWrapper.formatRAM(props.ram)} Server&nbsp;-&nbsp;
<Money money={cost} player={player} />
<Money money={cost} forPurchase={true} />
</Button>
<PurchaseServerModal
open={open}
@@ -51,7 +50,6 @@ type IProps = {
};
export function TechVendorLocation(props: IProps): React.ReactElement {
const player = use.Player();
const setRerender = useState(false)[1];
function rerender(): void {
setRerender((old) => !old);
@@ -76,11 +74,11 @@ export function TechVendorLocation(props: IProps): React.ReactElement {
<i>"You can order bigger servers via scripts. We don't take custom orders in person."</i>
</Typography>
<br />
<TorButton p={player} rerender={rerender} />
<TorButton rerender={rerender} />
<br />
<RamButton p={player} rerender={rerender} />
<RamButton rerender={rerender} />
<br />
<CoresButton p={player} rerender={rerender} />
<CoresButton rerender={rerender} />
</>
);
}
+36 -7
View File
@@ -1,32 +1,61 @@
import React from "react";
import Button from "@mui/material/Button";
import { purchaseTorRouter } from "../LocationsHelpers";
import { dialogBoxCreate } from "../../ui/React/DialogBox";
import { GetServer } from "../../Server/AllServers";
import { SpecialServers } from "../../Server/data/SpecialServers";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { Player } from "../../Player";
import { Money } from "../../ui/React/Money";
/**
* Attempt to purchase a TOR router using the button.
*/
export function purchaseTorRouter(): void {
if (Player.hasTorRouter()) {
dialogBoxCreate(`You already have a TOR Router!`);
return;
}
if (!Player.canAfford(CONSTANTS.TorRouterCost)) {
dialogBoxCreate("You cannot afford to purchase the TOR router!");
return;
}
Player.loseMoney(CONSTANTS.TorRouterCost, "other");
const darkweb = GetServer(SpecialServers.DarkWeb);
if (!darkweb) {
throw new Error("Dark web is not a server.");
}
Player.getHomeComputer().serversOnNetwork.push(darkweb.hostname);
darkweb.serversOnNetwork.push(Player.getHomeComputer().hostname);
dialogBoxCreate(
"You have purchased a TOR router!\n" +
"You now have access to the dark web from your home computer.\n" +
"Use the scan/scan-analyze commands to search for the dark web connection.",
);
}
type IProps = {
p: IPlayer;
rerender: () => void;
};
export function TorButton(props: IProps): React.ReactElement {
function buy(): void {
purchaseTorRouter(props.p);
purchaseTorRouter();
props.rerender();
}
if (props.p.hasTorRouter()) {
if (Player.hasTorRouter()) {
return <Button>TOR Router - Purchased</Button>;
}
return (
<Button disabled={!props.p.canAfford(CONSTANTS.TorRouterCost)} onClick={buy}>
<Button disabled={!Player.canAfford(CONSTANTS.TorRouterCost)} onClick={buy}>
Purchase TOR router -&nbsp;
<Money money={CONSTANTS.TorRouterCost} player={props.p} />
<Money money={CONSTANTS.TorRouterCost} forPurchase={true} />
</Button>
);
}
+15 -23
View File
@@ -9,11 +9,10 @@ import { CityName } from "../data/CityNames";
import { TravelConfirmationModal } from "./TravelConfirmationModal";
import { CONSTANTS } from "../../Constants";
import { IPlayer } from "../../PersonObjects/IPlayer";
import { IRouter } from "../../ui/Router";
import { Player } from "../../Player";
import { Router } from "../../ui/GameRoot";
import { Settings } from "../../Settings/Settings";
import { use } from "../../ui/Context";
import { Money } from "../../ui/React/Money";
import { WorldMap } from "../../ui/React/WorldMap";
import { dialogBoxCreate } from "../../ui/React/DialogBox";
@@ -22,26 +21,19 @@ import Typography from "@mui/material/Typography";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
type IProps = {
p: IPlayer;
router: IRouter;
};
function travel(p: IPlayer, router: IRouter, to: CityName): void {
function travel(to: CityName): void {
const cost = CONSTANTS.TravelCost;
if (!p.canAfford(cost)) {
if (!Player.canAfford(cost)) {
return;
}
p.loseMoney(cost, "other");
p.travel(to);
dialogBoxCreate(<>You are now in {to}!</>);
router.toCity();
Player.loseMoney(cost, "other");
Player.travel(to);
dialogBoxCreate(`You are now in ${to}!`);
Router.toCity();
}
export function TravelAgencyRoot(props: IProps): React.ReactElement {
const player = use.Player();
const router = use.Router();
export function TravelAgencyRoot(): React.ReactElement {
const setRerender = useState(false)[1];
const [open, setOpen] = useState(false);
const [destination, setDestination] = useState(CityName.Sector12);
@@ -56,11 +48,11 @@ export function TravelAgencyRoot(props: IProps): React.ReactElement {
function startTravel(city: CityName): void {
const cost = CONSTANTS.TravelCost;
if (!player.canAfford(cost)) {
if (!Player.canAfford(cost)) {
return;
}
if (Settings.SuppressTravelConfirmation) {
travel(player, router, city);
travel(city);
return;
}
setOpen(true);
@@ -73,12 +65,12 @@ export function TravelAgencyRoot(props: IProps): React.ReactElement {
<Box mx={2}>
<Typography>
From here, you can travel to any other city! A ticket costs{" "}
<Money money={CONSTANTS.TravelCost} player={props.p} />.
<Money money={CONSTANTS.TravelCost} forPurchase={true} />.
</Typography>
{Settings.DisableASCIIArt ? (
<>
{Object.values(CityName)
.filter((city: string) => city != props.p.city)
.filter((city: string) => city != Player.city)
.map((city: string) => {
const match = Object.entries(CityName).find((entry) => entry[1] === city);
if (match === undefined) throw new Error(`could not find key for city '${city}'`);
@@ -93,12 +85,12 @@ export function TravelAgencyRoot(props: IProps): React.ReactElement {
})}
</>
) : (
<WorldMap currentCity={props.p.city} onTravel={(city: CityName) => startTravel(city)} />
<WorldMap currentCity={Player.city} onTravel={(city: CityName) => startTravel(city)} />
)}
</Box>
<TravelConfirmationModal
city={destination}
travel={() => travel(player, router, destination)}
travel={() => travel(destination)}
open={open}
onClose={() => setOpen(false)}
/>
+1 -3
View File
@@ -2,7 +2,6 @@ import React from "react";
import { CONSTANTS } from "../../Constants";
import { Money } from "../../ui/React/Money";
import { Modal } from "../../ui/React/Modal";
import { use } from "../../ui/Context";
import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
@@ -15,7 +14,6 @@ interface IProps {
}
export function TravelConfirmationModal(props: IProps): React.ReactElement {
const player = use.Player();
const cost = CONSTANTS.TravelCost;
function travel(): void {
props.travel();
@@ -24,7 +22,7 @@ export function TravelConfirmationModal(props: IProps): React.ReactElement {
return (
<Modal open={props.open} onClose={props.onClose}>
<Typography>
Would you like to travel to {props.city}? The trip will cost <Money money={cost} player={player} />.
Would you like to travel to {props.city}? The trip will cost <Money money={cost} forPurchase={true} />.
</Typography>
<br />
<br />
+10 -12
View File
@@ -10,7 +10,8 @@ import Button from "@mui/material/Button";
import { Location } from "../Location";
import { Money } from "../../ui/React/Money";
import { use } from "../../ui/Context";
import { Router } from "../../ui/GameRoot";
import { Player } from "../../Player";
import { Box } from "@mui/material";
import { ClassWork, ClassType, Classes } from "../../Work/ClassWork";
@@ -21,19 +22,16 @@ type IProps = {
};
export function UniversityLocation(props: IProps): React.ReactElement {
const player = use.Player();
const router = use.Router();
function take(classType: ClassType): void {
player.startWork(
Player.startWork(
new ClassWork({
classType: classType,
location: props.loc.name,
singularity: false,
}),
);
player.startFocusing();
router.toWork();
Player.startFocusing();
Router.toWork();
}
const dataStructuresCost = calculateCost(Classes[ClassType.DataStructures], props.loc);
@@ -53,31 +51,31 @@ export function UniversityLocation(props: IProps): React.ReactElement {
<Tooltip title={earnHackingExpTooltip}>
<Button onClick={() => take(ClassType.DataStructures)}>
Take Data Structures course (
<Money money={dataStructuresCost} player={player} /> / sec)
<Money money={dataStructuresCost} forPurchase={true} /> / sec)
</Button>
</Tooltip>
<Tooltip title={earnHackingExpTooltip}>
<Button onClick={() => take(ClassType.Networks)}>
Take Networks course (
<Money money={networksCost} player={player} /> / sec)
<Money money={networksCost} forPurchase={true} /> / sec)
</Button>
</Tooltip>
<Tooltip title={earnHackingExpTooltip}>
<Button onClick={() => take(ClassType.Algorithms)}>
Take Algorithms course (
<Money money={algorithmsCost} player={player} /> / sec)
<Money money={algorithmsCost} forPurchase={true} /> / sec)
</Button>
</Tooltip>
<Tooltip title={earnCharismaExpTooltip}>
<Button onClick={() => take(ClassType.Management)}>
Take Management course (
<Money money={managementCost} player={player} /> / sec)
<Money money={managementCost} forPurchase={true} /> / sec)
</Button>
</Tooltip>
<Tooltip title={earnCharismaExpTooltip}>
<Button onClick={() => take(ClassType.Leadership)}>
Take Leadership course (
<Money money={leadershipCost} player={player} /> / sec)
<Money money={leadershipCost} forPurchase={true} /> / sec)
</Button>
</Tooltip>
</Box>