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");
}}