Spaces:
Sleeping
Sleeping
import { ServerGame } from "@/hooks/serverGame"; | |
import { SelectElement } from "./Player"; | |
import { GameId } from "../../convex/aiTown/ids"; | |
import Button from "./buttons/Button"; | |
import { useQuery } from "convex/react"; | |
import { api } from "../../convex/_generated/api"; | |
import { Id } from '../../convex/_generated/dataModel'; | |
import { characters } from "../../data/characters"; | |
import { useEffect, useState } from "react"; | |
import { BaseTexture, SCALE_MODES, Spritesheet } from "pixi.js"; | |
import { Sprite, Stage } from "@pixi/react"; | |
import { Character } from "./Character"; | |
import { useSendInput } from "../hooks/sendInput"; | |
import { GameCycle } from "../../convex/aiTown/gameCycle"; | |
export type Vote = (id: GameId<'players'>) => void; | |
export function VotingName(gameCycle: GameCycle) { | |
switch (gameCycle.cycleIndex) { | |
case 2: | |
return { | |
name: 'Warewolf Vote', | |
desc: 'Select a player who is warewolf', | |
type: 'WarewolfVote', | |
}; | |
case 3: | |
return { | |
name: 'Player Kill', | |
desc: 'Select a player to kill', | |
type: 'PlayerKill', | |
}; | |
default: | |
return { | |
name: 'Error', | |
desc: 'Select a player to vote', | |
type: 'Error' | |
}; | |
} | |
} | |
export const VoteModal = ({ | |
worldId, | |
engineId, | |
game, | |
}: { | |
worldId: Id<'worlds'>, | |
engineId: Id<'engines'>, | |
game: ServerGame, | |
}) => { | |
const [hasVoted, setHasVoted] = useState<boolean>(false); | |
const vote = useSendInput(engineId, 'vote'); | |
const onVote = (playerId: GameId<'players'>) => { | |
if (hasVoted) return; | |
vote({votedPlayerId: playerId, voteType: gameState}); | |
setHasVoted(true); | |
} | |
const gameState = "warewolf-vote" | |
const humanTokenIdentifier = useQuery(api.world.userStatus, {worldId}); | |
const [spriteSheet, setSpriteSheet] = useState<Spritesheet>(); | |
const character = characters[0] | |
useEffect(() => { | |
const parseSheet = async () => { | |
const sheet = new Spritesheet( | |
BaseTexture.from(character.textureUrl, { | |
scaleMode: SCALE_MODES.NEAREST, | |
}), | |
character.spritesheetData, | |
); | |
await sheet.parse(); | |
setSpriteSheet(sheet); | |
}; | |
void parseSheet(); | |
}, []); | |
// TODO only let people select non-dead players | |
const selectablePlayers = [...game.world.players.values()].filter( | |
(player) => player.id !== humanTokenIdentifier | |
); | |
return ( | |
<> | |
<div className="flex flex-col items-center mb-4"> | |
<h2 className="text-2xl font-bold">{VotingName(game.world.gameCycle).name}</h2> | |
<p className="text-lg">{VotingName(game.world.gameCycle).desc}</p> | |
</div> | |
{selectablePlayers.map((playable) => { | |
const playerDesc = game.playerDescriptions.get(playable.id); | |
const character = characters.find((c) => c.name === playerDesc?.character); | |
if (!character) return null; | |
return ( | |
<> | |
<Button onClick={() => onVote(playable.id)} | |
className="lg:block border-2 border-gold" | |
title={character?.name} | |
key={playable.id} | |
> | |
{character?.name} | |
<Stage width={30} height={40} options={{backgroundAlpha: 0.0}}> | |
{ | |
spriteSheet && <Character textureUrl={character.textureUrl} isViewer={true} spritesheetData={character.spritesheetData} x={15} y={15} orientation={0} onClick={() => {} } /> | |
} | |
</Stage> | |
</Button> | |
</> | |
) | |
})} | |
</> | |
) | |
} | |