diff --git a/src/App.tsx b/src/App.tsx index 79bc138..87bcffe 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,30 +10,26 @@ import { import { Creature, Card } from "./engine/card"; import { Ability } from "./engine/ability"; import { get } from "./engine/CardMap"; -import { G } from "vitest/dist/reporters-MmQN-57K.js"; +import { G, an } from "vitest/dist/reporters-MmQN-57K.js"; + -var log = []; -log.push(
Player 1 activated "Spell name!"
); -log.push(
Player 2 activated "Spell name!"
); -log.push(
Player 1 summoned "Monster name!"
); -log.push(
Player 2 summoned "Monster name!"
); /** * v0 by Vercel. * @see https://v0.dev/t/WuNN16G0fnd * Documentation: https://v0.dev/docs#integrating-generated-code-into-your-nextjs-app - * - * + * @author Tanner Brown + * This has changed a lot since I've made it so let me redo the documentation. Renders a card with onclick/onhover functionality. "state" is poorly named. * @returns Returns a card component - * @param cardName: the actual name of the card, cardText: the description of the text on the card, - * actionCost: the cost of the card, landscapeType: the type of landscape that the card needs, - * imagePath: the location of the image for the card. this is made for spell/building cards + * @param card: the card to render. state: sets the summoning buttons state to a number that makes it true or something. setHover: changes state on the hover useState. + * essentially, it just makes the magnified card the hovered card. currentplayer: the current player (needed for making events turn exclusive). ownerPlayer: the + * player the cards are assigned to. phase: current turn phase. needed for making events phase exclusive */ function CardComponent({ card, - children, state, position, + setHover, currentPlayer, ownerPlayer, phase @@ -41,20 +37,23 @@ function CardComponent({ card: Card | Creature; children?: ReactNode; state: React.Dispatch>, - position: number + setHover: any, + position: number, currentPlayer: Player, ownerPlayer: Player, phase: number }) { function handleClick(){ + //in future, if we add spells/buildings again there should be an if statement for activating those if(card instanceof Creature){ + // if the card being clicked belongs to the current turn player if(currentPlayer.id==ownerPlayer.id){ + // if the current phase is the main phase if(phase==0){ + //why did i make this a number instead of a boolean? am i stupid or something? state(position); } - } - // mark pos of hand } // else if (card instanceof Building){ @@ -66,7 +65,9 @@ function CardComponent({ } return ( ); } - +/** + * @author Tanner Brown + * I spoke about this in my documentation on the CreatureComponentOnBoard component. Check there for why this is a thing + * @param param0 + * @returns + */ function CardComponentOnBoard({ card, - children + setHover }: { card: Card | Creature; children?: ReactNode; + setHover: any }) { return ( @@ -150,15 +141,17 @@ function CreatureComponent({ card, state, position, + setHover, currentPlayer, ownerPlayer, phase }: { card: Creature, state: React.Dispatch>, - position: number, + setHover: any, currentPlayer: Player, ownerPlayer: Player, + position: number, phase: number }) { let child = ( @@ -171,20 +164,27 @@ function CreatureComponent({ {child} ); } - +/** + * Kinda dumb, but since cards on board have different function than ones in hand I felt this was necessary. Currently, this just is the other creature/card + * component but without triggering summoning buttons + * @param param0 + * @returns + */ function CreatureComponentOnBoard({ - card + card, setHover }: { card: Creature +setHover: any }) { let child = ( <> @@ -195,39 +195,88 @@ let child = ( return ( - {child} ); } /** + * @author Tanner Brown + * So basically this is the markup that sits on the left of the screen. If its null (ie. no one has hovered a card yet) then its blank. However, if a card + * (whether it be field or hand) is hovered we show it here. It's essentially a magnified version of the card so you don't have to break out the reading glasses + * to read a card. + * @param param0 + * @returns + */ +function HoverCard({card}: {card: Creature}){ + if(card===null){ + return( +
+ +
+ ) + } + return ( +
+
+ {card.name} +
+
+

{card.name}

+

{card.flavorText}

+
+
+ AC: {card.getCost()} Type: {card.landscapeType}{" "} +
+
+ +
Attack: {card.attack}
+
Defense: {card.defense}
+
+
+
+ ) +} +/** + * @author Tanner Brown * Displays card shape with a number on it indicating how many cards are in the pile. This one has onclick to allow player to draw * @returns returns markup displaying what i wrote just above + * @param player: the player whom the deck belongs to. resetState: state to cause re-render. reset: variable necessary for determining re-render. + * log: the log. needed for if player cannot draw anymore and game must tell player as such. setLog: useState for re-rendering log. game: the game object */ -function Deck({ player, setGameState, game}: { player: Player, setGameState: any, game: Game}) { - let handleDraw = function () { - let boolean = player.drawCardUsingAction(); - setGameState(game); - if (!boolean) { - console.log("it was false!!!") - log.push( -
- {player.username} attempted to draw, but does not have enough actions. -
, - ); +function Deck({ player, resetState, reset, log, setLog, game}: { player: Player, resetState: any, reset: number, log: any, setLog: any, game: Game}) { + function handleDraw() { + if(player===game.currentPlayer){ + if(game.turnPhase==0){ + if(!player.drawCardUsingAction()){ + setLog([...log,
{player.username} attempted to draw, but lacks the actions to
]) + } + resetState(dumbStupidFunction(reset)); + } } - }; return ( + ); } @@ -238,7 +287,7 @@ function Deck({ player, setGameState, game}: { player: Player, setGameState: any */ function DiscardPile({ size }: { size: number }) { return ( -
+
{size}
@@ -248,12 +297,15 @@ function DiscardPile({ size }: { size: number }) { /** * Creates markup that displays players hand * @author Tanner Brown - * @returns Array of CardComponents/CreatureComponents + * @returns a rendered hand of cards\ + * @param playerHand: the actual hand we'll render. stateChange: another poorly named variable? what was i thinking? anyways this is the statechange for letting + * the summoning buttons appear. currentPlayer: the current player. needed for turn exclusivity reasons. ownerPlayer: the player who owns the cards in hand. + * phase: the current turn phase. needed for exclusivity reasons. setHover: statechange for magnifying cards. */ -function HandOfCards({ playerHand, stateChange, currentPlayer, ownerPlayer, phase}: - { playerHand: Card[], stateChange: React.Dispatch>, currentPlayer: Player, ownerPlayer: Player, phase: number}) { +function HandOfCards({ playerHand, stateChange, currentPlayer, ownerPlayer, phase, setHover}: + { playerHand: Card[], stateChange: React.Dispatch>, currentPlayer: Player, ownerPlayer: Player, phase: number, setHover: any}) { let shownHand = []; - console.log(playerHand) + //create players hand for (let i = 0; i < playerHand.length; i++) { let currentCard = playerHand[i]; if (currentCard instanceof Creature) { @@ -261,18 +313,22 @@ function HandOfCards({ playerHand, stateChange, currentPlayer, ownerPlayer, phas CreatureComponent({ card: currentCard, state: stateChange, - position: i, + setHover: setHover, ownerPlayer: ownerPlayer, currentPlayer: currentPlayer, + position: i, phase: phase }), ); + //not really relevant anymore since back-end axed spells/buildings, but in case we have time and they re-implement them i see no reason to remove this + // else statement. currently does not execute } else { shownHand.push( CardComponent({ card: currentCard, state: stateChange, + setHover: setHover, position: i, ownerPlayer: ownerPlayer, currentPlayer: currentPlayer, @@ -286,27 +342,37 @@ function HandOfCards({ playerHand, stateChange, currentPlayer, ownerPlayer, phas } /** - * + *@author Tanner Brown * Board loops through the board (the actual array that keeps track of the board) to display each * creature, building in the array inside of each landscape inside of a larger board. * @returns markup that displays the board. + * @param game: the actual game object. board: the board from the game. why do i pass this as a parameter even? setHover: magnify the cards when hovered. */ -function Board({ game, }: { game: Game}) { +function Board({ game, board, setHover}: { game: Game, board: SidedBoard, setHover: any}) { let p1Board = []; let p2Board = []; - let board = game.board; + + let p1 = game.getPlayerById(0); + let p2 = game.getPlayerById(1); + let t = board.getSideByOwnerId(0); //Looping through board to display it for (let i = 0; i < 4; i++) { p1Board.push( LandscapeCard({ creature: board.getBoardPosByOwnerId(0, i)?.creature, + player: p1, + landscapeColor: board.getBoardPosByOwnerId(p1.id, i)?.landscape, + setHover: setHover //building: game.board.getBoardPosByOwnerId(0, i)?.building }), ); - + p2Board.push( LandscapeCard({ creature: board.getBoardPosByOwnerId(1, i)?.creature, + player: p2, + landscapeColor: board.getBoardPosByOwnerId(p1.id, i)?.landscape, + setHover: setHover //building: game.board.getBoardPosByOwnerId(1, i)?.building, }), ); @@ -330,34 +396,43 @@ function Board({ game, }: { game: Game}) { ); } /** + * @author Tanner Brown * This method will take in a Creature and building from a given "landscape card" from the backend. This will * then dynamically render them inside of the landscape. * @returns markup that displays a landscape box with building and creature optionally inside + * @param creature: the creature in the landscape. player: the player. needed for dynamic css reasons. landscape color: the landscape type. setHover: magnify cards + * when hovered oooooh so cool */ function LandscapeCard({ //building, creature, + player, + landscapeColor, + setHover }: { //building: Building | undefined; creature: Creature | undefined; + player: Player; + landscapeColor: string; + setHover: any; }) { //c is creature, b is building. default values are empty tags (is that what they're called?) let c; let b = <>; // check if creature is undefined - console.log(creature?.name); if (creature?.name === "Null") { c = (<>) } else{ - c = CreatureComponentOnBoard({card: creature}); + c = CreatureComponentOnBoard({card: creature, setHover: setHover}); } // check if building is undefined // if (building?.name == null) { // b = CardComponent({card: building}); // } + return ( -
+
{c} {/* {b} */}
@@ -365,13 +440,16 @@ function LandscapeCard({ } /** + * @author Tanner Brown + * Man I really should've updated my documentation as I went instead of putting it off. My fingers are getting TIRED. Anyways, + * * Block that shows players hp, username, and actions - * @param game object (probably temporarily) and a player id (0 or 1) + * @param player: gotta know which player we rendering * @returns markup that shows what I just wrote above */ -function PlayerDisplay({ game, player }: { game: Game; player: Player }) { +function PlayerDisplay({player }: {player: Player }) { return ( -
+

{player.username}username

HP: {player.hp} @@ -383,95 +461,128 @@ function PlayerDisplay({ game, player }: { game: Game; player: Player }) { } function getDemoPlayer(player: Player) { player.deck.push(get("Dark Angel")!); + player.deck.push(get("Swamp Dragon")!); player.deck.push(get("Dark Angel")!); - // player.deck.push(get("Dark Angel")!); - player.deck.push(get("Dark Angel")!); + player.deck.push(get("Swamp Dragon")!); player.deck.push(get("Dark Angel")!); player.hand.push(get("Dark Angel")!); + player.hand.push(get("Swamp Dragon")!); player.hand.push(get("Dark Angel")!); - // player.hand.push(get("Dark Angel")!); - player.hand.push(get("Dark Angel")!); + player.hand.push(get("Swamp Dragon")!); player.hand.push(get("Dark Angel")!); } /** + * @author Tanner Brown * This is like the big daddy of the components. This makes up pretty much the entire game. Shows players board, hp, hands, etc etc. + * + * How very descript me from a few weeks ago. Anyways yeah this is where everything goes on. We manage state here and stuff. I don't + * think a paragraph of documentation is fit for the massive wall of text that this component is so I'll just document as we go, okay? + * * @returns Markup to display the game + * @param game: the game object we're rendering. setBegin: when we set this as true the game ends and we go backto deck select screen */ -function GameBoard({ game, setGameState }: { game: Game, setGameState: React.Dispatch> }) { - //States: - - const [summoningCard, setSummoningCard] = useState(-1); - //const[board, setBoard] = useState(game.board); - console.log(setGameState); - +function GameBoard({ game, setBegin }: { game: Game, setBegin: any}) { + // grab our players. a lot of components need this guys as parameters let player1 = game.getPlayerById(0); let player2 = game.getPlayerById(1); + // same for him + let board = game.board; + //States: + const [turn, setTurn] = useState(game.currentTurn); //good + const [phase, setPhase] = useState(game.turnPhase); //good + const [currentPlayer, setCurrentPlayer] = useState(game.currentPlayer);// good(?) + const [log, setLog] = useState([<>]); + const [reset, setReset] = useState(-1); + const [summoningCard, setSummoningCard] = useState(-1); //good + const [hoverCard, setHoverCard] = useState(null); + let buttons1 = (<>) let buttons2 = (<>) - if(game.turnPhase==0){ - if(summoningCard+1){ - if(game.currentPlayer.id==0){ - buttons1 = + //only in main phase can we summon + if(phase==0){ + //Anyways, if we're summoning a card then these buttons need to render (for player 1 or two depending). otherwise they'll stay empty + if(summoningCard>-1){ + if(currentPlayer.id==0){ + buttons1 = } else{ - buttons2 = + buttons2 = } } } - else if(game.turnPhase==1){ - if(game.currentPlayer.id==0){ - buttons1 = + //if we're in battle phase then we need to render the attacking buttons + else if(phase==1){ + if(currentPlayer.id==0){ + buttons1 = } else{ - buttons2 = + buttons2 = } } - + + // you should probably just ignore this. its probaly not important. forget you ever saw it + let dumbStupidVariable = <> + if(reset==0){ + dumbStupidVariable=<><> + } + else if(reset==1){ + dumbStupidVariable=<><><> + } + return (
+ {dumbStupidVariable}
- {buttons2} + {/*buttons2 are summoning buttons */} {/*Gonna need to comment much of this just so we're aware of what is happening in some of these.*/} {/*This div is a row that shows a players stats and then their hand of cards*/}




+ {/*rendered in a seperate div so they'll be in a row*/}
- +
{buttons2}
{/*This div pretty large. It's where discard piles, decks, and the actual board goes*/} -
+
+ + {/*the magnified card*/} + {/*This column shows a deck and discard pile*/}
- - - + + +
{/*The board between two columns*/} - + {/*This is a row of two columns*/}
{/*The first column shows the deck and discard pile (like the one you saw earlier*/}
- - - + + +
{/*This column shows the game log text bot and the button for moving phases below it*/}
@@ -481,19 +592,33 @@ function GameBoard({ game, setGameState }: { game: Game, setGameState: React.Dis {buttons1}
- +
); } - -function SummoningButtons({cardPos, game, setSummonState, hand, setGame, playerid}: {cardPos: number, game: Game, setSummonState: any, - hand: Card[], setGame: any, playerid: number}){ - +/** + * @author Tanner Brown + * I always thought it was weird that common practice was to put an author on these. Like, I get its so down the line someone can call you up and be like + * "why does your code suck?", but I can't shake the feeling like I'm a child writing my name on my toys so no one else can play with them. + * + * Anyways, summoning buttons are the buttons that render when we're summoning a card. 4 buttons show up; one for each zone. + * @param cardPos: the position in hand the card we're summoning is. game: the game object. setSummonState: the state that controls when the buttons are rendering. + * marked -1 to make buttons disappear after we summon. playerid: the id of the player who will be summoning the card. log/setLog: the log the game keeps + * and the function to update it + * @returns markup for summoning buttons + */ +function SummoningButtons({cardPos, game, setSummonState, playerid, log, setLog}: {cardPos: number, game: Game, setSummonState: any, + board: any, playerid: number, log: any, setLog: any}){ function handle(boardPos: number, playerid: number){ - game.summonCardFromHand(playerid,boardPos, cardPos) - setGame(game); + let name = game.summonCardFromHand(playerid,boardPos, cardPos) + if(name){ + setLog([...log,
{game.getPlayerById(playerid).username} summoned the "{name}" at zone {boardPos+1}
]) + } + else{ + setLog([...log,
{game.getPlayerById(playerid).username} attempted to summon a creature, but lacks the actions
]) + } setSummonState(-1); } return( @@ -511,15 +636,26 @@ function SummoningButtons({cardPos, game, setSummonState, hand, setGame, playeri handle(3, playerid); }}>Zone 4
- ) } -function AttackingButtons({player, game, setGame}: {player: Player, game: Game, setGame: any}){ +/** + * @author Tanner Brown + * + * These are the buttons that show up during battle phase and let you attack. if an attack kills the opponent then we alert and reset the game + * @param player: the player who will be attacking. game: the game object. reset/setReset: variable and function for controlling re-render. setbegin: need this + * to return to deck select screen + * @returns mark up for attacking buttons + */ +function AttackingButtons({player, game, reset, resetState, setBegin}: {player: Player, game: Game, reset: number, resetState: any, setBegin: any}){ let playerid = player.id; function handle(boardPos: number, playerid: number){ game.simulateCombat(boardPos, playerid); - setGame(game); + if(game.getOtherPlayer(player.id).hp <= 0){ + alert(`${player.username} has won. Press OK to return to deck select screen.`); + setBegin(false); + } + resetState(dumbStupidFunction(reset)); } return (
@@ -538,36 +674,43 @@ function AttackingButtons({player, game, setGame}: {player: Player, game: Game,
) } + + + /** * has a block of scrollable text showing player actions and shows turn and phase * @returns markup that displays the gamelog in the browser */ function GameLog({ - game, - setGame + turn, + phase, + currentPlayer, + log }: { - game: Game, - setGame: any + turn: number; + phase: number; + currentPlayer: Player; + log: any }) { let phaseName; - if(game.turnPhase==0){ + if(phase==0){ phaseName="Main phase"; } - else if(game.turnPhase==1){ + else if(phase==1){ phaseName="Battle phase"; } - else if(game.turnPhase==2){ + else if(phase==2){ phaseName="End phase"; } return ( <>
{log}
- Turn: {game.turnPhase} + Turn: {turn}

Phase: {phaseName}

- Turn Player: {game.currentPlayer.username} + Turn Player: {currentPlayer.username}test
); @@ -579,18 +722,24 @@ function GameLog({ function PhaseButton({ game, imagePath, - setGame, + setPhase, + setTurn, + setCurrentPlayer, setSummoning }: { game: Game; imagePath: string; - setGame: any, + setPhase: React.Dispatch>; + setTurn: React.Dispatch>; + setCurrentPlayer: React.Dispatch>; setSummoning: React.Dispatch> }) { function handle() { game.enterNextPhase(); - setGame(game); + setPhase(game.turnPhase); + setTurn(game.currentTurn); setSummoning(-1); + setCurrentPlayer(game.currentPlayer); } return (