diff --git a/client/src/components/Counter.tsx b/client/src/components/Counter.tsx index 4a7b429a8..2dddc9b08 100644 --- a/client/src/components/Counter.tsx +++ b/client/src/components/Counter.tsx @@ -8,7 +8,7 @@ export default function Counter(props: Readonly<{ }>): ReactElement { const circles = []; - for (let i = 0; i < props.max; i++) { + for (let i = 0; i < Math.max(props.max, props.current); i++) { const filled = i < props.current ? "filled" : "empty"; circles.push(
) diff --git a/client/src/game/gameState.d.tsx b/client/src/game/gameState.d.tsx index ccfdbe8ee..ef95961ed 100644 --- a/client/src/game/gameState.d.tsx +++ b/client/src/game/gameState.d.tsx @@ -78,8 +78,7 @@ type GameState = { clientState: PlayerGameState | {type: "spectator"}, host: boolean, - missedChatMessages: boolean, - missedWhispers: PlayerIndex[] + missedChatMessages: boolean } export default GameState; @@ -105,6 +104,8 @@ export type PlayerGameState = { sendChatGroups: ChatGroup[], insiderGroups: InsiderGroup[], + + missedWhispers: PlayerIndex[] } export type PlayerIndex = number; diff --git a/client/src/game/gameState.tsx b/client/src/game/gameState.tsx index f0e60e07d..399516938 100644 --- a/client/src/game/gameState.tsx +++ b/client/src/game/gameState.tsx @@ -62,8 +62,7 @@ export function createGameState(): GameState { clientState: createPlayerGameState(), host: false, - missedChatMessages: false, - missedWhispers: [], + missedChatMessages: false } } @@ -90,6 +89,8 @@ export function createPlayerGameState(): PlayerGameState { sendChatGroups: [], insiderGroups: [], + + missedWhispers: [] } } diff --git a/client/src/game/messageListener.tsx b/client/src/game/messageListener.tsx index 0fef89ba6..30109beca 100644 --- a/client/src/game/messageListener.tsx +++ b/client/src/game/messageListener.tsx @@ -472,8 +472,12 @@ export default function messageListener(packet: ToClientPacket){ GAME_MANAGER.state.missedChatMessages = true; for(let chatMessage of packet.chatMessages){ - if(chatMessage.variant.type === "whisper"){ - GAME_MANAGER.state.missedWhispers.push(chatMessage.variant.fromPlayerIndex); + if( + chatMessage.variant.type === "whisper" && + GAME_MANAGER.state.clientState.type === "player" && + chatMessage.variant.toPlayerIndex === GAME_MANAGER.state.clientState.myIndex + ){ + GAME_MANAGER.state.clientState.missedWhispers.push(chatMessage.variant.fromPlayerIndex); } } } diff --git a/client/src/menu/game/gameScreenContent/AbilityMenu/RoleSpecific.tsx b/client/src/menu/game/gameScreenContent/AbilityMenu/RoleSpecific.tsx index 8271d2209..09981d0c4 100644 --- a/client/src/menu/game/gameScreenContent/AbilityMenu/RoleSpecific.tsx +++ b/client/src/menu/game/gameScreenContent/AbilityMenu/RoleSpecific.tsx @@ -30,8 +30,12 @@ export default function RoleSpecificSection(): ReactElement{ gameState => gameState.dayNumber, ["phase"] )!; + const numPlayers = useGameState( + gameState => gameState.players.length, + ["gamePlayers"] + )!; - const inner = roleSpecificSectionInner(phaseState, dayNumber, roleState); + const inner = roleSpecificSectionInner(phaseState, dayNumber, roleState, numPlayers); return <>{inner===null ? null : ; } +function abilityChargesCounter(numPlayers: number): number{ + return Math.ceil(numPlayers/5); +} + function roleSpecificSectionInner( phaseState: PhaseState, dayNumber: number, - roleState: RoleState + roleState: RoleState, + numPlayers: number ): ReactElement | null{ + let chargesCounter = abilityChargesCounter(numPlayers); + switch(roleState.type){ case "auditor": return ; @@ -56,7 +67,7 @@ function roleSpecificSectionInner( return ; case "jailor": return {translate("role.jailor.roleDataText.executionsRemaining", roleState.executionsRemaining)} @@ -101,7 +112,7 @@ function roleSpecificSectionInner(
case "loaded": return {translate("role.vigilante.roleDataText", roleState.state.bullets)} @@ -111,14 +122,14 @@ function roleSpecificSectionInner( } case "veteran": return {translate("role.veteran.roleDataText", roleState.alertsRemaining)} case "armorsmith": return {translate("role.armorsmith.roleDataText", roleState.openShopsRemaining)} @@ -128,14 +139,14 @@ function roleSpecificSectionInner( case "counterfeiter": case "forger": return {translate("role.forger.roleDataText", roleState.forgesRemaining)} case "mortician": return {translate("role.mortician.roleDataText", roleState.cremationsRemaining)} @@ -147,7 +158,8 @@ function roleSpecificSectionInner( case "spiral": return ; case "puppeteer": - return ; @@ -164,7 +176,7 @@ function roleSpecificSectionInner( {translate("role.martyr.roleDataText.eccentric")} {translate("role.martyr.roleDataText", roleState.state.bullets)} diff --git a/client/src/menu/game/gameScreenContent/AbilityMenu/RoleSpecificMenus/SmallPuppeteerMenu.tsx b/client/src/menu/game/gameScreenContent/AbilityMenu/RoleSpecificMenus/SmallPuppeteerMenu.tsx index 413285163..a209591cc 100644 --- a/client/src/menu/game/gameScreenContent/AbilityMenu/RoleSpecificMenus/SmallPuppeteerMenu.tsx +++ b/client/src/menu/game/gameScreenContent/AbilityMenu/RoleSpecificMenus/SmallPuppeteerMenu.tsx @@ -5,10 +5,10 @@ import StyledText from "../../../../../components/StyledText"; import translate from "../../../../../game/lang"; import { PhaseType } from "../../../../../game/gameState.d"; -export default function SmallPuppeteerMenu(props: {marionettesRemaining: number, phase: PhaseType}): ReactElement { +export default function SmallPuppeteerMenu(props: Readonly<{marionettesRemaining: number, maxCharges: number, phase: PhaseType}>): ReactElement { return <> {translate("role.puppeteer.smallRoleMenu.marionettesRemaining", props.marionettesRemaining)} diff --git a/client/src/menu/game/gameScreenContent/PlayerListMenu.tsx b/client/src/menu/game/gameScreenContent/PlayerListMenu.tsx index 53ce51596..df1a6225b 100644 --- a/client/src/menu/game/gameScreenContent/PlayerListMenu.tsx +++ b/client/src/menu/game/gameScreenContent/PlayerListMenu.tsx @@ -136,12 +136,13 @@ function PlayerCard(props: Readonly<{ ["addGrave"] )! - const whisperNotification = useGameState( + const whisperNotification = usePlayerState( gameState => gameState.missedWhispers.some(player => player === props.playerIndex) && !isPlayerSelf && !whisperChatOpen, - ["addChatMessages", "whisperChatOpenOrClose"] + ["addChatMessages", "whisperChatOpenOrClose"], + false ); return <>
{ // GAME_MANAGER.prependWhisper(props.playerIndex); return true; setWhisperChatOpen(!whisperChatOpen); - if(GAME_MANAGER.state.stateType === 'game'){ - GAME_MANAGER.state.missedWhispers = - GAME_MANAGER.state.missedWhispers.filter(player => player !== props.playerIndex); + if(GAME_MANAGER.state.stateType === 'game' && GAME_MANAGER.state.clientState.type === 'player'){ + GAME_MANAGER.state.clientState.missedWhispers = + GAME_MANAGER.state.clientState.missedWhispers.filter(player => player !== props.playerIndex); } GAME_MANAGER.invokeStateListeners("whisperChatOpenOrClose"); }}