1
0

HouseRules.tsx is fully functional!

This commit is contained in:
James Ketr 2025-09-26 18:39:28 -07:00
parent e1eaf49b7c
commit 95db2475b2
2 changed files with 199 additions and 112 deletions

View File

@ -32,6 +32,7 @@ import volcanoTile from "./assets/single-volcano.png";
import { GlobalContext } from "./GlobalContext"; import { GlobalContext } from "./GlobalContext";
import { Placard } from "./Placard"; import { Placard } from "./Placard";
import Box from "@mui/material/Box/Box"; import Box from "@mui/material/Box/Box";
import { Typography } from "@mui/material";
const categoryImages: { [key: string]: string } = { const categoryImages: { [key: string]: string } = {
board: boardImg, board: boardImg,
@ -256,11 +257,16 @@ const VictoryPoints: React.FC<VictoryPointsProps> = ({ ws, rules, field }) => {
}; };
return ( return (
<div className="VictoryPoints"> <Box className="VictoryPoints" sx={{display: 'flex', flexDirection: 'column', gap: 2, marginTop: 2}}>
<b>{points}</b> points. <Box>
The first to reach <b>{points}</b> points wins!
<Button onClick={() => update(+1)}>up</Button>&nbsp;/&nbsp; <Button onClick={() => update(+1)}>up</Button>&nbsp;/&nbsp;
<Button onClick={() => update(-1)}> down</Button> <Button onClick={() => update(-1)}> down</Button>
</div> </Box>
<Box>
This flexible twist of a rule lets you customize the number of Victory Points needed to claim victory, whether youre aiming for a quick 7-point skirmish or a marathon 12-point conquest. Adjust the goal to match your moodkeep it low for a fast-paced showdown or crank it up for an epic battle of strategy and luck, ensuring every game feels fresh and perfectly suited to your crews competitive spirit!
</Box>
</Box>
); );
}; };
@ -269,7 +275,10 @@ interface HouseRulesProps {
setHouseRulesActive: React.Dispatch<React.SetStateAction<boolean>>; setHouseRulesActive: React.Dispatch<React.SetStateAction<boolean>>;
} }
const HouseRules: React.FC<HouseRulesProps> = ({ houseRulesActive, setHouseRulesActive }) => { const HouseRules: React.FC<HouseRulesProps> = ({
houseRulesActive,
setHouseRulesActive,
}) => {
const { ws, name } = useContext(GlobalContext); const { ws, name } = useContext(GlobalContext);
const [rules, setRules] = useState<any>({}); const [rules, setRules] = useState<any>({});
const [state, setState] = useState<any>({}); const [state, setState] = useState<any>({});
@ -340,108 +349,184 @@ const HouseRules: React.FC<HouseRulesProps> = ({ houseRulesActive, setHouseRules
); );
const ruleList = useMemo( const ruleList = useMemo(
() => [ () =>
{ [
key: "volcano", {
label: "Volcanoes are a lava fun!", key: "volcano",
description: "A volcano is on the island! Let the lava flow!", label: "Volcanoes are a lava fun!",
category: "board", description: "A volcano is on the island! Let the lava flow!",
defaultChecked: false, category: "board",
element: ( defaultChecked: false,
<Volcano element: (
ws={ws} <Volcano
rules={rules} ws={ws}
field={"volcano"} rules={rules}
disabled={gameState !== "lobby"} field={"volcano"}
/> disabled={gameState !== "lobby"}
), />
}, ),
{ },
key: "victory-points", {
label: "More victory points", key: "victory-points",
description: "Customize how many Victory Points are required to win.", label: "More victory points",
category: "rules", description: "Customize how many Victory Points are required to win.",
defaultChecked: false, category: "rules",
element: ( defaultChecked: false,
<VictoryPoints ws={ws} rules={rules} field={"victory-points"} /> element: (
), <VictoryPoints ws={ws} rules={rules} field={"victory-points"} />
}, ),
{ },
key: "tiles-start-facing-down", {
label: "Tiles start facing down", key: "tiles-start-facing-down",
description: label: "Tiles start facing down",
"Resource tiles start upside-down while placing starting settlements.", description:
category: "board", "Resource tiles start upside-down while placing starting settlements.",
defaultChecked: false, category: "board",
element: ( defaultChecked: false,
<div> element: (
Once all players have placed their initial settlements and roads, <div>
the tiles are flipped and you discover what the resources are. Once all players have placed their initial settlements and roads,
</div> the tiles are flipped and you discover what the resources are.
), </div>
}, ),
{ },
key: "most-developed", {
label: "You are so developed!", key: "most-developed",
description: label: "You are so developed!",
"The player with the most development cards (more than 4) receives 2VP.", description:
category: "expansion", "The player with the most development cards (more than 4) receives 2VP.",
defaultChecked: false, category: "expansion",
element: <Placard type="most-developed" />, defaultChecked: false,
}, element: (
{ <Box sx={{ display: "block", flexDirection: "column" }}>
key: "port-of-call", <Placard
label: "Another round of port?", sx={{
description: float: "left",
"The player with the most harbor ports (more than 2) receives 2VP.", shapeOutside: "inset(0)" /* Text wraps the full rectangle */,
category: "expansion", clipPath: "inset(0)" /* Ensures proper wrapping area */,
defaultChecked: false, marginRight: "1rem",
element: <Placard type="port-of-call" />, marginBottom: "1rem",
}, }}
{ type="most-developed"
key: "slowest-turn", />
label: "Why you play so slow?", <Typography variant="body2">
description: This card rewards the player who amasses more than 4 development
"The player with the longest turn idle time (longer than 2 minutes) so far loses 2VP.", cards with a glorious 2 Victory Points, turning your strategic
category: "expansion", savvy into a medieval masterpiece complete with towering cities
defaultChecked: false, and bustling fields. Picture yourself snagging this beautifully
element: <Placard type="longest-turn" />, illustrated cardfeaturing hardworking villagers and a majestic
}, castle!
{ </Typography>
key: "roll-double-roll-again", </Box>
label: "Roll double, roll again", ),
description: "Roll again if you roll two of the same number.", },
category: "rolling", {
defaultChecked: false, key: "port-of-call",
element: ( label: "Another round of port?",
<div> description:
If you roll doubles, players get those resources and then you must "The player with the most harbor ports (more than 2) receives 2VP.",
roll again. category: "expansion",
</div> defaultChecked: false,
), element: (
}, <Box sx={{ display: "block", flexDirection: "column" }}>
{ <Placard
key: "twelve-and-two-are-synonyms", sx={{
label: "Twelve and Two are synonyms", float: "left",
description: "If twelve is rolled, two scores as well. And vice-versa.", shapeOutside: "inset(0)" /* Text wraps the full rectangle */,
category: "rolling", clipPath: "inset(0)" /* Ensures proper wrapping area */,
defaultChecked: false, marginRight: "1rem",
element: ( marginBottom: "1rem",
<div> }}
If you roll a twelve or two, resources are triggered for both. type="port-of-call"
</div> />
), <Typography variant="body2">
}, Raise your mugs and hoist the sails! This lively card rewards
{ the most seasoned seafarer among the settlers. When you control
key: "robin-hood-robber", more than two harbor ports, you claim this card and earn 2
label: "Robin Hood robber", Victory Points as a tribute to your mastery of the seas. But
description: beware other ambitious captains are watching closely! The
"Robbers can't steal from players with two or less victory points.", moment someone else builds a larger network of harbors, theyll
category: "rules", steal both the card and the glory right from under your nose.
defaultChecked: false, Keep those ships moving and never let your rivals toast to your
element: <></>, downfall!
}, </Typography>
].sort((a, b) => a.category.localeCompare(b.category)), </Box>
),
},
{
key: "slowest-turn",
label: "Why you play so slow?",
description:
"The player with the longest turn idle time (longer than 2 minutes) so far loses 2VP.",
category: "expansion",
defaultChecked: false,
element: (
<Box sx={{ display: "block", flexDirection: "column" }}>
<Placard
sx={{
float: "left",
shapeOutside: "inset(0)" /* Text wraps the full rectangle */,
clipPath: "inset(0)" /* Ensures proper wrapping area */,
marginRight: "1rem",
marginBottom: "1rem",
}}
type="longest-turn"
/>
<Typography variant="body2" sx={{ marginTop: "1rem" }}>
If your turn idle time drags on past 2 minutes, youre slapped
with a -2 Victory Points penalty and handed this charming
cardfeaturing industrious villagers raking hay with a castle
looming in the backgrounduntil someone even slower takes it
from you with a sheepish grin!
</Typography>
</Box>
),
},
{
key: "roll-double-roll-again",
label: "Roll double, roll again",
description: "Roll again if you roll two of the same number.",
category: "rolling",
defaultChecked: false,
element: (
<div>
If you roll doubles, players get those resources and then you must
roll again.
<Box sx={{ display: "block", fontWeight: "bold", pt: 1, pb: 1 }}>
Note:
</Box>
This stacks with Two and Twelve are Synonyms. So if you roll double ones (2), you get resources for 2 and 12, then roll again!
</div>
),
},
{
key: "twelve-and-two-are-synonyms",
label: "Twelve and Two are synonyms",
description:
"If twelve is rolled, two scores as well. And vice-versa.",
category: "rolling",
defaultChecked: false,
element: (
<div>
If you roll a twelve or two, resources are triggered for both.
<Box sx={{ display: "block", fontWeight: "bold", pt: 1, pb: 1 }}>
Note:
</Box>{" "}
This stacks with Roll Double, Roll Again. So if you roll double
sixes (12), you get resources for 2 and 12, then roll again!
</div>
),
},
{
key: "robin-hood-robber",
label: "Robin Hood robber",
description:
"Robbers can't steal from players with two or less victory points.",
category: "rules",
defaultChecked: false,
element: <></>,
},
].sort((a, b) => a.category.localeCompare(b.category)),
[rules, setRules, state, ws, setRule, name, gameState] [rules, setRules, state, ws, setRule, name, gameState]
); );

View File

@ -2,6 +2,8 @@ import React, { useContext, useCallback } from "react";
import "./Placard.css"; import "./Placard.css";
import { assetsPath } from "./Common"; import { assetsPath } from "./Common";
import { GlobalContext } from "./GlobalContext"; import { GlobalContext } from "./GlobalContext";
import { SxProps, useTheme } from '@mui/material/styles';
import Box from "@mui/material/Box/Box";
type PlacardProps = { type PlacardProps = {
type?: string; type?: string;
@ -10,9 +12,10 @@ type PlacardProps = {
buildActive?: boolean; buildActive?: boolean;
setBuildActive?: (b: boolean) => void; setBuildActive?: (b: boolean) => void;
className?: string; className?: string;
sx?: SxProps;
}; };
const Placard: React.FC<PlacardProps> = ({ type, disabled, count, buildActive, setBuildActive, className }) => { const Placard: React.FC<PlacardProps> = ({ type, disabled, count, buildActive, setBuildActive, className, sx }) => {
const { ws } = useContext(GlobalContext); const { ws } = useContext(GlobalContext);
const sendMessage = useCallback( const sendMessage = useCallback(
(data: Record<string, unknown>) => { (data: Record<string, unknown>) => {
@ -85,20 +88,19 @@ const Placard: React.FC<PlacardProps> = ({ type, disabled, count, buildActive, s
if (!disabled) { if (!disabled) {
return ( return (
<div <Box sx={{...sx, ...style}}
className={`Placard${buildActive ? " Selected" : ""} ${className || ""}`} className={`Placard${buildActive ? " Selected" : ""} ${className || ""}`}
onClick={buildClicked} onClick={buildClicked}
data-type={t} data-type={t}
style={style}
> >
{buttons} {buttons}
</div> </Box>
); );
} }
return ( return (
<div className={`Placard${buildActive ? " Selected" : ""} ${className || ""}`} data-type={t} style={style}> <Box sx={{...sx, ...style}} className={`Placard${buildActive ? " Selected" : ""} ${className || ""}`} data-type={t}>
{count && <div className="Right">{count}</div>} {count && <div className="Right">{count}</div>}
</div> </Box>
); );
}; };