Feat : add most token effects
This commit is contained in:
@@ -1,10 +1,12 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { delay } from "~/netcode/events";
|
import { delay } from "~/netcode/events";
|
||||||
import type {
|
import {
|
||||||
Card,
|
CardEffects,
|
||||||
Container,
|
CardType,
|
||||||
Effect,
|
type Card,
|
||||||
PlayingTurn,
|
type Container,
|
||||||
|
type Effect,
|
||||||
|
type PlayingTurn,
|
||||||
} from "~/netcode/interfaces";
|
} from "~/netcode/interfaces";
|
||||||
import TokenComponent from "./tokens/TokenComponent.vue";
|
import TokenComponent from "./tokens/TokenComponent.vue";
|
||||||
|
|
||||||
@@ -15,6 +17,7 @@ export interface Props {
|
|||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
noEffects?: boolean;
|
noEffects?: boolean;
|
||||||
tokens?: Effect[];
|
tokens?: Effect[];
|
||||||
|
championsKillable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
@@ -22,6 +25,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
hidden: () => false,
|
hidden: () => false,
|
||||||
noEffects: () => false,
|
noEffects: () => false,
|
||||||
tokens: () => [],
|
tokens: () => [],
|
||||||
|
championsKillable: () => false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(["cardClick", "effectClick", "tokenClick"]);
|
const emit = defineEmits(["cardClick", "effectClick", "tokenClick"]);
|
||||||
@@ -110,6 +114,8 @@ const interval = ref<ReturnType<typeof setInterval>>();
|
|||||||
function tokenClick(token: Effect, card: Card) {
|
function tokenClick(token: Effect, card: Card) {
|
||||||
emit("tokenClick", { token, card });
|
emit("tokenClick", { token, card });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function damageChampion() {}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -121,15 +127,15 @@ function tokenClick(token: Effect, card: Card) {
|
|||||||
<CardPreview
|
<CardPreview
|
||||||
@click="$emit('cardClick', c._id)"
|
@click="$emit('cardClick', c._id)"
|
||||||
@effectClick="$emit('effectClick', c._id, $event)"
|
@effectClick="$emit('effectClick', c._id, $event)"
|
||||||
v-for="c in cards"
|
v-for="(c, i) in cards"
|
||||||
:card_id="c.cardId"
|
:card_id="c?.cardId"
|
||||||
:wrapped="wrapped"
|
:wrapped="wrapped"
|
||||||
:key="c._id"
|
:key="c?._id || i"
|
||||||
:card="c"
|
:card="c"
|
||||||
:locked="
|
:locked="
|
||||||
!playingTurn || playingTurn?.cardsLocked.includes(c._id.toString())
|
!playingTurn || playingTurn?.cardsLocked.includes(c._id.toString())
|
||||||
"
|
"
|
||||||
:used_effects_indexes="c.effects?.reduce( (prev,e, i)=>{
|
:used_effects_indexes="c?.effects?.reduce( (prev,e, i)=>{
|
||||||
if(playingTurn?.lockedEffects.includes(e._id)){
|
if(playingTurn?.lockedEffects.includes(e._id)){
|
||||||
prev.push(i)
|
prev.push(i)
|
||||||
}
|
}
|
||||||
@@ -141,8 +147,29 @@ function tokenClick(token: Effect, card: Card) {
|
|||||||
<TokenComponent
|
<TokenComponent
|
||||||
:token="t"
|
:token="t"
|
||||||
@useToken="tokenClick(t, c)"
|
@useToken="tokenClick(t, c)"
|
||||||
|
v-if="
|
||||||
|
!(
|
||||||
|
t.effect == CardEffects.SACRIFICE &&
|
||||||
|
(!playingTurn ||
|
||||||
|
playingTurn?.cardsLocked.includes(c._id.toString()))
|
||||||
|
) &&
|
||||||
|
!(
|
||||||
|
t.effect == CardEffects.PREPARE &&
|
||||||
|
c.cardType == CardType.CHAMPION
|
||||||
|
) &&
|
||||||
|
!(
|
||||||
|
t.effect == CardEffects.STACK_NEXT_ACTION_BOUGHT &&
|
||||||
|
c.cardType != CardType.ACTION
|
||||||
|
) &&
|
||||||
|
t.effect == CardEffects.STUN &&
|
||||||
|
c.cardType == CardType.CHAMPION &&
|
||||||
|
championsKillable
|
||||||
|
"
|
||||||
></TokenComponent>
|
></TokenComponent>
|
||||||
</template>
|
</template>
|
||||||
|
<button v-if="championsKillable && c.cardType == CardType.CHAMPION">
|
||||||
|
Damage
|
||||||
|
</button>
|
||||||
</CardPreview>
|
</CardPreview>
|
||||||
</TransitionGroup>
|
</TransitionGroup>
|
||||||
<!-- <img :class="`card_image`" :src="'/cards/background.png'" draggable="false"> -->
|
<!-- <img :class="`card_image`" :src="'/cards/background.png'" draggable="false"> -->
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Game, Player } from "~/netcode/interfaces";
|
import { damagePlayer, makeDiscard } from "~/netcode";
|
||||||
|
import { CardEffects, type Game, type Player } from "~/netcode/interfaces";
|
||||||
|
|
||||||
const emit = defineEmits(["click"]);
|
const emit = defineEmits(["click"]);
|
||||||
|
|
||||||
@@ -15,6 +16,24 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
isTurn: () => false,
|
isTurn: () => false,
|
||||||
self: () => false,
|
self: () => false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
const playerList = computed(() =>
|
||||||
|
props.game!.teams.reduce((acc, t) => acc.concat(t.players), [] as Player[])
|
||||||
|
);
|
||||||
|
|
||||||
|
const selfPlayer = computed(() =>
|
||||||
|
authStore.logged
|
||||||
|
? playerList.value?.find((p) => p.user.userId == authStore.selfUser.userId)
|
||||||
|
: undefined
|
||||||
|
);
|
||||||
|
|
||||||
|
function makeDiscardClick() {
|
||||||
|
makeDiscard(props.game._id, props.player._id);
|
||||||
|
}
|
||||||
|
function damage() {
|
||||||
|
damagePlayer(props.game._id, props.player._id, 1);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -48,6 +67,24 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
<PlayerStats :game="props.game" :player="props.player"> </PlayerStats>
|
<PlayerStats :game="props.game" :player="props.player"> </PlayerStats>
|
||||||
<!-- </template> -->
|
<!-- </template> -->
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
v-if="
|
||||||
|
game.currentTurn.tokens.some(
|
||||||
|
(t) => t.effect == CardEffects.MAKE_DISCARD
|
||||||
|
) &&
|
||||||
|
props.player._id != selfPlayer?._id &&
|
||||||
|
!isTurn
|
||||||
|
"
|
||||||
|
@click.stop="makeDiscardClick"
|
||||||
|
>
|
||||||
|
Make Discard
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="props.player._id != selfPlayer?._id && !isTurn"
|
||||||
|
@click.stop="damage"
|
||||||
|
>
|
||||||
|
Damage
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -52,7 +52,9 @@ const isSelfTurn = computed(() => isSelf && isPlayerTurn);
|
|||||||
|
|
||||||
const cardTokens = computed(() =>
|
const cardTokens = computed(() =>
|
||||||
props.game.currentTurn.tokens.filter((t) =>
|
props.game.currentTurn.tokens.filter((t) =>
|
||||||
[CardEffects.SACRIFICE, CardEffects.PREPARE].includes(t.effect)
|
[CardEffects.SACRIFICE, CardEffects.PREPARE, CardEffects.STUN].includes(
|
||||||
|
t.effect
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -196,6 +198,7 @@ function tokenClick({ card, token }: { card: Card; token: Effect }) {
|
|||||||
@effectClick="effectClick"
|
@effectClick="effectClick"
|
||||||
:tokens="cardTokens"
|
:tokens="cardTokens"
|
||||||
@tokenClick="tokenClick"
|
@tokenClick="tokenClick"
|
||||||
|
:championsKillable="!isSelf && isSelfTurn.value"
|
||||||
>
|
>
|
||||||
</CardsGrouped>
|
</CardsGrouped>
|
||||||
|
|
||||||
|
|||||||
@@ -153,3 +153,59 @@ export async function lockEffect(game: string, effectId: string) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function makeDiscard(
|
||||||
|
game: string,
|
||||||
|
playerId: string,
|
||||||
|
amount: number = 1
|
||||||
|
) {
|
||||||
|
const config = useRuntimeConfig();
|
||||||
|
await $fetch(
|
||||||
|
new URL(
|
||||||
|
`games/${game}/turn/makeDiscard/${playerId}`,
|
||||||
|
config.public.endpoint
|
||||||
|
).href,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
credentials: "include",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function damagePlayer(
|
||||||
|
game: string,
|
||||||
|
playerId: string,
|
||||||
|
amount: number = 1
|
||||||
|
) {
|
||||||
|
const config = useRuntimeConfig();
|
||||||
|
await $fetch(
|
||||||
|
new URL(
|
||||||
|
`games/${game}/turn/damagePlayer/${playerId}`,
|
||||||
|
config.public.endpoint
|
||||||
|
).href,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
credentials: "include",
|
||||||
|
body: { amount },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function damageChampion(
|
||||||
|
game: string,
|
||||||
|
playerId: string,
|
||||||
|
cardId: string
|
||||||
|
) {
|
||||||
|
const config = useRuntimeConfig();
|
||||||
|
await $fetch(
|
||||||
|
new URL(
|
||||||
|
`games/${game}/turn/damageChampion/${cardId}`,
|
||||||
|
config.public.endpoint
|
||||||
|
).href,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
credentials: "include",
|
||||||
|
body: { playerId },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -41,6 +41,16 @@ export enum CardEffects {
|
|||||||
PICK_FACTION = "pick_faction",
|
PICK_FACTION = "pick_faction",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum CardType {
|
||||||
|
HERO = "hero",
|
||||||
|
HERO_ABILITY = "hero_ability",
|
||||||
|
CURRENCY = "currency",
|
||||||
|
WEAPON = "weapon",
|
||||||
|
CHAMPION = "champion",
|
||||||
|
ACTION = "action",
|
||||||
|
ITEM = "item",
|
||||||
|
}
|
||||||
|
|
||||||
export interface GameObject {
|
export interface GameObject {
|
||||||
_id: string;
|
_id: string;
|
||||||
}
|
}
|
||||||
@@ -95,5 +105,6 @@ export interface Effect extends GameObject {
|
|||||||
}
|
}
|
||||||
export interface Card extends GameObject {
|
export interface Card extends GameObject {
|
||||||
cardId: number;
|
cardId: number;
|
||||||
|
cardType: CardType;
|
||||||
effects: Effect[];
|
effects: Effect[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { subscribe } from "~/netcode";
|
|||||||
import { delay } from "~/netcode/events";
|
import { delay } from "~/netcode/events";
|
||||||
import { type Container, type Game, type Player } from "~/netcode/interfaces";
|
import { type Container, type Game, type Player } from "~/netcode/interfaces";
|
||||||
import { playSound } from "~/helpers/audioHelpers";
|
import { playSound } from "~/helpers/audioHelpers";
|
||||||
|
import TokenComponent from "~/components/tokens/TokenComponent.vue";
|
||||||
|
|
||||||
const config = useRuntimeConfig();
|
const config = useRuntimeConfig();
|
||||||
const settingsStore = useSettingsStore();
|
const settingsStore = useSettingsStore();
|
||||||
@@ -211,6 +212,20 @@ eventSource.addEventListener("message", async (message) => {
|
|||||||
console.log(`adding health amount : ` + data.operation);
|
console.log(`adding health amount : ` + data.operation);
|
||||||
team.health = data.health;
|
team.health = data.health;
|
||||||
});
|
});
|
||||||
|
} else if (data.type == "killTeam") {
|
||||||
|
queueAction(async () => {
|
||||||
|
const index = game.value?.teams.findIndex((t) => t._id == data.teamId);
|
||||||
|
if (!index) {
|
||||||
|
console.error("team index not found. Desyncs might happen");
|
||||||
|
await refresh();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
game.value?.teams.splice(index, 1);
|
||||||
|
});
|
||||||
|
} else if (data.type == "endGame") {
|
||||||
|
queueAction(async () => {
|
||||||
|
alert("game Ended");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -314,6 +329,12 @@ onUnmounted(() => {
|
|||||||
:fire_gems="game.fireGems"
|
:fire_gems="game.fireGems"
|
||||||
:marketStack="game.marketStack"
|
:marketStack="game.marketStack"
|
||||||
></MarketCards>
|
></MarketCards>
|
||||||
|
<div>
|
||||||
|
<TokenComponent
|
||||||
|
:token="t"
|
||||||
|
v-for="t in game.currentTurn.tokens"
|
||||||
|
></TokenComponent>
|
||||||
|
</div>
|
||||||
<div id="player_list_container">
|
<div id="player_list_container">
|
||||||
<div id="player_list">
|
<div id="player_list">
|
||||||
<PlayerListElement
|
<PlayerListElement
|
||||||
|
|||||||
Reference in New Issue
Block a user