Browse Source

更新(详情见description)

1.调整战斗逻辑,战斗伤害不再使用用期望值,每回合伤害独立计算,击败怪物的回合怪物将不造成伤害
2.新增战斗过程查看
master
许孟阳 2 weeks ago
parent
commit
ab23228b6b
  1. BIN
      src/assets/icons/tips.png
  2. 43
      src/components/tooltip.vue
  3. 2
      src/config/i18n/zh.ts
  4. 28
      src/tool/caller.ts
  5. 23
      src/views/dungeon/battle.vue
  6. 51
      src/views/message/bouts.vue
  7. 20
      src/views/message/sys-info.vue
  8. 11
      src/views/version/update-log.vue

BIN
src/assets/icons/tips.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

43
src/components/tooltip.vue

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
<slot></slot>
</div>
<div class="c-tooltip-tip" :class="placement" v-if="tipsShow" :style='tipsStyle'>
<img v-if="showIcon" src="/img/tips.png" class="tip-icons"></img>
<p v-for="info in infos" class="info">* {{ info }}</p>
<slot name="tip"></slot>
</div>
@ -18,7 +19,9 @@ import { useI18n } from "vue3-i18n"; @@ -18,7 +19,9 @@ import { useI18n } from "vue3-i18n";
const { t } = useI18n();
const { state, commit, dispatch } = useStore();
const tipsShow = ref(false);
const tipsStyle = ref({});
const tipsStyle = ref({
transform: ''
});
const prop = defineProps({
placement: {
@ -31,16 +34,25 @@ const prop = defineProps({ @@ -31,16 +34,25 @@ const prop = defineProps({
width: {
type: String,
default: '16rem'
},
showIcon: {
type: Boolean,
default: true
},
x: {
type: String,
default: null
}
})
const showTips = (e) => {
const x = e.pageX, y = e.pageY, maxH = window.innerHeight, maxW = window.innerWidth;
const xt = x < 100 ? '15%' : y < maxH - 100 ? '0%' : '-40%';
const yt = y < maxH - 200 ? '100%' : '-50%';
tipsStyle.value = {
transform: 'translate(' + xt + ', ' + yt + ')'
let xt = x < 100 ? '15%' : y < maxH - 100 ? '0%' : '-40%';
if (prop.x) {
xt = prop.x;
}
const yt = y < maxH / 2 ? '100%' : '-50%';
tipsStyle.value.transform = 'translate(' + xt + ', ' + yt + ')';
tipsShow.value = true
}
const closeTips = () => {
@ -66,28 +78,27 @@ onMounted(() => { }); @@ -66,28 +78,27 @@ onMounted(() => { });
border-radius: 4px;
padding: 1.2rem;
background: #111111;
padding-top: 3.6rem;
// padding-top: 3.6rem;
font-size: 0.86rem;
font-weight: normal;
z-index: 9999;
box-shadow: 0 0 3px 3px rgba($color: #000000, $alpha: 1.0);
.info {
font-weight: normal;
margin-top: 0.4rem;
}
&::after {
position: absolute;
top: 0.4rem;
left: 50%;
.tip-icons {
// position: absolute;
margin-left: 50%;
transform: translateX(-50%);
display: flex;
width: 3.2rem;
height: 3.2rem;
background-image: url(@/assets/icons/tips.png);
background-size: cover;
}
.info {
font-weight: normal;
margin-top: 0.4rem;
}
}
.top {

2
src/config/i18n/zh.ts

@ -2,6 +2,7 @@ export default class Zh { @@ -2,6 +2,7 @@ export default class Zh {
title = '挂机放置游戏';
welcome = ['欢迎你勇士,点击地图上的副本开始战斗。', '界面左上角菜单可以打开世界副本地图。'];
sys = '系统';
loadEmpty = '未读取到存档!';
loadError = '存档坏了!';
@ -146,6 +147,7 @@ export default class Zh { @@ -146,6 +147,7 @@ export default class Zh {
eliteMonster = '无尽模式精英怪';
startDungeon = '你已进入';
battle = '你遭遇了(lv${lv}${name}),正在战斗中...';
bouts = ['点击查看战斗过程', '回合', '触发了暴击', '你造成了${dmg}点伤害', '受到${dmg}点伤害', '战斗结束', '你获胜', '你战败'];
killMonster = '你击杀了(lv${lv}${name}),共受到了${dmg}点伤害';
beKilled = '你被(lv${lv}${name})击败,共受到了${dmg}点伤害';
getCoins = '获得金币:';

28
src/tool/caller.ts

@ -127,3 +127,31 @@ export const getPointsOfReborn = (playerAttribute) => { @@ -127,3 +127,31 @@ export const getPointsOfReborn = (playerAttribute) => {
return Math.round(points * 1.2);
};
export const callBattleResult = (player, monster) => {
const tmp = player.curHp,
crit = player.crit / 100,
critdmg = player.critDmg / 100,
atk = player.atk;
let monsterDmg = Math.ceil(monster.atk * (1 - player.reducPercent) - player.bloc);
monsterDmg < 1 && (monsterDmg = 1);
let curHp = player.curHp,
mHp = monster.hp;
const bouts: any = [];
while (true) {
const bout: any = {};
bouts.push(bout);
if (Math.random() < crit) {
bout.crit = true;
bout.dmg = Math.ceil(atk * critdmg);
} else {
bout.dmg = atk;
}
mHp -= bout.dmg;
if (mHp < 0) break;
bout.takeDmg = monsterDmg;
curHp -= monsterDmg;
if (curHp < 0) break;
}
return { win: curHp > 0, bouts: bouts, takeDmg: tmp - curHp };
};

23
src/views/dungeon/battle.vue

@ -16,7 +16,7 @@ import { useStore } from "vuex"; @@ -16,7 +16,7 @@ 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";
import { randonBootyEquip, callBattleResult } from "@/tool";
const { t } = useI18n();
const { state, commit, dispatch } = useStore();
@ -103,30 +103,31 @@ const playerMove = (monsterIdx?, playerIdx?) => { @@ -103,30 +103,31 @@ const playerMove = (monsterIdx?, playerIdx?) => {
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 result = callBattleResult(player, monster);
// 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 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('difficulty.' + props.dungeon?.difficulty) + t(monster.type)).replace('${dmg}', takeDmg + '');
return t(i18nName).replace('${lv}', monster.lv).replace('${name}', t('difficulty.' + props.dungeon?.difficulty) + t(monster.type)).replace('${dmg}', result.takeDmg + '');
};
commit("set_sys_info", { msg: getMsg('battle'), type: 'battle' });
battle.value.timeOut = setTimeout(() => {
nextTick(() => {
commit('add_player_curhp', -1 * takeDmg);
commit('add_player_curhp', -1 * result.takeDmg);
})
if (monsterDeadTime < playerDeadTime) {
commit("set_sys_info", { msg: getMsg('killMonster'), type: 'battle' });
if (result.win) {
commit("set_sys_info", { msg: getMsg('killMonster'), type: 'battle', bouts: result.bouts });
//
const equips = randonBootyEquip(monster);
commit('add_bootys', { equips: equips, coins: monster.coins });
resolve(true);
} else {
commit("set_sys_info", { msg: getMsg('beKilled'), type: 'warning' });
commit("set_sys_info", { msg: getMsg('beKilled'), type: 'warning', bouts: result.bouts });
battle.value.battleShow = false;
dispatch('play_music', 'backgound');
}

51
src/views/message/bouts.vue

@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
<template>
<div class="bouts">
<div v-for="bout, idx in bouts" class="bout">
<span class="seq">{{ t('bouts.1') + (idx + 1) }}:</span>
<span class="crit" v-if="bout.crit">{{ t('bouts.2') }},</span>
<span class="dmg">{{ t('bouts.3').replace('${dmg}', bout.dmg) }},</span>
<span class="take-dmg" v-if="bout.takeDmg">{{ t('bouts.4').replace('${dmg}', bout.takeDmg) }}</span>
<span v-if="idx == bouts.length - 1">
{{ t('bouts.5') }}{{ bout.takeDmg ? t('bouts.7') : t('bouts.6') }}
</span>
</div>
</div>
</template>
<script lang="ts" setup>
import { useStore } from "vuex";
import { reactive, onMounted, ref } from "vue";
import { useI18n } from "vue3-i18n";
const { t } = useI18n();
const { state, commit, dispatch } = useStore();
defineProps({
bouts: {
type: Array as () => any[],
default: []
}
})
onMounted(() => { });
</script>
<style lang="scss" scoped>
.bout {
text-align: left;
.seq {
font-size: 1.1rem;
}
.crit {
color: red;
}
.dmg {
color: #2fe20f;
}
.take-dmg {
color: #de8618;
}
}
</style>

20
src/views/message/sys-info.vue

@ -1,9 +1,17 @@ @@ -1,9 +1,17 @@
<template>
<div class='sysInfo' ref="sysInfo">
<div :class="['info', v.type]" v-for="(v, k) in state.sysInfo" :key="k">
<span>系统</span>
<span>{{ t('sys') }}</span>
<i class="time" v-if="v.time">({{ v.time }})</i>
<span class="msg">{{ v.msg }}</span>
<div style="float: inline-end;" v-if="v.bouts">
<Tooltip :show-icon="false" width="25rem" x="-50%">
<a class="bouts-link">{{ t('bouts.0') }}</a>
<template #tip>
<Bouts :bouts="v.bouts"></Bouts>
</template>
</Tooltip>
</div>
<span v-if="v.equips" v-for="(o, p) in v.equips" :key="p">
<a :style="{ color: o.quality.color }" @mouseleave="commit('close_equip_tip')"
@mouseover="commit('show_equip_tip', { equip: o, compare: true, e: $event })">
@ -13,6 +21,9 @@ @@ -13,6 +21,9 @@
</span>
</div>
</div>
</template>
<script lang="ts" setup>
@ -20,6 +31,8 @@ import { useStore } from "vuex"; @@ -20,6 +31,8 @@ import { useStore } from "vuex";
import { watch, nextTick, onMounted, ref } from "vue";
import { useI18n } from "vue3-i18n";
import { qualitys } from "@/config";
import { Tooltip } from "@/components";
import Bouts from "./bouts.vue";
const { t } = useI18n();
const { state, commit, dispatch } = useStore();
@ -75,4 +88,9 @@ a { @@ -75,4 +88,9 @@ a {
.booty>.msg {
color: #2fe20f;
}
.bouts-link {
color: aqua;
padding-left: 0.3rem;
}
</style>

11
src/views/version/update-log.vue

@ -31,7 +31,16 @@ const { state, commit, dispatch } = useStore(); @@ -31,7 +31,16 @@ const { state, commit, dispatch } = useStore();
const curVersion = '测试版';
const updateLogs: any = [{
date: '2025-04-22', version: '测试版', desc: '新增装备图鉴',
date: '2025-04-23', version: '测试版',
adjust: [
'调整战斗逻辑,战斗伤害不再使用用期望值,每回合伤害独立计算,击败怪物的回合怪物将不造成伤害',
'新增战斗过程查看'
],
tuning: [
'修复菜单tip突变不显示BUG'
]
}, {
date: '2025-04-22', version: '测试版',
adjust: [
'新增版本信息和更新日志',
],

Loading…
Cancel
Save