1. 新增大招CD档位配置ULT_CDS/ULT_CD_MAP,与普攻档位分离 2. 为职业默认值添加大招CD档配置,支持按职业类型适配 3. 改造技能编辑器与英雄向导,支持选择大招CD档位 4. 批量更新现有英雄数据与配置文件,统一使用档位化CD配置 5. 补充文档说明,规范大招CD配置规则
125 lines
5.3 KiB
Vue
125 lines
5.3 KiB
Vue
<template>
|
||
<div>
|
||
<div class="form-grid">
|
||
<el-form-item label="技能底座">
|
||
<el-select v-model="skill.uuid" placeholder="选择技能" filterable @change="onUuidChange">
|
||
<el-option v-for="s in options" :key="s.uuid" :label="`${s.uuid} ${s.name}`" :value="s.uuid">
|
||
<span>{{ s.uuid }} {{ s.name }}</span>
|
||
<span class="muted" style="float: right">{{ s.info }}</span>
|
||
</el-option>
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="显示名">
|
||
<el-input v-model="skill.name" placeholder="对外展示名(可选)" />
|
||
</el-form-item>
|
||
<el-form-item :label="isUlt ? '大招CD档位' : '攻速档位'">
|
||
<el-select v-model="cdTierKey" @change="onTierChange">
|
||
<el-option v-for="s in (isUlt ? ULT_CDS : ATK_SPEEDS)" :key="s.key" :label="s.label" :value="s.key" />
|
||
</el-select>
|
||
</el-form-item>
|
||
<el-form-item label="CD(秒)">
|
||
<el-input-number v-model="skill.cd" :step="0.05" :min="0" :controls="false" style="width: 100%" @change="onCdManual" />
|
||
</el-form-item>
|
||
<el-form-item label="描述模板" class="grid-span">
|
||
<el-input v-model="skill.desc" type="textarea" :rows="2" placeholder="支持 {target}/{ap}/{para} 等占位符" />
|
||
</el-form-item>
|
||
</div>
|
||
<el-form-item label="overrides">
|
||
<OverrideEditor v-model="skill.overrides" :skill-options="skillOptions" :buff-options="buffOptions" :base-skill-uuid="skill.uuid" />
|
||
</el-form-item>
|
||
|
||
<!-- 分档编辑:大招(is-ult)全档编辑;普攻(basic-lv2)仅 lv2 强化档(客户端独立技能图标消费) -->
|
||
<template v-if="isUlt || basicLv2">
|
||
<el-divider content-position="left">{{ basicLv2 ? '普攻 lv2 强化档(独立技能)' : '大招 lv_entries 分档' }}</el-divider>
|
||
<div v-for="(e, idx) in skill.lv_entries" :key="idx" class="skill-block">
|
||
<div class="head">
|
||
<span>档位 lv {{ e.lv }} (SkillLv.Lv{{ e.s_lv }})</span>
|
||
<el-button v-if="!basicLv2" type="danger" size="small" text @click="skill.lv_entries.splice(idx, 1)">移除</el-button>
|
||
</div>
|
||
<div class="form-grid">
|
||
<el-form-item label="等级 lv">
|
||
<el-input-number v-model="e.lv" :min="1" :max="20" :controls="false" :disabled="basicLv2" style="width: 100%" />
|
||
</el-form-item>
|
||
<el-form-item label="SkillLv">
|
||
<el-select v-model="e.s_lv" :disabled="basicLv2">
|
||
<el-option v-for="n in 5" :key="n" :label="`Lv${n}`" :value="n" />
|
||
</el-select>
|
||
</el-form-item>
|
||
</div>
|
||
<el-form-item label="overrides">
|
||
<OverrideEditor v-model="e.overrides" :skill-options="skillOptions" :buff-options="buffOptions" :base-skill-uuid="skill.uuid" />
|
||
</el-form-item>
|
||
<el-form-item label="描述">
|
||
<el-input v-model="e.desc" type="textarea" :rows="2" />
|
||
</el-form-item>
|
||
</div>
|
||
<template v-if="!basicLv2">
|
||
<el-button size="small" @click="addEntry">+ 添加档位(lv9/lv16)</el-button>
|
||
<span class="muted" style="margin-left: 8px">建议按 lv9 / lv16 两档</span>
|
||
</template>
|
||
<span v-else class="muted">固定 lv=2 / SkillLv.Lv2,客户端图鉴按独立技能图标展示(名称/图标取 lv1,只显示 lv2 说明)</span>
|
||
</template>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { computed } from 'vue'
|
||
import { ATK_SPEEDS, ATK_SPEED_MAP, ULT_CDS, ULT_CD_MAP } from '../constants'
|
||
import OverrideEditor from './OverrideEditor.vue'
|
||
|
||
const props = defineProps({
|
||
skill: { type: Object, required: true },
|
||
options: { type: Array, default: () => [] },
|
||
// 全部技能候选(proc_skill.s_uuid 下拉用),由 App 透传
|
||
skillOptions: { type: Array, default: () => [] },
|
||
// 全部 buff 候选(timed_buff_id 下拉用),由 App 透传
|
||
buffOptions: { type: Array, default: () => [] },
|
||
isUlt: { type: Boolean, default: false },
|
||
// 普攻 lv2 强化档模式:仅允许配置单个 lv2 档(lv=2 / s_lv=2 锁定,禁用增删)
|
||
basicLv2: { type: Boolean, default: false },
|
||
})
|
||
|
||
// 普攻 lv2 模式:确保 lv_entries 恰为一个 lv2 档(无则补,多则只保留首个并规范化)
|
||
if (props.basicLv2) {
|
||
if (!props.skill.lv_entries?.length) {
|
||
props.skill.lv_entries = [{ lv: 2, s_lv: 2, overrides: {}, desc: '' }]
|
||
} else {
|
||
props.skill.lv_entries.splice(1)
|
||
Object.assign(props.skill.lv_entries[0], { lv: 2, s_lv: 2 })
|
||
}
|
||
}
|
||
|
||
// 档位配置:大招(isUlt)走 UltCdSet 档(6~10s),普攻走 AtkSpeedSet 档(0.75~1.5s),两档数值不重叠可按 cd 反查
|
||
function tierConf(key) {
|
||
return (props.isUlt ? ULT_CD_MAP : ATK_SPEED_MAP)[key]
|
||
}
|
||
|
||
const cdTierKey = computed({
|
||
get() {
|
||
const list = props.isUlt ? ULT_CDS : ATK_SPEEDS
|
||
const found = list.find((s) => Math.abs(tierConf(s.key).cd - props.skill.cd) < 0.001)
|
||
return found?.key || 'Normal'
|
||
},
|
||
set() {},
|
||
})
|
||
|
||
function onTierChange(key) {
|
||
const conf = tierConf(key)
|
||
props.skill.cd = conf.cd
|
||
props.skill.cdExpr = conf.cdExpr
|
||
}
|
||
function onCdManual() {
|
||
props.skill.cdExpr = null
|
||
}
|
||
function onUuidChange() {
|
||
// 选择底座时清空名字(回退默认)
|
||
}
|
||
function addEntry() {
|
||
props.skill.lv_entries.push({ lv: 9, s_lv: 2, overrides: {}, desc: '' })
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.grid-span { grid-column: 1 / -1; }
|
||
</style>
|