Merge branch 'feat/netcode-rework' of https://git.legonzaur.fr/heronfief/front into feat/netcode-rework
release-tag / release-image (push) Successful in 28s
release-tag / release-image (push) Successful in 28s
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
NUXT_PUBLIC_ENDPOINT=http://localhost:8765
|
||||
NUXT_PUBLIC_DISCORD_LOGIN_ENDPOINT=https://discord.com/oauth2/authorize?client_id=
|
||||
NUXT_DEV_MODE=TRUE
|
||||
@@ -6,6 +6,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- feat/netcode-rework
|
||||
|
||||
jobs:
|
||||
release-image:
|
||||
|
||||
+215
-36
@@ -10,6 +10,7 @@ export interface Props {
|
||||
interactible?: boolean;
|
||||
noEffects?: boolean;
|
||||
used_effects_indexes?: number[];
|
||||
discardable?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
@@ -18,9 +19,17 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
locked: () => true,
|
||||
interactible: () => true,
|
||||
noEffects: () => false,
|
||||
discardable: () => false,
|
||||
});
|
||||
|
||||
const emit = defineEmits(["click", "effectClick"]);
|
||||
const emit = defineEmits([
|
||||
"click",
|
||||
"effectClick",
|
||||
"drop",
|
||||
"move",
|
||||
"startMove",
|
||||
"stopMove",
|
||||
]);
|
||||
|
||||
const settingsStore = useSettingsStore();
|
||||
|
||||
@@ -28,12 +37,35 @@ const childCount = ref<number>(0);
|
||||
|
||||
const card = ref<HTMLElement>();
|
||||
|
||||
const dragStatus = ref<{
|
||||
hasClickedDown: boolean;
|
||||
dragging: boolean;
|
||||
intervalEvent?: ReturnType<typeof setTimeout>;
|
||||
}>({
|
||||
hasClickedDown: false,
|
||||
dragging: false,
|
||||
});
|
||||
const initialOffsetX = ref(0);
|
||||
const initialOffsetY = ref(0);
|
||||
|
||||
const mousePageX = ref(0);
|
||||
const mousePageY = ref(0);
|
||||
|
||||
const offsetX = ref(0);
|
||||
const offsetY = ref(0);
|
||||
const offsetWidth = ref(0);
|
||||
const offsetHeight = ref(0);
|
||||
|
||||
const translateX = ref(0);
|
||||
const translateY = ref(0);
|
||||
|
||||
const extension = computed(() => {
|
||||
if (settingsStore.cardStyle == CardStyles.SVG) {
|
||||
return ".svg";
|
||||
}
|
||||
return ".png";
|
||||
});
|
||||
|
||||
function cardClick() {
|
||||
if (!props.card_id) return;
|
||||
emit("click");
|
||||
@@ -61,8 +93,126 @@ function rightClickUp(e: MouseEvent) {
|
||||
isZooming.value = false;
|
||||
}
|
||||
|
||||
function startDrag(e: MouseEvent) {
|
||||
emit("startMove");
|
||||
dragStatus.value.dragging = true;
|
||||
translateX.value = 0;
|
||||
translateY.value = 0;
|
||||
const cardElement = card.value;
|
||||
if (!cardElement) {
|
||||
return;
|
||||
}
|
||||
mousePageX.value = e.pageX;
|
||||
mousePageY.value = e.pageY;
|
||||
initialOffsetX.value = e.offsetX;
|
||||
initialOffsetY.value = e.offsetY;
|
||||
offsetX.value = cardElement.offsetLeft + e.offsetX;
|
||||
offsetY.value = cardElement.offsetTop + e.offsetY;
|
||||
translateX.value = mousePageX.value - offsetX.value;
|
||||
translateY.value = mousePageY.value - offsetY.value;
|
||||
}
|
||||
|
||||
function leftClickDown(e: MouseEvent) {
|
||||
dragStatus.value.hasClickedDown = true;
|
||||
window.addEventListener("mousemove", mouseMove, false);
|
||||
}
|
||||
|
||||
function leftClickUpGlobal(e: MouseEvent) {
|
||||
mousePageX.value = e.pageX;
|
||||
mousePageY.value = e.pageY;
|
||||
|
||||
if (dragStatus.value.dragging && dragStatus.value.hasClickedDown) {
|
||||
dragStatus.value.dragging = false;
|
||||
emit("drop", { x: e.pageX, y: e.pageY, uuid: props.card?._id });
|
||||
emit("stopMove");
|
||||
}
|
||||
dragStatus.value.hasClickedDown = false;
|
||||
clearTimeout(dragStatus.value.intervalEvent);
|
||||
window.removeEventListener("mousemove", mouseMove, false);
|
||||
}
|
||||
|
||||
function leftClickUp(e: MouseEvent) {
|
||||
if (dragStatus.value.dragging == false && dragStatus.value.hasClickedDown) {
|
||||
dragStatus.value.hasClickedDown = false;
|
||||
cardClick();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const sensitivity = 0.5;
|
||||
function mouseMove(e: MouseEvent) {
|
||||
if (
|
||||
dragStatus.value.hasClickedDown &&
|
||||
!dragStatus.value.dragging &&
|
||||
Math.sqrt(Math.abs(e.movementX * e.movementY)) > sensitivity
|
||||
) {
|
||||
startDrag(e);
|
||||
}
|
||||
|
||||
const cardElement = card.value;
|
||||
if (!cardElement) {
|
||||
return;
|
||||
}
|
||||
mousePageX.value = e.pageX;
|
||||
mousePageY.value = e.pageY;
|
||||
// console.log(cardElement.offsetLeft);
|
||||
offsetX.value = cardElement.offsetLeft + initialOffsetX.value;
|
||||
offsetY.value = cardElement.offsetTop + initialOffsetY.value;
|
||||
|
||||
translateX.value = mousePageX.value - offsetX.value;
|
||||
translateY.value = mousePageY.value - offsetY.value;
|
||||
|
||||
// emit("move", { x: e.pageX, y: e.pageY, uuid: props.card?._id });
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
offsetX,
|
||||
offsetY,
|
||||
offsetWidth,
|
||||
offsetHeight,
|
||||
uuid: props.card?._id,
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
card.value?.style.setProperty("--random-seed", -Math.random() * 10 + "s");
|
||||
window.addEventListener("mouseup", leftClickUpGlobal, false);
|
||||
const cardElement = card.value;
|
||||
if (!cardElement) {
|
||||
return;
|
||||
}
|
||||
offsetX.value = cardElement.offsetLeft;
|
||||
offsetY.value = cardElement.offsetTop;
|
||||
offsetWidth.value = cardElement.offsetWidth;
|
||||
offsetHeight.value = cardElement.offsetHeight;
|
||||
cardElement.offsetWidth;
|
||||
});
|
||||
|
||||
// onRenderTriggered(() => {
|
||||
// const cardElement = card.value;
|
||||
// if (!cardElement) {
|
||||
// return;
|
||||
// }
|
||||
// offsetX.value = cardElement.offsetLeft + initialOffsetX.value;
|
||||
// offsetY.value = cardElement.offsetTop + initialOffsetY.value;
|
||||
|
||||
// translateX.value = mousePageX.value - offsetX.value;
|
||||
// translateY.value = mousePageY.value - offsetY.value;
|
||||
// });
|
||||
|
||||
onUpdated(() => {
|
||||
const cardElement = card.value;
|
||||
if (!cardElement) {
|
||||
return;
|
||||
}
|
||||
offsetX.value = cardElement.offsetLeft + initialOffsetX.value;
|
||||
offsetY.value = cardElement.offsetTop + initialOffsetY.value;
|
||||
|
||||
translateX.value = mousePageX.value - offsetX.value;
|
||||
translateY.value = mousePageY.value - offsetY.value;
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener("mouseup", leftClickUpGlobal, false);
|
||||
// window.addEventListener("mousemove", mouseMove, false);
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -71,25 +221,22 @@ onMounted(() => {
|
||||
ref="card"
|
||||
class="card"
|
||||
:class="{
|
||||
dragging: dragStatus.dragging,
|
||||
active: childCount > 0,
|
||||
wrapped,
|
||||
unlocked: !props.locked,
|
||||
zoom: isZooming,
|
||||
no_effects: noEffects || !props.locked,
|
||||
discardable,
|
||||
}"
|
||||
@contextmenu.prevent="false"
|
||||
@click.left="cardClick"
|
||||
@mousedown.right="rightClickDown"
|
||||
@mouseup.right="rightClickUp"
|
||||
@mousedown.left="leftClickDown"
|
||||
@mouseup.left="leftClickUp"
|
||||
@mouseenter="mouseenter"
|
||||
@mouseleave="mouseleave"
|
||||
>
|
||||
<div
|
||||
id="contextMenuButtons"
|
||||
:ref="(el) => { childCount = ((el as Element)?.childElementCount ?? 0) }"
|
||||
>
|
||||
<slot></slot>
|
||||
</div>
|
||||
<template v-if="props.card_id">
|
||||
<!-- <svg
|
||||
width="180"
|
||||
@@ -124,7 +271,7 @@ onMounted(() => {
|
||||
"
|
||||
draggable="false"
|
||||
/>
|
||||
<div></div>
|
||||
<div id="overlay"><slot></slot></div>
|
||||
</template>
|
||||
|
||||
<img
|
||||
@@ -137,19 +284,15 @@ onMounted(() => {
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.card {
|
||||
--max-height: 250px;
|
||||
--max-width: 179px;
|
||||
--margin-bottom: calc(var(--max-height) * 0.05);
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 0px;
|
||||
margin-top: var(--margin-bottom);
|
||||
transition: all 0.075s cubic-bezier(1, 1.81, 0.59, 1.42);
|
||||
pointer-events: all;
|
||||
max-height: var(--max-height);
|
||||
max-width: var(--max-width);
|
||||
.card.dragging {
|
||||
transform: translateX(v-bind("translateX + 'px'"))
|
||||
translateY(v-bind("translateY + 'px'"));
|
||||
cursor: grabbing;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.card.dragging > svg {
|
||||
transform: scale(110%);
|
||||
}
|
||||
|
||||
.card.active {
|
||||
@@ -172,15 +315,6 @@ onMounted(() => {
|
||||
drop-shadow(-0.5px -0.5px 0.5px gray);
|
||||
}
|
||||
|
||||
.card.unlocked {
|
||||
margin-top: 0px;
|
||||
margin-bottom: var(--margin-bottom);
|
||||
transform: translateY(calc(var(--margin-bottom) * -0.25));
|
||||
filter: drop-shadow(
|
||||
calc(var(--margin-bottom) * 0.3) var(--margin-bottom) 1px rgba(0, 0, 0, 0.6)
|
||||
);
|
||||
}
|
||||
|
||||
.card.zoom {
|
||||
transform: scale(200%);
|
||||
z-index: 10;
|
||||
@@ -207,10 +341,6 @@ onMounted(() => {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.card.no_effects {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#contextMenuButtons > * {
|
||||
flex: 1;
|
||||
border-radius: 12px;
|
||||
@@ -253,4 +383,53 @@ onMounted(() => {
|
||||
filter: grayscale(0.6);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.svg_effect text {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.card {
|
||||
--max-height: 250px;
|
||||
--max-width: 179px;
|
||||
--margin-bottom: calc(var(--max-height) * 0.05);
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 0px;
|
||||
margin-top: var(--margin-bottom);
|
||||
transition: all 0.15s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
pointer-events: all;
|
||||
max-height: var(--max-height);
|
||||
max-width: var(--max-width);
|
||||
/* cursor: grab; */
|
||||
}
|
||||
|
||||
.card:not(svg) {
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
#overlay {
|
||||
position: absolute;
|
||||
top: 20%;
|
||||
width: calc(100% - 8%);
|
||||
height: 49%;
|
||||
}
|
||||
|
||||
.card.unlocked {
|
||||
margin-top: 0px;
|
||||
margin-bottom: var(--margin-bottom);
|
||||
transform: translateY(calc(var(--margin-bottom) * -0.25));
|
||||
filter: drop-shadow(
|
||||
calc(var(--margin-bottom) * 0.3) var(--margin-bottom) 1px rgba(0, 0, 0, 0.6)
|
||||
);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.card.discardable {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.card.discardable svg {
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import { delay } from "~/netcode/events";
|
||||
import type { Card, Container, PlayingTurn } from "~/netcode/interfaces";
|
||||
import {
|
||||
CardEffects,
|
||||
CardType,
|
||||
type Card,
|
||||
type Container,
|
||||
type Effect,
|
||||
type PlayingTurn,
|
||||
} from "~/netcode/interfaces";
|
||||
import TokenComponent from "./tokens/TokenComponent.vue";
|
||||
|
||||
export interface Props {
|
||||
container: Container;
|
||||
@@ -8,15 +16,27 @@ export interface Props {
|
||||
wrapped?: boolean;
|
||||
hidden?: boolean;
|
||||
noEffects?: boolean;
|
||||
tokens?: Effect[];
|
||||
championsKillable?: boolean;
|
||||
discardable?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
wrapped: () => false,
|
||||
hidden: () => false,
|
||||
noEffects: () => false,
|
||||
tokens: () => [],
|
||||
championsKillable: () => false,
|
||||
discardable: () => false,
|
||||
});
|
||||
|
||||
const emit = defineEmits(["cardClick", "effectClick"]);
|
||||
const emit = defineEmits([
|
||||
"cardClick",
|
||||
"effectClick",
|
||||
"tokenClick",
|
||||
"damageChampionClick",
|
||||
"discardCardClick",
|
||||
]);
|
||||
|
||||
const settingsStore = useSettingsStore();
|
||||
|
||||
@@ -34,6 +54,7 @@ const animationSpeed = computed(() => settingsStore.animationSpeed + "ms");
|
||||
const shuffleAnimationSpeed = computed(
|
||||
() => settingsStore.animationSpeed * 2 + "ms"
|
||||
);
|
||||
|
||||
function populateContainer() {}
|
||||
|
||||
// const rotate = ref(false);
|
||||
@@ -87,6 +108,28 @@ function endAnimation() {
|
||||
onUnmounted(() => {
|
||||
// containerEvents.delete(props.container._id);
|
||||
});
|
||||
|
||||
const interval = ref<ReturnType<typeof setInterval>>();
|
||||
// function startMove() {
|
||||
// interval.value = setInterval(() => {
|
||||
// props.container.cards.sort((a, b) => Math.random() - 0.5);
|
||||
// }, 1000);
|
||||
// }
|
||||
// function stopMove() {
|
||||
// clearInterval(interval.value);
|
||||
// }
|
||||
|
||||
function tokenClick(token: Effect, card: Card) {
|
||||
emit("tokenClick", { token, card });
|
||||
}
|
||||
|
||||
function damageChampionClick(card: Card) {
|
||||
emit("damageChampionClick", card);
|
||||
}
|
||||
|
||||
function discardCardClick(card: Card) {
|
||||
emit("discardCardClick", card);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -98,22 +141,64 @@ onUnmounted(() => {
|
||||
<CardPreview
|
||||
@click="$emit('cardClick', c._id)"
|
||||
@effectClick="$emit('effectClick', c._id, $event)"
|
||||
v-for="c in cards"
|
||||
:card_id="c.cardId"
|
||||
v-for="(c, i) in cards"
|
||||
:card_id="c?.cardId"
|
||||
:wrapped="wrapped"
|
||||
:key="c._id"
|
||||
:key="c?._id || i"
|
||||
:card="c"
|
||||
:locked="
|
||||
!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)){
|
||||
prev.push(i)
|
||||
}
|
||||
return prev
|
||||
},[] as number[])"
|
||||
:noEffects="noEffects"
|
||||
:discardable="discardable"
|
||||
>
|
||||
<template v-for="t in tokens">
|
||||
<TokenComponent
|
||||
:token="t"
|
||||
@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) ||
|
||||
t.effect == CardEffects.PLAY_NEXT_CARD_BOUGHT ||
|
||||
t.effect == CardEffects.STACK_NEXT_CARD_BOUGHT ||
|
||||
t.effect == CardEffects.RESTACK_DISCARDED_CARD ||
|
||||
(t.effect == CardEffects.RESTACK_DISCARDED_ACTION &&
|
||||
c.cardType == CardType.ACTION) ||
|
||||
(t.effect == CardEffects.RESTACK_DISCARDED_CHAMPION &&
|
||||
c.cardType == CardType.CHAMPION)
|
||||
"
|
||||
></TokenComponent>
|
||||
</template>
|
||||
<button
|
||||
v-if="championsKillable && c.cardType == CardType.CHAMPION"
|
||||
@click.stop="damageChampionClick(c)"
|
||||
@mousedown.left.stop=""
|
||||
>
|
||||
Damage
|
||||
</button>
|
||||
<button
|
||||
v-if="
|
||||
discardable && !playingTurn?.cardsLocked.includes(c._id.toString())
|
||||
"
|
||||
@mousedown.left.stop=""
|
||||
@click.stop="discardCardClick(c)"
|
||||
>
|
||||
Discard
|
||||
</button>
|
||||
</CardPreview>
|
||||
</TransitionGroup>
|
||||
<!-- <img :class="`card_image`" :src="'/cards/background.png'" draggable="false"> -->
|
||||
@@ -147,6 +232,7 @@ onUnmounted(() => {
|
||||
flex-direction: row;
|
||||
justify-content: space-evenly;
|
||||
min-width: 200px;
|
||||
flex-wrap: wrap;
|
||||
transition: rotate v-bind("shuffleAnimationSpeed") ease;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
<script setup lang="ts">
|
||||
import { buyCard, buyGem, useToken } from "~/netcode";
|
||||
import {
|
||||
CardEffects,
|
||||
type Card,
|
||||
type Container,
|
||||
type Effect,
|
||||
type Game,
|
||||
type Player,
|
||||
} from "~/netcode/interfaces";
|
||||
import TokenComponent from "./tokens/TokenComponent.vue";
|
||||
|
||||
export interface Props {
|
||||
game: Game;
|
||||
discard: Container;
|
||||
player: Player;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const authStore = useAuthStore();
|
||||
|
||||
const emit = defineEmits(["close"]);
|
||||
function marketCardClick(e: string) {
|
||||
buyCard(props.game._id, e);
|
||||
}
|
||||
|
||||
function fireGemCardClick(e: string) {
|
||||
buyGem(props.game._id);
|
||||
}
|
||||
|
||||
const discardTokens = computed(() =>
|
||||
props.game.currentTurn.tokens.filter((t) =>
|
||||
[
|
||||
CardEffects.RESTACK_DISCARDED_ACTION,
|
||||
CardEffects.RESTACK_DISCARDED_CARD,
|
||||
CardEffects.RESTACK_DISCARDED_CHAMPION,
|
||||
CardEffects.SACRIFICE,
|
||||
].includes(t.effect)
|
||||
)
|
||||
);
|
||||
|
||||
function tokenClick({ card, token }: { card: Card; token: Effect }) {
|
||||
useToken(props.game._id, token._id, card._id);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="overlay">
|
||||
<button @click="$emit('close')">Close</button>
|
||||
<span>Discard of {{ player.user.username }}</span>
|
||||
|
||||
<div class="discard_unwrapped" @click.stop>
|
||||
<CardsGrouped
|
||||
:container="discard"
|
||||
:wrapped="false"
|
||||
:hidden="false"
|
||||
:tokens="discardTokens"
|
||||
:noEffects="true"
|
||||
:playingTurn="game.currentTurn"
|
||||
@tokenClick="tokenClick"
|
||||
></CardsGrouped>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
span {
|
||||
background: white;
|
||||
}
|
||||
.overlay {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
position: fixed;
|
||||
z-index: 200;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.discard_unwrapped {
|
||||
width: max-content;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
/* position: relative; */
|
||||
gap: 2px;
|
||||
margin: 10px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
padding-bottom: 10px;
|
||||
border-radius: 10px;
|
||||
/* filter: drop-shadow(2.5px 7.5px 1px rgba(0, 0, 0, 0.6)); */
|
||||
/* backdrop-filter: blur(5px) brightness(80%); */
|
||||
background: rgba(60, 47, 117, 0.46);
|
||||
/* left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%); */
|
||||
}
|
||||
</style>
|
||||
+46
-10
@@ -1,6 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { buyCard } from "~/netcode";
|
||||
import type { Container, Game } from "~/netcode/interfaces";
|
||||
import { buyCard, buyGem, useToken } from "~/netcode";
|
||||
import {
|
||||
CardEffects,
|
||||
type Card,
|
||||
type Container,
|
||||
type Effect,
|
||||
type Game,
|
||||
} from "~/netcode/interfaces";
|
||||
import TokenComponent from "./tokens/TokenComponent.vue";
|
||||
|
||||
export interface Props {
|
||||
game: Game;
|
||||
@@ -25,12 +32,35 @@ function marketCardClick(e: string) {
|
||||
}
|
||||
|
||||
function fireGemCardClick(e: string) {
|
||||
console.log(e);
|
||||
buyGem(props.game._id);
|
||||
}
|
||||
|
||||
const marketTokens = computed(() =>
|
||||
props.game.currentTurn.tokens.filter((t) =>
|
||||
[
|
||||
CardEffects.STACK_NEXT_CARD_BOUGHT,
|
||||
CardEffects.STACK_NEXT_ACTION_BOUGHT,
|
||||
CardEffects.PLAY_NEXT_CARD_BOUGHT,
|
||||
].includes(t.effect)
|
||||
)
|
||||
);
|
||||
|
||||
const gemsTokens = computed(() =>
|
||||
props.game.currentTurn.tokens.filter((t) =>
|
||||
[
|
||||
CardEffects.STACK_NEXT_CARD_BOUGHT,
|
||||
CardEffects.PLAY_NEXT_CARD_BOUGHT,
|
||||
].includes(t.effect)
|
||||
)
|
||||
);
|
||||
|
||||
function tokenClick({ card, token }: { card: Card; token: Effect }) {
|
||||
useToken(props.game._id, token._id, card._id);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div id="market">
|
||||
<div class="market">
|
||||
<CardsGrouped
|
||||
:container="marketStack"
|
||||
:wrapped="true"
|
||||
@@ -41,34 +71,40 @@ function fireGemCardClick(e: string) {
|
||||
:container="market"
|
||||
@cardClick="marketCardClick"
|
||||
:noEffects="true"
|
||||
></CardsGrouped>
|
||||
:tokens="marketTokens"
|
||||
@tokenClick="tokenClick"
|
||||
>
|
||||
</CardsGrouped>
|
||||
<div class="separator"></div>
|
||||
<CardsGrouped
|
||||
:container="fire_gems"
|
||||
:wrapped="true"
|
||||
@cardClick="fireGemCardClick"
|
||||
:noEffects="true"
|
||||
:tokens="gemsTokens"
|
||||
@tokenClick="tokenClick"
|
||||
></CardsGrouped>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
#market {
|
||||
width: min-content;
|
||||
.market {
|
||||
width: max-content;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
/* position: relative; */
|
||||
gap: 2px;
|
||||
margin: 10px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
padding-bottom: 10px;
|
||||
border-radius: 10px;
|
||||
filter: drop-shadow(2.5px 7.5px 1px rgba(0, 0, 0, 0.6));
|
||||
backdrop-filter: blur(5px) brightness(80%);
|
||||
isolation: initial;
|
||||
/* filter: drop-shadow(2.5px 7.5px 1px rgba(0, 0, 0, 0.6)); */
|
||||
/* backdrop-filter: blur(5px) brightness(80%); */
|
||||
background: rgba(155, 62, 62, 0.46);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<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"]);
|
||||
|
||||
@@ -15,6 +16,24 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
isTurn: () => 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>
|
||||
|
||||
<template>
|
||||
@@ -48,6 +67,24 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
<PlayerStats :game="props.game" :player="props.player"> </PlayerStats>
|
||||
<!-- </template> -->
|
||||
</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>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,21 @@
|
||||
<script setup lang="ts">
|
||||
import { endTurn, joinGame, lockCard, lockEffect, startGame } from "~/netcode";
|
||||
import type { Game, Player } from "~/netcode/interfaces";
|
||||
import {
|
||||
damageChampion,
|
||||
discardCard,
|
||||
endTurn,
|
||||
joinGame,
|
||||
lockCard,
|
||||
lockEffect,
|
||||
startGame,
|
||||
useToken,
|
||||
} from "~/netcode";
|
||||
import {
|
||||
CardEffects,
|
||||
type Card,
|
||||
type Effect,
|
||||
type Game,
|
||||
type Player,
|
||||
} from "~/netcode/interfaces";
|
||||
import { useTurnStore } from "~/stores/turnStore";
|
||||
|
||||
export interface Props {
|
||||
@@ -37,8 +52,15 @@ const isSelf = computed(
|
||||
);
|
||||
const isSelfTurn = computed(() => isSelf && isPlayerTurn);
|
||||
|
||||
const cardTokens = computed(() =>
|
||||
props.game.currentTurn.tokens.filter(
|
||||
(t) =>
|
||||
[CardEffects.PREPARE, CardEffects.STUN].includes(t.effect) ||
|
||||
(CardEffects.SACRIFICE == t.effect && isSelf)
|
||||
)
|
||||
);
|
||||
|
||||
const warningText = ref("Effets restants!");
|
||||
const turnStore = useTurnStore();
|
||||
|
||||
// const make_discard = (target: Player) =>
|
||||
// clientStore.findUseEffect(CardEffects.MAKE_DISCARD, target);
|
||||
@@ -114,6 +136,16 @@ function effectClick(cardUUID: string, effectIndex: number) {
|
||||
// function check_for_guard(player: Player) {
|
||||
// return player.board.some(c => c.guard === true)
|
||||
// }
|
||||
|
||||
function tokenClick({ card, token }: { card: Card; token: Effect }) {
|
||||
useToken(props.game._id, token._id, card._id, props.player._id);
|
||||
}
|
||||
function damageChampionClick(card: Card) {
|
||||
damageChampion(props.game._id, props.player._id, card._id);
|
||||
}
|
||||
function discardCardClick(card: Card) {
|
||||
discardCard(props.game._id, card._id);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -172,6 +204,14 @@ function effectClick(cardUUID: string, effectIndex: number) {
|
||||
:playingTurn="props.game.currentTurn"
|
||||
@cardClick="boardCardClick"
|
||||
@effectClick="effectClick"
|
||||
:tokens="cardTokens"
|
||||
@tokenClick="tokenClick"
|
||||
:championsKillable="!isSelf && isSelfTurn.value"
|
||||
:discardable="
|
||||
(player.fuckUMarkers > 0 || player.discardMarkers > 0) && isSelf
|
||||
"
|
||||
@damageChampionClick="damageChampionClick"
|
||||
@discardCardClick="discardCardClick"
|
||||
>
|
||||
</CardsGrouped>
|
||||
|
||||
|
||||
+12
-12
@@ -28,21 +28,21 @@ const isTurn = computed(
|
||||
</span>
|
||||
</div>
|
||||
<div class="turn_icon" v-if="isTurn">
|
||||
<img src="/img/gold.png" class="icon_img" draggable="false" />
|
||||
<span class="turn_icon_number">
|
||||
{{ game.currentTurn.gold }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="turn_icon" v-if="isTurn">
|
||||
<img src="/img/damage.png" class="icon_img" draggable="false" />
|
||||
<span class="turn_icon_number">
|
||||
{{ game.currentTurn.damage }}
|
||||
</span>
|
||||
</div>
|
||||
<img src="/img/gold.png" class="icon_img" draggable="false" />
|
||||
<span class="turn_icon_number">
|
||||
{{ game.currentTurn.gold }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="turn_icon" v-if="isTurn">
|
||||
<img src="/img/damage.png" class="icon_img" draggable="false" />
|
||||
<span class="turn_icon_number">
|
||||
{{ game.currentTurn.damage }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="turn_icon">
|
||||
<img src="/img/fuck.svg" class="icon_img" draggable="false" />
|
||||
<span class="turn_icon_number">{{
|
||||
(isTurn && (player.discardMarkers ?? 0) + (player.fuckUMarkers ?? 0)) || 0
|
||||
(player.discardMarkers ?? 0) + (player.fuckUMarkers ?? 0)
|
||||
}}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<script setup lang="ts">
|
||||
import type { Effect } from "~/netcode/interfaces";
|
||||
|
||||
type Props = {
|
||||
token: Effect;
|
||||
};
|
||||
const props = defineProps<Props>();
|
||||
|
||||
const emit = defineEmits(["useToken"]);
|
||||
|
||||
function onClick(e: MouseEvent) {
|
||||
emit("useToken", props.token);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div @click.stop="onClick" @mousedown.left.stop="" id="token">
|
||||
{{ props.token.effect }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
#token {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: white;
|
||||
border: 1px solid white;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
transition: 0.2s all;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
#token:hover {
|
||||
border: 1px solid red;
|
||||
}
|
||||
</style>
|
||||
+98
-24
@@ -2,7 +2,7 @@ import type { Game, User } from "./interfaces";
|
||||
|
||||
export function subscribe(endpoint: string) {
|
||||
const config = useRuntimeConfig();
|
||||
const evtSource = new EventSource(new URL(endpoint, config.public.endpoint), {
|
||||
const evtSource = new EventSource(config.public.endpoint + endpoint, {
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
@@ -11,12 +11,9 @@ export function subscribe(endpoint: string) {
|
||||
|
||||
export async function getLobby() {
|
||||
const config = useRuntimeConfig();
|
||||
const req = await useFetch<Array<Game>>(
|
||||
new URL("/games", config.public.endpoint).href,
|
||||
{
|
||||
credentials: "include",
|
||||
}
|
||||
);
|
||||
const req = await useFetch<Array<Game>>(config.public.endpoint + "/games", {
|
||||
credentials: "include",
|
||||
});
|
||||
if (req.data.value == null) {
|
||||
throw new Error("Lobby answer is empty");
|
||||
}
|
||||
@@ -26,7 +23,7 @@ export async function getLobby() {
|
||||
export async function whoami() {
|
||||
const config = useRuntimeConfig();
|
||||
const { data, pending, error, refresh } = await useFetch<User>(
|
||||
new URL("/whoami", config.public.endpoint).href,
|
||||
config.public.endpoint + "/whoami",
|
||||
{
|
||||
credentials: "include",
|
||||
}
|
||||
@@ -48,13 +45,10 @@ export async function whoami() {
|
||||
|
||||
export async function createGame() {
|
||||
const config = useRuntimeConfig();
|
||||
const res = await $fetch<Game>(
|
||||
new URL("/games", config.public.endpoint).href,
|
||||
{
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
}
|
||||
);
|
||||
const res = await $fetch<Game>(config.public.endpoint + "/games", {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
});
|
||||
console.log(res);
|
||||
navigateTo("/game/" + res._id);
|
||||
}
|
||||
@@ -62,7 +56,7 @@ export async function createGame() {
|
||||
export async function startGame(game: string) {
|
||||
const config = useRuntimeConfig();
|
||||
const res = await $fetch<Game>(
|
||||
new URL(`games/${game}/start`, config.public.endpoint).href,
|
||||
config.public.endpoint + `/games/${game}/start`,
|
||||
{
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
@@ -73,7 +67,7 @@ export async function startGame(game: string) {
|
||||
export async function joinGame(game: string) {
|
||||
const config = useRuntimeConfig();
|
||||
const res = await $fetch<Game>(
|
||||
new URL(`games/${game}/join`, config.public.endpoint).href,
|
||||
config.public.endpoint + `/games/${game}/join`,
|
||||
{
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
@@ -83,7 +77,7 @@ export async function joinGame(game: string) {
|
||||
|
||||
export async function endTurn(game: string) {
|
||||
const config = useRuntimeConfig();
|
||||
await $fetch(new URL(`games/${game}/endTurn`, config.public.endpoint).href, {
|
||||
await $fetch(config.public.endpoint + `/games/${game}/endTurn`, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
});
|
||||
@@ -92,8 +86,7 @@ export async function endTurn(game: string) {
|
||||
export async function lockCard(game: string, cardId: string) {
|
||||
const config = useRuntimeConfig();
|
||||
await $fetch(
|
||||
new URL(`games/${game}/turn/lockCard/${cardId}`, config.public.endpoint)
|
||||
.href,
|
||||
config.public.endpoint + `/games/${game}/turn/lockCard/${cardId}`,
|
||||
{
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
@@ -104,8 +97,7 @@ export async function lockCard(game: string, cardId: string) {
|
||||
export async function buyCard(game: string, cardId: string) {
|
||||
const config = useRuntimeConfig();
|
||||
await $fetch(
|
||||
new URL(`games/${game}/turn/buyCard/${cardId}`, config.public.endpoint)
|
||||
.href,
|
||||
config.public.endpoint + `/games/${game}/turn/buyCard/${cardId}`,
|
||||
{
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
@@ -113,11 +105,93 @@ export async function buyCard(game: string, cardId: string) {
|
||||
);
|
||||
}
|
||||
|
||||
export async function buyGem(game: string) {
|
||||
const config = useRuntimeConfig();
|
||||
await $fetch(config.public.endpoint + `/games/${game}/turn/buyGem`, {
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
});
|
||||
}
|
||||
|
||||
export async function useToken(
|
||||
game: string,
|
||||
tokenId: string,
|
||||
cardId?: string,
|
||||
playerId?: string
|
||||
) {
|
||||
const config = useRuntimeConfig();
|
||||
await $fetch(
|
||||
config.public.endpoint + `/games/${game}/turn/useToken/${tokenId}`,
|
||||
{
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
body: { cardId, playerId },
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export async function lockEffect(game: string, effectId: string) {
|
||||
const config = useRuntimeConfig();
|
||||
await $fetch(
|
||||
new URL(`games/${game}/turn/lockEffect/${effectId}`, config.public.endpoint)
|
||||
.href,
|
||||
config.public.endpoint + `/games/${game}/turn/lockEffect/${effectId}`,
|
||||
{
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export async function makeDiscard(
|
||||
game: string,
|
||||
playerId: string,
|
||||
amount: number = 1
|
||||
) {
|
||||
const config = useRuntimeConfig();
|
||||
await $fetch(
|
||||
config.public.endpoint + `/games/${game}/turn/makeDiscard/${playerId}`,
|
||||
{
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export async function damagePlayer(
|
||||
game: string,
|
||||
playerId: string,
|
||||
amount: number = 1
|
||||
) {
|
||||
const config = useRuntimeConfig();
|
||||
await $fetch(
|
||||
config.public.endpoint + `/games/${game}/turn/damagePlayer/${playerId}`,
|
||||
{
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
body: { amount },
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export async function damageChampion(
|
||||
game: string,
|
||||
playerId: string,
|
||||
cardId: string
|
||||
) {
|
||||
const config = useRuntimeConfig();
|
||||
await $fetch(
|
||||
config.public.endpoint + `/games/${game}/turn/damageChampion/${cardId}`,
|
||||
{
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
body: { playerId },
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export async function discardCard(game: string, cardId: string) {
|
||||
const config = useRuntimeConfig();
|
||||
await $fetch(
|
||||
config.public.endpoint + `/games/${game}/turn/discardCard/${cardId}`,
|
||||
{
|
||||
method: "POST",
|
||||
credentials: "include",
|
||||
|
||||
+57
-1
@@ -1,3 +1,56 @@
|
||||
export enum CardEffects {
|
||||
//Base
|
||||
GOLD = "gold",
|
||||
DAMAGE = "damage",
|
||||
HEAL = "heal",
|
||||
PREPARE = "prepare",
|
||||
STUN = "stun",
|
||||
SACRIFICE = "sacrifice",
|
||||
DRAW = "draw",
|
||||
DRAW_AND_DISCARD = "draw_and_discard",
|
||||
MAKE_DISCARD = "make_discard",
|
||||
RESTACK_DISCARDED_CHAMPION = "restack_discarded_champion",
|
||||
RESTACK_DISCARDED_CARD = "restack_discarded_card",
|
||||
STACK_NEXT_ACTION_BOUGHT = "stack_next_action_bought",
|
||||
STACK_NEXT_CARD_BOUGHT = "stack_next_card_bought",
|
||||
PLAY_NEXT_CARD_BOUGHT = "play_next_card_bought",
|
||||
|
||||
//DLCs
|
||||
BUY_FOR_FREE = "buy_for_free",
|
||||
|
||||
//Journeys
|
||||
DAMAGE_ALL_CHAMPIONS = "damage_all_champions",
|
||||
|
||||
//Journeys: Hunters
|
||||
DISCARD_X_AND_DRAW_X = "discard_x_and_draw_x",
|
||||
PREPARE_ANOTHER_CHAMPION = "prepare_another_champion",
|
||||
//Journey: Travelers
|
||||
PREPARE_ALL_CHAMPIONS = "prepare_all_champions",
|
||||
CHEAPER_CHAMPION = "cheaper_champion",
|
||||
CHEAPER_CHAMPIONS_PASSIVE = "cheaper_champions_passive",
|
||||
CHEAPER_ACTION = "cheaper_action",
|
||||
CONTROL_OPPOSING_CHAMPION_PASSIVE = "control_opposing_champion_passive",
|
||||
|
||||
RESTACK_DISCARDED_ACTION = "restack_discarded_action",
|
||||
|
||||
//Ancestry
|
||||
KEEP_IN_HAND = "keep_in_hand",
|
||||
BUY_GEM_FOR_FREE = "buy_gem_for_free",
|
||||
CHEAPER_SKILLS_PASSIVE = "cheaper_skills_passive",
|
||||
CHEAPER_CARD_IF_HIGHER_PRICE = "cheaper_card_if_higher_price",
|
||||
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 {
|
||||
_id: string;
|
||||
}
|
||||
@@ -47,8 +100,11 @@ export interface Container extends GameObject {
|
||||
shuffling?: boolean;
|
||||
}
|
||||
|
||||
export interface Effect extends GameObject {}
|
||||
export interface Effect extends GameObject {
|
||||
effect: CardEffects;
|
||||
}
|
||||
export interface Card extends GameObject {
|
||||
cardId: number;
|
||||
cardType: CardType;
|
||||
effects: Effect[];
|
||||
}
|
||||
|
||||
+2
-3
@@ -4,9 +4,8 @@ export default defineNuxtConfig({
|
||||
ssr: false,
|
||||
runtimeConfig: {
|
||||
public: {
|
||||
endpoint: "http://localhost:8765", // can be overridden by NUXT_PUBLIC_ENDPOINT environment variable
|
||||
discordLoginEndpoint:
|
||||
"https://discord.com/oauth2/authorize?client_id=460020057867681792&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A8765%2Flogin&scope=identify",
|
||||
endpoint: process.env.NUXT_PUBLIC_ENDPOINT, // can be overridden by NUXT_PUBLIC_ENDPOINT environment variable
|
||||
discordLoginEndpoint: process.env.NUXT_PUBLIC_DISCORD_LOGIN_ENDPOINT,
|
||||
},
|
||||
},
|
||||
modules: ["@pinia/nuxt", "@pinia-plugin-persistedstate/nuxt"],
|
||||
|
||||
+120
-12
@@ -1,9 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import LoadingScreen from "~/components/LoadingScreen.vue";
|
||||
import { subscribe } from "~/netcode";
|
||||
import { subscribe, useToken } from "~/netcode";
|
||||
import { delay } from "~/netcode/events";
|
||||
import { type Container, type Game, type Player } from "~/netcode/interfaces";
|
||||
import {
|
||||
type Container,
|
||||
type Effect,
|
||||
type Game,
|
||||
type Player,
|
||||
} from "~/netcode/interfaces";
|
||||
import { playSound } from "~/helpers/audioHelpers";
|
||||
import TokenComponent from "~/components/tokens/TokenComponent.vue";
|
||||
|
||||
const config = useRuntimeConfig();
|
||||
const settingsStore = useSettingsStore();
|
||||
@@ -17,19 +23,15 @@ const {
|
||||
pending,
|
||||
error,
|
||||
refresh,
|
||||
} = await useFetch<Game>(
|
||||
new URL(`/games/${gameId}`, config.public.endpoint).href,
|
||||
{
|
||||
credentials: "include",
|
||||
}
|
||||
);
|
||||
} = await useFetch<Game>(config.public.endpoint + `/games/${gameId}`, {
|
||||
credentials: "include",
|
||||
});
|
||||
|
||||
if (game.value == null) {
|
||||
navigateTo("/lobby");
|
||||
throw new Error("game not found");
|
||||
}
|
||||
|
||||
console.log(game);
|
||||
const containers = computed<Record<string, Container>>(() => ({
|
||||
[game.value!.fireGems._id]: game.value!.fireGems,
|
||||
[game.value!.market._id]: game.value!.market,
|
||||
@@ -147,6 +149,20 @@ eventSource.addEventListener("message", async (message) => {
|
||||
current_game.currentTurn.cardsLocked.push(data.card);
|
||||
await delay(settingsStore.animationSpeed);
|
||||
});
|
||||
} else if (data.type == "destroyCard") {
|
||||
const fromContainer = containers.value[data.from as string];
|
||||
queueAction(async () => {
|
||||
const index = fromContainer.cards.findIndex(
|
||||
(c) => !c || c._id == data.card
|
||||
);
|
||||
fromContainer.cards.splice(index, 1);
|
||||
await delay(settingsStore.animationSpeed);
|
||||
});
|
||||
|
||||
queueAction(async () => {
|
||||
playSound("/sounds/destroy.mp3");
|
||||
await delay(settingsStore.animationSpeed);
|
||||
});
|
||||
} else if (data.type == "joinGame") {
|
||||
queueAction(async () => {
|
||||
playSound("/sounds/teleport.mp3");
|
||||
@@ -157,6 +173,14 @@ eventSource.addEventListener("message", async (message) => {
|
||||
current_game.currentTurn.lockedEffects.push(data.effect);
|
||||
await delay(settingsStore.animationSpeed);
|
||||
});
|
||||
} else if (data.type == "unlockEffect") {
|
||||
queueAction(async () => {
|
||||
const effectIndex = current_game.currentTurn.lockedEffects.indexOf(
|
||||
data.effect
|
||||
);
|
||||
current_game.currentTurn.lockedEffects.splice(effectIndex, 1);
|
||||
await delay(settingsStore.animationSpeed);
|
||||
});
|
||||
} else if (data.type == "currentTurn.updateGold") {
|
||||
queueAction(async () => {
|
||||
console.log(`adding gold amount : ` + data.operation);
|
||||
@@ -172,6 +196,14 @@ eventSource.addEventListener("message", async (message) => {
|
||||
current_game.currentTurn.tokens.push(data.token);
|
||||
await delay(settingsStore.animationSpeed);
|
||||
});
|
||||
} else if (data.type == "currentTurn.useToken") {
|
||||
queueAction(async () => {
|
||||
const index = current_game.currentTurn.tokens.findIndex(
|
||||
(t) => t._id == data.tokenId
|
||||
);
|
||||
current_game.currentTurn.tokens.splice(index, 1);
|
||||
await delay(settingsStore.animationSpeed);
|
||||
});
|
||||
} else if (data.type == "team.updateHealth") {
|
||||
queueAction(async () => {
|
||||
const team = game.value?.teams.find((t) => t._id == data.team);
|
||||
@@ -181,6 +213,56 @@ eventSource.addEventListener("message", async (message) => {
|
||||
console.log(`adding health amount : ` + data.operation);
|
||||
team.health = data.health;
|
||||
});
|
||||
} else if (data.type == "player.addFuckUMarker") {
|
||||
queueAction(async () => {
|
||||
console.log(`adding fuckUMarkers : ` + data.operation);
|
||||
const targetPlayer = playerList.value.find((p) => p._id == data.playerId);
|
||||
if (!targetPlayer) {
|
||||
throw new Error("Cannot add fuckU Markers : player not found");
|
||||
}
|
||||
targetPlayer.fuckUMarkers = data.fuckUMarkers;
|
||||
});
|
||||
} else if (data.type == "player.removeFuckUMarker") {
|
||||
queueAction(async () => {
|
||||
console.log(`adding fuckUMarkers : ` + data.operation);
|
||||
const targetPlayer = playerList.value.find((p) => p._id == data.playerId);
|
||||
if (!targetPlayer) {
|
||||
throw new Error("Cannot remove fuckU Markers : player not found");
|
||||
}
|
||||
targetPlayer.fuckUMarkers = data.fuckUMarkers;
|
||||
});
|
||||
} else if (data.type == "player.addDiscardMarker") {
|
||||
queueAction(async () => {
|
||||
console.log(`adding discardMarkers : ` + data.operation);
|
||||
const targetPlayer = playerList.value.find((p) => p._id == data.playerId);
|
||||
if (!targetPlayer) {
|
||||
throw new Error("Cannot add discard Markers : player not found");
|
||||
}
|
||||
targetPlayer.discardMarkers = data.discardMarkers;
|
||||
});
|
||||
} else if (data.type == "player.removeDiscardMarker") {
|
||||
queueAction(async () => {
|
||||
console.log(`adding fuckUMarkers : ` + data.operation);
|
||||
const targetPlayer = playerList.value.find((p) => p._id == data.playerId);
|
||||
if (!targetPlayer) {
|
||||
throw new Error("Cannot remove discard Markers : player not found");
|
||||
}
|
||||
targetPlayer.discardMarkers = data.discardMarkers;
|
||||
});
|
||||
} 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");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -245,6 +327,14 @@ function focusPlayer(p: Player) {
|
||||
// focusPlayer(first_player)
|
||||
// })
|
||||
|
||||
function useTokenClick(t: Effect) {
|
||||
console.log(t);
|
||||
useToken(game.value!._id, t._id);
|
||||
}
|
||||
|
||||
function showDiscard() {
|
||||
discard_unwrapped.value = true;
|
||||
}
|
||||
onUnmounted(() => {
|
||||
eventSource.close();
|
||||
});
|
||||
@@ -272,7 +362,12 @@ onUnmounted(() => {
|
||||
:class="{ invisible: discard_unwrapped }"
|
||||
@click="() => (discard_unwrapped = true)"
|
||||
>
|
||||
<CardsGrouped :container="focusedPlayer.discard" :wrapped="true">
|
||||
<CardsGrouped
|
||||
:container="focusedPlayer.discard"
|
||||
:wrapped="true"
|
||||
@card-click="showDiscard"
|
||||
:no-effects="true"
|
||||
>
|
||||
</CardsGrouped>
|
||||
</div>
|
||||
</div>
|
||||
@@ -284,7 +379,13 @@ onUnmounted(() => {
|
||||
:fire_gems="game.fireGems"
|
||||
:marketStack="game.marketStack"
|
||||
></MarketCards>
|
||||
<div id="turnStats">{{ game.currentTurn.tokens }}</div>
|
||||
<div>
|
||||
<TokenComponent
|
||||
:token="t"
|
||||
v-for="t in game.currentTurn.tokens"
|
||||
@useToken="useTokenClick"
|
||||
></TokenComponent>
|
||||
</div>
|
||||
<div id="player_list_container">
|
||||
<div id="player_list">
|
||||
<PlayerListElement
|
||||
@@ -309,6 +410,13 @@ onUnmounted(() => {
|
||||
></PlayerSlot>
|
||||
</Transition>
|
||||
</div>
|
||||
<DiscardOverlay
|
||||
v-show="discard_unwrapped"
|
||||
:game="game"
|
||||
:player="focusedPlayer"
|
||||
:discard="focusedPlayer.discard"
|
||||
@close="discard_unwrapped = false"
|
||||
></DiscardOverlay>
|
||||
<ResultDialog
|
||||
:isVisible="showResults"
|
||||
:won="isWinner"
|
||||
@@ -432,7 +540,7 @@ onUnmounted(() => {
|
||||
|
||||
.slide-left-enter-active,
|
||||
.slide-left-leave-active {
|
||||
transition: all v-bind("turnChangeAnimationSpeed") ease-out;
|
||||
transition: all v-bind("settingsStore.animationSpeed * 2 + 'ms'") ease-out;
|
||||
}
|
||||
|
||||
.slide-left-enter-from {
|
||||
|
||||
BIN
Binary file not shown.
Reference in New Issue
Block a user