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
<Tooltip
title={
<Typography>
Throughout the game you may receive invitations from factions. There are many different factions, and each 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 faction has different criteria for determining its potential members. Joining a faction and furthering its
is crucial to progressing in the game and unlocking endgame content. 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"
sx={{
gap: 1,
gridTemplateColumns: (invitations.length > 0 ? "1fr " : "") + "2fr",
[theme.breakpoints.down("lg")]: { gridTemplateColumns: "1fr", "& > span:nth-child(1)": { order: 1 } },
gridTemplateRows: "minmax(0, 1fr)",
"& > span > .MuiBox-root": {
display: "grid",
gridAutoRows: "70px",
gap: 1,
},
}}
>
{invitations.length > 0 && (
<span>
<Typography variant="h5" color="primary">
Faction Invitations
</Typography> </Typography>
{(allJoinedFactions.length > 0 && ( <Box>
<Paper sx={{ my: 1, p: 1, pb: 0, display: "inline-block" }}> {invitations.map((facName) => {
<Table padding="none" style={{ width: "fit-content" }}> if (!Factions.hasOwnProperty(facName)) return null;
<TableBody> return (
{allJoinedFactions.map((faction: string) => ( <FactionElement
<TableRow key={faction}> key={facName}
<TableCell> faction={Factions[facName]}
<Typography noWrap mb={1}> player={props.player}
{faction} router={props.router}
</Typography> joined={false}
</TableCell> rerender={rerender}
<TableCell align="right"> />
<Box ml={1} mb={1}> );
<Button onClick={() => openFaction(Factions[faction])}>Details</Button> })}
</Box> </Box>
</TableCell> </span>
<TableCell align="right"> )}
<Box ml={1} mb={1}>
<Button sx={{ width: "100%" }} onClick={() => openFactionAugPage(Factions[faction])}> <span>
Augmentations Left: {getAugsLeft(Factions[faction], props.player)} <Typography variant="h5" color="primary">
</Button> Your Factions
</Typography>
<Box>
{allJoinedFactions.length > 0 ? (
allJoinedFactions.map((facName) => {
if (!Factions.hasOwnProperty(facName)) return null;
return (
<FactionElement
key={facName}
faction={Factions[facName]}
player={props.player}
router={props.router}
joined={true}
rerender={rerender}
/>
);
})
) : (
<Typography>You have not yet joined any Factions.</Typography>
)}
</Box> </Box>
</TableCell> </span>
</TableRow>
))}
</TableBody>
</Table>
</Paper>
)) || <Typography>You haven't joined any factions.</Typography>}
<Typography variant="h5" color="primary" mt={4} mb={1}>
Outstanding Faction Invitations
</Typography>
<Typography mb={1}>
Factions you have been invited to. You can accept these faction invitations at any time:
</Typography>
{(props.player.factionInvitations.length > 0 && (
<Paper sx={{ my: 1, mb: 4, p: 1, pb: 0, display: "inline-block" }}>
<Table padding="none">
<TableBody>
{props.player.factionInvitations.map((faction: string) => (
<TableRow key={faction}>
<TableCell>
<Typography noWrap mb={1}>
{faction}
</Typography>
</TableCell>
<TableCell align="right">
<Box ml={1} mb={1}>
<Button onClick={(e) => acceptInvitation(e, faction)}>Join!</Button>
</Box> </Box>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</Paper>
)) || <Typography>You have no outstanding faction invites.</Typography>}
</Container> </Container>
); );
} }