Skip to content

Commit

Permalink
feat(game): idiot spared life event (#618)
Browse files Browse the repository at this point in the history
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
  - Added a confirm dialog before starting a game.
  - Disabled player cards based on the current play type.
- Introduced new "Idiot" role with specific game events and
interactions.
  - Added sound effect "dumb-huh."

- **Bug Fixes**
  - Fixed player card targetability based on play type.

- **Tests**
- Added unit and acceptance tests for new "Idiot" role and game events.

- **Chores**
  - Updated dependencies, including prettier-plugin-gherkin and tsx.
  - Incremented application version to 1.25.0.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
  • Loading branch information
antoinezanardi authored Jul 8, 2024
1 parent b84e26e commit b5b77d1
Show file tree
Hide file tree
Showing 25 changed files with 72,758 additions and 69,780 deletions.
12 changes: 12 additions & 0 deletions .run/Idiot Role.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Idiot Role" type="cucumber.js" factoryName="Cucumber.js" folderName="Tags">
<option name="myFilePath" value="$PROJECT_DIR$/tests/acceptance" />
<option name="myNameFilter" value="" />
<option name="cucumberJsArguments" value="--config config/cucumber/cucumber.json --parallel 1 --tags @idiot-role" />
<option name="workingDirectory" value="$PROJECT_DIR$" />
<envs>
<env name="NODE_OPTIONS" value="--import tsx/esm" />
</envs>
<method v="2" />
</configuration>
</component>
48 changes: 48 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,53 @@
# 🐺 Werewolves Assistant Web Versioning Changelog

## [1.25.0](https://github.com/antoinezanardi/werewolves-assistant-web-next/compare/v1.24.0...v1.25.0) (2024-07-07)

### 🚀 Features

* **game-lobby:** confirm dialog before starting a game ([#611](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/611)) ([eb5ccc0](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/eb5ccc0a5770f6a61af2dfd8469ba36b8c7c07fc))
* **game:** disabled player card based on current play type ([#600](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/600)) ([313aba8](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/313aba8f77ca2943ec1350816ab2430de69e72ec))

### ✅ Tests

* **game:** check if player cards are not targetable in vote playgrounds ([#606](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/606)) ([5aada1f](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/5aada1f2001d3108d3dfa8b69585c16d254a6d57))
* **mocks:** consistent way to mock composables ([#613](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/613)) ([5ac49d7](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/5ac49d701bfa31c1ea00d61c88f7bdc0f31176c1))

### 🧹 Chore

* **deps:** update dependency prettier-plugin-gherkin to ^2.4.0 ([#608](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/608)) ([864e3e8](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/864e3e859a01a3e653e6b885133cd17420894c2c))
* **deps:** update dependency rimraf to ^5.0.8 ([#610](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/610)) ([2abed2d](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/2abed2df4a9ed69ebd24e4091c6203776fc97b49))
* **deps:** update dependency tsx to ^4.16.2 ([#604](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/604)) ([d6cb80d](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/d6cb80d4f9dcbf0a1c9d8cca2563b618ad4773ca))
* **deps:** update dependency type-fest to ^4.21.0 ([#599](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/599)) ([023a49e](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/023a49ed1fa7d315fd7ba8adeeed024795363967))
* **deps:** update dependency vue-tsc to ^2.0.26 ([#607](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/607)) ([d55ac41](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/d55ac41dc81a926680cf695329a1966f47b8ded9))
* **deps:** update nuxtjs monorepo to ^3.12.3 ([#602](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/602)) ([86e7f91](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/86e7f91741bb6eff18666aaf962b5da1dd2be82d))
* **deps:** update playwright monorepo to ^1.45.1 ([#603](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/603)) ([4fd661b](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/4fd661bca5d5e483e52d61d84df6982052ada1ac))
* **events:** consistent way to handle events ([#612](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/612)) ([b6f9238](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/b6f923893a6909408f26eabe184d654386bea580))
* **i18n:** remove spaces before punctuation marks in english ([#614](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/614)) ([ca3c1a4](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/ca3c1a4d50bf9173eb7255e1610c132edf72bddd))

## [1.24.0](https://github.com/antoinezanardi/werewolves-assistant-web-next/compare/v1.23.0...v1.24.0) (2024-07-02)

### 🚀 Features

* **game-lobby:** position coordinator ([#589](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/589)) ([95a7976](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/95a79763a966a1c0e98bb3f07a208cb16e363238))

### ✅ Tests

* **little-girl:** acceptance tests ([#596](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/596)) ([ea2004c](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/ea2004c8f22284694a6157e5e887b3cead03c029))

### 🔁 CI

* **e2e:** e2e sharded tests ([#592](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/592)) ([005858f](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/005858fea8929c7b0a70d0c5fc337e446e3513d1))

### 🧹 Chore

* **deps:** update dependency eslint-plugin-vue to ^9.27.0 ([#597](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/597)) ([f8d45aa](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/f8d45aa93092a1fe0bd763bbca7baa83bca5d140))
* **deps:** update dependency qs to ^6.12.2 ([#593](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/593)) ([356a638](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/356a638a8b0b8375f9d86c686888655f867de1f3))
* **deps:** update dependency typescript to ^5.5.3 ([#595](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/595)) ([93e7a6a](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/93e7a6a1a2f8197031cca4ee558e15f7484d1bfd))
* **deps:** update dependency vue-tsc to ^2.0.24 ([#588](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/588)) ([1870ad6](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/1870ad6083a8c68b4b90e7b74788f4027b8a97a7))
* **deps:** update typescript-eslint monorepo to ^7.15.0 ([#594](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/594)) ([f929264](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/f929264525d1bd3a63d077a447438198eb4e352e))
* **docker:** specify sandbox api version in docker ([#598](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/598)) ([0b6f6ae](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/0b6f6aeb602571e3839418843be330d3d808f810))
* **prime-vue:** flip suffix ([#591](https://github.com/antoinezanardi/werewolves-assistant-web-next/issues/591)) ([dae0500](https://github.com/antoinezanardi/werewolves-assistant-web-next/commit/dae05002b8b0903d9445e7d0a35ef15622ba071f))

## [1.23.0](https://github.com/antoinezanardi/werewolves-assistant-web-next/compare/v1.22.0...v1.23.0) (2024-06-29)

### 🚀 Features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { storeToRefs } from "pinia";
import type { GameEventsMonitorEventTypeComponent } from "~/components/pages/game/GamePlaying/GameEventsMonitor/GameEventsMonitorCurrentEvent/game-events-monitor-current-event.types";
import GameAccursedWolfFatherMayHaveInfectedEvent from "~/components/pages/game/GamePlaying/GameEventsMonitor/GameEventsMonitorCurrentEvent/GameAccursedWolfFatherMayHaveInfectedEvent/GameAccursedWolfFatherMayHaveInfectedEvent.vue";
import GameCupidHasCharmedEvent from "~/components/pages/game/GamePlaying/GameEventsMonitor/GameEventsMonitorCurrentEvent/GameCupidHasCharmedEvent/GameCupidHasCharmedEvent.vue";
import GameIdiotIsSparedEvent from "~/components/pages/game/GamePlaying/GameEventsMonitor/GameEventsMonitorCurrentEvent/GameIdiotIsSparedEvent/GameIdiotIsSparedEvent.vue";
import GamePhaseStartsEvent from "~/components/pages/game/GamePlaying/GameEventsMonitor/GameEventsMonitorCurrentEvent/GamePhaseStartsEvent/GamePhaseStartsEvent.vue";
import GamePiedPiperHasCharmedEvent from "~/components/pages/game/GamePlaying/GameEventsMonitor/GameEventsMonitorCurrentEvent/GamePiedPiperHasCharmedEvent/GamePiedPiperHasCharmedEvent.vue";
import GamePlayerDiesEvent from "~/components/pages/game/GamePlaying/GameEventsMonitor/GameEventsMonitorCurrentEvent/GamePlayerDiesEvent/GamePlayerDiesEvent.vue";
Expand Down Expand Up @@ -54,6 +55,7 @@ const currentGameEventTypeComponent = computed<GameEventsMonitorEventTypeCompone
"pied-piper-has-charmed": GamePiedPiperHasCharmedEvent,
"cupid-has-charmed": GameCupidHasCharmedEvent,
"wolf-hound-has-chosen-side": GameWolfHoundHasChosenSide,
"idiot-is-spared": GameIdiotIsSparedEvent,
};
if (!currentGameEvent.value) {
return undefined;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<template>
<GameEventWithTexts
id="game-idiot-is-spared-event"
:texts="gameIdiotIsSparedEventTexts"
@game-event-text-change="onGameEventTextChangeFromGameEventWithTexts"
>
<div class="flex h-full items-center justify-center">
<GameEventFlippingPlayerCard
v-if="idiotInPlayers"
id="game-event-flipping-idiot-card"
:players="[idiotInPlayers]"
svg-icon-path="/svg/game/player/player-attribute/seen.svg"
/>
</div>
</GameEventWithTexts>
</template>

<script setup lang="ts">
import { storeToRefs } from "pinia";
import GameEventFlippingPlayerCard from "~/components/shared/game/game-event/GameEventFlippingPlayerCard/GameEventFlippingPlayerCard.vue";
import GameEventWithTexts from "~/components/shared/game/game-event/GameEventWithTexts/GameEventWithTexts.vue";
import type { Player } from "~/composables/api/game/types/players/player.class";
import { useGamePlayers } from "~/composables/api/game/useGamePlayers";
import { useAudioStore } from "~/stores/audio/useAudioStore";
import { useGameStore } from "~/stores/game/useGameStore";
const gameStore = useGameStore();
const { game } = storeToRefs(gameStore);
const { getPlayersWithCurrentRole } = useGamePlayers(game);
const audioStore = useAudioStore();
const { playSoundEffect } = audioStore;
const { t } = useI18n();
const idiotInPlayers = computed<Player | undefined>(() => getPlayersWithCurrentRole("idiot")[0]);
const gameIdiotIsSparedEventTexts = computed<string[]>(() => {
if (!idiotInPlayers.value) {
return [t("components.GameIdiotIsSparedEvent.cantFindIdiot")];
}
return [
t("components.GameIdiotIsSparedEvent.playerDies", { playerName: idiotInPlayers.value.name }),
t("components.GameIdiotIsSparedEvent.playerIsActuallyIdiot", { playerName: idiotInPlayers.value.name }),
t("components.GameIdiotIsSparedEvent.idiotIsSpared"),
];
});
function onGameEventTextChangeFromGameEventWithTexts(newGameEventText: string | undefined): void {
if (newGameEventText === gameIdiotIsSparedEventTexts.value[0]) {
playSoundEffect("death");
} else if (newGameEventText === gameIdiotIsSparedEventTexts.value[1]) {
playSoundEffect("dumb-huh");
}
}
playSoundEffect("death");
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@ import { storeToRefs } from "pinia";
import GameEventNextTextButton from "~/components/shared/game/game-event/GameEventWithTexts/GameEventTextsManager/GameEventNextTextButton/GameEventNextTextButton.vue";
import GameEventPreviousTextButton from "~/components/shared/game/game-event/GameEventWithTexts/GameEventTextsManager/GameEventPreviousTextButton/GameEventPreviousTextButton.vue";
import { useGameEventsStore } from "~/stores/game/game-event/useGameEventsStore";
import type { GameEventTextsManagerProps } from "~/components/shared/game/game-event/GameEventWithTexts/GameEventTextsManager/game-event-texts-manager.types";
import type { GameEventTextsManagerEmits, GameEventTextsManagerProps } from "~/components/shared/game/game-event/GameEventWithTexts/GameEventTextsManager/game-event-texts-manager.types";
import { useGameStore } from "~/stores/game/useGameStore";
const props = defineProps<GameEventTextsManagerProps>();
const emit = defineEmits<GameEventTextsManagerEmits>();
const gameStore = useGameStore();
const { makingGamePlayStatus } = storeToRefs(gameStore);
Expand Down Expand Up @@ -76,4 +78,8 @@ async function onClickFromGameEventNextTextButton(): Promise<void> {
}
currentIndex.value++;
}
watch(currentGameEventText, () => {
emit("gameEventTextChange", currentGameEventText.value);
});
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,11 @@ type GameEventTextsManagerProps = {
texts: string[];
};

export type { GameEventTextsManagerProps };
type GameEventTextsManagerEmits = {
gameEventTextChange: [string | undefined];
};

export type {
GameEventTextsManagerProps,
GameEventTextsManagerEmits,
};
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,23 @@
<GameEventTextsManager
id="game-event-texts-manager"
:texts="props.texts"
@game-event-text-change="onGameEventTextChangeFromGameEventTextsManager"
/>
</div>
</template>

<script setup lang="ts">
import type { GameEventWithTextsProps } from "~/components/shared/game/game-event/GameEventWithTexts/game-event-with-texts.types";
import type { GameEventWithTextsEmits, GameEventWithTextsProps } from "~/components/shared/game/game-event/GameEventWithTexts/game-event-with-texts.types";
import GameEventTextsManager from "~/components/shared/game/game-event/GameEventWithTexts/GameEventTextsManager/GameEventTextsManager.vue";
const props = defineProps<GameEventWithTextsProps>();
const emit = defineEmits<GameEventWithTextsEmits>();
function onGameEventTextChangeFromGameEventTextsManager(newGameEventText: string | undefined): void {
emit("gameEventTextChange", newGameEventText);
}
defineSlots<{
default: () => void;
}>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,11 @@ type GameEventWithTextsProps = {
texts: string[];
};

export type { GameEventWithTextsProps };
type GameEventWithTextsEmits = {
gameEventTextChange: [string | undefined];
};

export type {
GameEventWithTextsProps,
GameEventWithTextsEmits,
};
1 change: 1 addition & 0 deletions app/stores/audio/constants/audio.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const SOUND_EFFECT_NAMES = [
"dog-barking",
"dramatic-announcement",
"dramatic-drums",
"dumb-huh",
"evil-demonic-laugh",
"evil-laugh",
"flute-and-drums",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const GAME_EVENT_TYPES = [
"pied-piper-has-charmed",
"wolf-hound-has-chosen-side",
"cupid-has-charmed",
"idiot-is-spared",
] as const;

export { GAME_EVENT_TYPES };
13 changes: 11 additions & 2 deletions app/stores/game/game-event/useGameEventsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const useGameEventsStore = defineStore(StoreIds.GAME_EVENTS, () => {
currentGameEventIndex.value = 0;
}

function getLastGameHistoryRecordCharmEvents(game: Game, source: GamePlaySourceName): GameEvent[] {
function getLastGameHistoryRecordCharmEvents(source: GamePlaySourceName): GameEvent[] {
const sourcesGameEvents: Partial<Record<GamePlaySourceName, GameEvent[]>> = {
"pied-piper": [GameEvent.create({ type: "pied-piper-has-charmed" })],
"cupid": [GameEvent.create({ type: "cupid-has-charmed" })],
Expand All @@ -45,12 +45,20 @@ const useGameEventsStore = defineStore(StoreIds.GAME_EVENTS, () => {
"mark": [GameEvent.create({ type: "scandalmonger-has-marked" })],
"infect": [GameEvent.create({ type: "accursed-wolf-father-may-have-infected" })],
"choose-side": [GameEvent.create({ type: "wolf-hound-has-chosen-side" })],
"charm": getLastGameHistoryRecordCharmEvents(game, source.name),
"charm": getLastGameHistoryRecordCharmEvents(source.name),
};

return actionsGameEvents[action] ?? [];
}

function getRevealedRolePlayerGameEvents(game: Game): GameEvent[] {
const { lastGameHistoryRecord } = game;
if (lastGameHistoryRecord?.revealedPlayers?.some(player => player.role.current === "idiot") === true) {
return [GameEvent.create({ type: "idiot-is-spared" })];
}
return [];
}

function getDeadPlayerGameEvents(game: Game): GameEvent[] {
const { getEligibleTargetsWithInteractionInCurrentGamePlay } = useCurrentGamePlay(ref(game));
const deadPlayers = getEligibleTargetsWithInteractionInCurrentGamePlay("bury");
Expand All @@ -66,6 +74,7 @@ const useGameEventsStore = defineStore(StoreIds.GAME_EVENTS, () => {
gameEvents.value.push(GameEvent.create({ type: "villager-villager-introduction" }));
}
}
gameEvents.value.push(...getRevealedRolePlayerGameEvents(game));
gameEvents.value.push(...getLastGameHistoryRecordEvents(game));
if (game.phase.tick === 1 && game.phase.name !== "twilight") {
gameEvents.value.push(GameEvent.create({ type: "game-phase-starts" }));
Expand Down
6 changes: 6 additions & 0 deletions modules/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1396,6 +1396,12 @@
"playersPosition": "Players position",
"someRolesArePositionDependant": "Some roles rely on players position. Are players placed correctly in the game lobby?",
"showMeHowToPositionPlayers": "Show me how to position players"
},
"GameIdiotIsSparedEvent": {
"cantFindIdiot": "The Idiot can't be found… Please proceed.",
"playerDies": "{playerName} is dead! What a tragedy… He/she can reveal his/her role to the others.",
"playerIsActuallyIdiot": "{playerName} is actually the Idiot!",
"idiotIsSpared": "The survivors have pity for the Idiot and spare him. He is not eliminated but can't vote for the rest of the game."
}
}
}
8 changes: 7 additions & 1 deletion modules/i18n/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1313,7 +1313,7 @@
"GamePlayerDiesEvent": {
"cantFindDeadPlayer": "L'Assistant ne trouve pas le joueur mort… Veuillez continuer.",
"playerDies": "{playerName} est mort ! Quelle tragédie…",
"playerCanRevealRole": "Il ou elle peut révéler son rôle aux autres.",
"playerCanRevealRole": "Il ou elle peut révéler son rôle aux autres joueurs.",
"playerDoesntRevealRole": "Dans cette spéciale, le rôle du joueur mort n'est pas révélé aux autres. Le mystère demeure…"
},
"RoleFlippingImageSvgIcon": {
Expand Down Expand Up @@ -1396,6 +1396,12 @@
"playersPosition": "Position des joueurs",
"someRolesArePositionDependant": "Certains rôles dépendent de la position des joueurs. Est-ce que tous les joueurs sont bien positionnés dans l'Assistant ?",
"showMeHowToPositionPlayers": "Montrez-moi comment positionner les joueurs"
},
"GameIdiotIsSparedEvent": {
"cantFindIdiot": "L'Idiot ne peut être trouvé… Veuillez continuer.",
"playerDies": "{playerName} est mort ! Quelle tragédie… Il ou elle peut révéler son rôle aux autres joueurs.",
"playerIsActuallyIdiot": "{playerName} est en fait l'Idiot du village !",
"idiotIsSpared": "Les survivants ont pitié de lui, c'est un simplet après tout… Le village le laisse en vie mais il ne pourra plus voter pour le reste de la partie."
}
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "werewolves-assistant-web-next",
"version": "1.23.0",
"version": "1.25.0",
"description": "Werewolves Assistant Web is a Nuxt Web App using the Werewolves Assistant API. It helps you, the game master, to manage your games of Werewolves Of Millers Hollow.",
"readme": "README.md",
"type": "module",
Expand Down
Binary file added public/audio/sound-effects/dumb-huh.webm
Binary file not shown.
Loading

0 comments on commit b5b77d1

Please sign in to comment.