Feat : allow buying cards
This commit is contained in:
@@ -5,7 +5,8 @@ export interface Props {
|
|||||||
locked?: boolean;
|
locked?: boolean;
|
||||||
wrapped?: boolean;
|
wrapped?: boolean;
|
||||||
tilted?: boolean;
|
tilted?: boolean;
|
||||||
interactible?: boolean
|
interactible?: boolean;
|
||||||
|
noEffects?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
@@ -13,6 +14,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
tilted: () => true,
|
tilted: () => true,
|
||||||
locked: () => true,
|
locked: () => true,
|
||||||
interactible: () => true,
|
interactible: () => true,
|
||||||
|
noEffects: () => false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(["click"]);
|
const emit = defineEmits(["click"]);
|
||||||
@@ -74,6 +76,7 @@ onMounted(() => {
|
|||||||
wrapped,
|
wrapped,
|
||||||
unlocked: !props.locked,
|
unlocked: !props.locked,
|
||||||
zoom: isZooming,
|
zoom: isZooming,
|
||||||
|
no_effects: noEffects || !props.locked,
|
||||||
}"
|
}"
|
||||||
@contextmenu.prevent="false"
|
@contextmenu.prevent="false"
|
||||||
@click.left="cardClick"
|
@click.left="cardClick"
|
||||||
@@ -168,7 +171,6 @@ onMounted(() => {
|
|||||||
filter: drop-shadow(
|
filter: drop-shadow(
|
||||||
calc(var(--margin-bottom) * 0.3) var(--margin-bottom) 1px rgba(0, 0, 0, 0.6)
|
calc(var(--margin-bottom) * 0.3) var(--margin-bottom) 1px rgba(0, 0, 0, 0.6)
|
||||||
);
|
);
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.card.zoom {
|
.card.zoom {
|
||||||
@@ -193,10 +195,14 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<style>
|
<style>
|
||||||
.card.unlocked > * {
|
.card.no_effects svg > * {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card.no_effects {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
#contextMenuButtons > * {
|
#contextMenuButtons > * {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ export interface Props {
|
|||||||
playingTurn?: PlayingTurn;
|
playingTurn?: PlayingTurn;
|
||||||
wrapped?: boolean;
|
wrapped?: boolean;
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
|
noEffects?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
wrapped: () => false,
|
wrapped: () => false,
|
||||||
hidden: () => false,
|
hidden: () => false,
|
||||||
|
noEffects: () => false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(["cardClick"]);
|
const emit = defineEmits(["cardClick"]);
|
||||||
@@ -82,18 +84,17 @@ function endAnimation() {
|
|||||||
// animationCallbacks.value.push(done);
|
// animationCallbacks.value.push(done);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
// containerEvents.delete(props.container._id);
|
// containerEvents.delete(props.container._id);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="cards_container" :class="{ wrapped, rotate:container.shuffling }">
|
<div
|
||||||
<TransitionGroup
|
class="cards_container"
|
||||||
name="list"
|
:class="{ wrapped, rotate: container.shuffling }"
|
||||||
>
|
>
|
||||||
|
<TransitionGroup name="list">
|
||||||
<CardPreview
|
<CardPreview
|
||||||
@click="$emit('cardClick', c._id)"
|
@click="$emit('cardClick', c._id)"
|
||||||
v-for="c in cards"
|
v-for="c in cards"
|
||||||
@@ -104,6 +105,7 @@ onUnmounted(() => {
|
|||||||
:locked="
|
:locked="
|
||||||
!playingTurn || playingTurn?.cardsLocked.includes(c._id.toString())
|
!playingTurn || playingTurn?.cardsLocked.includes(c._id.toString())
|
||||||
"
|
"
|
||||||
|
:noEffects="noEffects"
|
||||||
>
|
>
|
||||||
</CardPreview>
|
</CardPreview>
|
||||||
</TransitionGroup>
|
</TransitionGroup>
|
||||||
@@ -126,7 +128,7 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
.list-leave-active {
|
.list-leave-active {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height:unset;
|
height: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rotate {
|
.rotate {
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { Container } from "~/netcode/interfaces";
|
import { buyCard } from "~/netcode";
|
||||||
|
import type { Container, Game } from "~/netcode/interfaces";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
game: Game;
|
||||||
market: Container;
|
market: Container;
|
||||||
marketStack: Container;
|
marketStack: Container;
|
||||||
fire_gems: Container;
|
fire_gems: Container;
|
||||||
@@ -19,7 +21,7 @@ const authStore = useAuthStore();
|
|||||||
// const buyableFiregem = computed(() => goStore?.current_game?.gem_stack.at(-1))
|
// const buyableFiregem = computed(() => goStore?.current_game?.gem_stack.at(-1))
|
||||||
|
|
||||||
function marketCardClick(e: string) {
|
function marketCardClick(e: string) {
|
||||||
console.log(e);
|
buyCard(props.game._id, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
function fireGemCardClick(e: string) {
|
function fireGemCardClick(e: string) {
|
||||||
@@ -38,12 +40,14 @@ function fireGemCardClick(e: string) {
|
|||||||
<CardsGrouped
|
<CardsGrouped
|
||||||
:container="market"
|
:container="market"
|
||||||
@cardClick="marketCardClick"
|
@cardClick="marketCardClick"
|
||||||
|
:noEffects="true"
|
||||||
></CardsGrouped>
|
></CardsGrouped>
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
<CardsGrouped
|
<CardsGrouped
|
||||||
:container="fire_gems"
|
:container="fire_gems"
|
||||||
:wrapped="true"
|
:wrapped="true"
|
||||||
@cardClick="fireGemCardClick"
|
@cardClick="fireGemCardClick"
|
||||||
|
:noEffects="true"
|
||||||
></CardsGrouped>
|
></CardsGrouped>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const isTurn = computed(
|
|||||||
{{ team?.health }}
|
{{ team?.health }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="turn_icon" v-if="isTurn">
|
<div class="turn_icon" v-if="isTurn">
|
||||||
<img src="/img/gold.png" class="icon_img" draggable="false" />
|
<img src="/img/gold.png" class="icon_img" draggable="false" />
|
||||||
<span class="turn_icon_number">
|
<span class="turn_icon_number">
|
||||||
{{ game.currentTurn.gold }}
|
{{ game.currentTurn.gold }}
|
||||||
@@ -38,7 +38,7 @@ const isTurn = computed(
|
|||||||
<span class="turn_icon_number">
|
<span class="turn_icon_number">
|
||||||
{{ game.currentTurn.damage }}
|
{{ game.currentTurn.damage }}
|
||||||
</span>
|
</span>
|
||||||
</div> -->
|
</div>
|
||||||
<div class="turn_icon">
|
<div class="turn_icon">
|
||||||
<img src="/img/fuck.svg" class="icon_img" draggable="false" />
|
<img src="/img/fuck.svg" class="icon_img" draggable="false" />
|
||||||
<span class="turn_icon_number">{{
|
<span class="turn_icon_number">{{
|
||||||
|
|||||||
+48
-29
@@ -48,45 +48,64 @@ export async function whoami() {
|
|||||||
|
|
||||||
export async function createGame() {
|
export async function createGame() {
|
||||||
const config = useRuntimeConfig();
|
const config = useRuntimeConfig();
|
||||||
const res = await $fetch<Game>(new URL("/games", config.public.endpoint).href, {
|
const res = await $fetch<Game>(
|
||||||
method: "POST",
|
new URL("/games", config.public.endpoint).href,
|
||||||
credentials: "include",
|
|
||||||
});
|
|
||||||
console.log(res)
|
|
||||||
navigateTo("/game/" + res._id)
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function startGame(game: string) {
|
|
||||||
const config = useRuntimeConfig();
|
|
||||||
const res = await $fetch<Game>(new URL(`games/${game}/start`, config.public.endpoint).href, {
|
|
||||||
method: "POST",
|
|
||||||
credentials: "include",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function joinGame(game: string) {
|
|
||||||
const config = useRuntimeConfig();
|
|
||||||
const res = await $fetch<Game>(new URL(`games/${game}/join`, config.public.endpoint).href, {
|
|
||||||
method: "POST",
|
|
||||||
credentials: "include",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function endTurn(game: string) {
|
|
||||||
const config = useRuntimeConfig();
|
|
||||||
await $fetch(
|
|
||||||
new URL(`games/${game}/endTurn`, config.public.endpoint).href,
|
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
console.log(res);
|
||||||
|
navigateTo("/game/" + res._id);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function startGame(game: string) {
|
||||||
|
const config = useRuntimeConfig();
|
||||||
|
const res = await $fetch<Game>(
|
||||||
|
new URL(`games/${game}/start`, config.public.endpoint).href,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
credentials: "include",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function joinGame(game: string) {
|
||||||
|
const config = useRuntimeConfig();
|
||||||
|
const res = await $fetch<Game>(
|
||||||
|
new URL(`games/${game}/join`, config.public.endpoint).href,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
credentials: "include",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function endTurn(game: string) {
|
||||||
|
const config = useRuntimeConfig();
|
||||||
|
await $fetch(new URL(`games/${game}/endTurn`, config.public.endpoint).href, {
|
||||||
|
method: "POST",
|
||||||
|
credentials: "include",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function lockCard(game: string, cardId: string) {
|
export async function lockCard(game: string, cardId: string) {
|
||||||
const config = useRuntimeConfig();
|
const config = useRuntimeConfig();
|
||||||
await $fetch(
|
await $fetch(
|
||||||
new URL(`games/${game}/turn/lockCard/${cardId}`, config.public.endpoint).href,
|
new URL(`games/${game}/turn/lockCard/${cardId}`, config.public.endpoint)
|
||||||
|
.href,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
credentials: "include",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function buyCard(game: string, cardId: string) {
|
||||||
|
const config = useRuntimeConfig();
|
||||||
|
await $fetch(
|
||||||
|
new URL(`games/${game}/turn/buyCard/${cardId}`, config.public.endpoint)
|
||||||
|
.href,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
|
|||||||
+60
-27
@@ -93,10 +93,10 @@ eventSource.addEventListener("message", async (message) => {
|
|||||||
queueAction(async () => {
|
queueAction(async () => {
|
||||||
playSound("/sounds/shuffle.mp3");
|
playSound("/sounds/shuffle.mp3");
|
||||||
const container = containers.value[data.container as string];
|
const container = containers.value[data.container as string];
|
||||||
container.shuffling = true
|
container.shuffling = true;
|
||||||
await delay(settingsStore.animationSpeed *2)
|
await delay(settingsStore.animationSpeed * 2);
|
||||||
container.shuffling = false
|
container.shuffling = false;
|
||||||
await delay(settingsStore.animationSpeed *2)
|
await delay(settingsStore.animationSpeed * 2);
|
||||||
});
|
});
|
||||||
} else if (data.type == "distributeCards") {
|
} else if (data.type == "distributeCards") {
|
||||||
// containerEvents.get(data.from)?.getCardsPosition(data.cards)
|
// containerEvents.get(data.from)?.getCardsPosition(data.cards)
|
||||||
@@ -163,6 +163,15 @@ eventSource.addEventListener("message", async (message) => {
|
|||||||
console.log(`adding damage amount : ` + data.operation);
|
console.log(`adding damage amount : ` + data.operation);
|
||||||
current_game.currentTurn.damage = data.damage;
|
current_game.currentTurn.damage = data.damage;
|
||||||
});
|
});
|
||||||
|
} else if (data.type == "team.updateHealth") {
|
||||||
|
queueAction(async () => {
|
||||||
|
const team = game.value?.teams.find((t) => t._id == data.team);
|
||||||
|
if (!team) {
|
||||||
|
throw new Error("Team not found");
|
||||||
|
}
|
||||||
|
console.log(`adding health amount : ` + data.operation);
|
||||||
|
team.health = data.health;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -182,6 +191,9 @@ const isTurn = computed(
|
|||||||
game.value.currentTurn.currentTeam
|
game.value.currentTurn.currentTeam
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const turnChangeAnimationSpeed = computed(
|
||||||
|
() => settingsStore.animationSpeed * 2 + "ms"
|
||||||
|
);
|
||||||
// TODO : current turn sound
|
// TODO : current turn sound
|
||||||
|
|
||||||
// TODO : winner screen
|
// TODO : winner screen
|
||||||
@@ -235,27 +247,30 @@ onUnmounted(() => {
|
|||||||
@ready="loaded = true"
|
@ready="loaded = true"
|
||||||
:isTurn="isTurn ?? false"
|
:isTurn="isTurn ?? false"
|
||||||
></AnimatedBackground>
|
></AnimatedBackground>
|
||||||
<div id="stack_discard">
|
<Transition name="slide-left" mode="out-in">
|
||||||
<div id="stack">
|
<div id="stack_discard" :key="focusedPlayer._id">
|
||||||
<CardsGrouped
|
<div id="stack">
|
||||||
:container="focusedPlayer.stack"
|
<CardsGrouped
|
||||||
:wrapped="true"
|
:container="focusedPlayer.stack"
|
||||||
:hidden="true"
|
:wrapped="true"
|
||||||
>
|
:hidden="true"
|
||||||
</CardsGrouped>
|
>
|
||||||
</div>
|
</CardsGrouped>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
id="discard"
|
id="discard"
|
||||||
:class="{ invisible: discard_unwrapped }"
|
:class="{ invisible: discard_unwrapped }"
|
||||||
@click="() => (discard_unwrapped = true)"
|
@click="() => (discard_unwrapped = true)"
|
||||||
>
|
>
|
||||||
<CardsGrouped :container="focusedPlayer.discard" :wrapped="true">
|
<CardsGrouped :container="focusedPlayer.discard" :wrapped="true">
|
||||||
</CardsGrouped>
|
</CardsGrouped>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Transition>
|
||||||
|
|
||||||
<MarketCards
|
<MarketCards
|
||||||
|
:game="game"
|
||||||
:market="game.market"
|
:market="game.market"
|
||||||
:fire_gems="game.fireGems"
|
:fire_gems="game.fireGems"
|
||||||
:marketStack="game.marketStack"
|
:marketStack="game.marketStack"
|
||||||
@@ -276,11 +291,14 @@ onUnmounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="current_player">
|
<div id="current_player">
|
||||||
<PlayerSlot
|
<Transition name="slide-left" mode="out-in">
|
||||||
v-if="focusedPlayer"
|
<PlayerSlot
|
||||||
:player="focusedPlayer"
|
v-if="focusedPlayer"
|
||||||
:game="game!"
|
:player="focusedPlayer"
|
||||||
></PlayerSlot>
|
:game="game!"
|
||||||
|
:key="focusedPlayer._id"
|
||||||
|
></PlayerSlot>
|
||||||
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
<ResultDialog
|
<ResultDialog
|
||||||
:isVisible="showResults"
|
:isVisible="showResults"
|
||||||
@@ -402,4 +420,19 @@ onUnmounted(() => {
|
|||||||
/* border: 5px solid #000; */
|
/* border: 5px solid #000; */
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
|
.slide-left-enter-active,
|
||||||
|
.slide-left-leave-active {
|
||||||
|
transition: all v-bind("turnChangeAnimationSpeed") ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-left-enter-from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-left-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(-100%);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user