refactor: 重构技能触发逻辑,将proc_skill从命中触发改为施法后触发
1. 调整proc_skill触发时机为施法出手时判定,一次施法仅判定一次,与命中/弹道数无关 2. 移除HeroAtkSystem中旧的proc_skill触发逻辑,新增SCastSystem的tryProcSkill方法 3. 更新技能配置注释、编辑器文案与文档说明,同步调整服务端技能描述显示 4. 全局设置Element Plus组件为small尺寸,优化编辑器UI布局 5. 清理冗余的proc_skill快照传递逻辑,移除unused的reviveOptions计算属性
This commit is contained in:
@@ -92,7 +92,7 @@
|
||||
特殊存储格式(导出时由 server 还原为 TS 枚举表达式):
|
||||
- `TGroup`:JSON 存字符串(如 `"Team"`),导出还原 `TGroup.Team`;`null` 表示不覆写;
|
||||
- `buff_target`:存数字 0~3(Hit/Self/Ally/Enemy),导出还原 `BuffTarget.X`;
|
||||
- `proc_skill`:对象 `{s_uuid, chance?, overrides?}`(命中后概率触发另一技能);
|
||||
- `proc_skill`:对象 `{s_uuid, chance?, overrides?}`(施法后概率触发另一技能,出手即判定,与命中/弹道数无关);
|
||||
- `icon`:字符串图标帧名(uicons 图集),非数值;
|
||||
- 其余一律直存数值。
|
||||
|
||||
@@ -126,11 +126,11 @@
|
||||
|
||||
**语义陷阱**:`timed_buff_id` 在伤害技能上缺省挂**施法者自身**——若想"命中给敌人挂减益",必须用 `timed_debuff_id`,否则会把减益挂到自己身上。
|
||||
|
||||
### 6.2 proc_skill(命中概率触发主动技能)
|
||||
### 6.2 proc_skill(施法后概率触发主动技能)
|
||||
|
||||
**定位**:命中后概率触发一个**主动技能**(大招/触发技底座,如 6100+/6200+ 段伤害技能),以施法者身份完整释放(含伤害/弹道/特效)。它是技能触发器,不是挂 buff 的方式——debuff 注入请用 `timed_buff_id`(见 §6.1)。
|
||||
**定位**:施法出手后概率触发一个**主动技能**(大招/触发技底座,如 6100+/6200+ 段伤害技能),以施法者身份完整释放(含伤害/弹道/特效)。它是技能触发器,不是挂 buff 的方式——debuff 注入请用 `timed_buff_id`(见 §6.1)。
|
||||
|
||||
**编辑器 UI**:overrides 添加 `proc_skill 命中概率触发主动技能` 行后展开结构化编辑:
|
||||
**编辑器 UI**:overrides 添加 `proc_skill 施法后概率触发技能` 行后展开结构化编辑:
|
||||
1. `被触发技能 uuid`:下拉列出全部 SkillSet(`uuid 名称`);
|
||||
2. `概率%`:0~100 数字输入,默认 100;
|
||||
3. `被触发技能覆写`:内嵌 OverrideEditor(同套白名单),可递归覆写被触发技能的 `ap`/`TGroup`/`hit_count` 等。
|
||||
@@ -145,14 +145,16 @@
|
||||
```
|
||||
|
||||
**运行时行为**:
|
||||
- 触发链路:技能命中 → 掷 `chance` 骰(≥100 直接成功不掷骰;无 70% 封顶)→ 以施法者身份走 `forceCastTriggerSkill`(无视 CD、无施法前摇,触发类型记为 atking);
|
||||
- 触发链路:施法出手 → 掷 `chance` 骰(≥100 直接成功不掷骰;无 70% 封顶)→ 以施法者身份走 `forceCastTriggerSkill`(无视 CD、无施法前摇,触发类型记为 atking);
|
||||
- 出手即判定:**一次施法只判定一次**,与命中次数、弹道数、召唤数均无关(多弹道技能不会按实体数重复判定);
|
||||
- 不再依赖命中:即使技能落空/无目标可命中,只要施法动作出手就会判定;
|
||||
- `overrides` 与被触发技能自身 heroSet overrides 叠加,本次传入优先;
|
||||
- DoT 伤害不触发 proc;被触发的技能不再累加普攻计数(防递归);
|
||||
- 被触发的技能不再累加普攻计数(防递归);
|
||||
- 内嵌 `TGroup` 可改变被触发技能的释放对象(如触发一个友方增益)。
|
||||
|
||||
**选型指引**(对敌附带效果):
|
||||
- 挂 debuff(冰冻/中毒/易伤等)→ `timed_buff_id`:写入 SkillSet 底座,或用友方技能 + `buff_target: 3` 分流挂敌;
|
||||
- 命中后追发一个主动技能(陨石/火球等完整释放)→ `proc_skill`。
|
||||
- 施法后追发一个主动技能(陨石/火球等完整释放)→ `proc_skill`。
|
||||
|
||||
## 7. 新增英雄操作清单
|
||||
|
||||
|
||||
@@ -268,12 +268,12 @@ function overrideShort(ov, { includeAp = true } = {}) {
|
||||
const chance = ov.debuff_chance != null ? `debuff_chance${ov.debuff_chance}` : ''
|
||||
parts.push(`命中附加${val}${debuffName}${ov.timed_debuff_id}${chance}`)
|
||||
}
|
||||
// proc_skill:命中后概率触发额外技能,标注被触发技能名/概率/覆写 ap(若有)
|
||||
// proc_skill:施法后概率触发额外技能(出手即判定,与命中/弹道数无关),标注被触发技能名/概率/覆写 ap(若有)
|
||||
if (ov.proc_skill?.s_uuid != null) {
|
||||
const procName = cache?.SkillSet?.[ov.proc_skill.s_uuid]?.name || ''
|
||||
const procChance = ov.proc_skill.chance != null ? `${ov.proc_skill.chance}%` : '100%'
|
||||
const procAp = ov.proc_skill.overrides?.ap != null ? `ap${ov.proc_skill.overrides.ap}` : ''
|
||||
parts.push(`触发${procName}${ov.proc_skill.s_uuid}(${procChance}${procAp ? `;${procAp}` : ''})`)
|
||||
parts.push(`施法触发${procName}${ov.proc_skill.s_uuid}(${procChance}${procAp ? `;${procAp}` : ''})`)
|
||||
}
|
||||
return parts.join(';')
|
||||
}
|
||||
|
||||
@@ -242,8 +242,6 @@ const allSkills = computed(() => Object.values(skillMap.value).sort((a, b) => a.
|
||||
const fieldOptions = computed(() => Object.values(meta.value?.FieldSkillSet || {}).sort((a, b) => a.uuid - b.uuid))
|
||||
// buff 候选:timed_buff_id 覆写下拉用(BuffList 按 id 升序)
|
||||
const buffOptions = computed(() => Object.values(meta.value?.BuffList || {}).sort((a, b) => a.id - b.id))
|
||||
// 复活已纳入 dead 触发组,通过 dead 编辑器的 overrides 配置 revive_hp / revive_count
|
||||
const reviveOptions = computed(() => allSkills.value.filter((s) => s.uuid >= 6500 && s.uuid < 6600))
|
||||
|
||||
const roleBase = computed(() => {
|
||||
if (!current.value || !meta.value?.HERO_ROLE_BASE) return null
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
>
|
||||
<el-option v-for="opt in enumOptions(item.key)" :key="String(opt.value)" :label="opt.label" :value="opt.value" />
|
||||
</el-select>
|
||||
<!-- 对象型覆写(proc_skill):命中后概率触发额外技能,结构化编辑 s_uuid/chance/overrides -->
|
||||
<!-- 对象型覆写(proc_skill):施法后概率触发额外技能(出手即判定,与命中/弹道数无关),结构化编辑 s_uuid/chance/overrides -->
|
||||
<template v-else-if="isObjectKey(item.key)">
|
||||
<div class="proc-skill-editor">
|
||||
<el-select
|
||||
@@ -75,6 +75,17 @@
|
||||
<el-input-number v-else v-model="item.value" size="small" :controls="false" style="width: 120px" />
|
||||
<el-button type="danger" size="small" text @click="remove(idx)">删除</el-button>
|
||||
</div>
|
||||
<!-- 选中 proc_skill 后的触发语义提示:施法出手即判定,与命中/弹道数无关 -->
|
||||
<el-alert
|
||||
v-if="hasProcSkill"
|
||||
type="warning"
|
||||
:closable="false"
|
||||
show-icon
|
||||
class="hint-alert"
|
||||
style="margin-bottom: 6px"
|
||||
title="proc_skill 为施法后触发"
|
||||
description="出手即判定概率,一次施法只判定一次(多弹道/多召唤技能不会按实体数重复判定),不再依赖命中;即使技能落空也会触发。"
|
||||
/>
|
||||
<!-- 选中 debuff 后的取值语义提示:依 BuffList 配置(tick/modifier/易伤/控制)说明 debuff_value 的正负与生效方式 -->
|
||||
<el-alert
|
||||
v-if="debuffHint"
|
||||
@@ -105,7 +116,7 @@
|
||||
class="hint-alert"
|
||||
style="margin-bottom: 6px"
|
||||
title="buff/debuff 配置提示"
|
||||
description="buff 为增益语义:缺省挂施法者自身(如吸血/攻击后强化),可用 buff_target 改为全体友方;debuff 为对敌减益语义:缺省挂被命中者(目标不可覆写),对敌技能请用 timed_debuff_id。proc_skill 用于命中后概率触发主动技能,不是挂 buff 的方式。"
|
||||
description="buff 为增益语义:缺省挂施法者自身(如吸血/攻击后强化),可用 buff_target 改为全体友方;debuff 为对敌减益语义:缺省挂被命中者(目标不可覆写),对敌技能请用 timed_debuff_id。proc_skill 为施法后概率触发主动技能(出手即判定,与命中/弹道数无关),不是挂 buff 的方式。"
|
||||
/>
|
||||
<el-button size="small" @click="add">+ 添加覆盖</el-button>
|
||||
</div>
|
||||
@@ -137,6 +148,9 @@ const isEnemyHost = computed(() => {
|
||||
// 对敌技能且注入了 timed_buff_id → 运行时断链不生效,警示引导改用 proc_skill / 底座表
|
||||
const showEnemyBuffWarn = computed(() => isEnemyHost.value && rows.value.some((r) => r.key === 'timed_buff_id'))
|
||||
|
||||
// 是否配置了 proc_skill(施法后概率触发主动技能):控制触发语义提示显隐
|
||||
const hasProcSkill = computed(() => rows.value.some((r) => r.key === 'proc_skill'))
|
||||
|
||||
// 易伤 buff id(与游戏侧 BuffSet.VULNERABLE_BUFF_ID 对应),取值语义特殊需单独提示
|
||||
const VULNERABLE_ID = 7002
|
||||
|
||||
|
||||
@@ -141,8 +141,8 @@ export const OVERRIDE_KEYS = [
|
||||
{ key: 'call_hero', label: 'call_hero 召唤英雄id' },
|
||||
{ key: 'revive_hp', label: 'revive_hp 复活回血比例(%)' },
|
||||
{ key: 'revive_count', label: 'revive_count 复活次数上限' },
|
||||
// 对象型覆写:命中后概率触发主动技能(大招/触发技),含 s_uuid/chance/overrides 子字段
|
||||
{ key: 'proc_skill', label: 'proc_skill 命中概率触发主动技能', type: 'object' },
|
||||
// 对象型覆写:施法后概率触发主动技能(大招/触发技),出手即判定、一次施法一次判定,含 s_uuid/chance/overrides 子字段
|
||||
{ key: 'proc_skill', label: 'proc_skill 施法后概率触发技能', type: 'object' },
|
||||
// 字符串型覆写:value 为图标ID(uicons 图集帧名),非数值
|
||||
{ key: 'icon', label: 'icon 英雄语境图标(覆写 SkillSet.icon)', type: 'string' },
|
||||
]
|
||||
|
||||
@@ -6,5 +6,6 @@ import App from './App.vue'
|
||||
import './style.css'
|
||||
|
||||
const app = createApp(App)
|
||||
app.use(ElementPlus, { locale: zhCn })
|
||||
// 全局 small 尺寸:编辑页所有 Element Plus 控件(输入框/下拉/按钮等)默认缩小一档
|
||||
app.use(ElementPlus, { locale: zhCn, size: 'small' })
|
||||
app.mount('#app')
|
||||
|
||||
@@ -28,9 +28,19 @@ body {
|
||||
/* 行间距压缩:表单项下边距 + 行高收紧 */
|
||||
.hero-app .el-form-item { margin-bottom: 8px; line-height: 1.2; }
|
||||
.hero-app .el-form-item__label { line-height: 1.2; padding-bottom: 2px; }
|
||||
.hero-app .el-button { font-size: 12px; height: 26px; padding: 8px 10px; }
|
||||
.hero-app .el-button--small { height: 22px; padding: 5px 8px; }
|
||||
.hero-app .el-input__inner { --el-input-height: 26px; }
|
||||
.hero-app .el-button { font-size: 12px; height: 24px; padding: 5px 10px; }
|
||||
.hero-app .el-button--small { height: 20px; padding: 4px 8px; }
|
||||
/* 控件高度压缩:用 CSS 变量统一覆盖 Element Plus 各尺寸档(small 由 main.js 全局注册) */
|
||||
.hero-app {
|
||||
--el-component-size-small: 22px;
|
||||
--el-component-size: 24px;
|
||||
--el-component-size-large: 28px;
|
||||
--el-input-height: 22px;
|
||||
}
|
||||
.hero-app .el-input__wrapper { padding: 0 8px; }
|
||||
.hero-app .el-select__wrapper { min-height: 22px; padding: 0 8px; }
|
||||
.hero-app .el-input-number { width: auto; }
|
||||
.hero-app .el-input-number .el-input__inner { text-align: left; }
|
||||
.hero-app .el-tabs__item { font-size: 12px; height: 30px; }
|
||||
.hero-app .el-tabs__header { margin-bottom: 8px; }
|
||||
.hero-app .el-tabs__nav-wrap::after { height: 1px; }
|
||||
|
||||
Reference in New Issue
Block a user