Skip to content

Commit

Permalink
Merge pull request #42 from JollyGrin/feat/add-banished
Browse files Browse the repository at this point in the history
Feat/add banished
  • Loading branch information
JollyGrin authored Sep 29, 2024
2 parents 90444b2 + 7f090de commit 2f05fb9
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 81 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ Find instructions if you wish to setup your own game server.
- [x] add four cores deck import https://fourcores.xyz/api/tts/T33jdoAJy8PGY9Agq1fo
- [ ] add hand drawing mode (for mobile, just deck and hand)
- [x] add setting to flip enemy card upside down
- [x] add precon decks to default load
- [ ] banish cards from cemetary

## Feature ideas
- [ ] support 4players
- [ ] support battlebox (shared deck)

## Bugs
- [x] updating mana or rolling dice causes board state to clear
- [ ] graveyard sorting. Ensure that in the handle drag it ignores ordering conditions
- [x] graveyard sorting. Ensure that in the handle drag it ignores ordering conditions
- [ ] firefox maybe shows context menu on right click
- [x] right click modal, taps card

Expand Down
101 changes: 74 additions & 27 deletions src/components/organisms/GameBoard/Footer/Grave/DiscardModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,29 @@ import { Box, Grid, HStack } from "styled-system/jsx";
import { button } from "styled-system/recipes";

import { PiHandWithdrawFill as IconHand } from "react-icons/pi";
import { GiSilenced as IconBanish } from "react-icons/gi";
import { useHover } from "@/utils/hooks/useHover";
import { useRef } from "react";
import { GameStateActions } from "../..";
import { actDrawDiscard } from "@/utils/actions/discard";
import { actDrawDiscard, actToggleBanishCard } from "@/utils/actions/discard";

export const DiscardModalBody = (
props: {
cards: GridItem;
} & GameStateActions,
} & Partial<GameStateActions>,
) => {
function returnToHand(cardIndex: number) {
if (!props.setGridItems || !props.gridItems) return;
props.setGridItems(actDrawDiscard(props.gridItems, cardIndex));
}

function toggleBanish(cardIndex: number) {
if (!props.setGridItems || !props.gridItems) return;
props.setGridItems(actToggleBanishCard(props.gridItems, cardIndex));
}

const hasFunctions = !!props.setGridItems;

return (
<Grid
gridTemplateColumns="repeat(auto-fill, minmax(300px, 1fr))"
Expand All @@ -27,23 +36,36 @@ export const DiscardModalBody = (
overflowX="clip"
overflowY="scroll"
>
{props.cards?.map((card, index) => (
<Card
key={card.id}
card={card}
returnToHand={() => returnToHand(index)}
/>
))}
{props.cards
?.sort((a, b) => {
if (a.isBanished && b.isBanished) {
return 0; // no sorting if both are the same
}
return a.isBanished ? 1 : -1; // move banished cards to the bottom
})
?.map((card, index) => (
<Card
key={card.id}
card={card}
returnToHand={() => returnToHand(index)}
toggleBanish={() => toggleBanish(index)}
hasFunctions={hasFunctions}
/>
))}
</Grid>
);
};

const Card = ({
card,
returnToHand,
toggleBanish,
hasFunctions,
}: {
card: GameCard;
returnToHand(): void;
toggleBanish(): void;
hasFunctions: boolean;
}) => {
const hoverRef = useRef(null);
const isHovering = useHover(hoverRef);
Expand All @@ -57,29 +79,54 @@ const Card = ({
h="100%"
maxH="500px"
position="relative"
filter="saturate(1)"
filter={card.isBanished ? "saturate(0)" : "saturate(1)"}
_hover={{
filter: "saturate(1.75)",
filter: card.isBanished ? "" : "saturate(1.75)",
}}
>
<CardImage img={card.img} minH={"0"} />
<button
onClick={returnToHand}
className={button()}
style={{
position: "absolute",
bottom: "50%",
right: "calc(50% - 50px)",
opacity: isHovering ? 1 : 0.1,
width: "100px",
transition: "all 0.25s ease",
}}
<HStack
display={hasFunctions ? "flex" : "none"}
position="absolute"
bottom="50%"
right="calc(50% - 100px)"
>
<HStack gap={0}>
<p>Return</p>
<IconHand size="2rem" style={{ fontSize: "2rem", color: "white" }} />
</HStack>
</button>
<button
onClick={returnToHand}
className={button()}
style={{
opacity: isHovering ? 1 : 0.1,
width: "100px",
transition: "all 0.25s ease",
}}
>
<HStack gap={0}>
<p>Return</p>
<IconHand
size="2rem"
style={{ fontSize: "2rem", color: "white" }}
/>
</HStack>
</button>

<button
onClick={toggleBanish}
className={button()}
style={{
opacity: isHovering ? 1 : 0.1,
width: "100px",
transition: "all 0.25s ease",
}}
>
<HStack gap={0}>
<p>{card.isBanished ? "Unbanish" : "Banish"}</p>
<IconBanish
size="2rem"
style={{ fontSize: "2rem", color: "white" }}
/>
</HStack>
</button>
</HStack>
</Box>
);
};
23 changes: 18 additions & 5 deletions src/components/organisms/GameBoard/Footer/Grave/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { DiscardModalBody } from "./DiscardModal";
export const GraveTray = (props: GameStateActions) => {
const graveCards = props.gridItems[GRIDS.GRAVE];
const graveAmount = graveCards?.length ?? 0;
console.log({ graveAmount });
const hasCards = graveCards?.length > 0;

const [preview, setPreview] = useState(false);
Expand Down Expand Up @@ -51,7 +52,10 @@ export const GraveTray = (props: GameStateActions) => {
>
{graveAmount > 0 && (
<Box w="100px" h="120px" position="absolute">
<CardImage img={graveCards?.[0].img} minH={"0"} />
<CardImage
img={graveCards?.[graveAmount - 1 - 0].img}
minH={"0"}
/>
</Box>
)}

Expand All @@ -64,7 +68,10 @@ export const GraveTray = (props: GameStateActions) => {
top={9}
rotate="4deg"
>
<CardImage img={graveCards?.[1].img} minH={"0"} />
<CardImage
img={graveCards?.[graveAmount - 1 - 1].img}
minH={"0"}
/>
</Box>
)}

Expand All @@ -77,7 +84,10 @@ export const GraveTray = (props: GameStateActions) => {
top={8}
rotate="-2deg"
>
<CardImage img={graveCards?.[2].img} minH={"0"} />
<CardImage
img={graveCards?.[graveAmount - 1 - 2].img}
minH={"0"}
/>
</Box>
)}

Expand All @@ -90,7 +100,10 @@ export const GraveTray = (props: GameStateActions) => {
top={4}
rotate="3deg"
>
<CardImage img={graveCards?.[3].img} minH={"0"} />
<CardImage
img={graveCards?.[graveAmount - 1 - 3].img}
minH={"0"}
/>
</Box>
)}

Expand All @@ -103,7 +116,7 @@ export const GraveTray = (props: GameStateActions) => {
top={9}
rotate="0deg"
>
<CardImage img={graveCards?.[graveAmount - 1].img} minH={"0"} />
<CardImage img={graveCards?.[0].img} minH={"0"} />
</Box>
)}
</Grid>
Expand Down
17 changes: 13 additions & 4 deletions src/components/organisms/GameBoard/Header/PlayerBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import {
} from "react-icons/gi";
import { LiaDiceD6Solid as IconD6 } from "react-icons/lia";
import { FaDiceD20 as IconD20 } from "react-icons/fa";
import { ViewGraveyardModal } from "./ViewGraveyardModal";
import { Modal } from "@/components/atoms/Modal";
import { DiscardModalBody } from "../Footer/Grave/DiscardModal";

export const PlayerBox = ({
name,
Expand Down Expand Up @@ -52,9 +53,17 @@ export const PlayerBox = ({
return (
<>
{disclosure.isOpen && (
<ViewGraveyardModal
cards={player.state[GRIDS.GRAVE]}
onClose={disclosure.onClose}
<Modal
wrapperProps={{
open: disclosure.isOpen,
onOpenChange: disclosure.onClose,
}}
content={
<DiscardModalBody
cards={player?.state[GRIDS.GRAVE]}
gridItems={player?.state}
/>
}
/>
)}
<HStack fontSize="1rem" gap={1}>
Expand Down
44 changes: 0 additions & 44 deletions src/components/organisms/GameBoard/Header/ViewGraveyardModal.tsx

This file was deleted.

1 change: 1 addition & 0 deletions src/types/card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export type SorceryCard = {
type GameProps = {
id: string;
isTapped?: boolean;
isBanished?: boolean;
playerName?: string;
counter?: number;
};
Expand Down
13 changes: 13 additions & 0 deletions src/utils/actions/discard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,16 @@ export function actDrawDiscard(state: GameState, graveCardIndex: number) {
// Return the updated newState array to trigger a re-render
return newState;
}

export function actToggleBanishCard(state: GameState, graveCardIndex: number) {
const newState = [...state];

const newGrave = [...newState[GRIDS.GRAVE]];

const card = newGrave[graveCardIndex];
card.isBanished = !card.isBanished;
newGrave[graveCardIndex] = card;
newState[GRIDS.GRAVE] = newGrave;

return newState;
}

0 comments on commit 2f05fb9

Please sign in to comment.