Merge pull request 'Road to Beta' (#3) from experimental into main

Reviewed-on: legonzaur/heron-realms-front#3
This commit was merged in pull request #3.
This commit is contained in:
2024-05-03 19:02:11 +00:00
16 changed files with 473 additions and 150 deletions
+12 -2
View File
@@ -2,7 +2,7 @@
import { ref } from 'vue';
import goStore, { GameObjectRegister, register, setReady } from '@/netcode';
import goStore, { register, setReady } from '@/netcode';
let username = ref<string>('legonzaur')
@@ -15,6 +15,16 @@ let username = ref<string>('legonzaur')
type="checkbox" id="ready">
<label v-if="goStore.self && !goStore.game?.started" for="scales">Ready</label>
<div>
<GameBoard :game="goStore.game"></GameBoard>
<GameBoard></GameBoard>
</div>
</template>
<style>
html {
text-align: center;
}
body {
margin: 0;
}
</style>
+50 -7
View File
@@ -3,11 +3,15 @@ import type { Card } from '~/netcode/Card';
export interface Props {
data?: Card | null
data: Card | null | undefined
locked?: boolean
wrapped?: boolean
}
const props = defineProps<Props>()
const props = withDefaults(defineProps<Props>(), {
wrapped: () => false,
})
const emit = defineEmits(["click"])
@@ -15,7 +19,7 @@ const buttonsElement = ref<HTMLElement | null>(null)
const rightClicked = ref(false)
function cardClick() {
if (props.data == null) return
if (!props.data) return
emit("click")
}
@@ -24,17 +28,31 @@ function contextmenu(e: MouseEvent) {
buttonsElement.value?.setAttribute("style", `top:${e.clientY + 10}px;left:${e.clientX + 10}px`)
rightClicked.value = true
}
const rotation = ref(0)
// onBeforeUpdate(() => {
// rotation.value = Math.random() > .5 ? 2 : -2
// })
watch(
() => props.data,
() => {
rotation.value = Math.random() > .5 ? 2 : -2
},
{ immediate: true })
</script>
<template>
<div :class="`card ${Number(buttonsElement?.childElementCount) > 0 ? 'active' : ''}`" @contextmenu.prevent="false"
@click.left="cardClick" @click.right="contextmenu">
<div :class="`card ${Number(buttonsElement?.childElementCount) > 0 ? 'active' : ''} ${wrapped ? 'wrapped' : ''}`"
@contextmenu.prevent="false" @click.left="cardClick" @click.right="contextmenu"
:style="`rotate:${rotation}deg;`">
<img :class="`card_image ${rightClicked ? 'outlined' : ''} ${props.locked ? 'locked' : ''}`" v-if="props.data"
:src="'/cards/' + data?.card_id?.toString().padStart(3, '0') + '.png'">
<img :class="`card_image ${rightClicked ? 'outlined' : ''} ${props.locked ? 'locked' : ''}`" v-if="!props.data"
:src="'/cards/background.png'">
</div>
<div :class="rightClicked ? '' : 'hidden'" id="contextMenu" @click.self.prevent="rightClicked = false">
@@ -46,17 +64,41 @@ function contextmenu(e: MouseEvent) {
</template>
<style scoped>
.card {
transition: 0.025s rotate linear;
transition: max-width .125s linear;
max-width: 256px;
}
.card.active {
cursor: pointer
}
.card_image {
max-height: 250px;
transition: all .125s cubic-bezier(0.075, 0.82, 0.165, 1);
margin-top: 15px;
margin-bottom: 0px
}
.card_image.outlined {
outline: 2px solid red;
outline-offset: -2px;
}
.card_image.locked {
filter: brightness(0.5);
/* filter: brightness(0.5); */
filter: drop-shadow(5px 15px 2px rgba(0, 0, 0, .60));
margin-top: 0px;
margin-bottom: 15px;
}
.card.wrapped {
max-width: 10px;
}
.card.wrapped:last-child {
max-width: 256px;
}
.card_image {
@@ -68,6 +110,7 @@ function contextmenu(e: MouseEvent) {
}
#contextMenu {
z-index: 5;
position: fixed;
height: 100%;
width: 100%;
+18 -15
View File
@@ -9,26 +9,29 @@ const props = withDefaults(defineProps<Props>(), {
stack: () => [],
})
const wrapped = ref(false)
const unwrapped = ref(false)
</script>
<template>
{{ props.stack?.length }}
<input type="checkbox" v-model="wrapped" />
<div class="cards_container">
<CardPreview v-if="!wrapped" :data="props.stack.at(-1) ?? null">
<slot></slot>
</CardPreview>
<template v-if="wrapped" v-for="c in props.stack">
<CardPreview :data="c">
<slot></slot>
</CardPreview>
</template>
<div>
<input type="checkbox" v-model="unwrapped" class="checkbox" />
<div class="cards_container">
<template v-if="props.stack.length > 0" v-for="c in props.stack">
<CardPreview :data="c" :wrapped="!unwrapped">
<slot></slot>
</CardPreview>
</template>
</div>
</div>
</template>
</template>
<style scoped>
.cards_container {
position: relative;
max-width: 30vw;
grid-auto-columns: auto;
}
</style>
+31 -34
View File
@@ -1,5 +1,5 @@
<script setup lang="ts">
import goStore, { buy, endTurn, useEffect } from '@/netcode';
import goStore, { buy, useEffect } from '@/netcode';
import { CardEffects } from '@/netcode/Effect'
import { CardType } from '@/netcode/Card'
@@ -9,56 +9,48 @@ const isTurn = computed(() => goStore.self && goStore.game?.started && (goStore.
<template>
<div @contextmenu.prevent="false">
<button v-if="isTurn" @click="endTurn">END TURN</button>
<div v-if="!goStore.self"><b>SPECTATOR MODE</b></div>
<div>
market_amount = {{ goStore.game?.market_stack?.length }}
<br>
market =
<div class="cards_container">
<CardSlot :stack="goStore.game?.gem_stack">
<template v-if="isTurn && goStore.game?.gem_stack.length && goStore.game?.gem_stack.length > 0">
<button @click="buy(goStore.game.gem_stack.at(-1)!)">
BUY
</button>
<button
@click="useEffect(goStore.self!.turn.find_effect(CardEffects.PLAY_NEXT_CARD_BOUGHT)!, goStore.game.gem_stack.at(-1))"
:disabled="(goStore.self === undefined || goStore.game.gem_stack.at(-1)!.cost === undefined || (goStore.self?.turn.gold_reserve ?? 0) < goStore.game.gem_stack.at(-1)!.cost!) || !goStore.self!.turn.find_effect(CardEffects.PLAY_NEXT_CARD_BOUGHT)">
BUY IN HAND</button>
<button
@click="useEffect(goStore.self!.turn.find_effect(CardEffects.STACK_NEXT_CARD_BOUGHT)!, goStore.game.gem_stack.at(-1))"
:disabled="(goStore.self === undefined || goStore.game.gem_stack.at(-1)?.cost === undefined || (goStore.self?.turn.gold_reserve ?? 0) < (goStore.game.gem_stack.at(-1)?.cost ?? Infinity)) || !goStore.self!.turn.find_effect(CardEffects.STACK_NEXT_CARD_BOUGHT)">
BUY IN STACK(generic)
</button>
</template>
</CardSlot>
<CardPreview :data="c" v-for="c in goStore.game?.market" @click="c && buy(c)">
<template v-if="isTurn && c">
<button @click="buy(c)"
:disabled="goStore.self === undefined || c.cost === undefined || goStore.self?.turn.gold_reserve < c.cost">BUY</button>
:disabled="goStore.self === undefined || c.cost === undefined || (goStore.self?.turn.gold_reserve ?? 0) < c.cost">BUY</button>
<button
@click="useEffect(goStore.self!.turn.effects_availables.find(e => (e.effect == CardEffects.PLAY_NEXT_CARD_BOUGHT) && e.usable)!, c)"
:disabled="(goStore.self === undefined || c.cost === undefined || goStore.self.turn.gold_reserve < c.cost) || !goStore.self!.turn.effects_availables.some(e => (e.effect == CardEffects.PLAY_NEXT_CARD_BOUGHT) && e.usable)">
@click="useEffect(goStore.self!.turn.find_effect(CardEffects.PLAY_NEXT_CARD_BOUGHT)!, c)"
:disabled="(goStore.self === undefined || c.cost === undefined || (goStore.self?.turn.gold_reserve ?? 0) < c.cost) || !goStore.self!.turn.find_effect(CardEffects.PLAY_NEXT_CARD_BOUGHT)">
BUY IN HAND</button>
<button
@click="useEffect(goStore.self!.turn.effects_availables.find(e => (e.effect == CardEffects.STACK_NEXT_CARD_BOUGHT) && e.usable)!, c)"
:disabled="(goStore.self === undefined || c.cost === undefined || goStore.self.turn.gold_reserve < c.cost) || !goStore.self!.turn.effects_availables.some(e => (e.effect == CardEffects.STACK_NEXT_CARD_BOUGHT) && e.usable)">
@click="useEffect(goStore.self!.turn.find_effect(CardEffects.STACK_NEXT_CARD_BOUGHT)!, c)"
:disabled="(goStore.self === undefined || c.cost === undefined || (goStore.self?.turn.gold_reserve ?? 0) < c.cost) || !goStore.self!.turn.find_effect(CardEffects.STACK_NEXT_CARD_BOUGHT)">
BUY IN STACK (generic)</button>
<button v-if="c.card_type == CardType.ACTION"
@click="useEffect(goStore.self!.turn.effects_availables.find(e => (e.effect == CardEffects.STACK_NEXT_ACTION_BOUGHT) && e.usable)!, c)"
:disabled="(goStore.self === undefined || c.cost === undefined || goStore.self.turn.gold_reserve < c.cost) || !goStore.self!.turn.effects_availables.some(e => (e.effect == CardEffects.STACK_NEXT_ACTION_BOUGHT) && e.usable)">
@click="useEffect(goStore.self!.turn.find_effect(CardEffects.STACK_NEXT_ACTION_BOUGHT)!, c)"
:disabled="(goStore.self === undefined || c.cost === undefined || (goStore.self?.turn.gold_reserve ?? 0) < c.cost) || !goStore.self!.turn.find_effect(CardEffects.STACK_NEXT_ACTION_BOUGHT)">
BUY IN STACK (actions)</button>
</template>
</CardPreview>
</div>
<br>
gems =
<CardSlot :stack="goStore.game?.gem_stack">
<template v-if="isTurn && goStore.game?.gem_stack.length && goStore.game?.gem_stack.length > 0">
<button @click="buy(goStore.game.gem_stack.at(-1)!)">
BUY
</button>
<button
@click="useEffect(goStore.self!.turn.effects_availables.find(e => (e.effect == CardEffects.PLAY_NEXT_CARD_BOUGHT) && e.usable)!, goStore.game.gem_stack.at(-1))"
:disabled="(goStore.self === undefined || goStore.game.gem_stack.at(-1)!.cost === undefined || goStore.self.turn.gold_reserve < goStore.game.gem_stack.at(-1)!.cost!) || !goStore.self!.turn.effects_availables.some(e => (e.effect == CardEffects.PLAY_NEXT_CARD_BOUGHT) && e.usable)">
BUY IN HAND</button>
<button
@click="useEffect(goStore.self!.turn.effects_availables.find(e => (e.effect == CardEffects.STACK_NEXT_CARD_BOUGHT) && e.usable)!, goStore.game.gem_stack.at(-1))"
:disabled="(goStore.self === undefined || goStore.game.gem_stack.at(-1)?.cost === undefined || goStore.self.turn.gold_reserve < (goStore.game.gem_stack.at(-1)?.cost ?? Infinity)) || !goStore.self!.turn.effects_availables.some(e => (e.effect == CardEffects.STACK_NEXT_CARD_BOUGHT) && e.usable)">
BUY IN STACK (generic)</button>
<!-- <button @click="buy_in_hand(props.game.gem_stack.at(-1))">
BUY IN HAND
</button>
<button @click="buy_on_stack(props.game.gem_stack.at(-1))">
BUY ON STACK
</button> -->
</template>
</CardSlot>
</div>
<div>
<PlayerList>
@@ -70,6 +62,11 @@ const isTurn = computed(() => goStore.self && goStore.game?.started && (goStore.
<style>
.cards_container {
display: flex;
flex-direction: row;
flex-direction: row-reverse;
justify-content: center;
}
.separator {
margin-left: 100px;
}
</style>
+3 -11
View File
@@ -1,19 +1,11 @@
<script setup lang="ts">
import goStore from '@/netcode';
const players = useState<{ [key: string]: any }>('players')
const player = computed(() => Array.from(goStore.players.keys()).sort((k) => {
if (goStore.self?.uuid === k) {
return -1
} else {
return 1
}
}))
</script>
<template>
<div v-for="k in player">
<PlayerSlot :player="goStore.players.get(k)!" />
<div v-for="[k, l] in goStore.players">
<PlayerSlot :player="l" v-if="l !== goStore.self" :key="k" />
</div>
<SelfView v-if="goStore.self"></SelfView>
</template>
+79 -59
View File
@@ -30,31 +30,51 @@ const discard_unwrapped = ref(false)
Damage
</button>
<button v-if="props.player.team != goStore.self?.team"
@click="useEffect(goStore.self?.turn.effects_availables.find(e => (e.effect == CardEffects.DISCARD) && e.usable)!, props.player)"
:disabled="!goStore.self?.turn.effects_availables.some(e => (e.effect == CardEffects.DISCARD) && e.usable)">
@click="useEffect(goStore.self?.turn.find_effect(CardEffects.DISCARD)!, props.player)"
:disabled="!goStore.self?.turn.find_effect(CardEffects.DISCARD)">
make Discard</button>
<div id="turn" v-if="props.player.turn">
heal_reserve = {{ props.player.turn.heal_reserve }} <br>
damage_reserve = {{ props.player.turn.damage_reserve }} <br>
gold_reserve = {{ props.player.turn.gold_reserve }} <br>
discard_markers = {{ props.player.turn.discard_markers }} <br>
effects_availables = <div v-for="e in props.player.turn.effects_availables">
<button v-if="e" @click="useEffect(e)">
{{ e.effect + ' ' + e.effect_type }}
</button>
<div id="turn_data">
<div class="turn_icon">
<img src="/images/champion-shield.png" />
<span class="turn_icon_number">
{{ props.player.team.health }}
</span>
</div>
<div class="turn_icon">
<img src="/images/heal.png" />
<span class="turn_icon_number">
{{ props.player.turn.heal_reserve }}
</span>
</div>
<div class="turn_icon">
<img src="/images/damage.png" />
<span class="turn_icon_number">
{{ props.player.turn.damage_reserve }}
</span>
</div>
<div class="turn_icon">
<img src="/images/gold.png" />
<span class="turn_icon_number">
{{ props.player.turn.gold_reserve }}
</span>
</div>
</div>
<span>discard_markers = {{ props.player.turn.discard_markers }} </span>
<div v-if="isSelf"><b>YOU</b></div>
<span>effects_availables = <div v-for=" e in props.player.turn.effects_availables ">
<button v-if="e" @click="useEffect(e)" :disabled="!e.usable">
{{ e.effect + ' ' + e.effect_type }}
</button>
</div></span>
<br>
username = <b>{{ props.player.username }}</b>
<br>
health = {{ props.player.team.health }}
<br>
hand =
<div class="cards_container">
<CardPreview :data="c" v-for=" c in props.player.hand " @click="c && playCard(c)">
<CardPreview :data="c" v-for=" c in props.player.hand " @click="c && playCard(c)">
<button v-if="c && isSelf && isTurn" @click="playCard(c)">PLAY</button>
<button v-if="c && isSelf && isTurn && props.player.turn.discard_markers > 0"
@click="discard(c)">DISCARD</button>
@@ -66,7 +86,7 @@ const discard_unwrapped = ref(false)
<br>
board =
<div class="cards_container">
<CardPreview :data="c" v-for=" c in props.player.board " @click="lockCard(c)"
<CardPreview :data="c" v-for=" c in props.player.board " @click="lockCard(c)"
:locked="c.uuid in props.player.turn.cards_locked">
<button v-if="isSelf && isTurn && props.player.turn.discard_markers > 0"
@click="discard(c)">DISCARD</button>
@@ -74,10 +94,9 @@ const discard_unwrapped = ref(false)
:disabled="c.uuid in props.player.turn.cards_locked">
LOCK
</button>
<button
v-if="isSelf && isTurn && props.player.turn.effects_availables.some(e => (e.effect == CardEffects.SACRIFICE) && e.usable)"
<button v-if="isSelf && isTurn && props.player.turn.find_effect(CardEffects.SACRIFICE)"
:disabled="!goStore.self || !c || c.uuid in props.player.turn.cards_locked"
@click="useEffect(goStore.self!.turn.effects_availables.find(e => (e.effect == CardEffects.SACRIFICE) && e.usable)!, c)">SACRIFICE</button>
@click="useEffect(props.player.turn.find_effect(CardEffects.SACRIFICE)!, c)">SACRIFICE</button>
<div>{{ c.health_as_champion }}</div>
@@ -86,56 +105,35 @@ const discard_unwrapped = ref(false)
:disabled="(goStore.self?.turn.damage_reserve ?? 0) <= 0"
@click="damage_champion(c)">DAMAGE</button>
<button
v-if="!isSelf && !isTurn && goStore.self?.team == goStore.game?.current_turn && goStore.self?.turn.effects_availables.some(e => (e.effect == CardEffects.STUN) && e.usable) && (c.health_as_champion ?? 0) > 0"
@click="useEffect(goStore.self!.turn.effects_availables.find(e => (e.effect == CardEffects.STUN) && e.usable)!, c)">STUN</button>
v-if="!isSelf && !isTurn && goStore.self?.team == goStore.game?.current_turn && goStore.self?.turn.find_effect(CardEffects.STUN) && (c.health_as_champion ?? 0) > 0"
@click="useEffect(goStore.self.turn.find_effect(CardEffects.STUN)!, c)">STUN</button>
</CardPreview>
</div>
<br>
stack =
<CardSlot :stack="props.player.stack_pile">
<!-- <button v-if="isSelf && isTurn" @click="draw">DRAW</button> -->
</CardSlot>
<br>
discard =
{{ props.player.discard_pile.length }}
<input type="checkbox" v-model="discard_unwrapped" />
<div class="stack_and_discard">
<CardSlot :stack="props.player.stack_pile">
<!-- <button v-if="isSelf && isTurn" @click="draw">DRAW</button> -->
</CardSlot>
<div class="separator"></div>
<div class="separator"></div>
<CardPreview v-if="!discard_unwrapped" :data="props.player.discard_pile.at(-1) ?? null">
<!-- <button v-if="isSelf && isTurn" @click="play_from_discard(props.player.discard_pile.at(-1))">DRAW</button>
<button v-if="isSelf && isTurn" @click="put_on_stack_from_discard(props.player.discard_pile.at(-1))">PUT ON
STACK</button> -->
<CardSlot :stack="props.player.discard_pile">
<button v-if="isSelf && isTurn"
:disabled="!goStore.self || !props.player.discard_pile.at(-1) || !props.player.turn.effects_availables.some(e => (e.effect == CardEffects.SACRIFICE) && e.usable) || props.player.discard_pile.at(-1)!.uuid in props.player.turn.cards_locked"
@click="useEffect(goStore.self!.turn.effects_availables.find(e => (e.effect == CardEffects.SACRIFICE) && e.usable)!, props.player.discard_pile.at(-1))">SACRIFICE</button>
</CardPreview>
<template v-if="discard_unwrapped" v-for="c in props.player.discard_pile ">
<CardPreview :data="c">
<!-- <button v-if="isSelf && isTurn" @click="play_from_discard(c)">DRAW</button>
<button v-if="isSelf && isTurn" @click="put_on_stack_from_discard(c)">PUT ON STACK</button>
-->
<button v-if="isSelf && isTurn && c.card_type == CardType.CHAMPION"
:disabled="!goStore.self || !c || !props.player.turn.effects_availables.some(e => (e.effect == CardEffects.RESTACK_DISCARDED_CHAMPION) && e.usable)"
@click="useEffect(goStore.self!.turn.effects_availables.find(e => (e.effect == CardEffects.RESTACK_DISCARDED_CHAMPION) && e.usable)!, c)">RESTACK
(champion)</button>
<button v-if="isSelf && isTurn"
:disabled="!goStore.self || !c || !props.player.turn.effects_availables.some(e => (e.effect == CardEffects.RESTACK_DISCARDED_CARD) && e.usable)"
@click="useEffect(goStore.self!.turn.effects_availables.find(e => (e.effect == CardEffects.RESTACK_DISCARDED_CARD) && e.usable)!, c)">RESTACK
(card)</button>
<button v-if="isSelf && isTurn"
:disabled="!goStore.self || !c || !props.player.turn.effects_availables.some(e => (e.effect == CardEffects.SACRIFICE) && e.usable)"
@click="useEffect(goStore.self!.turn.effects_availables.find(e => (e.effect == CardEffects.SACRIFICE) && e.usable)!, c)">SACRIFICE</button>
</CardPreview>
</template>
</CardSlot>
</div>
</div>
</template>
<style scoped>
.stack_and_discard {
display: flex;
flex-direction: row-reverse;
justify-content: center;
}
.player {
border-top: 5px solid black;
}
@@ -143,4 +141,26 @@ const discard_unwrapped = ref(false)
.turn {
background: lightgreen;
}
.turn_icon {
position: relative;
}
#turn_data {
display: flex;
flex-direction: row;
align-items: flex-start;
justify-content: center;
}
.turn_icon img {
height: 50px;
}
.turn_icon_number {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
+58
View File
@@ -0,0 +1,58 @@
<script setup lang="ts">
import type { Player } from '~/netcode/Player';
export interface Props {
player: Player
}
const props = defineProps<Props>()
</script>
<template>
<div class="turn_icon">
<img src="/images/heal.png" />
<span class="turn_icon_number">
{{ player.turn.heal_reserve }}
</span>
</div>
<div class="turn_icon">
<img src="/images/damage.png" />
<span class="turn_icon_number">
{{ player.turn.damage_reserve }}
</span>
</div>
<div class="turn_icon">
<img src="/images/gold.png" />
<span class="turn_icon_number">
{{ player.turn.gold_reserve }}
</span>
</div>
<div class="turn_icon">
<img src="/images/champion-shield.png" />
<span class="turn_icon_number">
{{ player.team.health }}
</span>
</div>
</template>
<style scoped>
.turn_icon {
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.turn_icon img {
height: 50px;
}
.turn_icon_number {
position: absolute;
text-shadow: white 0 0 1px;
}
</style>
+184
View File
@@ -0,0 +1,184 @@
<script setup lang="ts">
import goStore, { useEffect, playCard, playAllCards, discard, lockCard, heal, damage_champion, damage_team, endTurn } from '~/netcode';
import type { Card } from '~/netcode/Card';
import { CardEffects } from '@/netcode/Effect'
import { CardType } from '~/netcode/Card';
const isTurn = computed(() => goStore.self?.team == goStore.game?.current_turn)
const discard_unwrapped = ref(false)
</script>
<template>
<div :class="'player ' + (isTurn ? 'turn' : '')">
<button @click="heal" v-if="goStore.self?.team == goStore.self?.team"
:disabled="(goStore.self?.turn.heal_reserve ?? 0) <= 0">
Heal
</button>
<button v-if="goStore.self && goStore.self?.team != goStore.self?.team"
@click="useEffect(goStore.self!.turn.find_effect(CardEffects.DISCARD)!, goStore.self)"
:disabled="!goStore.self!.turn.find_effect(CardEffects.DISCARD)">
make Discard</button>
<div id="turn_data">
<button id="end_turn" v-if="isTurn" @click="endTurn">END TURN</button>
<PlayerStats v-if="goStore.self" :player='goStore.self'></PlayerStats>
</div>
<div class="cards_container" id="self_hand">
<CardPreview :data="c" v-for=" c in goStore.self?.hand " @click="c && playCard(c)">
<button v-if="c && isTurn && (goStore.self?.turn.discard_markers ?? 0) > 0"
@click="discard(c!)">DISCARD</button>
</CardPreview>
</div>
<span>discard_markers = {{ goStore.self?.turn.discard_markers }} <br></span>
<span>effects_availables = <div v-for="e in goStore.self?.turn.effects_availables">
<button @click="useEffect(e)" :disabled="!e.usable">
{{ e.effect + ' ' + e.effect_type + ' ' + e.amount }}
</button>
</div></span>
<br>
board =
<div class="cards_container">
<CardPreview :data="c" v-for=" c in goStore.self?.board " @click="lockCard(c)"
:locked="c.uuid in (goStore.self?.turn.cards_locked ?? [])">
<button v-if="isTurn && (goStore.self?.turn.discard_markers ?? 0) > 0"
@click="discard(c)">DISCARD</button>
<button v-if="isTurn && goStore.self?.turn.discard_markers == 0" @click="lockCard(c)"
:disabled="c.uuid in goStore.self?.turn.cards_locked">
LOCK
</button>
<button v-if="isTurn && goStore.self!.turn.find_effect(CardEffects.SACRIFICE)"
:disabled="!goStore.self || !c || c.uuid in goStore.self?.turn.cards_locked"
@click="useEffect(goStore.self!.turn.find_effect(CardEffects.SACRIFICE)!, c)">SACRIFICE</button>
<button
v-if="isTurn && goStore.self!.turn.find_effect(CardEffects.PREPARE) && c.card_type == CardType.CHAMPION"
:disabled="!goStore.self || !c || !(c.uuid in goStore.self?.turn.cards_locked)"
@click="useEffect(goStore.self!.turn.find_effect(CardEffects.PREPARE)!, c)">PREPARE</button>
<div>{{ c.health_as_champion }}</div>
</CardPreview>
</div>
<br>
<div class="stack_and_discard">
<div>
<input type="checkbox" v-model="discard_unwrapped" />
<div class="cards_container">
<template v-for="c in goStore.self?.discard_pile ">
<CardPreview :data="c" :wrapped="!discard_unwrapped">
<!-- <button v-if="isSelf && isTurn" @click="play_from_discard(c)">DRAW</button>
<button v-if="isSelf && isTurn" @click="put_on_stack_from_discard(c)">PUT ON STACK</button>
-->
<button v-if="isTurn && c.card_type == CardType.CHAMPION"
:disabled="!goStore.self || !c || !goStore.self!.turn.find_effect(CardEffects.RESTACK_DISCARDED_CHAMPION)"
@click="useEffect(goStore.self!.turn.find_effect(CardEffects.RESTACK_DISCARDED_CHAMPION)!, c)">RESTACK
(champion)</button>
<button v-if="isTurn"
:disabled="!goStore.self || !c || !goStore.self!.turn.find_effect(CardEffects.RESTACK_DISCARDED_CARD)"
@click="useEffect(goStore.self!.turn.find_effect(CardEffects.RESTACK_DISCARDED_CARD)!, c)">RESTACK
(card)</button>
<button v-if="isTurn"
:disabled="!goStore.self || !c || !goStore.self!.turn.find_effect(CardEffects.SACRIFICE)"
@click="useEffect(goStore.self!.turn.find_effect(CardEffects.SACRIFICE)!, c)">SACRIFICE</button>
</CardPreview>
</template>
</div>
</div>
<CardSlot :stack="goStore.self?.stack_pile">
<!-- <button v-if="isSelf && isTurn" @click="draw">DRAW</button> -->
</CardSlot>
</div>
</div>
</template>
<style scoped>
.stack_and_discard {
display: flex;
flex-direction: row-reverse;
justify-content: center;
}
.player {
border-top: 5px solid black;
}
.turn {
background: lightgreen;
}
#play_all {
display: flex;
flex-direction: row;
align-items: center;
font-size: 10em;
}
#turn_data {
position: fixed;
bottom: 10px;
left: 10px;
display: flex;
flex-direction: column;
align-items: flex-start;
}
#self_hand {
position: fixed;
z-index: 1;
display: flex;
align-items: stretch;
flex-direction: row;
flex-wrap: nowrap;
left: 70px;
bottom: -50px;
max-width: 100vw;
justify-content: flex-start;
transition: 0.5s all cubic-bezier(0.075, 0.82, 0.165, 1);
transform: translateY(150px)
}
#self_hand:hover {
transform: translateY(0px);
}
#end_turn {
width: 50px;
height: 50px;
}
</style>
<style>
#turn_data * {
margin: 2.5px 0 2.5px 0;
}
#self_hand .card {
transition: 0.5s all cubic-bezier(0.075, 0.82, 0.165, 1);
overflow: visible;
}
#self_hand .card:hover {
transform: translateY(-40px);
}
.cards_container {
min-width: 250px;
}
</style>
+3 -6
View File
@@ -5,7 +5,7 @@ export enum CardEffects {
GOLD = "gold",
DAMAGE = "damage",
HEAL = "heal",
PERPARE = "prepare",
PREPARE = "prepare",
STUN = "stun",
SACRIFICE = "sacrifice",
DRAW = "draw",
@@ -60,13 +60,10 @@ export function create_effect(input: EffectNetcode, register: GameObjectRegister
if (target.effect_type == EffectType.FACTION_COMBO) {
if (!register.self) { return false }
// ugly bastard
const card = register.self.board.find(c => c.effects.map(e => e.uuid).includes(effect.uuid))
const card = register.self.value?.board.find(c => c.effects.map(e => e.uuid).includes(effect.uuid))
if (!card) { return false }
console.log(
register.self.board.some(c => c !== card && c.faction === card.faction)
)
return register.self.board.some(c => c !== card && c.faction === card.faction)
return register.self.value?.board.some(c => c !== card && c.faction === card.faction)
}
return true
}
+9 -2
View File
@@ -1,6 +1,6 @@
import { type GameObjectRegister } from "."
import type { Card } from "./Card"
import { type Effect } from "./Effect"
import { type Effect, CardEffects } from "./Effect"
import type { GameObjectNetcode } from "./GameObject"
export interface TurnNetcode extends GameObjectNetcode {
cards_locked: Array<string>
@@ -17,9 +17,10 @@ export type Turn = Omit<TurnNetcode, 'cards_locked' | 'effects_availables' | 'ch
cards_locked: { [key: string]: Card }
effects_availables: Array<Effect>
champions_health: Map<string, number>
find_effect: (card_effect: CardEffects) => Effect | undefined
}
export function create_turn(input: TurnNetcode, register: GameObjectRegister) {
return new Proxy<any>(input, {
const turn = new Proxy<any>(input, {
get(target: TurnNetcode, prop, reciever) {
if (prop == "cards_locked") {
return Object.fromEntries(target.cards_locked.map(e => [e, register.cards.get(e)]))
@@ -34,10 +35,16 @@ export function create_turn(input: TurnNetcode, register: GameObjectRegister) {
}
return healths
}
if (prop == "find_effect") {
return (card_effect: CardEffects) => {
return turn.effects_availables.find(e => (e.effect == card_effect) && e.usable)
}
}
return Reflect.get(target, prop, reciever);
},
set(target, prop, val, receiver) {
return Reflect.set(target, prop, val, receiver);
}
}) as Turn
return turn
}
+11 -14
View File
@@ -6,6 +6,8 @@ import { type Player, create_player, type PlayerNetcode } from "./Player"
import { type Team, create_team, type TeamNetcode } from "./Team"
import { type Turn, create_turn } from "./Turn"
import { type Ref } from "vue"
export const socket = new WebSocket("ws://127.0.0.1:8765")
export class GameObjectRegister {
@@ -18,8 +20,8 @@ export class GameObjectRegister {
context: 'login' | 'pregame' | 'game' = "login"
private readonly objects: Map<string, GameObjectNetcode>
game?: Game
self?: Player
game: Ref<Game | null>
self: Ref<Player | null>
constructor() {
this.effects = reactive(new Map())
this.cards = reactive(new Map())
@@ -28,6 +30,9 @@ export class GameObjectRegister {
this.turns = reactive(new Map())
this.objects = reactive(new Map())
this.game = ref(null)
this.self = ref(null)
}
update_object(obj: GameObjectNetcode) {
@@ -57,8 +62,8 @@ export class GameObjectRegister {
this.objects.set(data.uuid, team)
},
"game": (data: GameNetcode) => {
this.game = create_game(data, this)
this.objects.set(data.uuid, this.game)
this.game.value = create_game(data, this)
this.objects.set(data.uuid, this.game.value)
},
"turn": (data: any) => {
const turn = create_turn(data, this)
@@ -67,8 +72,8 @@ export class GameObjectRegister {
}
} as { [id: string]: (data: any) => any }
set_self(uuid: string) {
this.self = this.players.get(uuid)
set_self = (uuid: string) => {
this.self.value = this.players.get(uuid) ?? null
}
}
@@ -176,14 +181,6 @@ export function lockCard(card: Card) {
data_type: "lock_card",
data: card.uuid
}))
card.effects.forEach(e => {
if (e.effect_type !== EffectType.SUICIDE && e.usable && [CardEffects.DAMAGE, CardEffects.GOLD, CardEffects.HEAL].includes(e.effect)) {
for (let i = 0; i < e.amount; i++) {
useEffect(e)
}
}
})
}
export function useEffect(effect: Effect, target?: Effect | Card | Player | Team) {
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.