-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(elder): elder has taken revenge event (#656)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced a new game event: Elder taking revenge, with associated visuals and audio effects. - Added functionality to track player attribute alterations in game history. - New options for game setup affecting the Elder's gameplay. - Enhanced event handling with a dedicated component for Elder's revenge event. - **Bug Fixes** - Improved import statements for clarity and consistency in component mapping. - **Documentation** - Added new localization entries for game events in English, enhancing narrative depth. - **Tests** - Expanded test coverage for game events, particularly focusing on the Elder's role and related attributes. - **Chores** - Streamlined pre-commit and commit message hook scripts for better efficiency. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
- Loading branch information
1 parent
2b6f4be
commit 25f46d5
Showing
35 changed files
with
84,090 additions
and
80,247 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,2 @@ | ||
#!/usr/bin/env sh | ||
. "$(dirname -- "$0")/_/husky.sh" | ||
|
||
npx commitlint -g config/commitlint/.commitlintrc.json --edit $1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<component name="ProjectRunConfigurationManager"> | ||
<configuration default="false" name="Elder 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 @elder-role" /> | ||
<option name="workingDirectory" value="$PROJECT_DIR$" /> | ||
<envs> | ||
<env name="NODE_OPTIONS" value="--import tsx/esm" /> | ||
</envs> | ||
<method v="2" /> | ||
</configuration> | ||
</component> |
49 changes: 49 additions & 0 deletions
49
...EventsMonitorCurrentEvent/GameElderHasTakenRevengeEvent/GameElderHasTakenRevengeEvent.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<template> | ||
<GameEventWithTexts | ||
id="game-elder-has-taken-revenge-event" | ||
:texts="gameElderHasTakenRevengeEventTexts" | ||
> | ||
<div class="flex h-full items-center justify-center"> | ||
<GameEventFlippingPlayerCard | ||
v-if="elderInPlayers" | ||
id="game-event-flipping-elder-card" | ||
:players="[elderInPlayers]" | ||
svg-icon-path="svg/misc/storm.svg" | ||
/> | ||
</div> | ||
</GameEventWithTexts> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import GameEventFlippingPlayerCard from "~/components/shared/game/game-event/GameEventFlippingPlayerCard/GameEventFlippingPlayerCard.vue"; | ||
import GameEventWithTexts from "~/components/shared/game/game-event/GameEventWithTexts/GameEventWithTexts.vue"; | ||
import { storeToRefs } from "pinia"; | ||
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 { t } = useI18n(); | ||
const audioStore = useAudioStore(); | ||
const { playSoundEffect } = audioStore; | ||
const elderInPlayers = computed<Player | undefined>(() => getPlayersWithCurrentRole("elder")[0]); | ||
const gameElderHasTakenRevengeEventTexts = computed<string[]>(() => { | ||
if (!elderInPlayers.value) { | ||
return [t("components.GameElderHasTakenRevengeEvent.cantFindElder")]; | ||
} | ||
return [ | ||
t("components.GameElderHasTakenRevengeEvent.elderHasBeenMurderedByVillager"), | ||
t("components.GameElderHasTakenRevengeEvent.elderHasTakenRevenge"), | ||
]; | ||
}); | ||
playSoundEffect("thunder"); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
100 changes: 100 additions & 0 deletions
100
app/composables/api/game/game-event/useGameEventsGenerator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { useGameLastHistoryRecord } from "~/composables/api/game/game-history-record/useGameLastHistoryRecord"; | ||
import { useCurrentGamePlay } from "~/composables/api/game/game-play/useCurrentGamePlay"; | ||
import type { GamePlaySourceName } from "~/composables/api/game/types/game-play/game-play-source/game-play-source.types"; | ||
import type { GamePlayAction } from "~/composables/api/game/types/game-play/game-play.types"; | ||
import type { Game } from "~/composables/api/game/types/game.class"; | ||
import { GameEvent } from "~/stores/game/game-event/types/game-event.class"; | ||
|
||
type UseGameEventsGenerator = { | ||
getLastGameHistoryRecordCharmEvents: (source: GamePlaySourceName) => GameEvent[]; | ||
getLastGameActionEvents: (game: Game) => GameEvent[]; | ||
getRevealedRolePlayerGameEvents: (game: Game) => GameEvent[]; | ||
getDeadPlayerGameEvents: (game: Game) => GameEvent[]; | ||
generateGameEventsFromGame: (game: Game) => GameEvent[]; | ||
}; | ||
|
||
function useGameEventsGenerator(): UseGameEventsGenerator { | ||
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" })], | ||
}; | ||
|
||
return sourcesGameEvents[source] ?? []; | ||
} | ||
|
||
function getLastGameActionEvents(game: Game): GameEvent[] { | ||
const { lastGameHistoryRecord } = game; | ||
if (!lastGameHistoryRecord) { | ||
return []; | ||
} | ||
const { source, action, voting } = lastGameHistoryRecord.play; | ||
if (action === "elect-sheriff" && voting?.result === "sheriff-election" || action === "delegate") { | ||
return [GameEvent.create({ type: "sheriff-promotion" })]; | ||
} | ||
const actionsGameEvents: Partial<Record<GamePlayAction, GameEvent[]>> = { | ||
"look": [GameEvent.create({ type: "seer-has-seen" })], | ||
"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(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(game); | ||
const deadPlayers = getEligibleTargetsWithInteractionInCurrentGamePlay("bury"); | ||
|
||
return deadPlayers.map(player => GameEvent.create({ type: "player-dies", players: [player] })); | ||
} | ||
|
||
function getLastGameHistoryRecordPlayerAttributeAlterationEvents(game: Game): GameEvent[] { | ||
const { doesHavePlayerAttributeAlteration } = useGameLastHistoryRecord(game); | ||
const hasElderTakenRevenge = doesHavePlayerAttributeAlteration("powerless", "elder", "attached"); | ||
if (hasElderTakenRevenge) { | ||
return [GameEvent.create({ type: "elder-has-taken-revenge" })]; | ||
} | ||
return []; | ||
} | ||
|
||
function generateGameEventsFromGame(game: Game): GameEvent[] { | ||
const gameEvents: GameEvent[] = []; | ||
if (game.tick === 1) { | ||
gameEvents.push(GameEvent.create({ type: "game-starts" })); | ||
if (game.players.some(player => player.role.current === "villager-villager")) { | ||
gameEvents.push(GameEvent.create({ type: "villager-villager-introduction" })); | ||
} | ||
} | ||
gameEvents.push(...getRevealedRolePlayerGameEvents(game)); | ||
gameEvents.push(...getLastGameActionEvents(game)); | ||
gameEvents.push(...getLastGameHistoryRecordPlayerAttributeAlterationEvents(game)); | ||
if (game.phase.tick === 1 && game.phase.name !== "twilight") { | ||
gameEvents.push(GameEvent.create({ type: "game-phase-starts" })); | ||
} | ||
if (game.currentPlay?.action === "bury-dead-bodies") { | ||
gameEvents.push(...getDeadPlayerGameEvents(game)); | ||
} | ||
gameEvents.push(GameEvent.create({ type: "game-turn-starts" })); | ||
|
||
return gameEvents; | ||
} | ||
return { | ||
getLastGameHistoryRecordCharmEvents, | ||
getLastGameActionEvents, | ||
getRevealedRolePlayerGameEvents, | ||
getDeadPlayerGameEvents, | ||
generateGameEventsFromGame, | ||
}; | ||
} | ||
|
||
export { useGameEventsGenerator }; |
28 changes: 23 additions & 5 deletions
28
app/composables/api/game/game-history-record/useGameLastHistoryRecord.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,38 @@ | ||
import type { Ref } from "vue"; | ||
import type { MaybeRef, Ref } from "vue"; | ||
import type { GameHistoryRecordPlayerAttributeAlterationStatus } from "~/composables/api/game/types/game-history-record/game-history-record-player-attribute-alteration/game-history-record-player-attribute-alteration.types"; | ||
import type { GameHistoryRecord } from "~/composables/api/game/types/game-history-record/game-history-record.class"; | ||
import type { Game } from "~/composables/api/game/types/game.class"; | ||
import type { GameSource } from "~/composables/api/game/types/game.types"; | ||
import type { PlayerAttributeName } from "~/composables/api/game/types/players/player-attribute/player-attribute.types"; | ||
import type { Player } from "~/composables/api/game/types/players/player.class"; | ||
|
||
type UseGameLastHistoryRecord = { | ||
lastTargetedPlayers: Ref<Player[]>; | ||
doesHavePlayerAttributeAlteration: (attributeName: PlayerAttributeName, source: GameSource, status: GameHistoryRecordPlayerAttributeAlterationStatus) => boolean; | ||
}; | ||
|
||
function useGameLastHistoryRecord(game: Ref<Game>): UseGameLastHistoryRecord { | ||
function useGameLastHistoryRecord(game: MaybeRef<Game>): UseGameLastHistoryRecord { | ||
const lastGameHistoryRecord = computed<GameHistoryRecord | null>(() => (isRef(game) ? game.value.lastGameHistoryRecord : game.lastGameHistoryRecord)); | ||
|
||
const lastTargetedPlayers = computed<Player[]>(() => { | ||
if (!game.value.lastGameHistoryRecord?.play.targets) { | ||
if (!lastGameHistoryRecord.value?.play.targets) { | ||
return []; | ||
} | ||
return game.value.lastGameHistoryRecord.play.targets.map(target => target.player); | ||
return lastGameHistoryRecord.value.play.targets.map(target => target.player); | ||
}); | ||
|
||
return { lastTargetedPlayers }; | ||
function doesHavePlayerAttributeAlteration(attributeName: PlayerAttributeName, source: GameSource, status: GameHistoryRecordPlayerAttributeAlterationStatus): boolean { | ||
if (!lastGameHistoryRecord.value?.playerAttributeAlterations) { | ||
return false; | ||
} | ||
return lastGameHistoryRecord.value.playerAttributeAlterations.some(playerAttributeAlteration => playerAttributeAlteration.name === attributeName && | ||
playerAttributeAlteration.source === source && | ||
playerAttributeAlteration.status === status); | ||
} | ||
return { | ||
lastTargetedPlayers, | ||
doesHavePlayerAttributeAlteration, | ||
}; | ||
} | ||
|
||
export { useGameLastHistoryRecord }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
...cord-player-attribute-alteration/game-history-record-player-attribute-alteration.class.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { Expose, plainToInstance } from "class-transformer"; | ||
import type { GameHistoryRecordPlayerAttributeAlterationStatus } from "~/composables/api/game/types/game-history-record/game-history-record-player-attribute-alteration/game-history-record-player-attribute-alteration.types"; | ||
import type { GameSource } from "~/composables/api/game/types/game.types"; | ||
import type { PlayerAttributeName } from "~/composables/api/game/types/players/player-attribute/player-attribute.types"; | ||
import { DEFAULT_PLAIN_TO_INSTANCE_OPTIONS } from "~/utils/constants/class-transformer.constants"; | ||
|
||
class GameHistoryRecordPlayerAttributeAlteration { | ||
@Expose() | ||
public name: PlayerAttributeName; | ||
|
||
@Expose() | ||
public source: GameSource; | ||
|
||
@Expose() | ||
public playerName: string; | ||
|
||
@Expose() | ||
public status: GameHistoryRecordPlayerAttributeAlterationStatus; | ||
|
||
public static create(gameHistoryRecordPlayerAttributeAlteration: GameHistoryRecordPlayerAttributeAlteration): GameHistoryRecordPlayerAttributeAlteration { | ||
return plainToInstance(GameHistoryRecordPlayerAttributeAlteration, gameHistoryRecordPlayerAttributeAlteration, DEFAULT_PLAIN_TO_INSTANCE_OPTIONS); | ||
} | ||
} | ||
|
||
export { GameHistoryRecordPlayerAttributeAlteration }; |
6 changes: 6 additions & 0 deletions
6
...cord-player-attribute-alteration/game-history-record-player-attribute-alteration.types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import type { TupleToUnion } from "type-fest"; | ||
import type { GAME_HISTORY_RECORD_PLAYER_ATTRIBUTE_ALTERATION_STATUSES } from "~/composables/api/game/constants/game-history-record/game-history-record.constants"; | ||
|
||
type GameHistoryRecordPlayerAttributeAlterationStatus = TupleToUnion<typeof GAME_HISTORY_RECORD_PLAYER_ATTRIBUTE_ALTERATION_STATUSES>; | ||
|
||
export type { GameHistoryRecordPlayerAttributeAlterationStatus }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.