mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-17 14:59:16 +02:00
pre-dialogbox-convert
This commit is contained in:
@@ -148,6 +148,7 @@
|
|||||||
"format": "prettier --write .",
|
"format": "prettier --write .",
|
||||||
"start": "http-server -p 8000",
|
"start": "http-server -p 8000",
|
||||||
"start:dev": "webpack-dev-server --progress --env.devServer --mode development",
|
"start:dev": "webpack-dev-server --progress --env.devServer --mode development",
|
||||||
|
"start:dev-fast": "webpack-dev-server --progress --env.devServer --mode development --fast true",
|
||||||
"start:container": "webpack-dev-server --progress --env.devServer --mode development --env.runInContainer",
|
"start:container": "webpack-dev-server --progress --env.devServer --mode development --env.runInContainer",
|
||||||
"build": "webpack --mode production",
|
"build": "webpack --mode production",
|
||||||
"build:dev": "webpack --mode development",
|
"build:dev": "webpack --mode development",
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ import { Deck } from "./CardDeck/Deck";
|
|||||||
import { Hand } from "./CardDeck/Hand";
|
import { Hand } from "./CardDeck/Hand";
|
||||||
import { InputAdornment } from "@mui/material";
|
import { InputAdornment } from "@mui/material";
|
||||||
import { ReactCard } from "./CardDeck/ReactCard";
|
import { ReactCard } from "./CardDeck/ReactCard";
|
||||||
import { MuiTextField } from "../ui/React/MuiTextField";
|
import Button from "@mui/material/Button";
|
||||||
import { MuiButton } from "../ui/React/MuiButton";
|
import Paper from "@mui/material/Paper";
|
||||||
import { MuiPaper } from "../ui/React/MuiPaper";
|
import Box from "@mui/material/Box";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import TextField from "@mui/material/TextField";
|
||||||
|
|
||||||
const MAX_BET = 100e6;
|
const MAX_BET = 100e6;
|
||||||
|
|
||||||
@@ -308,7 +310,7 @@ export class Blackjack extends Game<Props, State> {
|
|||||||
<div>
|
<div>
|
||||||
{/* Wager input */}
|
{/* Wager input */}
|
||||||
<div>
|
<div>
|
||||||
<MuiTextField
|
<TextField
|
||||||
value={betInput}
|
value={betInput}
|
||||||
label={
|
label={
|
||||||
<>
|
<>
|
||||||
@@ -322,12 +324,15 @@ export class Blackjack extends Game<Props, State> {
|
|||||||
error={wagerInvalid}
|
error={wagerInvalid}
|
||||||
helperText={wagerInvalid ? wagerInvalidHelperText : ""}
|
helperText={wagerInvalid ? wagerInvalidHelperText : ""}
|
||||||
type="number"
|
type="number"
|
||||||
variant="filled"
|
|
||||||
style={{
|
style={{
|
||||||
width: "200px",
|
width: "200px",
|
||||||
}}
|
}}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
startAdornment: <InputAdornment position="start">$</InputAdornment>,
|
startAdornment: (
|
||||||
|
<InputAdornment position="start">
|
||||||
|
<Typography>$</Typography>
|
||||||
|
</InputAdornment>
|
||||||
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@@ -340,16 +345,16 @@ export class Blackjack extends Game<Props, State> {
|
|||||||
{/* Buttons */}
|
{/* Buttons */}
|
||||||
{!gameInProgress ? (
|
{!gameInProgress ? (
|
||||||
<div>
|
<div>
|
||||||
<MuiButton onClick={this.startOnClick} disabled={wagerInvalid || !this.canStartGame()}>
|
<Button onClick={this.startOnClick} disabled={wagerInvalid || !this.canStartGame()}>
|
||||||
Start
|
Start
|
||||||
</MuiButton>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
<MuiButton onClick={this.playerHit}>Hit</MuiButton>
|
<Button onClick={this.playerHit}>Hit</Button>
|
||||||
<MuiButton color="secondary" onClick={this.playerStay}>
|
<Button color="secondary" onClick={this.playerStay}>
|
||||||
Stay
|
Stay
|
||||||
</MuiButton>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -357,36 +362,40 @@ export class Blackjack extends Game<Props, State> {
|
|||||||
* the cards that led to that result. */}
|
* the cards that led to that result. */}
|
||||||
{(gameInProgress || result !== Result.Pending) && (
|
{(gameInProgress || result !== Result.Pending) && (
|
||||||
<div>
|
<div>
|
||||||
<MuiPaper variant="outlined" elevation={2}>
|
<Box display="flex">
|
||||||
<pre>Player</pre>
|
<Paper elevation={2}>
|
||||||
{playerHand.cards.map((card, i) => (
|
<pre>Player</pre>
|
||||||
<ReactCard card={card} key={i} />
|
{playerHand.cards.map((card, i) => (
|
||||||
))}
|
<ReactCard card={card} key={i} />
|
||||||
|
))}
|
||||||
|
|
||||||
<pre>Value(s): </pre>
|
<pre>Value(s): </pre>
|
||||||
{playerHandValues.map((value, i) => (
|
{playerHandValues.map((value, i) => (
|
||||||
<pre key={i}>{value}</pre>
|
<pre key={i}>{value}</pre>
|
||||||
))}
|
))}
|
||||||
</MuiPaper>
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<MuiPaper variant="outlined" elevation={2}>
|
<Box display="flex">
|
||||||
<pre>Dealer</pre>
|
<Paper elevation={2}>
|
||||||
{dealerHand.cards.map((card, i) => (
|
<pre>Dealer</pre>
|
||||||
// Hide every card except the first while game is in progress
|
{dealerHand.cards.map((card, i) => (
|
||||||
<ReactCard card={card} hidden={gameInProgress && i !== 0} key={i} />
|
// Hide every card except the first while game is in progress
|
||||||
))}
|
<ReactCard card={card} hidden={gameInProgress && i !== 0} key={i} />
|
||||||
|
))}
|
||||||
|
|
||||||
{!gameInProgress && (
|
{!gameInProgress && (
|
||||||
<>
|
<>
|
||||||
<pre>Value(s): </pre>
|
<pre>Value(s): </pre>
|
||||||
{dealerHandValues.map((value, i) => (
|
{dealerHandValues.map((value, i) => (
|
||||||
<pre key={i}>{value}</pre>
|
<pre key={i}>{value}</pre>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</MuiPaper>
|
</Paper>
|
||||||
|
</Box>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,43 @@
|
|||||||
import React, { FC } from "react";
|
import React, { FC } from "react";
|
||||||
import { Card, Suit } from "./Card";
|
import { Card, Suit } from "./Card";
|
||||||
|
import { Theme } from "@mui/material";
|
||||||
|
import makeStyles from "@mui/styles/makeStyles";
|
||||||
|
import createStyles from "@mui/styles/createStyles";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
card: Card;
|
card: Card;
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const useStyles = makeStyles(() =>
|
||||||
|
createStyles({
|
||||||
|
card: {
|
||||||
|
padding: "10px",
|
||||||
|
border: "solid 1px #808080",
|
||||||
|
backgroundColor: "white",
|
||||||
|
display: "inline-block",
|
||||||
|
borderRadius: "10px",
|
||||||
|
fontSize: "18.5px",
|
||||||
|
textAlign: "center",
|
||||||
|
margin: "3px",
|
||||||
|
fontWeight: "bold",
|
||||||
|
},
|
||||||
|
red: {
|
||||||
|
color: "red",
|
||||||
|
},
|
||||||
|
|
||||||
|
black: {
|
||||||
|
color: "black",
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
fontSize: "20px",
|
||||||
|
fontFamily: "sans-serif",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
export const ReactCard: FC<Props> = ({ card, hidden }) => {
|
export const ReactCard: FC<Props> = ({ card, hidden }) => {
|
||||||
|
const classes = useStyles();
|
||||||
let suit: React.ReactNode;
|
let suit: React.ReactNode;
|
||||||
switch (card.suit) {
|
switch (card.suit) {
|
||||||
case Suit.Clubs:
|
case Suit.Clubs:
|
||||||
@@ -25,10 +56,10 @@ export const ReactCard: FC<Props> = ({ card, hidden }) => {
|
|||||||
throw new Error(`MissingCaseException: ${card.suit}`);
|
throw new Error(`MissingCaseException: ${card.suit}`);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className={`casino-card ${card.isRedSuit() ? "red" : "black"}`}>
|
<div className={`${classes.card} ${card.isRedSuit() ? classes.red : classes.black}`}>
|
||||||
<>
|
<>
|
||||||
<div className="value">{hidden ? " - " : card.formatValue()}</div>
|
<div className={classes.value}>{hidden ? " - " : card.formatValue()}</div>
|
||||||
<div className={`suit`}>{hidden ? " - " : suit}</div>
|
<div>{hidden ? " - " : suit}</div>
|
||||||
</>
|
</>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,44 +3,32 @@
|
|||||||
*
|
*
|
||||||
* This subcomponent renders all of the buttons for training at the gym
|
* This subcomponent renders all of the buttons for training at the gym
|
||||||
*/
|
*/
|
||||||
import * as React from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { StdButton } from "../ui/React/StdButton";
|
|
||||||
import { BadRNG } from "./RNG";
|
import { BadRNG } from "./RNG";
|
||||||
import { Game } from "./Game";
|
import { win, reachedLimit } from "./Game";
|
||||||
import { trusted } from "./utils";
|
import { trusted } from "./utils";
|
||||||
|
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import TextField from "@mui/material/TextField";
|
||||||
|
import Button from "@mui/material/Button";
|
||||||
|
import Box from "@mui/material/Box";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
p: IPlayer;
|
p: IPlayer;
|
||||||
};
|
};
|
||||||
|
|
||||||
type IState = {
|
|
||||||
investment: number;
|
|
||||||
result: any;
|
|
||||||
status: string;
|
|
||||||
playLock: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
const minPlay = 0;
|
const minPlay = 0;
|
||||||
const maxPlay = 10e3;
|
const maxPlay = 10e3;
|
||||||
|
|
||||||
export class CoinFlip extends Game<IProps, IState> {
|
export function CoinFlip(props: IProps): React.ReactElement {
|
||||||
constructor(props: IProps) {
|
const [investment, setInvestment] = useState(1000);
|
||||||
super(props);
|
const [result, setResult] = useState(<span> </span>);
|
||||||
|
const [status, setStatus] = useState("");
|
||||||
|
const [playLock, setPlayLock] = useState(false);
|
||||||
|
|
||||||
this.state = {
|
function updateInvestment(e: React.ChangeEvent<HTMLInputElement>): void {
|
||||||
investment: 1000,
|
|
||||||
result: <span> </span>,
|
|
||||||
status: "",
|
|
||||||
playLock: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.play = this.play.bind(this);
|
|
||||||
this.updateInvestment = this.updateInvestment.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateInvestment(e: React.FormEvent<HTMLInputElement>): void {
|
|
||||||
let investment: number = parseInt(e.currentTarget.value);
|
let investment: number = parseInt(e.currentTarget.value);
|
||||||
if (isNaN(investment)) {
|
if (isNaN(investment)) {
|
||||||
investment = minPlay;
|
investment = minPlay;
|
||||||
@@ -51,11 +39,11 @@ export class CoinFlip extends Game<IProps, IState> {
|
|||||||
if (investment < minPlay) {
|
if (investment < minPlay) {
|
||||||
investment = minPlay;
|
investment = minPlay;
|
||||||
}
|
}
|
||||||
this.setState({ investment: investment });
|
setInvestment(investment);
|
||||||
}
|
}
|
||||||
|
|
||||||
play(guess: string): void {
|
function play(guess: string): void {
|
||||||
if (this.reachedLimit(this.props.p)) return;
|
if (reachedLimit(props.p)) return;
|
||||||
const v = BadRNG.random();
|
const v = BadRNG.random();
|
||||||
let letter: string;
|
let letter: string;
|
||||||
if (v < 0.5) {
|
if (v < 0.5) {
|
||||||
@@ -64,39 +52,51 @@ export class CoinFlip extends Game<IProps, IState> {
|
|||||||
letter = "T";
|
letter = "T";
|
||||||
}
|
}
|
||||||
const correct: boolean = guess === letter;
|
const correct: boolean = guess === letter;
|
||||||
this.setState({
|
|
||||||
result: <span className={correct ? "text" : "failure"}>{letter}</span>,
|
setResult(<span className={correct ? "text" : "failure"}>{letter}</span>);
|
||||||
status: correct ? " win!" : "lose!",
|
setStatus(correct ? " win!" : "lose!");
|
||||||
playLock: true,
|
setPlayLock(true);
|
||||||
});
|
|
||||||
setTimeout(() => this.setState({ playLock: false }), 250);
|
setTimeout(() => setPlayLock(false), 250);
|
||||||
if (correct) {
|
if (correct) {
|
||||||
this.win(this.props.p, this.state.investment);
|
win(props.p, investment);
|
||||||
} else {
|
} else {
|
||||||
this.win(this.props.p, -this.state.investment);
|
win(props.p, -investment);
|
||||||
}
|
}
|
||||||
if (this.reachedLimit(this.props.p)) return;
|
if (reachedLimit(props.p)) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): React.ReactNode {
|
return (
|
||||||
return (
|
<>
|
||||||
<>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>{`+———————+`}</Typography>
|
||||||
<pre>{`+———————+`}</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>{`| | | |`}</Typography>
|
||||||
<pre>{`| | | |`}</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>
|
||||||
<pre>
|
{`| | `}
|
||||||
{`| | `}
|
{result}
|
||||||
{this.state.result}
|
{` | |`}
|
||||||
{` | |`}
|
</Typography>
|
||||||
</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>{`| | | |`}</Typography>
|
||||||
<pre>{`| | | |`}</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>{`+———————+`}</Typography>
|
||||||
<pre>{`+———————+`}</pre>
|
<Box display="flex" alignItems="center">
|
||||||
<span className="text">Play for: </span>
|
<TextField
|
||||||
<input type="number" className="text-input" onChange={this.updateInvestment} value={this.state.investment} />
|
type="number"
|
||||||
<br />
|
onChange={updateInvestment}
|
||||||
<StdButton onClick={trusted(() => this.play("H"))} text={"Head!"} disabled={this.state.playLock} />
|
InputProps={{
|
||||||
<StdButton onClick={trusted(() => this.play("T"))} text={"Tail!"} disabled={this.state.playLock} />
|
endAdornment: (
|
||||||
<h1>{this.state.status}</h1>
|
<>
|
||||||
</>
|
<Button onClick={trusted(() => play("H"))} disabled={playLock}>
|
||||||
);
|
Head!
|
||||||
}
|
</Button>
|
||||||
|
<Button onClick={trusted(() => play("T"))} disabled={playLock}>
|
||||||
|
Tail!
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Typography variant="h3">{status}</Typography>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,19 @@ import { dialogBoxCreate } from "../ui/React/DialogBox";
|
|||||||
|
|
||||||
const gainLimit = 10e9;
|
const gainLimit = 10e9;
|
||||||
|
|
||||||
|
export function win(p: IPlayer, n: number): void {
|
||||||
|
p.gainMoney(n);
|
||||||
|
p.recordMoneySource(n, "casino");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function reachedLimit(p: IPlayer): boolean {
|
||||||
|
const reached = p.getCasinoWinnings() > gainLimit;
|
||||||
|
if (reached) {
|
||||||
|
dialogBoxCreate(<>Alright cheater get out of here. You're not allowed here anymore.</>);
|
||||||
|
}
|
||||||
|
return reached;
|
||||||
|
}
|
||||||
|
|
||||||
export class Game<T, U> extends React.Component<T, U> {
|
export class Game<T, U> extends React.Component<T, U> {
|
||||||
win(p: IPlayer, n: number): void {
|
win(p: IPlayer, n: number): void {
|
||||||
p.gainMoney(n);
|
p.gainMoney(n);
|
||||||
|
|||||||
@@ -1,25 +1,18 @@
|
|||||||
import * as React from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { StdButton } from "../ui/React/StdButton";
|
|
||||||
import { Money } from "../ui/React/Money";
|
import { Money } from "../ui/React/Money";
|
||||||
import { Game } from "./Game";
|
import { win, reachedLimit } from "./Game";
|
||||||
import { WHRNG } from "./RNG";
|
import { WHRNG } from "./RNG";
|
||||||
import { trusted } from "./utils";
|
import { trusted } from "./utils";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import Button from "@mui/material/Button";
|
||||||
|
import TextField from "@mui/material/TextField";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
p: IPlayer;
|
p: IPlayer;
|
||||||
};
|
};
|
||||||
|
|
||||||
type IState = {
|
|
||||||
investment: number;
|
|
||||||
canPlay: boolean;
|
|
||||||
status: string | JSX.Element;
|
|
||||||
n: number;
|
|
||||||
lock: boolean;
|
|
||||||
strategy: Strategy;
|
|
||||||
};
|
|
||||||
|
|
||||||
const minPlay = 0;
|
const minPlay = 0;
|
||||||
const maxPlay = 1e7;
|
const maxPlay = 1e7;
|
||||||
|
|
||||||
@@ -118,48 +111,32 @@ function Single(s: number): Strategy {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Roulette extends Game<IProps, IState> {
|
export function Roulette(props: IProps): React.ReactElement {
|
||||||
interval = -1;
|
const [rng] = useState(new WHRNG(new Date().getTime()));
|
||||||
rng: WHRNG;
|
const [investment, setInvestment] = useState(1000);
|
||||||
|
const [canPlay, setCanPlay] = useState(true);
|
||||||
|
const [status, setStatus] = useState<string | JSX.Element>("waiting");
|
||||||
|
const [n, setN] = useState(0);
|
||||||
|
const [lock, setLock] = useState(true);
|
||||||
|
const [strategy, setStrategy] = useState<Strategy>({
|
||||||
|
payout: 0,
|
||||||
|
match: (): boolean => {
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
constructor(props: IProps) {
|
useEffect(() => {
|
||||||
super(props);
|
const i = window.setInterval(step, 50);
|
||||||
|
return () => clearInterval(i);
|
||||||
|
});
|
||||||
|
|
||||||
this.rng = new WHRNG(new Date().getTime());
|
function step(): void {
|
||||||
this.state = {
|
if (!lock) {
|
||||||
investment: 1000,
|
setN(Math.floor(Math.random() * 37));
|
||||||
canPlay: true,
|
|
||||||
status: "waiting",
|
|
||||||
n: 0,
|
|
||||||
lock: true,
|
|
||||||
strategy: {
|
|
||||||
payout: 0,
|
|
||||||
match: (): boolean => {
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
this.step = this.step.bind(this);
|
|
||||||
this.currentNumber = this.currentNumber.bind(this);
|
|
||||||
this.updateInvestment = this.updateInvestment.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount(): void {
|
|
||||||
this.interval = window.setInterval(this.step, 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
step(): void {
|
|
||||||
if (!this.state.lock) {
|
|
||||||
this.setState({ n: Math.floor(Math.random() * 37) });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount(): void {
|
function updateInvestment(e: React.ChangeEvent<HTMLInputElement>): void {
|
||||||
clearInterval(this.interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateInvestment(e: React.FormEvent<HTMLInputElement>): void {
|
|
||||||
let investment: number = parseInt(e.currentTarget.value);
|
let investment: number = parseInt(e.currentTarget.value);
|
||||||
if (isNaN(investment)) {
|
if (isNaN(investment)) {
|
||||||
investment = minPlay;
|
investment = minPlay;
|
||||||
@@ -170,265 +147,312 @@ export class Roulette extends Game<IProps, IState> {
|
|||||||
if (investment < minPlay) {
|
if (investment < minPlay) {
|
||||||
investment = minPlay;
|
investment = minPlay;
|
||||||
}
|
}
|
||||||
this.setState({ investment: investment });
|
setInvestment(investment);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentNumber(): string {
|
function currentNumber(): string {
|
||||||
if (this.state.n === 0) return "0";
|
if (n === 0) return "0";
|
||||||
const color = isRed(this.state.n) ? "R" : "B";
|
const color = isRed(n) ? "R" : "B";
|
||||||
return `${this.state.n}${color}`;
|
return `${n}${color}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
play(s: Strategy): void {
|
function play(s: Strategy): void {
|
||||||
if (this.reachedLimit(this.props.p)) return;
|
if (reachedLimit(props.p)) return;
|
||||||
this.setState({
|
|
||||||
canPlay: false,
|
setCanPlay(false);
|
||||||
lock: false,
|
setLock(false);
|
||||||
status: "playing",
|
setStatus("playing");
|
||||||
strategy: s,
|
setStrategy(s);
|
||||||
});
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
let n = Math.floor(this.rng.random() * 37);
|
let n = Math.floor(rng.random() * 37);
|
||||||
let status = <></>;
|
let status = <></>;
|
||||||
let gain = 0;
|
let gain = 0;
|
||||||
let playerWin = this.state.strategy.match(n);
|
let playerWin = strategy.match(n);
|
||||||
// oh yeah, the house straight up cheats. Try finding the seed now!
|
// oh yeah, the house straight up cheats. Try finding the seed now!
|
||||||
if (playerWin && Math.random() > 0.9) {
|
if (playerWin && Math.random() > 0.9) {
|
||||||
playerWin = false;
|
playerWin = false;
|
||||||
while (this.state.strategy.match(n)) {
|
while (strategy.match(n)) {
|
||||||
n = (n + 1) % 36;
|
n = (n + 1) % 36;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (playerWin) {
|
if (playerWin) {
|
||||||
gain = this.state.investment * this.state.strategy.payout;
|
gain = investment * strategy.payout;
|
||||||
status = (
|
status = (
|
||||||
<>
|
<>
|
||||||
won <Money money={gain} />
|
won <Money money={gain} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
gain = -this.state.investment;
|
gain = -investment;
|
||||||
status = (
|
status = (
|
||||||
<>
|
<>
|
||||||
lost <Money money={-gain} />
|
lost <Money money={-gain} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.win(this.props.p, gain);
|
win(props.p, gain);
|
||||||
this.setState({
|
|
||||||
canPlay: true,
|
setCanPlay(true);
|
||||||
lock: true,
|
setLock(true);
|
||||||
status: status,
|
setStatus(status);
|
||||||
n: n,
|
setN(n);
|
||||||
});
|
|
||||||
this.reachedLimit(this.props.p);
|
reachedLimit(props.p);
|
||||||
}, 1600);
|
}, 1600);
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): React.ReactNode {
|
return (
|
||||||
return (
|
<>
|
||||||
<>
|
<Typography variant="h4">{currentNumber()}</Typography>
|
||||||
<h1>{this.currentNumber()}</h1>
|
<TextField type="number" onChange={updateInvestment} placeholder={"Amount to play"} disabled={!canPlay} />
|
||||||
<input
|
<Typography variant="h4">{status}</Typography>
|
||||||
type="number"
|
<table>
|
||||||
className="text-input"
|
<tbody>
|
||||||
onChange={this.updateInvestment}
|
<tr>
|
||||||
placeholder={"Amount to play"}
|
<td>
|
||||||
value={this.state.investment}
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(3)))}>
|
||||||
disabled={!this.state.canPlay}
|
3
|
||||||
/>
|
</Button>
|
||||||
<h1>{this.state.status}</h1>
|
</td>
|
||||||
<table>
|
<td>
|
||||||
<tbody>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(6)))}>
|
||||||
<tr>
|
6
|
||||||
<td>
|
</Button>
|
||||||
<StdButton text={"3"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(3)))} />
|
</td>
|
||||||
</td>
|
<td>
|
||||||
<td>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(9)))}>
|
||||||
<StdButton text={"6"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(6)))} />
|
9
|
||||||
</td>
|
</Button>
|
||||||
<td>
|
</td>
|
||||||
<StdButton text={"9"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(9)))} />
|
<td>
|
||||||
</td>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(12)))}>
|
||||||
<td>
|
12
|
||||||
<StdButton text={"12"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(12)))} />
|
</Button>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<StdButton text={"15"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(15)))} />
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(15)))}>
|
||||||
</td>
|
15
|
||||||
<td>
|
</Button>
|
||||||
<StdButton text={"18"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(18)))} />
|
</td>
|
||||||
</td>
|
<td>
|
||||||
<td>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(18)))}>
|
||||||
<StdButton text={"21"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(21)))} />
|
18
|
||||||
</td>
|
</Button>
|
||||||
<td>
|
</td>
|
||||||
<StdButton text={"24"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(24)))} />
|
<td>
|
||||||
</td>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(21)))}>
|
||||||
<td>
|
21
|
||||||
<StdButton text={"27"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(27)))} />
|
</Button>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<StdButton text={"30"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(30)))} />
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(24)))}>
|
||||||
</td>
|
24
|
||||||
<td>
|
</Button>
|
||||||
<StdButton text={"33"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(33)))} />
|
</td>
|
||||||
</td>
|
<td>
|
||||||
<td>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(27)))}>
|
||||||
<StdButton text={"36"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(36)))} />
|
27
|
||||||
</td>
|
</Button>
|
||||||
</tr>
|
</td>
|
||||||
<tr>
|
<td>
|
||||||
<td>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(30)))}>
|
||||||
<StdButton text={"2"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(2)))} />
|
30
|
||||||
</td>
|
</Button>
|
||||||
<td>
|
</td>
|
||||||
<StdButton text={"5"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(5)))} />
|
<td>
|
||||||
</td>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(33)))}>
|
||||||
<td>
|
33
|
||||||
<StdButton text={"8"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(8)))} />
|
</Button>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<StdButton text={"11"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(11)))} />
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(36)))}>
|
||||||
</td>
|
36
|
||||||
<td>
|
</Button>
|
||||||
<StdButton text={"14"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(14)))} />
|
</td>
|
||||||
</td>
|
</tr>
|
||||||
<td>
|
<tr>
|
||||||
<StdButton text={"17"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(17)))} />
|
<td>
|
||||||
</td>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(2)))}>
|
||||||
<td>
|
2
|
||||||
<StdButton text={"20"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(20)))} />
|
</Button>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<StdButton text={"23"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(23)))} />
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(5)))}>
|
||||||
</td>
|
5
|
||||||
<td>
|
</Button>
|
||||||
<StdButton text={"26"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(26)))} />
|
</td>
|
||||||
</td>
|
<td>
|
||||||
<td>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(8)))}>
|
||||||
<StdButton text={"29"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(29)))} />
|
8
|
||||||
</td>
|
</Button>
|
||||||
<td>
|
</td>
|
||||||
<StdButton text={"32"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(32)))} />
|
<td>
|
||||||
</td>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(11)))}>
|
||||||
<td>
|
11
|
||||||
<StdButton text={"35"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(35)))} />
|
</Button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
<td>
|
||||||
<tr>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(14)))}>
|
||||||
<td>
|
14
|
||||||
<StdButton text={"1"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(1)))} />
|
</Button>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<StdButton text={"4"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(4)))} />
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(17)))}>
|
||||||
</td>
|
17
|
||||||
<td>
|
</Button>
|
||||||
<StdButton text={"7"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(7)))} />
|
</td>
|
||||||
</td>
|
<td>
|
||||||
<td>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(20)))}>
|
||||||
<StdButton text={"10"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(10)))} />
|
20
|
||||||
</td>
|
</Button>
|
||||||
<td>
|
</td>
|
||||||
<StdButton text={"13"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(13)))} />
|
<td>
|
||||||
</td>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(23)))}>
|
||||||
<td>
|
23
|
||||||
<StdButton text={"16"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(16)))} />
|
</Button>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<StdButton text={"19"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(19)))} />
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(26)))}>
|
||||||
</td>
|
26
|
||||||
<td>
|
</Button>
|
||||||
<StdButton text={"22"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(22)))} />
|
</td>
|
||||||
</td>
|
<td>
|
||||||
<td>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(29)))}>
|
||||||
<StdButton text={"25"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(25)))} />
|
29
|
||||||
</td>
|
</Button>
|
||||||
<td>
|
</td>
|
||||||
<StdButton text={"28"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(28)))} />
|
<td>
|
||||||
</td>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(32)))}>
|
||||||
<td>
|
32
|
||||||
<StdButton text={"31"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(31)))} />
|
</Button>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<StdButton text={"34"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(34)))} />
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(35)))}>
|
||||||
</td>
|
35
|
||||||
</tr>
|
</Button>
|
||||||
<tr>
|
</td>
|
||||||
<td colSpan={4}>
|
</tr>
|
||||||
<StdButton
|
<tr>
|
||||||
text={"1 to 12"}
|
<td>
|
||||||
disabled={!this.state.canPlay}
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(1)))}>
|
||||||
onClick={trusted(() => this.play(strategies.Third1))}
|
1
|
||||||
/>
|
</Button>
|
||||||
</td>
|
</td>
|
||||||
<td colSpan={4}>
|
<td>
|
||||||
<StdButton
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(4)))}>
|
||||||
text={"13 to 24"}
|
4
|
||||||
disabled={!this.state.canPlay}
|
</Button>
|
||||||
onClick={trusted(() => this.play(strategies.Third2))}
|
</td>
|
||||||
/>
|
<td>
|
||||||
</td>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(7)))}>
|
||||||
<td colSpan={4}>
|
7
|
||||||
<StdButton
|
</Button>
|
||||||
text={"25 to 36"}
|
</td>
|
||||||
disabled={!this.state.canPlay}
|
<td>
|
||||||
onClick={trusted(() => this.play(strategies.Third3))}
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(10)))}>
|
||||||
/>
|
10
|
||||||
</td>
|
</Button>
|
||||||
</tr>
|
</td>
|
||||||
<tr>
|
<td>
|
||||||
<td colSpan={2}>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(13)))}>
|
||||||
<StdButton
|
13
|
||||||
text={"Red"}
|
</Button>
|
||||||
disabled={!this.state.canPlay}
|
</td>
|
||||||
onClick={trusted(() => this.play(strategies.Red))}
|
<td>
|
||||||
/>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(16)))}>
|
||||||
</td>
|
16
|
||||||
<td colSpan={2}>
|
</Button>
|
||||||
<StdButton
|
</td>
|
||||||
text={"Black"}
|
<td>
|
||||||
disabled={!this.state.canPlay}
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(19)))}>
|
||||||
onClick={trusted(() => this.play(strategies.Black))}
|
19
|
||||||
/>
|
</Button>
|
||||||
</td>
|
</td>
|
||||||
<td colSpan={2}>
|
<td>
|
||||||
<StdButton
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(22)))}>
|
||||||
text={"Odd"}
|
22
|
||||||
disabled={!this.state.canPlay}
|
</Button>
|
||||||
onClick={trusted(() => this.play(strategies.Odd))}
|
</td>
|
||||||
/>
|
<td>
|
||||||
</td>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(25)))}>
|
||||||
<td colSpan={2}>
|
25
|
||||||
<StdButton
|
</Button>
|
||||||
text={"Even"}
|
</td>
|
||||||
disabled={!this.state.canPlay}
|
<td>
|
||||||
onClick={trusted(() => this.play(strategies.Even))}
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(28)))}>
|
||||||
/>
|
28
|
||||||
</td>
|
</Button>
|
||||||
<td colSpan={2}>
|
</td>
|
||||||
<StdButton
|
<td>
|
||||||
text={"High"}
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(31)))}>
|
||||||
disabled={!this.state.canPlay}
|
31
|
||||||
onClick={trusted(() => this.play(strategies.High))}
|
</Button>
|
||||||
/>
|
</td>
|
||||||
</td>
|
<td>
|
||||||
<td colSpan={2}>
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(34)))}>
|
||||||
<StdButton
|
34
|
||||||
text={"Low"}
|
</Button>
|
||||||
disabled={!this.state.canPlay}
|
</td>
|
||||||
onClick={trusted(() => this.play(strategies.Low))}
|
</tr>
|
||||||
/>
|
<tr>
|
||||||
</td>
|
<td colSpan={4}>
|
||||||
</tr>
|
<Button disabled={!canPlay} onClick={trusted(() => play(strategies.Third1))}>
|
||||||
<tr>
|
1 to 12
|
||||||
<td>
|
</Button>
|
||||||
<StdButton text={"0"} disabled={!this.state.canPlay} onClick={trusted(() => this.play(Single(0)))} />
|
</td>
|
||||||
</td>
|
<td colSpan={4}>
|
||||||
</tr>
|
<Button disabled={!canPlay} onClick={trusted(() => play(strategies.Third2))}>
|
||||||
</tbody>
|
13 to 24
|
||||||
</table>
|
</Button>
|
||||||
</>
|
</td>
|
||||||
);
|
<td colSpan={4}>
|
||||||
}
|
<Button disabled={!canPlay} onClick={trusted(() => play(strategies.Third3))}>
|
||||||
|
25 to 36
|
||||||
|
</Button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colSpan={2}>
|
||||||
|
<Button disabled={!canPlay} onClick={trusted(() => play(strategies.Red))}>
|
||||||
|
Red
|
||||||
|
</Button>
|
||||||
|
</td>
|
||||||
|
<td colSpan={2}>
|
||||||
|
<Button disabled={!canPlay} onClick={trusted(() => play(strategies.Black))}>
|
||||||
|
Black
|
||||||
|
</Button>
|
||||||
|
</td>
|
||||||
|
<td colSpan={2}>
|
||||||
|
<Button disabled={!canPlay} onClick={trusted(() => play(strategies.Odd))}>
|
||||||
|
Odd
|
||||||
|
</Button>
|
||||||
|
</td>
|
||||||
|
<td colSpan={2}>
|
||||||
|
<Button disabled={!canPlay} onClick={trusted(() => play(strategies.Even))}>
|
||||||
|
Even
|
||||||
|
</Button>
|
||||||
|
</td>
|
||||||
|
<td colSpan={2}>
|
||||||
|
<Button disabled={!canPlay} onClick={trusted(() => play(strategies.High))}>
|
||||||
|
High
|
||||||
|
</Button>
|
||||||
|
</td>
|
||||||
|
<td colSpan={2}>
|
||||||
|
<Button disabled={!canPlay} onClick={trusted(() => play(strategies.Low))}>
|
||||||
|
Low
|
||||||
|
</Button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Button disabled={!canPlay} onClick={trusted(() => play(Single(0)))}>
|
||||||
|
0
|
||||||
|
</Button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import * as React from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
|
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
import { StdButton } from "../ui/React/StdButton";
|
|
||||||
import { Money } from "../ui/React/Money";
|
import { Money } from "../ui/React/Money";
|
||||||
import { WHRNG } from "./RNG";
|
import { WHRNG } from "./RNG";
|
||||||
import { Game } from "./Game";
|
import { win, reachedLimit } from "./Game";
|
||||||
import { trusted } from "./utils";
|
import { trusted } from "./utils";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import TextField from "@mui/material/TextField";
|
||||||
|
import Button from "@mui/material/Button";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
p: IPlayer;
|
p: IPlayer;
|
||||||
@@ -147,104 +149,76 @@ const payLines = [
|
|||||||
const minPlay = 0;
|
const minPlay = 0;
|
||||||
const maxPlay = 1e6;
|
const maxPlay = 1e6;
|
||||||
|
|
||||||
export class SlotMachine extends Game<IProps, IState> {
|
export function SlotMachine(props: IProps): React.ReactElement {
|
||||||
rng: WHRNG;
|
const [rng] = useState(new WHRNG(props.p.totalPlaytime));
|
||||||
interval = -1;
|
const [index, setIndex] = useState<number[]>([0, 0, 0, 0, 0]);
|
||||||
|
const [locks, setLocks] = useState<number[]>([0, 0, 0, 0, 0]);
|
||||||
|
const [investment, setInvestment] = useState(1000);
|
||||||
|
const [canPlay, setCanPlay] = useState(true);
|
||||||
|
const [status, setStatus] = useState<string | JSX.Element>("waiting");
|
||||||
|
|
||||||
constructor(props: IProps) {
|
useEffect(() => {
|
||||||
super(props);
|
const i = window.setInterval(step, 50);
|
||||||
this.rng = new WHRNG(this.props.p.totalPlaytime);
|
return () => clearInterval(i);
|
||||||
|
});
|
||||||
|
|
||||||
this.state = {
|
function step(): void {
|
||||||
index: [0, 0, 0, 0, 0],
|
|
||||||
investment: 1000,
|
|
||||||
locks: [0, 0, 0, 0, 0],
|
|
||||||
canPlay: true,
|
|
||||||
status: "waiting",
|
|
||||||
};
|
|
||||||
|
|
||||||
this.play = this.play.bind(this);
|
|
||||||
this.lock = this.lock.bind(this);
|
|
||||||
this.unlock = this.unlock.bind(this);
|
|
||||||
this.step = this.step.bind(this);
|
|
||||||
this.checkWinnings = this.checkWinnings.bind(this);
|
|
||||||
this.getTable = this.getTable.bind(this);
|
|
||||||
this.updateInvestment = this.updateInvestment.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount(): void {
|
|
||||||
this.interval = window.setInterval(this.step, 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
step(): void {
|
|
||||||
let stoppedOne = false;
|
let stoppedOne = false;
|
||||||
const index = this.state.index.slice();
|
const copy = index.slice();
|
||||||
for (const i in index) {
|
for (const i in copy) {
|
||||||
if (index[i] === this.state.locks[i] && !stoppedOne) continue;
|
if (copy[i] === locks[i] && !stoppedOne) continue;
|
||||||
index[i] = (index[i] + 1) % symbols.length;
|
copy[i] = (copy[i] + 1) % symbols.length;
|
||||||
stoppedOne = true;
|
stoppedOne = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({ index: index });
|
setIndex(copy);
|
||||||
|
|
||||||
if (stoppedOne && index.every((e, i) => e === this.state.locks[i])) {
|
if (stoppedOne && copy.every((e, i) => e === locks[i])) {
|
||||||
this.checkWinnings();
|
checkWinnings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount(): void {
|
function getTable(): string[][] {
|
||||||
clearInterval(this.interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTable(): string[][] {
|
|
||||||
return [
|
return [
|
||||||
[
|
[
|
||||||
symbols[(this.state.index[0] + symbols.length - 1) % symbols.length],
|
symbols[(index[0] + symbols.length - 1) % symbols.length],
|
||||||
symbols[(this.state.index[1] + symbols.length - 1) % symbols.length],
|
symbols[(index[1] + symbols.length - 1) % symbols.length],
|
||||||
symbols[(this.state.index[2] + symbols.length - 1) % symbols.length],
|
symbols[(index[2] + symbols.length - 1) % symbols.length],
|
||||||
symbols[(this.state.index[3] + symbols.length - 1) % symbols.length],
|
symbols[(index[3] + symbols.length - 1) % symbols.length],
|
||||||
symbols[(this.state.index[4] + symbols.length - 1) % symbols.length],
|
symbols[(index[4] + symbols.length - 1) % symbols.length],
|
||||||
],
|
],
|
||||||
|
[symbols[index[0]], symbols[index[1]], symbols[index[2]], symbols[index[3]], symbols[index[4]]],
|
||||||
[
|
[
|
||||||
symbols[this.state.index[0]],
|
symbols[(index[0] + 1) % symbols.length],
|
||||||
symbols[this.state.index[1]],
|
symbols[(index[1] + 1) % symbols.length],
|
||||||
symbols[this.state.index[2]],
|
symbols[(index[2] + 1) % symbols.length],
|
||||||
symbols[this.state.index[3]],
|
symbols[(index[3] + 1) % symbols.length],
|
||||||
symbols[this.state.index[4]],
|
symbols[(index[4] + 1) % symbols.length],
|
||||||
],
|
|
||||||
[
|
|
||||||
symbols[(this.state.index[0] + 1) % symbols.length],
|
|
||||||
symbols[(this.state.index[1] + 1) % symbols.length],
|
|
||||||
symbols[(this.state.index[2] + 1) % symbols.length],
|
|
||||||
symbols[(this.state.index[3] + 1) % symbols.length],
|
|
||||||
symbols[(this.state.index[4] + 1) % symbols.length],
|
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
play(): void {
|
function play(): void {
|
||||||
if (this.reachedLimit(this.props.p)) return;
|
if (reachedLimit(props.p)) return;
|
||||||
this.setState({ status: "playing" });
|
setStatus("playing");
|
||||||
this.win(this.props.p, -this.state.investment);
|
win(props.p, -investment);
|
||||||
if (!this.state.canPlay) return;
|
if (!canPlay) return;
|
||||||
this.unlock();
|
unlock();
|
||||||
setTimeout(this.lock, this.rng.random() * 2000 + 1000);
|
setTimeout(lock, rng.random() * 2000 + 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
lock(): void {
|
function lock(): void {
|
||||||
this.setState({
|
setLocks([
|
||||||
locks: [
|
Math.floor(rng.random() * symbols.length),
|
||||||
Math.floor(this.rng.random() * symbols.length),
|
Math.floor(rng.random() * symbols.length),
|
||||||
Math.floor(this.rng.random() * symbols.length),
|
Math.floor(rng.random() * symbols.length),
|
||||||
Math.floor(this.rng.random() * symbols.length),
|
Math.floor(rng.random() * symbols.length),
|
||||||
Math.floor(this.rng.random() * symbols.length),
|
Math.floor(rng.random() * symbols.length),
|
||||||
Math.floor(this.rng.random() * symbols.length),
|
]);
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkWinnings(): void {
|
function checkWinnings(): void {
|
||||||
const t = this.getTable();
|
const t = getTable();
|
||||||
const getPaylineData = function (payline: number[][]): string[] {
|
const getPaylineData = function (payline: number[][]): string[] {
|
||||||
const data = [];
|
const data = [];
|
||||||
for (const point of payline) {
|
for (const point of payline) {
|
||||||
@@ -263,35 +237,31 @@ export class SlotMachine extends Game<IProps, IState> {
|
|||||||
return count;
|
return count;
|
||||||
};
|
};
|
||||||
|
|
||||||
let gains = -this.state.investment;
|
let gains = -investment;
|
||||||
for (const payline of payLines) {
|
for (const payline of payLines) {
|
||||||
const data = getPaylineData(payline);
|
const data = getPaylineData(payline);
|
||||||
const count = countSequence(data);
|
const count = countSequence(data);
|
||||||
if (count < 3) continue;
|
if (count < 3) continue;
|
||||||
const payout = getPayout(data[0], count - 3);
|
const payout = getPayout(data[0], count - 3);
|
||||||
gains += this.state.investment * payout;
|
gains += investment * payout;
|
||||||
this.win(this.props.p, this.state.investment * payout);
|
win(props.p, investment * payout);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
setStatus(
|
||||||
status: (
|
<>
|
||||||
<>
|
{gains > 0 ? "gained" : "lost"} <Money money={Math.abs(gains)} />
|
||||||
{gains > 0 ? "gained" : "lost"} <Money money={Math.abs(gains)} />
|
</>,
|
||||||
</>
|
);
|
||||||
),
|
setCanPlay(true);
|
||||||
canPlay: true,
|
if (reachedLimit(props.p)) return;
|
||||||
});
|
|
||||||
if (this.reachedLimit(this.props.p)) return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock(): void {
|
function unlock(): void {
|
||||||
this.setState({
|
setLocks([-1, -1, -1, -1, -1]);
|
||||||
locks: [-1, -1, -1, -1, -1],
|
setCanPlay(false);
|
||||||
canPlay: false,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateInvestment(e: React.FormEvent<HTMLInputElement>): void {
|
function updateInvestment(e: React.ChangeEvent<HTMLInputElement>): void {
|
||||||
let investment: number = parseInt(e.currentTarget.value);
|
let investment: number = parseInt(e.currentTarget.value);
|
||||||
if (isNaN(investment)) {
|
if (isNaN(investment)) {
|
||||||
investment = minPlay;
|
investment = minPlay;
|
||||||
@@ -302,53 +272,49 @@ export class SlotMachine extends Game<IProps, IState> {
|
|||||||
if (investment < minPlay) {
|
if (investment < minPlay) {
|
||||||
investment = minPlay;
|
investment = minPlay;
|
||||||
}
|
}
|
||||||
this.setState({ investment: investment });
|
setInvestment(investment);
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): React.ReactNode {
|
const t = getTable();
|
||||||
const t = this.getTable();
|
// prettier-ignore
|
||||||
// prettier-ignore
|
return (
|
||||||
return (
|
|
||||||
<>
|
<>
|
||||||
<pre>+———————————————————————+</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>+———————————————————————+</Typography>
|
||||||
<pre>| | {t[0][0]} | {t[0][1]} | {t[0][2]} | {t[0][3]} | {t[0][4]} | |</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>| | {t[0][0]} | {t[0][1]} | {t[0][2]} | {t[0][3]} | {t[0][4]} | |</Typography>
|
||||||
<pre>| | | | | | | |</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>| | | | | | | |</Typography>
|
||||||
<pre>| | {symbols[this.state.index[0]]} | {symbols[this.state.index[1]]} | {symbols[this.state.index[2]]} | {symbols[this.state.index[3]]} | {symbols[this.state.index[4]]} | |</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>| | {symbols[index[0]]} | {symbols[index[1]]} | {symbols[index[2]]} | {symbols[index[3]]} | {symbols[index[4]]} | |</Typography>
|
||||||
<pre>| | | | | | | |</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>| | | | | | | |</Typography>
|
||||||
<pre>| | {symbols[(this.state.index[0]+1)%symbols.length]} | {symbols[(this.state.index[1]+1)%symbols.length]} | {symbols[(this.state.index[2]+1)%symbols.length]} | {symbols[(this.state.index[3]+1)%symbols.length]} | {symbols[(this.state.index[4]+1)%symbols.length]} | |</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>| | {symbols[(index[0]+1)%symbols.length]} | {symbols[(index[1]+1)%symbols.length]} | {symbols[(index[2]+1)%symbols.length]} | {symbols[(index[3]+1)%symbols.length]} | {symbols[(index[4]+1)%symbols.length]} | |</Typography>
|
||||||
<pre>+———————————————————————+</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>+———————————————————————+</Typography>
|
||||||
<input
|
<TextField
|
||||||
type="number"
|
type="number"
|
||||||
className="text-input"
|
onChange={updateInvestment}
|
||||||
onChange={this.updateInvestment}
|
|
||||||
placeholder={"Amount to play"}
|
placeholder={"Amount to play"}
|
||||||
value={this.state.investment}
|
disabled={!canPlay}
|
||||||
disabled={!this.state.canPlay}
|
InputProps={{endAdornment:(<Button
|
||||||
|
onClick={trusted(play)}
|
||||||
|
disabled={!canPlay}
|
||||||
|
>Spin!</Button>)}}
|
||||||
/>
|
/>
|
||||||
<StdButton
|
|
||||||
onClick={trusted(this.play)}
|
<Typography variant="h4">{status}</Typography>
|
||||||
text={"Spin!"}
|
<Typography>Pay lines</Typography>
|
||||||
disabled={!this.state.canPlay}
|
|
||||||
/>
|
|
||||||
<h1>{this.state.status}</h1>
|
|
||||||
<h2>Pay lines</h2>
|
|
||||||
|
|
||||||
<pre>----- ····· ·····</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>----- ····· ·····</Typography>
|
||||||
<pre>····· ----- ·····</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>····· ----- ·····</Typography>
|
||||||
<pre>····· ····· -----</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>····· ····· -----</Typography>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<pre>··^·· \···/ \···/</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>··^·· \···/ \···/</Typography>
|
||||||
<pre>·/·\· ·\·/· ·---·</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>·/·\· ·\·/· ·---·</Typography>
|
||||||
<pre>/···\ ··v·· ·····</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>/···\ ··v·· ·····</Typography>
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<pre>····· ·---· ·····</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>····· ·---· ·····</Typography>
|
||||||
<pre>·---· /···\ \···/</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>·---· /···\ \···/</Typography>
|
||||||
<pre>/···\ ····· ·---·</pre>
|
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>/···\ ····· ·---·</Typography>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://felgo.com/doc/how-to-make-a-slot-game-tutorial/
|
// https://felgo.com/doc/how-to-make-a-slot-game-tutorial/
|
||||||
|
|||||||
@@ -3,14 +3,13 @@
|
|||||||
*
|
*
|
||||||
* This subcomponent renders all of the buttons for training at the gym
|
* This subcomponent renders all of the buttons for training at the gym
|
||||||
*/
|
*/
|
||||||
import * as React from "react";
|
import React, { useState } from "react";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import { Blackjack } from "../../Casino/Blackjack";
|
import { Blackjack } from "../../Casino/Blackjack";
|
||||||
import { CoinFlip } from "../../Casino/CoinFlip";
|
import { CoinFlip } from "../../Casino/CoinFlip";
|
||||||
import { Roulette } from "../../Casino/Roulette";
|
import { Roulette } from "../../Casino/Roulette";
|
||||||
import { SlotMachine } from "../../Casino/SlotMachine";
|
import { SlotMachine } from "../../Casino/SlotMachine";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { StdButton } from "../../ui/React/StdButton";
|
|
||||||
|
|
||||||
enum GameType {
|
enum GameType {
|
||||||
None = "none",
|
None = "none",
|
||||||
@@ -28,71 +27,35 @@ type IState = {
|
|||||||
game: GameType;
|
game: GameType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class CasinoLocation extends React.Component<IProps, IState> {
|
export function CasinoLocation(props: IProps): React.ReactElement {
|
||||||
constructor(props: IProps) {
|
const [game, setGame] = useState(GameType.None);
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.state = {
|
function updateGame(game: GameType): void {
|
||||||
game: GameType.None,
|
setGame(game);
|
||||||
};
|
|
||||||
|
|
||||||
this.updateGame = this.updateGame.bind(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateGame(game: GameType): void {
|
return (
|
||||||
this.setState({
|
<>
|
||||||
game,
|
{game === GameType.None && (
|
||||||
});
|
<>
|
||||||
}
|
<Button onClick={() => updateGame(GameType.Coin)}>Play coin flip</Button>
|
||||||
|
<br />
|
||||||
renderGames(): React.ReactNode {
|
<Button onClick={() => updateGame(GameType.Slots)}>Play slots</Button>
|
||||||
return (
|
<br />
|
||||||
<>
|
<Button onClick={() => updateGame(GameType.Roulette)}>Play roulette</Button>
|
||||||
<Button onClick={() => this.updateGame(GameType.Coin)}>Play coin flip</Button>
|
<br />
|
||||||
<br />
|
<Button onClick={() => updateGame(GameType.Blackjack)}>Play blackjack</Button>
|
||||||
<Button onClick={() => this.updateGame(GameType.Slots)}>Play slots</Button>
|
</>
|
||||||
<br />
|
)}
|
||||||
<Button onClick={() => this.updateGame(GameType.Roulette)}>Play roulette</Button>
|
{game !== GameType.None && (
|
||||||
<br />
|
<>
|
||||||
<Button onClick={() => this.updateGame(GameType.Blackjack)}>Play blackjack</Button>
|
<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} />}
|
||||||
renderGame(): React.ReactNode {
|
</>
|
||||||
let elem = null;
|
)}
|
||||||
switch (this.state.game) {
|
</>
|
||||||
case GameType.Coin:
|
);
|
||||||
elem = <CoinFlip p={this.props.p} />;
|
|
||||||
break;
|
|
||||||
case GameType.Slots:
|
|
||||||
elem = <SlotMachine p={this.props.p} />;
|
|
||||||
break;
|
|
||||||
case GameType.Roulette:
|
|
||||||
elem = <Roulette p={this.props.p} />;
|
|
||||||
break;
|
|
||||||
case GameType.Blackjack:
|
|
||||||
elem = <Blackjack p={this.props.p} />;
|
|
||||||
break;
|
|
||||||
case GameType.None:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error(`MissingCaseException: ${this.state.game}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<StdButton onClick={() => this.updateGame(GameType.None)} text={"Stop playing"} />
|
|
||||||
{elem}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render(): React.ReactNode {
|
|
||||||
if (this.state.game === GameType.None) {
|
|
||||||
return this.renderGames();
|
|
||||||
} else {
|
|
||||||
return this.renderGame();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,10 @@ import { Locations } from "../Locations";
|
|||||||
import { Location } from "../Location";
|
import { Location } from "../Location";
|
||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../Settings/Settings";
|
||||||
|
|
||||||
import { StdButton } from "../../ui/React/StdButton";
|
|
||||||
import { use } from "../../ui/Context";
|
import { use } from "../../ui/Context";
|
||||||
import { IRouter } from "../../ui/Router";
|
import { IRouter } from "../../ui/Router";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import Button from "@mui/material/Button";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
city: City;
|
city: City;
|
||||||
@@ -111,29 +112,30 @@ function ASCIICity(props: IProps): React.ReactElement {
|
|||||||
elems.push(<pre key={i}>{lineElems(lines[i])}</pre>);
|
elems.push(<pre key={i}>{lineElems(lines[i])}</pre>);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div className="noselect">{elems}</div>;
|
return <>{elems}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ListCity(props: IProps): React.ReactElement {
|
function ListCity(props: IProps): React.ReactElement {
|
||||||
const router = use.Router();
|
const router = use.Router();
|
||||||
const locationButtons = props.city.locations.map((locName) => {
|
const locationButtons = props.city.locations.map((locName) => {
|
||||||
return (
|
return (
|
||||||
<li key={locName}>
|
<React.Fragment key={locName}>
|
||||||
<StdButton onClick={() => toLocation(router, Locations[locName])} text={locName} />
|
<Button onClick={() => toLocation(router, Locations[locName])}>{locName}</Button>
|
||||||
</li>
|
<br />
|
||||||
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return <ul>{locationButtons}</ul>;
|
return <>{locationButtons}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function LocationCity(): React.ReactElement {
|
export function LocationCity(): React.ReactElement {
|
||||||
const player = use.Player();
|
const player = use.Player();
|
||||||
const city = Cities[player.city];
|
const city = Cities[player.city];
|
||||||
return (
|
return (
|
||||||
<div className="noselect">
|
<>
|
||||||
<h2>{city.name}</h2>
|
<Typography>{city.name}</Typography>
|
||||||
{Settings.DisableASCIIArt ? <ListCity city={city} /> : <ASCIICity city={city} />}
|
{Settings.DisableASCIIArt ? <ListCity city={city} /> : <ASCIICity city={city} />}
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ export function CompanyLocation(props: IProps): React.ReactElement {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Typography className={"tooltip"}>Company Favor: {Favor(company.favor)}</Typography>
|
<Typography>Company Favor: {Favor(company.favor)}</Typography>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Box>
|
</Box>
|
||||||
<Typography>-------------------------</Typography>
|
<Typography>-------------------------</Typography>
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ export function GenericLocation({ loc }: IProps): React.ReactElement {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button onClick={() => router.toCity()}>Return to World</Button>
|
<Button onClick={() => router.toCity()}>Return to World</Button>
|
||||||
<Typography variant="h4" className="noselect">
|
<Typography variant="h4">
|
||||||
{backdoorInstalled && !Settings.DisableTextEffects ? <CorruptableText content={loc.name} /> : loc.name}
|
{backdoorInstalled && !Settings.DisableTextEffects ? <CorruptableText content={loc.name} /> : loc.name}
|
||||||
</Typography>
|
</Typography>
|
||||||
{locContent}
|
{locContent}
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export function TechVendorLocation(props: IProps): React.ReactElement {
|
|||||||
<div>
|
<div>
|
||||||
{purchaseServerButtons}
|
{purchaseServerButtons}
|
||||||
<br />
|
<br />
|
||||||
<Typography className="noselect">
|
<Typography>
|
||||||
<i>"You can order bigger servers via scripts. We don't take custom order in person."</i>
|
<i>"You can order bigger servers via scripts. We don't take custom order in person."</i>
|
||||||
</Typography>
|
</Typography>
|
||||||
<br />
|
<br />
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import { IPlayer } from "../../PersonObjects/IPlayer";
|
|||||||
import { IRouter } from "../../ui/Router";
|
import { IRouter } from "../../ui/Router";
|
||||||
import { Settings } from "../../Settings/Settings";
|
import { Settings } from "../../Settings/Settings";
|
||||||
|
|
||||||
import { StdButton } from "../../ui/React/StdButton";
|
|
||||||
import { use } from "../../ui/Context";
|
import { use } from "../../ui/Context";
|
||||||
import { Money } from "../../ui/React/Money";
|
import { Money } from "../../ui/React/Money";
|
||||||
import { WorldMap } from "../../ui/React/WorldMap";
|
import { WorldMap } from "../../ui/React/WorldMap";
|
||||||
@@ -36,7 +35,7 @@ function travel(p: IPlayer, router: IRouter, to: CityName): void {
|
|||||||
|
|
||||||
p.loseMoney(cost);
|
p.loseMoney(cost);
|
||||||
p.travel(to);
|
p.travel(to);
|
||||||
dialogBoxCreate(<span className="noselect">You are now in {to}!</span>);
|
dialogBoxCreate(<>You are now in {to}!</>);
|
||||||
router.toCity();
|
router.toCity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ import { setTimeoutRef } from "./utils/SetTimeoutRef";
|
|||||||
import { is2DArray } from "./utils/helpers/is2DArray";
|
import { is2DArray } from "./utils/helpers/is2DArray";
|
||||||
import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions";
|
import { convertTimeMsToTimeElapsedString } from "./utils/StringHelperFunctions";
|
||||||
|
|
||||||
import { logBoxCreate } from "./ui/React/LogBox";
|
import { LogBoxEvents } from "./ui/React/LogBoxManager";
|
||||||
import { arrayToString } from "./utils/helpers/arrayToString";
|
import { arrayToString } from "./utils/helpers/arrayToString";
|
||||||
import { isString } from "./utils/helpers/isString";
|
import { isString } from "./utils/helpers/isString";
|
||||||
|
|
||||||
@@ -1203,7 +1203,7 @@ function NetscriptFunctions(workerScript: WorkerScript): NS {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logBoxCreate(runningScriptObj);
|
LogBoxEvents.emit(runningScriptObj);
|
||||||
},
|
},
|
||||||
nuke: function (ip: any): any {
|
nuke: function (ip: any): any {
|
||||||
updateDynamicRam("nuke", getRamCost("nuke"));
|
updateDynamicRam("nuke", getRamCost("nuke"));
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ import { Money } from "../../../ui/React/Money";
|
|||||||
import { numeralWrapper } from "../../../ui/numeralFormat";
|
import { numeralWrapper } from "../../../ui/numeralFormat";
|
||||||
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../../ui/React/DialogBox";
|
||||||
|
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import Paper from "@mui/material/Paper";
|
||||||
|
import Button from "@mui/material/Button";
|
||||||
|
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||||
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
|
import Grid from "@mui/material/Grid";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
resleeve: Resleeve;
|
resleeve: Resleeve;
|
||||||
player: IPlayer;
|
player: IPlayer;
|
||||||
@@ -19,81 +26,83 @@ export function ResleeveElem(props: IProps): React.ReactElement {
|
|||||||
function openStats(): void {
|
function openStats(): void {
|
||||||
dialogBoxCreate(
|
dialogBoxCreate(
|
||||||
<>
|
<>
|
||||||
<h2>
|
<Typography variant="h5" color="primary">
|
||||||
<u>Total Multipliers:</u>
|
Total Multipliers:
|
||||||
</h2>
|
</Typography>
|
||||||
Hacking Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_mult)}
|
<Typography>
|
||||||
<br />
|
Hacking Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_mult)}
|
||||||
Hacking Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_exp_mult)}
|
<br />
|
||||||
<br />
|
Hacking Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_exp_mult)}
|
||||||
Strength Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.strength_mult)}
|
<br />
|
||||||
<br />
|
Strength Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.strength_mult)}
|
||||||
Strength Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.strength_exp_mult)}
|
<br />
|
||||||
<br />
|
Strength Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.strength_exp_mult)}
|
||||||
Defense Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.defense_mult)}
|
<br />
|
||||||
<br />
|
Defense Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.defense_mult)}
|
||||||
Defense Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.defense_exp_mult)}
|
<br />
|
||||||
<br />
|
Defense Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.defense_exp_mult)}
|
||||||
Dexterity Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.dexterity_mult)}
|
<br />
|
||||||
<br />
|
Dexterity Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.dexterity_mult)}
|
||||||
Dexterity Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.dexterity_exp_mult)}
|
<br />
|
||||||
<br />
|
Dexterity Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.dexterity_exp_mult)}
|
||||||
Agility Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.agility_mult)}
|
<br />
|
||||||
<br />
|
Agility Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.agility_mult)}
|
||||||
Agility Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.agility_exp_mult)}
|
<br />
|
||||||
<br />
|
Agility Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.agility_exp_mult)}
|
||||||
Charisma Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.charisma_mult)}
|
<br />
|
||||||
<br />
|
Charisma Level multiplier: {numeralWrapper.formatPercentage(props.resleeve.charisma_mult)}
|
||||||
Charisma Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.charisma_exp_mult)}
|
<br />
|
||||||
<br />
|
Charisma Experience multiplier: {numeralWrapper.formatPercentage(props.resleeve.charisma_exp_mult)}
|
||||||
Hacking Chance multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_chance_mult)}
|
<br />
|
||||||
<br />
|
Hacking Chance multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_chance_mult)}
|
||||||
Hacking Speed multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_speed_mult)}
|
<br />
|
||||||
<br />
|
Hacking Speed multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_speed_mult)}
|
||||||
Hacking Money multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_money_mult)}
|
<br />
|
||||||
<br />
|
Hacking Money multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_money_mult)}
|
||||||
Hacking Growth multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_grow_mult)}
|
<br />
|
||||||
<br />
|
Hacking Growth multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacking_grow_mult)}
|
||||||
Salary multiplier: {numeralWrapper.formatPercentage(props.resleeve.work_money_mult)}
|
<br />
|
||||||
<br />
|
Salary multiplier: {numeralWrapper.formatPercentage(props.resleeve.work_money_mult)}
|
||||||
Company Reputation Gain multiplier: {numeralWrapper.formatPercentage(props.resleeve.company_rep_mult)}
|
<br />
|
||||||
<br />
|
Company Reputation Gain multiplier: {numeralWrapper.formatPercentage(props.resleeve.company_rep_mult)}
|
||||||
Faction Reputation Gain multiplier: {numeralWrapper.formatPercentage(props.resleeve.faction_rep_mult)}
|
<br />
|
||||||
<br />
|
Faction Reputation Gain multiplier: {numeralWrapper.formatPercentage(props.resleeve.faction_rep_mult)}
|
||||||
Crime Money multiplier: {numeralWrapper.formatPercentage(props.resleeve.crime_money_mult)}
|
<br />
|
||||||
<br />
|
Crime Money multiplier: {numeralWrapper.formatPercentage(props.resleeve.crime_money_mult)}
|
||||||
Crime Success multiplier: {numeralWrapper.formatPercentage(props.resleeve.crime_success_mult)}
|
<br />
|
||||||
<br />
|
Crime Success multiplier: {numeralWrapper.formatPercentage(props.resleeve.crime_success_mult)}
|
||||||
Hacknet Income multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacknet_node_money_mult)}
|
<br />
|
||||||
<br />
|
Hacknet Income multiplier: {numeralWrapper.formatPercentage(props.resleeve.hacknet_node_money_mult)}
|
||||||
Hacknet Purchase Cost multiplier:
|
<br />
|
||||||
{numeralWrapper.formatPercentage(props.resleeve.hacknet_node_purchase_cost_mult)}
|
Hacknet Purchase Cost multiplier:
|
||||||
<br />
|
{numeralWrapper.formatPercentage(props.resleeve.hacknet_node_purchase_cost_mult)}
|
||||||
Hacknet Level Upgrade Cost multiplier:
|
<br />
|
||||||
{numeralWrapper.formatPercentage(props.resleeve.hacknet_node_level_cost_mult)}
|
Hacknet Level Upgrade Cost multiplier:
|
||||||
<br />
|
{numeralWrapper.formatPercentage(props.resleeve.hacknet_node_level_cost_mult)}
|
||||||
Hacknet Ram Upgrade Cost multiplier:
|
<br />
|
||||||
{numeralWrapper.formatPercentage(props.resleeve.hacknet_node_ram_cost_mult)}
|
Hacknet Ram Upgrade Cost multiplier:
|
||||||
<br />
|
{numeralWrapper.formatPercentage(props.resleeve.hacknet_node_ram_cost_mult)}
|
||||||
Hacknet Core Upgrade Cost multiplier:
|
<br />
|
||||||
{numeralWrapper.formatPercentage(props.resleeve.hacknet_node_core_cost_mult)}
|
Hacknet Core Upgrade Cost multiplier:
|
||||||
<br />
|
{numeralWrapper.formatPercentage(props.resleeve.hacknet_node_core_cost_mult)}
|
||||||
Bladeburner Max Stamina multiplier:
|
<br />
|
||||||
{numeralWrapper.formatPercentage(props.resleeve.bladeburner_max_stamina_mult)}
|
Bladeburner Max Stamina multiplier:
|
||||||
<br />
|
{numeralWrapper.formatPercentage(props.resleeve.bladeburner_max_stamina_mult)}
|
||||||
Bladeburner Stamina Gain multiplier:
|
<br />
|
||||||
{numeralWrapper.formatPercentage(props.resleeve.bladeburner_stamina_gain_mult)}
|
Bladeburner Stamina Gain multiplier:
|
||||||
<br />
|
{numeralWrapper.formatPercentage(props.resleeve.bladeburner_stamina_gain_mult)}
|
||||||
Bladeburner Field Analysis multiplier:
|
<br />
|
||||||
{numeralWrapper.formatPercentage(props.resleeve.bladeburner_analysis_mult)}
|
Bladeburner Field Analysis multiplier:
|
||||||
<br />
|
{numeralWrapper.formatPercentage(props.resleeve.bladeburner_analysis_mult)}
|
||||||
Bladeburner Success Chance multiplier:
|
<br />
|
||||||
{numeralWrapper.formatPercentage(props.resleeve.bladeburner_success_chance_mult)}
|
Bladeburner Success Chance multiplier:
|
||||||
|
{numeralWrapper.formatPercentage(props.resleeve.bladeburner_success_chance_mult)}
|
||||||
|
</Typography>
|
||||||
</>,
|
</>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAugChange(event: React.ChangeEvent<HTMLSelectElement>): void {
|
function onAugChange(event: SelectChangeEvent<string>): void {
|
||||||
setAug(event.target.value);
|
setAug(event.target.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,50 +119,48 @@ export function ResleeveElem(props: IProps): React.ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="resleeve-elem" style={{ display: "block" }}>
|
<Paper sx={{ my: 1 }}>
|
||||||
<div className="resleeve-panel" style={{ width: "30%" }}>
|
<Grid container>
|
||||||
<p>
|
<Grid item xs={3}>
|
||||||
Hacking: {numeralWrapper.formatSkill(props.resleeve.hacking_skill)} (
|
<Typography>
|
||||||
{numeralWrapper.formatExp(props.resleeve.hacking_exp)} exp)
|
Hacking: {numeralWrapper.formatSkill(props.resleeve.hacking_skill)} (
|
||||||
<br />
|
{numeralWrapper.formatExp(props.resleeve.hacking_exp)} exp)
|
||||||
Strength: {numeralWrapper.formatSkill(props.resleeve.strength)} (
|
<br />
|
||||||
{numeralWrapper.formatExp(props.resleeve.strength_exp)} exp)
|
Strength: {numeralWrapper.formatSkill(props.resleeve.strength)} (
|
||||||
<br />
|
{numeralWrapper.formatExp(props.resleeve.strength_exp)} exp)
|
||||||
Defense: {numeralWrapper.formatSkill(props.resleeve.defense)} (
|
<br />
|
||||||
{numeralWrapper.formatExp(props.resleeve.defense_exp)} exp)
|
Defense: {numeralWrapper.formatSkill(props.resleeve.defense)} (
|
||||||
<br />
|
{numeralWrapper.formatExp(props.resleeve.defense_exp)} exp)
|
||||||
Dexterity: {numeralWrapper.formatSkill(props.resleeve.dexterity)} (
|
<br />
|
||||||
{numeralWrapper.formatExp(props.resleeve.dexterity_exp)} exp)
|
Dexterity: {numeralWrapper.formatSkill(props.resleeve.dexterity)} (
|
||||||
<br />
|
{numeralWrapper.formatExp(props.resleeve.dexterity_exp)} exp)
|
||||||
Agility: {numeralWrapper.formatSkill(props.resleeve.agility)} (
|
<br />
|
||||||
{numeralWrapper.formatExp(props.resleeve.agility_exp)} exp)
|
Agility: {numeralWrapper.formatSkill(props.resleeve.agility)} (
|
||||||
<br />
|
{numeralWrapper.formatExp(props.resleeve.agility_exp)} exp)
|
||||||
Charisma: {numeralWrapper.formatSkill(props.resleeve.charisma)} (
|
<br />
|
||||||
{numeralWrapper.formatExp(props.resleeve.charisma_exp)} exp)
|
Charisma: {numeralWrapper.formatSkill(props.resleeve.charisma)} (
|
||||||
<br /># Augmentations: {props.resleeve.augmentations.length}
|
{numeralWrapper.formatExp(props.resleeve.charisma_exp)} exp)
|
||||||
</p>
|
<br /># Augmentations: {props.resleeve.augmentations.length}
|
||||||
<button className="std-button" onClick={openStats}>
|
</Typography>
|
||||||
Multipliers
|
<Button onClick={openStats}>Multipliers</Button>
|
||||||
</button>
|
</Grid>
|
||||||
</div>
|
<Grid item xs={6}>
|
||||||
<div className="resleeve-panel" style={{ width: "50%" }}>
|
<Select value={aug} onChange={onAugChange}>
|
||||||
<select className="resleeve-aug-selector dropdown" onChange={onAugChange}>
|
{props.resleeve.augmentations.map((aug) => (
|
||||||
{props.resleeve.augmentations.map((aug) => (
|
<MenuItem key={aug.name} value={aug.name}>
|
||||||
<option key={aug.name} value={aug.name}>
|
{aug.name}
|
||||||
{aug.name}
|
</MenuItem>
|
||||||
</option>
|
))}
|
||||||
))}
|
</Select>
|
||||||
</select>
|
<Typography>{currentAug !== undefined && currentAug.info}</Typography>
|
||||||
<p>{currentAug !== undefined && currentAug.info}</p>
|
</Grid>
|
||||||
</div>
|
<Grid item xs={3}>
|
||||||
<div className="resleeve-panel" style={{ width: "20%" }}>
|
<Typography>
|
||||||
<p>
|
It costs <Money money={cost} player={props.player} /> to purchase this Sleeve.
|
||||||
It costs <Money money={cost} player={props.player} /> to purchase this Sleeve.
|
</Typography>
|
||||||
</p>
|
<Button onClick={purchase}>Purchase</Button>
|
||||||
<button className="std-button" onClick={purchase}>
|
</Grid>
|
||||||
Purchase
|
</Grid>
|
||||||
</button>
|
</Paper>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import { IPlayer } from "../../IPlayer";
|
|
||||||
import { generateResleeves } from "../Resleeving";
|
import { generateResleeves } from "../Resleeving";
|
||||||
import { Resleeve } from "../Resleeve";
|
import { Resleeve } from "../Resleeve";
|
||||||
import { ResleeveElem } from "./ResleeveElem";
|
import { ResleeveElem } from "./ResleeveElem";
|
||||||
|
import { use } from "../../../ui/Context";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||||
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
|
import Box from "@mui/material/Box";
|
||||||
|
|
||||||
const SortOption: {
|
const SortOption: {
|
||||||
[key: string]: string | undefined;
|
[key: string]: string | undefined;
|
||||||
@@ -69,28 +73,25 @@ const SortFunctions: {
|
|||||||
TotalNumAugmentations: (a: Resleeve, b: Resleeve): number => a.augmentations.length - b.augmentations.length,
|
TotalNumAugmentations: (a: Resleeve, b: Resleeve): number => a.augmentations.length - b.augmentations.length,
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IProps {
|
export function ResleeveRoot(): React.ReactElement {
|
||||||
player: IPlayer;
|
const player = use.Player();
|
||||||
}
|
|
||||||
|
|
||||||
export function ResleeveRoot(props: IProps): React.ReactElement {
|
|
||||||
const [sort, setSort] = useState(SortOption.Cost);
|
const [sort, setSort] = useState(SortOption.Cost);
|
||||||
// Randomly create all Resleeves if they dont already exist
|
// Randomly create all Resleeves if they dont already exist
|
||||||
if (props.player.resleeves.length === 0) {
|
if (player.resleeves.length === 0) {
|
||||||
props.player.resleeves = generateResleeves();
|
player.resleeves = generateResleeves();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSortChange(event: React.ChangeEvent<HTMLSelectElement>): void {
|
function onSortChange(event: SelectChangeEvent<string>): void {
|
||||||
setSort(event.target.value);
|
setSort(event.target.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const sortFunction = SortFunctions[sort];
|
const sortFunction = SortFunctions[sort];
|
||||||
if (sortFunction === undefined) throw new Error(`sort function '${sort}' is undefined`);
|
if (sortFunction === undefined) throw new Error(`sort function '${sort}' is undefined`);
|
||||||
props.player.resleeves.sort(sortFunction);
|
player.resleeves.sort(sortFunction);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p style={{ display: "block", width: "75%" }}>
|
<Typography>
|
||||||
Re-sleeving is the process of digitizing and transferring your consciousness into a new human body, or 'sleeve'.
|
Re-sleeving is the process of digitizing and transferring your consciousness into a new human body, or 'sleeve'.
|
||||||
Here at VitaLife, you can purchase new specially-engineered bodies for the re-sleeve process. Many of these
|
Here at VitaLife, you can purchase new specially-engineered bodies for the re-sleeve process. Many of these
|
||||||
bodies even come with genetic and cybernetic Augmentations!
|
bodies even come with genetic and cybernetic Augmentations!
|
||||||
@@ -104,17 +105,19 @@ export function ResleeveRoot(props: IProps): React.ReactElement {
|
|||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
NOTE: The stats and multipliers displayed on this page do NOT include your bonuses from Source-File.
|
NOTE: The stats and multipliers displayed on this page do NOT include your bonuses from Source-File.
|
||||||
</p>
|
</Typography>
|
||||||
<p style={{ display: "inline-block" }}>Sort By: </p>
|
<Box display="flex" alignItems="center">
|
||||||
<select className="dropdown" defaultValue={sort} onChange={onSortChange}>
|
<Typography>Sort By: </Typography>
|
||||||
{Object.keys(SortOption).map((opt) => (
|
<Select value={sort} onChange={onSortChange}>
|
||||||
<option key={opt} value={opt}>
|
{Object.keys(SortOption).map((opt) => (
|
||||||
{SortOption[opt]}
|
<MenuItem key={opt} value={opt}>
|
||||||
</option>
|
{SortOption[opt]}
|
||||||
))}
|
</MenuItem>
|
||||||
</select>
|
))}
|
||||||
{props.player.resleeves.map((resleeve, i) => (
|
</Select>
|
||||||
<ResleeveElem key={i} player={props.player} resleeve={resleeve} />
|
</Box>
|
||||||
|
{player.resleeves.map((resleeve, i) => (
|
||||||
|
<ResleeveElem key={i} player={player} resleeve={resleeve} />
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { ITerminal } from "../ITerminal";
|
|||||||
import { IRouter } from "../../ui/Router";
|
import { IRouter } from "../../ui/Router";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { BaseServer } from "../../Server/BaseServer";
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
import { logBoxCreate } from "../../ui/React/LogBox";
|
import { LogBoxEvents } from "../../ui/React/LogBoxManager";
|
||||||
import { startWorkerScript } from "../../NetscriptWorker";
|
import { startWorkerScript } from "../../NetscriptWorker";
|
||||||
import { RunningScript } from "../../Script/RunningScript";
|
import { RunningScript } from "../../Script/RunningScript";
|
||||||
import { findRunningScript } from "../../Script/ScriptHelpers";
|
import { findRunningScript } from "../../Script/ScriptHelpers";
|
||||||
@@ -84,7 +84,7 @@ export function runScript(
|
|||||||
`Running script with ${numThreads} thread(s), pid ${runningScript.pid} and args: ${JSON.stringify(args)}.`,
|
`Running script with ${numThreads} thread(s), pid ${runningScript.pid} and args: ${JSON.stringify(args)}.`,
|
||||||
);
|
);
|
||||||
if (tailFlag) {
|
if (tailFlag) {
|
||||||
logBoxCreate(runningScript);
|
LogBoxEvents.emit(runningScript);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import { ITerminal } from "../ITerminal";
|
|||||||
import { IRouter } from "../../ui/Router";
|
import { IRouter } from "../../ui/Router";
|
||||||
import { IPlayer } from "../../PersonObjects/IPlayer";
|
import { IPlayer } from "../../PersonObjects/IPlayer";
|
||||||
import { BaseServer } from "../../Server/BaseServer";
|
import { BaseServer } from "../../Server/BaseServer";
|
||||||
import { logBoxCreate } from "../../ui/React/LogBox";
|
|
||||||
import { findRunningScriptByPid } from "../../Script/ScriptHelpers";
|
import { findRunningScriptByPid } from "../../Script/ScriptHelpers";
|
||||||
import { isScriptFilename } from "../../Script/isScriptFilename";
|
import { isScriptFilename } from "../../Script/isScriptFilename";
|
||||||
import { compareArrays } from "../../utils/helpers/compareArrays";
|
import { compareArrays } from "../../utils/helpers/compareArrays";
|
||||||
|
import { LogBoxEvents } from "../../ui/React/LogBoxManager";
|
||||||
|
|
||||||
export function tail(
|
export function tail(
|
||||||
terminal: ITerminal,
|
terminal: ITerminal,
|
||||||
@@ -34,7 +34,7 @@ export function tail(
|
|||||||
// match, use it!
|
// match, use it!
|
||||||
for (let i = 0; i < server.runningScripts.length; ++i) {
|
for (let i = 0; i < server.runningScripts.length; ++i) {
|
||||||
if (server.runningScripts[i].filename === scriptName && compareArrays(server.runningScripts[i].args, args)) {
|
if (server.runningScripts[i].filename === scriptName && compareArrays(server.runningScripts[i].args, args)) {
|
||||||
logBoxCreate(server.runningScripts[i]);
|
LogBoxEvents.emit(server.runningScripts[i]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ export function tail(
|
|||||||
|
|
||||||
// If there's only 1 possible choice, use that.
|
// If there's only 1 possible choice, use that.
|
||||||
if (candidates.length === 1) {
|
if (candidates.length === 1) {
|
||||||
logBoxCreate(candidates[0]);
|
LogBoxEvents.emit(candidates[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ export function tail(
|
|||||||
terminal.error("No such script exists");
|
terminal.error("No such script exists");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logBoxCreate(runningScript);
|
LogBoxEvents.emit(runningScript);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
terminal.error(e + "");
|
terminal.error(e + "");
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ import { Money } from "./ui/React/Money";
|
|||||||
import { Hashes } from "./ui/React/Hashes";
|
import { Hashes } from "./ui/React/Hashes";
|
||||||
import { Reputation } from "./ui/React/Reputation";
|
import { Reputation } from "./ui/React/Reputation";
|
||||||
|
|
||||||
import { dialogBoxCreate } from "./ui/React/DialogBox";
|
import { AlertEvents } from "./ui/React/AlertManager";
|
||||||
import { exceptionAlert } from "./utils/helpers/exceptionAlert";
|
import { exceptionAlert } from "./utils/helpers/exceptionAlert";
|
||||||
|
|
||||||
import { startTampering } from "./Exploits/tampering";
|
import { startTampering } from "./Exploits/tampering";
|
||||||
@@ -399,12 +399,16 @@ const Engine: {
|
|||||||
Player.lastUpdate = Engine._lastUpdate;
|
Player.lastUpdate = Engine._lastUpdate;
|
||||||
Engine.start(); // Run main game loop and Scripts loop
|
Engine.start(); // Run main game loop and Scripts loop
|
||||||
const timeOfflineString = convertTimeMsToTimeElapsedString(time);
|
const timeOfflineString = convertTimeMsToTimeElapsedString(time);
|
||||||
dialogBoxCreate(
|
setTimeout(
|
||||||
<>
|
() =>
|
||||||
Offline for {timeOfflineString}. While you were offline, your scripts generated{" "}
|
AlertEvents.emit(
|
||||||
<Money money={offlineHackingIncome} />, your Hacknet Nodes generated {hacknetProdInfo} and you gained{" "}
|
<>
|
||||||
{Reputation(offlineReputation)} divided amongst your factions.
|
Offline for {timeOfflineString}. While you were offline, your scripts generated{" "}
|
||||||
</>,
|
<Money money={offlineHackingIncome} />, your Hacknet Nodes generated {hacknetProdInfo} and you gained{" "}
|
||||||
|
{Reputation(offlineReputation)} divided amongst your factions.
|
||||||
|
</>,
|
||||||
|
),
|
||||||
|
250,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// No save found, start new game
|
// No save found, start new game
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import { killWorkerScript } from "../../Netscript/killWorkerScript";
|
|||||||
import { WorkerScript } from "../../Netscript/WorkerScript";
|
import { WorkerScript } from "../../Netscript/WorkerScript";
|
||||||
|
|
||||||
import { dialogBoxCreate } from "../React/DialogBox";
|
import { dialogBoxCreate } from "../React/DialogBox";
|
||||||
import { logBoxCreate } from "../React/LogBox";
|
import { LogBoxEvents } from "../React/LogBoxManager";
|
||||||
import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
import { convertTimeMsToTimeElapsedString } from "../../utils/StringHelperFunctions";
|
||||||
import { arrayToString } from "../../utils/helpers/arrayToString";
|
import { arrayToString } from "../../utils/helpers/arrayToString";
|
||||||
import { Money } from "../React/Money";
|
import { Money } from "../React/Money";
|
||||||
@@ -50,7 +50,9 @@ export function WorkerScriptAccordion(props: IProps): React.ReactElement {
|
|||||||
const workerScript = props.workerScript;
|
const workerScript = props.workerScript;
|
||||||
const scriptRef = workerScript.scriptRef;
|
const scriptRef = workerScript.scriptRef;
|
||||||
|
|
||||||
const logClickHandler = logBoxCreate.bind(null, scriptRef);
|
function logClickHandler(): void {
|
||||||
|
LogBoxEvents.emit(scriptRef);
|
||||||
|
}
|
||||||
const killScript = killWorkerScript.bind(null, scriptRef as any, scriptRef.server);
|
const killScript = killWorkerScript.bind(null, scriptRef as any, scriptRef.server);
|
||||||
|
|
||||||
function killScriptClickHandler(): void {
|
function killScriptClickHandler(): void {
|
||||||
|
|||||||
@@ -67,6 +67,8 @@ import { BladeburnerCinematic } from "../Bladeburner/ui/BladeburnerCinematic";
|
|||||||
import { workerScripts } from "../Netscript/WorkerScripts";
|
import { workerScripts } from "../Netscript/WorkerScripts";
|
||||||
import { Unclickable } from "../Exploits/Unclickable";
|
import { Unclickable } from "../Exploits/Unclickable";
|
||||||
import { Snackbar } from "./React/Snackbar";
|
import { Snackbar } from "./React/Snackbar";
|
||||||
|
import { LogBoxManager } from "./React/LogBoxManager";
|
||||||
|
import { AlertManager } from "./React/AlertManager";
|
||||||
|
|
||||||
import { enterBitNode } from "../RedPill";
|
import { enterBitNode } from "../RedPill";
|
||||||
import { Context } from "./Context";
|
import { Context } from "./Context";
|
||||||
@@ -334,7 +336,7 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
) : page === Page.Bladeburner ? (
|
) : page === Page.Bladeburner ? (
|
||||||
<BladeburnerRoot />
|
<BladeburnerRoot />
|
||||||
) : page === Page.Resleeves ? (
|
) : page === Page.Resleeves ? (
|
||||||
<ResleeveRoot player={player} />
|
<ResleeveRoot />
|
||||||
) : page === Page.Travel ? (
|
) : page === Page.Travel ? (
|
||||||
<TravelAgencyRoot p={player} router={Router} />
|
<TravelAgencyRoot p={player} router={Router} />
|
||||||
) : page === Page.StockMarket ? (
|
) : page === Page.StockMarket ? (
|
||||||
@@ -394,6 +396,8 @@ export function GameRoot({ player, engine, terminal }: IProps): React.ReactEleme
|
|||||||
)}
|
)}
|
||||||
<Unclickable />
|
<Unclickable />
|
||||||
<Snackbar />
|
<Snackbar />
|
||||||
|
<LogBoxManager />
|
||||||
|
<AlertManager />
|
||||||
</Context.Router.Provider>
|
</Context.Router.Provider>
|
||||||
</Context.Player.Provider>
|
</Context.Player.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
50
src/ui/React/AlertManager.tsx
Normal file
50
src/ui/React/AlertManager.tsx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import { EventEmitter } from "../../utils/EventEmitter";
|
||||||
|
import { Modal } from "../../ui/React/Modal";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
|
||||||
|
export const AlertEvents = new EventEmitter<[string | JSX.Element]>();
|
||||||
|
|
||||||
|
interface Alert {
|
||||||
|
id: string;
|
||||||
|
text: string | JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
export function AlertManager(): React.ReactElement {
|
||||||
|
const [alerts, setAlerts] = useState<Alert[]>([]);
|
||||||
|
useEffect(
|
||||||
|
() =>
|
||||||
|
AlertEvents.subscribe((text: string | JSX.Element) => {
|
||||||
|
const id = i + "";
|
||||||
|
i++;
|
||||||
|
setAlerts((old) => {
|
||||||
|
return [
|
||||||
|
...old,
|
||||||
|
{
|
||||||
|
id: id,
|
||||||
|
text: text,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
function close(): void {
|
||||||
|
console.log("close");
|
||||||
|
setAlerts((old) => {
|
||||||
|
return old.slice(0, -1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{alerts.length > 0 && (
|
||||||
|
<Modal open={true} onClose={close}>
|
||||||
|
<Typography>{alerts[0].text}</Typography>
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
|
||||||
import ReactDOM from "react-dom";
|
|
||||||
import { killWorkerScript } from "../../Netscript/killWorkerScript";
|
|
||||||
import { RunningScript } from "../../Script/RunningScript";
|
|
||||||
|
|
||||||
import { createElement } from "../uiHelpers/createElement";
|
|
||||||
import { removeElementById } from "../uiHelpers/removeElementById";
|
|
||||||
|
|
||||||
let gameContainer: HTMLElement;
|
|
||||||
|
|
||||||
(function () {
|
|
||||||
function getGameContainer(): void {
|
|
||||||
const container = document.getElementById("root");
|
|
||||||
if (container == null) {
|
|
||||||
throw new Error(`Failed to find game container DOM element`);
|
|
||||||
}
|
|
||||||
|
|
||||||
gameContainer = container;
|
|
||||||
document.removeEventListener("DOMContentLoaded", getGameContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", getGameContainer);
|
|
||||||
})();
|
|
||||||
|
|
||||||
interface IProps {
|
|
||||||
script: RunningScript;
|
|
||||||
container: HTMLElement;
|
|
||||||
id: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
function ScriptLogPopup(props: IProps): React.ReactElement {
|
|
||||||
const setRerender = useState(false)[1];
|
|
||||||
|
|
||||||
function rerender(): void {
|
|
||||||
setRerender((old) => !old);
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const id = setInterval(rerender, 1000);
|
|
||||||
return () => clearInterval(id);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
function close(): void {
|
|
||||||
const content = document.getElementById(props.id);
|
|
||||||
if (content == null) return;
|
|
||||||
ReactDOM.unmountComponentAtNode(content);
|
|
||||||
removeElementById(props.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
function closeHandler(event: KeyboardEvent): void {
|
|
||||||
if (event.keyCode === 27) {
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("keydown", closeHandler);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
document.removeEventListener("keydown", closeHandler);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
function kill(): void {
|
|
||||||
killWorkerScript(props.script, props.script.server, true);
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
function drag(event: React.MouseEvent<HTMLElement, MouseEvent>): void {
|
|
||||||
event.preventDefault();
|
|
||||||
let x = event.clientX;
|
|
||||||
let y = event.clientY;
|
|
||||||
let left = props.container.offsetLeft + props.container.clientWidth / 2;
|
|
||||||
let top = props.container.offsetTop + props.container.clientWidth / 5;
|
|
||||||
function mouseMove(event: MouseEvent): void {
|
|
||||||
left += event.clientX - x;
|
|
||||||
top += event.clientY - y;
|
|
||||||
props.container.style.left = left + "px";
|
|
||||||
props.container.style.top = top + "px";
|
|
||||||
// reset right and bottom to avoid the window stretching
|
|
||||||
props.container.style.right = "";
|
|
||||||
props.container.style.bottom = "";
|
|
||||||
x = event.clientX;
|
|
||||||
y = event.clientY;
|
|
||||||
}
|
|
||||||
function mouseUp(): void {
|
|
||||||
document.removeEventListener("mouseup", mouseUp);
|
|
||||||
document.removeEventListener("mousemove", mouseMove);
|
|
||||||
}
|
|
||||||
document.addEventListener("mouseup", mouseUp);
|
|
||||||
document.addEventListener("mousemove", mouseMove);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="log-box-header" onMouseDown={drag}>
|
|
||||||
<p>
|
|
||||||
{props.script.filename} {props.script.args.map((x: any): string => `${x}`).join(" ")}
|
|
||||||
</p>
|
|
||||||
<div>
|
|
||||||
<button className="log-box-button" onClick={kill}>
|
|
||||||
Kill Script
|
|
||||||
</button>
|
|
||||||
<button className="log-box-button" onClick={close}>
|
|
||||||
Close
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="log-box-log-container">
|
|
||||||
<p>
|
|
||||||
{props.script.logs.map(
|
|
||||||
(line: string, i: number): JSX.Element => (
|
|
||||||
<span key={i} style={{ whiteSpace: "pre-line" }}>
|
|
||||||
{line}
|
|
||||||
<br />
|
|
||||||
</span>
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function logBoxCreate(script: RunningScript): void {
|
|
||||||
const id = script.server + "-" + script.filename + script.args.map((x: any): string => `${x}`).join("-");
|
|
||||||
if (document.getElementById(id) !== null) return;
|
|
||||||
const container = createElement("div", {
|
|
||||||
class: "log-box-container",
|
|
||||||
id: id,
|
|
||||||
});
|
|
||||||
gameContainer.appendChild(container);
|
|
||||||
ReactDOM.render(<ScriptLogPopup script={script} id={id} container={container} />, container);
|
|
||||||
}
|
|
||||||
161
src/ui/React/LogBoxManager.tsx
Normal file
161
src/ui/React/LogBoxManager.tsx
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
import React, { useState, useEffect, useRef } from "react";
|
||||||
|
import { EventEmitter } from "../../utils/EventEmitter";
|
||||||
|
import { RunningScript } from "../../Script/RunningScript";
|
||||||
|
import { killWorkerScript } from "../../Netscript/killWorkerScript";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import Box from "@mui/material/Box";
|
||||||
|
import Button from "@mui/material/Button";
|
||||||
|
import Paper from "@mui/material/Paper";
|
||||||
|
|
||||||
|
export const LogBoxEvents = new EventEmitter<[RunningScript]>();
|
||||||
|
|
||||||
|
interface Log {
|
||||||
|
id: string;
|
||||||
|
script: RunningScript;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function LogBoxManager(): React.ReactElement {
|
||||||
|
const [logs, setLogs] = useState<Log[]>([]);
|
||||||
|
useEffect(
|
||||||
|
() =>
|
||||||
|
LogBoxEvents.subscribe((script: RunningScript) => {
|
||||||
|
const id = script.server + "-" + script.filename + script.args.map((x: any): string => `${x}`).join("-");
|
||||||
|
setLogs((old) => {
|
||||||
|
return [
|
||||||
|
...old,
|
||||||
|
{
|
||||||
|
id: id,
|
||||||
|
script: script,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
function close(id: string): void {
|
||||||
|
setLogs((old) => old.filter((l) => l.id !== id));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{logs.map((log) => (
|
||||||
|
<LogWindow key={log.id} script={log.script} id={log.id} onClose={() => close(log.id)} />
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
script: RunningScript;
|
||||||
|
id: string;
|
||||||
|
onClose: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function LogWindow(props: IProps): React.ReactElement {
|
||||||
|
const container = useRef<HTMLDivElement>(null);
|
||||||
|
const setRerender = useState(false)[1];
|
||||||
|
function rerender(): void {
|
||||||
|
setRerender((old) => !old);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const id = setInterval(rerender, 1000);
|
||||||
|
return () => clearInterval(id);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
function closeHandler(event: KeyboardEvent): void {
|
||||||
|
if (event.keyCode === 27) {
|
||||||
|
props.onClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("keydown", closeHandler);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
document.removeEventListener("keydown", closeHandler);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function kill(): void {
|
||||||
|
killWorkerScript(props.script, props.script.server, true);
|
||||||
|
props.onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
function drag(event: React.MouseEvent<HTMLElement, MouseEvent>): void {
|
||||||
|
const c = container.current;
|
||||||
|
if (c === null) return;
|
||||||
|
event.preventDefault();
|
||||||
|
let x = event.clientX;
|
||||||
|
let y = event.clientY;
|
||||||
|
let left = c.offsetLeft + c.clientWidth / 2;
|
||||||
|
let top = c.offsetTop + c.clientWidth / 5;
|
||||||
|
function mouseMove(event: MouseEvent): void {
|
||||||
|
const c = container.current;
|
||||||
|
if (c === null) return;
|
||||||
|
left += event.clientX - x;
|
||||||
|
top += event.clientY - y;
|
||||||
|
c.style.left = left + "px";
|
||||||
|
c.style.top = top + "px";
|
||||||
|
// reset right and bottom to avoid the window stretching
|
||||||
|
c.style.right = "";
|
||||||
|
c.style.bottom = "";
|
||||||
|
x = event.clientX;
|
||||||
|
y = event.clientY;
|
||||||
|
}
|
||||||
|
function mouseUp(): void {
|
||||||
|
document.removeEventListener("mouseup", mouseUp);
|
||||||
|
document.removeEventListener("mousemove", mouseMove);
|
||||||
|
}
|
||||||
|
document.addEventListener("mouseup", mouseUp);
|
||||||
|
document.addEventListener("mousemove", mouseMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexFlow: "column",
|
||||||
|
backgroundColor: "gray",
|
||||||
|
width: "50%",
|
||||||
|
position: "fixed",
|
||||||
|
left: "50%",
|
||||||
|
top: "40%",
|
||||||
|
margin: "-10% 0 0 -25%",
|
||||||
|
height: "auto",
|
||||||
|
maxHeight: "50%",
|
||||||
|
zIndex: 10,
|
||||||
|
border: "2px solid $hacker-green",
|
||||||
|
}}
|
||||||
|
ref={container}
|
||||||
|
>
|
||||||
|
<Paper
|
||||||
|
style={{
|
||||||
|
cursor: "grab",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box display="flex" alignItems="center" onMouseDown={drag}>
|
||||||
|
<Typography color="primary" variant="h6" noWrap component="div">
|
||||||
|
{props.script.filename} {props.script.args.map((x: any): string => `${x}`).join(" ")}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Box display="flex" marginLeft="auto">
|
||||||
|
<Button onClick={kill}>Kill Script</Button>
|
||||||
|
<Button onClick={props.onClose}>Close</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Paper>
|
||||||
|
<Paper>
|
||||||
|
{props.script.logs.map(
|
||||||
|
(line: string, i: number): JSX.Element => (
|
||||||
|
<Typography key={i} style={{ whiteSpace: "pre-line" }}>
|
||||||
|
{line}
|
||||||
|
<br />
|
||||||
|
</Typography>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</Paper>
|
||||||
|
</Paper>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -33,7 +33,7 @@ interface IProps {
|
|||||||
export function WorldMap(props: IProps): React.ReactElement {
|
export function WorldMap(props: IProps): React.ReactElement {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
return (
|
return (
|
||||||
<div className="noselect">
|
<>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> ,_ . ._. _. .</Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> ,_ . ._. _. .</Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> , _-\','|~\~ ~/ ;-'_ _-' ,;_;_, ~~-</Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> , _-\','|~\~ ~/ ;-'_ _-' ,;_;_, ~~-</Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> /~~-\_/-'~'--' \~~| ', ,' / / ~|-_\_/~/~ ~~--~~~~'--_</Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> /~~-\_/-'~'--' \~~| ', ,' / / ~|-_\_/~/~ ~~--~~~~'--_</Typography>
|
||||||
@@ -56,6 +56,6 @@ export function WorldMap(props: IProps): React.ReactElement {
|
|||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> / ,' ~</Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> / ,' ~</Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> ',| ~</Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> ',| ~</Typography>
|
||||||
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> ~'</Typography>
|
<Typography sx={{lineHeight: '1em',whiteSpace: 'pre'}}> ~'</Typography>
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ module.exports = (env, argv) => {
|
|||||||
const isDevServer = (env || {}).devServer === true;
|
const isDevServer = (env || {}).devServer === true;
|
||||||
const runInContainer = (env || {}).runInContainer === true;
|
const runInContainer = (env || {}).runInContainer === true;
|
||||||
const isDevelopment = argv.mode === "development";
|
const isDevelopment = argv.mode === "development";
|
||||||
|
const isFastRefresh = argv.fast === "true";
|
||||||
const outputDirectory = isDevServer ? "dist-dev" : "dist";
|
const outputDirectory = isDevServer ? "dist-dev" : "dist";
|
||||||
const entry = "./src/index.tsx";
|
const entry = "./src/index.tsx";
|
||||||
|
|
||||||
@@ -130,7 +131,7 @@ module.exports = (env, argv) => {
|
|||||||
columns: true,
|
columns: true,
|
||||||
module: true,
|
module: true,
|
||||||
}),
|
}),
|
||||||
isDevelopment && new ReactRefreshWebpackPlugin(),
|
isFastRefresh && new ReactRefreshWebpackPlugin(),
|
||||||
new DeadCodePlugin({
|
new DeadCodePlugin({
|
||||||
patterns: ["src/**/*.(js|jsx|css|ts|tsx)"],
|
patterns: ["src/**/*.(js|jsx|css|ts|tsx)"],
|
||||||
exclude: ["**/*.(stories|spec).(js|jsx)"],
|
exclude: ["**/*.(stories|spec).(js|jsx)"],
|
||||||
@@ -150,7 +151,7 @@ module.exports = (env, argv) => {
|
|||||||
use: {
|
use: {
|
||||||
loader: "babel-loader",
|
loader: "babel-loader",
|
||||||
options: {
|
options: {
|
||||||
plugins: [isDevelopment && require.resolve("react-refresh/babel")].filter(Boolean),
|
plugins: [isFastRefresh && require.resolve("react-refresh/babel")].filter(Boolean),
|
||||||
cacheDirectory: true,
|
cacheDirectory: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user