re-merge 3575

This commit is contained in:
Olivier Gagnon 2022-05-20 15:46:45 -04:00
parent 3574f5df3f
commit 1c3d4fe1b5

@ -1,24 +1,194 @@
import { Explore, Info, LastPage, LocalPolice, NewReleases, Report, SportsMma } from "@mui/icons-material";
import { Box, Button, Container, Paper, Tooltip, Typography, useTheme } from "@mui/material";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { Box, Button, Container, Paper, TableBody, TableRow, Typography } from "@mui/material";
import { IPlayer } from "../../PersonObjects/IPlayer"; import { IPlayer } from "../../PersonObjects/IPlayer";
import { Table, TableCell } from "../../ui/React/Table"; import { Settings } from "../../Settings/Settings";
import { numeralWrapper } from "../../ui/numeralFormat";
import { IRouter } from "../../ui/Router"; import { IRouter } from "../../ui/Router";
import { Faction } from "../Faction";
import { joinFaction, getFactionAugmentationsFiltered } from "../FactionHelpers";
import { Factions } from "../Factions";
import { FactionNames } from "../data/FactionNames"; import { FactionNames } from "../data/FactionNames";
import { Faction } from "../Faction";
import { getFactionAugmentationsFiltered, joinFaction } from "../FactionHelpers";
import { Factions } from "../Factions";
export const InvitationsSeen: string[] = []; export const InvitationsSeen: string[] = [];
const getAugsLeft = (faction: Faction, player: IPlayer): number => {
const augs = getFactionAugmentationsFiltered(player, faction);
return augs.filter((augmentation: string) => !player.hasAugmentation(augmentation)).length;
};
interface IWorkTypeProps {
faction: Faction;
}
const fontSize = "small";
const marginRight = 0.5;
const WorkTypesOffered = (props: IWorkTypeProps): React.ReactElement => {
const info = props.faction.getInfo();
return (
<>
{info.offerFieldWork && (
<Tooltip title="This Faction offers field work">
<Explore sx={{ color: Settings.theme.info, mr: marginRight }} fontSize={fontSize} />
</Tooltip>
)}
{info.offerHackingWork && (
<Tooltip title="This Faction offers hacking work">
<LastPage sx={{ color: Settings.theme.hack, mr: marginRight }} fontSize={fontSize} />
</Tooltip>
)}
{info.offerSecurityWork && (
<Tooltip title="This Faction offers security work">
<LocalPolice sx={{ color: Settings.theme.combat, mr: marginRight }} fontSize={fontSize} />
</Tooltip>
)}
</>
);
};
interface IFactionProps {
player: IPlayer;
router: IRouter;
faction: Faction;
joined: boolean;
rerender: () => void;
}
const FactionElement = (props: IFactionProps): React.ReactElement => {
const facInfo = props.faction.getInfo();
function openFaction(faction: Faction): void {
props.router.toFaction(faction);
}
function openFactionAugPage(faction: Faction): void {
props.router.toFaction(faction, true);
}
function acceptInvitation(event: React.MouseEvent<HTMLButtonElement, MouseEvent>, faction: string): void {
if (!event.isTrusted) return;
joinFaction(Factions[faction]);
props.rerender();
}
return (
<Paper
sx={{
display: "grid",
p: 1,
alignItems: "center",
gridTemplateColumns: "minmax(0, 4fr)" + (props.joined ? " 1fr" : ""),
}}
>
<Box display="flex" sx={{ alignItems: "center" }}>
{props.joined ? (
<Box
display="grid"
sx={{
mr: 1,
gridTemplateColumns: "1fr 1fr",
minWidth: "fit-content",
gap: 0.5,
"& .MuiButton-root": { height: "48px" },
}}
>
<Button onClick={() => openFaction(props.faction)}>Details</Button>
<Button onClick={() => openFactionAugPage(props.faction)}>Augments</Button>
</Box>
) : (
<Button sx={{ height: "48px", mr: 1 }} onClick={(e) => acceptInvitation(e, props.faction.name)}>
Join!
</Button>
)}
<span style={{ maxWidth: props.joined ? "70%" : "95%" }}>
<Typography
variant="h6"
sx={{
mr: 1,
display: "grid",
gridTemplateColumns: "fit-content(100vw) max-content",
alignItems: "center",
}}
>
<span
style={{ overflow: "hidden", whiteSpace: "nowrap", textOverflow: "ellipsis" }}
title={props.faction.name}
>
{props.faction.name}
</span>
<span style={{ display: "flex", alignItems: "center" }}>
{props.player.hasGangWith(props.faction.name) && (
<Tooltip title="You have a gang with this Faction">
<SportsMma sx={{ color: Settings.theme.hp, ml: 1 }} />
</Tooltip>
)}
{facInfo.special && (
<Tooltip title="This is a special Faction">
<NewReleases sx={{ ml: 1, color: Settings.theme.money, transform: "rotate(180deg)" }} />
</Tooltip>
)}
{!props.joined && facInfo.enemies.length > 0 && (
<Tooltip
title={
<Typography>
This Faction is enemies with:
<ul>
{facInfo.enemies.map((enemy) => (
<li key={enemy}>{enemy}</li>
))}
</ul>
Joining this Faction will prevent you from joining its enemies
</Typography>
}
>
<Report sx={{ ml: 1, color: Settings.theme.error }} />
</Tooltip>
)}
</span>
</Typography>
<span style={{ display: "flex", alignItems: "center" }}>
{!props.player.hasGangWith(props.faction.name) && <WorkTypesOffered faction={props.faction} />}
{props.joined && (
<Typography variant="body2" sx={{ display: "flex" }}>
{getAugsLeft(props.faction, props.player)} Augmentations left
</Typography>
)}
</span>
</span>
</Box>
{props.joined && (
<Box display="grid" sx={{ alignItems: "center", justifyItems: "left", gridAutoFlow: "row" }}>
<Typography sx={{ color: Settings.theme.rep }}>
{numeralWrapper.formatFavor(props.faction.favor)} favor
</Typography>
<Typography sx={{ color: Settings.theme.rep }}>
{numeralWrapper.formatReputation(props.faction.playerReputation)} rep
</Typography>
</Box>
)}
</Paper>
);
};
interface IProps { interface IProps {
player: IPlayer; player: IPlayer;
router: IRouter; router: IRouter;
} }
export function FactionsRoot(props: IProps): React.ReactElement { export function FactionsRoot(props: IProps): React.ReactElement {
const theme = useTheme();
const setRerender = useState(false)[1]; const setRerender = useState(false)[1];
function rerender(): void { function rerender(): void {
setRerender((old) => !old); setRerender((old) => !old);
@ -35,99 +205,90 @@ export function FactionsRoot(props: IProps): React.ReactElement {
}); });
}, []); }, []);
function openFaction(faction: Faction): void {
props.router.toFaction(faction);
}
function openFactionAugPage(faction: Faction): void {
props.router.toFaction(faction, true);
}
function acceptInvitation(event: React.MouseEvent<HTMLButtonElement, MouseEvent>, faction: string): void {
if (!event.isTrusted) return;
joinFaction(Factions[faction]);
setRerender((x) => !x);
}
const getAugsLeft = (faction: Faction, player: IPlayer): number => {
const augs = getFactionAugmentationsFiltered(player, faction);
return augs.filter((augmentation: string) => !player.hasAugmentation(augmentation)).length;
};
const allFactions = Object.values(FactionNames).map((faction) => faction as string); const allFactions = Object.values(FactionNames).map((faction) => faction as string);
const allJoinedFactions = props.player.factions.slice(0); const allJoinedFactions = [...props.player.factions];
allJoinedFactions.sort((a, b) => allFactions.indexOf(a) - allFactions.indexOf(b)); allJoinedFactions.sort((a, b) => allFactions.indexOf(a) - allFactions.indexOf(b));
const invitations = props.player.factionInvitations;
return ( return (
<Container disableGutters maxWidth="md" sx={{ mx: 0, mb: 10 }}> <Container disableGutters maxWidth="lg" sx={{ mx: 0, mb: 10 }}>
<Typography variant="h4">Factions</Typography> <Typography variant="h4">
<Typography mb={4}> Factions
Throughout the game you may receive invitations from factions. There are many different factions, and each <Tooltip
faction has different criteria for determining its potential members. Joining a faction and furthering its cause title={
is crucial to progressing in the game and unlocking endgame content. <Typography>
Throughout the game you may receive invitations from factions. There are many different factions, and each
faction has different criteria for determining its potential members. Joining a faction and furthering its
cause is crucial to progressing in the game and unlocking endgame content.
</Typography>
}
>
<Info sx={{ ml: 1, mb: 0 }} color="info" />
</Tooltip>
</Typography> </Typography>
<Typography variant="h5" color="primary" mt={2} mb={1}> <Box
Factions you have joined: display="grid"
</Typography> sx={{
{(allJoinedFactions.length > 0 && ( gap: 1,
<Paper sx={{ my: 1, p: 1, pb: 0, display: "inline-block" }}> gridTemplateColumns: (invitations.length > 0 ? "1fr " : "") + "2fr",
<Table padding="none" style={{ width: "fit-content" }}> [theme.breakpoints.down("lg")]: { gridTemplateColumns: "1fr", "& > span:nth-child(1)": { order: 1 } },
<TableBody> gridTemplateRows: "minmax(0, 1fr)",
{allJoinedFactions.map((faction: string) => ( "& > span > .MuiBox-root": {
<TableRow key={faction}> display: "grid",
<TableCell> gridAutoRows: "70px",
<Typography noWrap mb={1}> gap: 1,
{faction} },
</Typography> }}
</TableCell> >
<TableCell align="right"> {invitations.length > 0 && (
<Box ml={1} mb={1}> <span>
<Button onClick={() => openFaction(Factions[faction])}>Details</Button> <Typography variant="h5" color="primary">
</Box> Faction Invitations
</TableCell> </Typography>
<TableCell align="right"> <Box>
<Box ml={1} mb={1}> {invitations.map((facName) => {
<Button sx={{ width: "100%" }} onClick={() => openFactionAugPage(Factions[faction])}> if (!Factions.hasOwnProperty(facName)) return null;
Augmentations Left: {getAugsLeft(Factions[faction], props.player)} return (
</Button> <FactionElement
</Box> key={facName}
</TableCell> faction={Factions[facName]}
</TableRow> player={props.player}
))} router={props.router}
</TableBody> joined={false}
</Table> rerender={rerender}
</Paper> />
)) || <Typography>You haven't joined any factions.</Typography>} );
<Typography variant="h5" color="primary" mt={4} mb={1}> })}
Outstanding Faction Invitations </Box>
</Typography> </span>
<Typography mb={1}> )}
Factions you have been invited to. You can accept these faction invitations at any time:
</Typography> <span>
{(props.player.factionInvitations.length > 0 && ( <Typography variant="h5" color="primary">
<Paper sx={{ my: 1, mb: 4, p: 1, pb: 0, display: "inline-block" }}> Your Factions
<Table padding="none"> </Typography>
<TableBody> <Box>
{props.player.factionInvitations.map((faction: string) => ( {allJoinedFactions.length > 0 ? (
<TableRow key={faction}> allJoinedFactions.map((facName) => {
<TableCell> if (!Factions.hasOwnProperty(facName)) return null;
<Typography noWrap mb={1}> return (
{faction} <FactionElement
</Typography> key={facName}
</TableCell> faction={Factions[facName]}
<TableCell align="right"> player={props.player}
<Box ml={1} mb={1}> router={props.router}
<Button onClick={(e) => acceptInvitation(e, faction)}>Join!</Button> joined={true}
</Box> rerender={rerender}
</TableCell> />
</TableRow> );
))} })
</TableBody> ) : (
</Table> <Typography>You have not yet joined any Factions.</Typography>
</Paper> )}
)) || <Typography>You have no outstanding faction invites.</Typography>} </Box>
</span>
</Box>
</Container> </Container>
); );
} }