You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
5.2 KiB
170 lines
5.2 KiB
2 weeks ago
|
<template>
|
||
|
<div v-if="dungeon" class="battle">
|
||
|
<div class="player" :style="battle.playerStyle">
|
||
|
</div>
|
||
|
<div class="monster" v-for="(v, k) in dungeon.monsters" :key="k"
|
||
|
:style="{ left: (95 / dungeon.monsters.length) * (k + 1) + '%' }">
|
||
|
<img :src="dungeon_icon[v.type]">
|
||
|
</div>
|
||
|
<div class="progress-bar"></div>
|
||
|
<button @click="stopDungeon" class="button">{{ t('stopDungeon.0') }}</button>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<script lang="ts" setup>
|
||
|
import { useStore } from "vuex";
|
||
|
import { computed, nextTick, onMounted, ref } from "vue";
|
||
|
import { useI18n } from "vue3-i18n";
|
||
|
import { dungeon_icon, player_move_time, player_battle_time } from "@/config";
|
||
|
import { randonBootyEquip} from "@/tool";
|
||
|
|
||
|
const { t } = useI18n();
|
||
|
const { state, commit, dispatch } = useStore();
|
||
|
const battle = computed(() => {
|
||
|
return state.battle;
|
||
|
})
|
||
|
|
||
|
const props = defineProps({
|
||
|
dungeon: {
|
||
|
type: Object,
|
||
|
}
|
||
|
})
|
||
|
|
||
|
const startDungeon = () => {
|
||
|
const dungeon = props.dungeon;
|
||
|
if (!dungeon) {
|
||
|
return;
|
||
|
}
|
||
|
dispatch('play_music', 'battle');
|
||
|
playerMove(0, 0);
|
||
|
const msg = t('startDungeon') + 'lv' + dungeon.lv + '_' + t('difficulty.' + dungeon.difficulty);
|
||
|
commit("set_sys_info", { msg: msg, type: 'warning' });
|
||
|
}
|
||
|
|
||
|
defineExpose({ startDungeon })
|
||
|
|
||
|
const stopDungeon = () => {
|
||
|
for (let i = 0; i < 5; i++) {
|
||
|
clearTimeout(battle.value.timeOut);
|
||
|
}
|
||
|
battle.value.battleShow = false;
|
||
|
dispatch('play_music', 'backgound');
|
||
|
commit("set_sys_info", { msg: t('stopDungeon.1'), type: 'warning' });
|
||
|
}
|
||
|
|
||
|
const exploreDungeon = (monsterIdx) => {
|
||
|
let idx2 = monsterIdx || 0;
|
||
|
const dungeon = props.dungeon;
|
||
|
if (!dungeon) {
|
||
|
return;
|
||
|
}
|
||
|
const monster = dungeon.monsters[idx2];
|
||
|
battleWithMonster(monster).then(rsp => {
|
||
|
idx2++;
|
||
|
if (idx2 < dungeon.monsters.length) {
|
||
|
playerMove(idx2);
|
||
|
} else {
|
||
|
commit("set_sys_info", { msg: t('dungeonSuccess'), type: 'battle' });
|
||
|
if (dungeon.lv > state.playerAttribute.lv) {
|
||
|
commit('set_player_lv', dungeon.lv)
|
||
|
commit('set_sys_info', { msg: t('upgrade'), type: 'win' })
|
||
|
}
|
||
|
if (dungeon.difficulty != 1) {
|
||
|
dungeon.setDifficulty(1);
|
||
|
battle.value.battleShow = false;
|
||
|
dispatch('play_music', 'backgound');
|
||
|
} else {
|
||
|
playerMove(0, 0);
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
const playerMove = (monsterIdx?, playerIdx?) => {
|
||
|
let idx2 = playerIdx || 0;
|
||
|
const max = 20;
|
||
|
const lenght = 95 / props.dungeon?.monsters.length;
|
||
|
const left = monsterIdx * lenght + lenght / max * idx2;
|
||
|
battle.value.playerStyle = {
|
||
|
left: left + '%',
|
||
|
backgroundPosition: Math.floor(left % 4) * 32 + 'px 96px'
|
||
|
}
|
||
|
if (idx2 > max) {
|
||
|
exploreDungeon(monsterIdx);
|
||
|
} else {
|
||
|
idx2++;
|
||
|
const moveTime = Math.round(player_move_time * 100 / (100 + state.rebornAttribute.moveSpeed) / max);
|
||
|
battle.value.timeOut = setTimeout(() => {
|
||
|
playerMove(monsterIdx, idx2);
|
||
|
}, moveTime);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const battleWithMonster = (monster) => {
|
||
|
return new Promise((resolve, reject) => {
|
||
|
const player = state.playerAttribute.attribute;
|
||
|
let monsterDmg = Math.ceil(monster.atk * (1 - player.reducPercent) - player.bloc);
|
||
|
monsterDmg < 1 && (monsterDmg = 1);
|
||
|
|
||
|
const playerDeadTime = Math.ceil(player.curHp / monsterDmg);
|
||
|
const monsterDeadTime = Math.ceil(monster.hp / player.dps);
|
||
|
const takeDmg = monsterDeadTime * monsterDmg;
|
||
|
const battleTime = Math.round(player_battle_time * 100 / (100 + state.rebornAttribute.battleSpeed))
|
||
|
|
||
|
const getMsg = (i18nName) => {
|
||
|
return t(i18nName).replace('${lv}', monster.lv).replace('${name}', t(monster.type)).replace('${dmg}', takeDmg + '');
|
||
|
};
|
||
|
commit("set_sys_info", { msg: getMsg('battle'), type: 'battle' });
|
||
|
battle.value.timeOut = setTimeout(() => {
|
||
|
nextTick(() => {
|
||
|
commit('add_player_curhp', -1 * takeDmg);
|
||
|
})
|
||
|
if (monsterDeadTime < playerDeadTime) {
|
||
|
commit("set_sys_info", { msg: getMsg('killMonster'), type: 'battle' });
|
||
|
//随机获取装备战利品
|
||
|
const equips = randonBootyEquip(monster);
|
||
|
commit('add_bootys', { equips: equips, coins: monster.coins });
|
||
|
resolve(true);
|
||
|
} else {
|
||
|
commit("set_sys_info", { msg: getMsg('beKilled'), type: 'warning' });
|
||
|
battle.value.battleShow = false;
|
||
|
dispatch('play_music', 'backgound');
|
||
|
}
|
||
|
}, battleTime);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
onMounted(() => { });
|
||
|
</script>
|
||
|
<style lang="scss" scoped>
|
||
|
.battle {
|
||
|
|
||
|
.player {
|
||
|
position: absolute;
|
||
|
z-index: 2;
|
||
|
top: 1.2rem;
|
||
|
height: 48px;
|
||
|
width: 32px;
|
||
|
background: url(@/assets/icons/map/player-s.png);
|
||
|
}
|
||
|
|
||
|
.monster {
|
||
|
position: absolute;
|
||
|
top: 2rem;
|
||
|
}
|
||
|
|
||
|
.progress-bar {
|
||
|
position: absolute;
|
||
|
top: 5rem;
|
||
|
left: 0.7rem;
|
||
|
right: 0.7rem;
|
||
|
border: 1px solid #fff;
|
||
|
}
|
||
|
|
||
|
.button {
|
||
|
position: absolute;
|
||
|
top: 6rem;
|
||
|
right: 1.2rem;
|
||
|
}
|
||
|
}
|
||
|
</style>
|