246 lines
9.2 KiB
Vue
246 lines
9.2 KiB
Vue
<template>
|
|
<div class="absolute" v-if="gameStore.uiSettings.isCharacterProfileOpen" :style="modalStyle">
|
|
<div class="relative">
|
|
<img src="/assets/ui-elements/profile-ui-box-outer.svg" class="absolute w-full h-full" />
|
|
<img src="/assets/ui-elements/profile-ui-box-inner.svg" class="absolute left-2 bottom-2 w-[calc(100%_-_16px)] h-[calc(100%_-_40px)]" />
|
|
<div @mousedown="startDrag" class="cursor-move px-5 py-2.5 flex justify-between items-center relative">
|
|
<span class="text-xs text-white font-thin">Character Profile [Alt+C]</span>
|
|
<button @click="gameStore.uiSettings.isCharacterProfileOpen = false" class="w-3.5 h-3.5 m-0 p-0 relative hover:rotate-180 transition-transform duration-300 ease-in-out">
|
|
<img alt="close" draggable="false" src="/assets/icons/modal/close-button-white.svg" class="w-full h-full" />
|
|
</button>
|
|
</div>
|
|
<div class="py-4 px-6 flex flex-col gap-7 relative z-10">
|
|
<div class="flex flex-col gap-2.5">
|
|
<div class="flex justify-between">
|
|
<div>
|
|
<p class="text-sm m-0 font-bold text-white tracking-wide">{{ gameStore.character?.name }}</p>
|
|
<span class="text-xs">{{ gameStore.character?.experience }} / 18.600XP</span>
|
|
</div>
|
|
<a class="hover:cursor-pointer bg-[url('/assets/ui-elements/button-ui-box-textured-small.svg')] bg-no-repeat block w-8 h-8 relative mx-[3px]">
|
|
<img class="hover:drop-shadow-default w-3.5 h-3.5 m-[9px] object-contain" draggable="false" src="/assets/icons/plus-green-icon.svg" />
|
|
</a>
|
|
</div>
|
|
<div class="flex justify-between">
|
|
<div class="flex flex-col gap-0.5">
|
|
<div class="w-9 h-9 default-border rounded-sm bg-gray relative hover:bg-gray-600">
|
|
<span class="absolute w-full top-1/2 -translate-y-1/2 text-[6px] text-center">CROWN</span>
|
|
</div>
|
|
<div class="w-9 h-9 default-border rounded-sm bg-gray relative hover:bg-gray-600">
|
|
<span class="absolute w-full top-1/2 -translate-y-1/2 text-[6px] text-center">R-HAND</span>
|
|
</div>
|
|
<div class="flex gap-0.5 items-end">
|
|
<div class="w-9 h-9 default-border rounded-sm bg-gray relative hover:bg-gray-600">
|
|
<span class="absolute w-full top-1/2 -translate-y-1/2 text-[6px] text-center">L-HAND</span>
|
|
</div>
|
|
<div class="w-6 h-6 default-border rounded-sm bg-gray relative hover:bg-gray-600">
|
|
<span class="absolute w-full top-1/2 -translate-y-1/2 text-[6px] text-center">RING</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<img src="/assets/placeholders/inventory_player.png" class="w-8 h-auto" />
|
|
<div class="flex flex-col items-end gap-0.5">
|
|
<div class="w-9 h-9 default-border rounded-sm bg-gray relative hover:bg-gray-600">
|
|
<img class="w-6 h-6 center-element" src="/assets/icons/profile/helmet.svg" />
|
|
</div>
|
|
<div class="w-9 h-9 default-border rounded-sm bg-gray relative hover:bg-gray-600">
|
|
<img class="w-6 h-6 center-element" src="/assets/icons/profile/chestplate.svg" />
|
|
</div>
|
|
<div class="flex gap-0.5 items-end">
|
|
<div class="w-6 h-6 default-border rounded-sm bg-gray relative hover:bg-gray-600">
|
|
<img class="w-4 h-4 center-element" src="/assets/icons/profile/boots.svg" />
|
|
</div>
|
|
<div class="w-9 h-9 default-border rounded-sm bg-gray relative hover:bg-gray-600">
|
|
<img class="w-6 h-6 center-element" src="/assets/icons/profile/legs.svg" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-between">
|
|
<div class="flex flex-col">
|
|
<div class="w-[105px] h-px mb-[3px] flex justify-between">
|
|
<div class="w-px h-full bg-gray-300"></div>
|
|
<div class="w-[101px] h-full bg-gray-300"></div>
|
|
<div class="w-px h-full bg-gray-300"></div>
|
|
</div>
|
|
<div class="flex gap-11">
|
|
<p class="m-0 text-xs text-white tracking-wide">Health</p>
|
|
<span class="m-0 text-xs text-white tracking-wide">+ 15</span>
|
|
</div>
|
|
<div class="w-[105px] h-px my-[3px] flex justify-between">
|
|
<div class="w-px h-full bg-gray-300"></div>
|
|
<div class="w-[101px] h-full bg-gray-300"></div>
|
|
<div class="w-px h-full bg-gray-300"></div>
|
|
</div>
|
|
<div class="flex gap-11">
|
|
<p class="m-0 text-xs text-white tracking-wide">Health</p>
|
|
<span class="m-0 text-xs text-white tracking-wide">+ 15</span>
|
|
</div>
|
|
<div class="w-[105px] h-px mt-[3px] flex justify-between">
|
|
<div class="w-px h-full bg-gray-300"></div>
|
|
<div class="w-[101px] h-full bg-gray-300"></div>
|
|
<div class="w-px h-full bg-gray-300"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="flex flex-col">
|
|
<div class="w-[105px] h-px mb-[3px] flex justify-between">
|
|
<div class="w-px h-full bg-gray-300"></div>
|
|
<div class="w-[101px] h-full bg-gray-300"></div>
|
|
<div class="w-px h-full bg-gray-300"></div>
|
|
</div>
|
|
<div class="flex gap-11">
|
|
<p class="m-0 text-xs text-white tracking-wide">Health</p>
|
|
<span class="m-0 text-xs text-white tracking-wide">+ 15</span>
|
|
</div>
|
|
<div class="w-[105px] h-px my-[3px] flex justify-between">
|
|
<div class="w-px h-full bg-gray-300"></div>
|
|
<div class="w-[101px] h-full bg-gray-300"></div>
|
|
<div class="w-px h-full bg-gray-300"></div>
|
|
</div>
|
|
<div class="flex gap-11">
|
|
<p class="m-0 text-xs text-white tracking-wide">Health</p>
|
|
<span class="m-0 text-xs text-white tracking-wide">+ 15</span>
|
|
</div>
|
|
<div class="w-[105px] h-px mt-[3px] flex justify-between">
|
|
<div class="w-px h-full bg-gray-300"></div>
|
|
<div class="w-[101px] h-full bg-gray-300"></div>
|
|
<div class="w-px h-full bg-gray-300"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="grid grid-rows-4 grid-cols-6 gap-0.5">
|
|
<div v-for="n in 24" class="w-9 h-9 default-border rounded-sm bg-gray relative hover:bg-gray-600"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { useGameStore } from '@/stores/gameStore'
|
|
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
|
|
const gameStore = useGameStore()
|
|
|
|
let startX = 0
|
|
let startY = 0
|
|
let initialX = 0
|
|
let initialY = 0
|
|
let modalPositionX = 0
|
|
let modalPositionY = 0
|
|
let modalWidth = 286
|
|
let modalHeight = 483
|
|
|
|
const width = ref(modalWidth)
|
|
const height = ref(modalHeight)
|
|
const x = ref(0)
|
|
const y = ref(0)
|
|
const isDragging = ref(false)
|
|
|
|
const modalStyle = computed(() => ({
|
|
top: `${y.value}px`,
|
|
left: `${x.value}px`,
|
|
width: `${width.value}px`,
|
|
height: `${height.value}px`,
|
|
maxWidth: '100vw',
|
|
maxHeight: '100vh'
|
|
}))
|
|
|
|
function startDrag(event: MouseEvent) {
|
|
isDragging.value = true
|
|
startX = event.clientX
|
|
startY = event.clientY
|
|
initialX = x.value
|
|
initialY = y.value
|
|
event.preventDefault()
|
|
}
|
|
|
|
function drag(event: MouseEvent) {
|
|
if (!isDragging.value) return
|
|
const dx = event.clientX - startX
|
|
const dy = event.clientY - startY
|
|
x.value = initialX + dx
|
|
y.value = initialY + dy
|
|
adjustPosition()
|
|
}
|
|
|
|
function stopDrag() {
|
|
isDragging.value = false
|
|
}
|
|
|
|
function adjustPosition() {
|
|
x.value = Math.min(x.value, window.innerWidth - width.value)
|
|
y.value = Math.min(y.value, window.innerHeight - height.value)
|
|
}
|
|
|
|
function initializePosition() {
|
|
width.value = Math.min(modalWidth, window.innerWidth)
|
|
height.value = Math.min(modalHeight, window.innerHeight)
|
|
if (modalPositionX !== 0 && modalPositionY !== 0) {
|
|
x.value = modalPositionX
|
|
y.value = modalPositionY
|
|
} else {
|
|
x.value = (window.innerWidth - width.value) / 2
|
|
y.value = (window.innerHeight - height.value) / 2
|
|
}
|
|
}
|
|
|
|
watch(
|
|
() => gameStore.uiSettings.isCharacterProfileOpen,
|
|
(value) => {
|
|
gameStore.uiSettings.isCharacterProfileOpen = value
|
|
if (value) {
|
|
initializePosition()
|
|
}
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() => modalWidth,
|
|
(value) => {
|
|
width.value = Math.min(value, window.innerWidth)
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() => modalHeight,
|
|
(value) => {
|
|
height.value = Math.min(value, window.innerHeight)
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() => modalPositionX,
|
|
(value) => {
|
|
x.value = value
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() => modalPositionY,
|
|
(value) => {
|
|
y.value = value
|
|
}
|
|
)
|
|
|
|
function keyPress(event: KeyboardEvent) {
|
|
if (event.altKey && event.key === 'c') {
|
|
gameStore.toggleCharacterProfile()
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
addEventListener('keydown', keyPress)
|
|
addEventListener('mousemove', drag)
|
|
addEventListener('mouseup', stopDrag)
|
|
initializePosition()
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
removeEventListener('keydown', keyPress)
|
|
removeEventListener('mousemove', drag)
|
|
removeEventListener('mouseup', stopDrag)
|
|
})
|
|
</script>
|