mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-04-18 17:48:52 +08:00
177 lines
4.4 KiB
Vue
177 lines
4.4 KiB
Vue
<template>
|
|
<div id="fixed">
|
|
<Box
|
|
v-model:height="height"
|
|
v-model:left="left"
|
|
v-model:top="top"
|
|
v-model:width="width"
|
|
>
|
|
<div id="enemy-fixed">
|
|
<span id="enemy-name">{{ enemy.enemy.name }}</span>
|
|
<div id="enemy-special">
|
|
<span
|
|
v-for="(text, i) of special"
|
|
:style="{ color: text[1] }"
|
|
>{{ text[0] }}</span
|
|
>
|
|
</div>
|
|
<div class="enemy-attr" v-for="(a, i) of detail">
|
|
<span class="attr-name" :style="{ color: a[2] }">{{
|
|
a[1]
|
|
}}</span>
|
|
<span class="attr-value" :style="{ color: a[2] }">{{
|
|
format(a[0])
|
|
}}</span>
|
|
</div>
|
|
</div>
|
|
</Box>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { onMounted, onUpdated, Ref, ref, watch } from 'vue';
|
|
import Box from '../components/box.vue';
|
|
import { GameUi } from '../controller';
|
|
import { nextFrame } from '../utils';
|
|
import { EnemyInfo, IDamageEnemy } from '@motajs/types';
|
|
|
|
const props = defineProps<{
|
|
num: number;
|
|
ui: GameUi;
|
|
enemy: IDamageEnemy;
|
|
close: Ref<boolean>;
|
|
loc: [x: number, y: number];
|
|
}>();
|
|
const emits = defineEmits<{
|
|
(e: 'close'): void;
|
|
}>();
|
|
|
|
watch(props.close, n => {
|
|
if (n) {
|
|
fixed.style.opacity = '0';
|
|
}
|
|
});
|
|
|
|
let main: HTMLDivElement;
|
|
let fixed: HTMLDivElement;
|
|
|
|
const format = core.formatBigNumber;
|
|
const enemy = props.enemy;
|
|
const detail = ((): [number, string, string][] => {
|
|
const info = enemy.info;
|
|
const data = enemy.calCritical()[0];
|
|
const ratio = core.status.thisMap?.ratio ?? 1;
|
|
return [
|
|
[info.hp, '生命', 'lightgreen'],
|
|
[info.atk, '攻击', 'lightcoral'],
|
|
[info.def, '防御', 'lightblue'],
|
|
[enemy.enemy.money, '金币', 'lightyellow'],
|
|
[enemy.enemy.exp, '经验', 'lawgreen'],
|
|
[data?.atkDelta ?? 0, '临界', 'lightsalmon'],
|
|
[data?.delta ?? 0, '临界减伤', 'lightpink'],
|
|
[enemy.calDefDamage(ratio).delta, `${ratio}防`, 'cyan']
|
|
];
|
|
})();
|
|
const special = (() => {
|
|
const s = [...enemy.info.special];
|
|
|
|
const fromFunc = (
|
|
func: string | ((enemy: EnemyInfo) => string),
|
|
enemy: EnemyInfo
|
|
) => {
|
|
return typeof func === 'string' ? func : func(enemy);
|
|
};
|
|
|
|
const show = s.slice(0, 2).map(v => {
|
|
const s = Mota.require('@user/data-state').specials[v];
|
|
return [fromFunc(s.name, enemy.info), s.color];
|
|
});
|
|
if (s.length > 2) show.push(['...', 'white']);
|
|
return show;
|
|
})();
|
|
|
|
const left = ref(0);
|
|
const top = ref(0);
|
|
const width = ref(300);
|
|
const height = ref(400);
|
|
let vh = window.innerHeight;
|
|
let vw = window.innerWidth;
|
|
|
|
async function calHeight() {
|
|
vh = window.innerHeight;
|
|
vw = window.innerWidth;
|
|
width.value = vh * 0.28;
|
|
await new Promise(res => requestAnimationFrame(res));
|
|
updateMain();
|
|
if (!main) return;
|
|
const style = getComputedStyle(main);
|
|
const h = parseFloat(style.height);
|
|
const [cx, cy] = props.loc;
|
|
if (cy + h + 10 > vh - 10) top.value = vh - h - 10;
|
|
else top.value = cy + 10;
|
|
if (cx + width.value + 10 > vw - 10) left.value = vw - width.value - 10;
|
|
else left.value = cx + 10;
|
|
height.value = h;
|
|
}
|
|
|
|
function updateMain() {
|
|
main = document.getElementById('enemy-fixed') as HTMLDivElement;
|
|
fixed = document.getElementById('fixed') as HTMLDivElement;
|
|
if (main) {
|
|
main.addEventListener('mouseleave', () => emits('close'));
|
|
}
|
|
nextFrame(() => {
|
|
fixed.style.opacity = '1';
|
|
});
|
|
}
|
|
|
|
onUpdated(calHeight);
|
|
|
|
onMounted(() => {
|
|
updateMain();
|
|
calHeight();
|
|
});
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
#fixed {
|
|
font-family: 'normal';
|
|
font-size: 2.5vh;
|
|
opacity: 0;
|
|
transition: opacity 0.2s linear;
|
|
}
|
|
|
|
#enemy-fixed {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
background-color: #000c;
|
|
padding: 1vh;
|
|
}
|
|
|
|
#enemy-special {
|
|
width: 100%;
|
|
display: flex;
|
|
flex-direction: row;
|
|
justify-content: space-around;
|
|
}
|
|
|
|
.enemy-attr {
|
|
display: flex;
|
|
flex-direction: row;
|
|
width: 100%;
|
|
}
|
|
|
|
.attr-name {
|
|
flex-basis: 50%;
|
|
width: 100%;
|
|
text-align: right;
|
|
padding-right: 5%;
|
|
}
|
|
|
|
.attr-value {
|
|
flex-basis: 50%;
|
|
padding-left: 5%;
|
|
}
|
|
</style>
|