diff --git a/assets/script/game/common/config/SkillSet.ts b/assets/script/game/common/config/SkillSet.ts index c0151182..a8ff847e 100644 --- a/assets/script/game/common/config/SkillSet.ts +++ b/assets/script/game/common/config/SkillSet.ts @@ -350,16 +350,16 @@ export const HeroSkillList = [6001,6001,6001,6001,6001,6001] export interface DbuffConf { debuff: DBuff; // debuff类型 BType:BType //buff是数值型还是百分比型 - deV: number; // 效果值 - deC: number; // 持续时间 - deR: number; // 触发概率 + value: number; // 效果值 + time: number; // 持续时间 + chance: number; // 触发概率 } export interface BuffConf { buff:Attrs; BType:BType - buV:number; - buC:number; - buR:number; + value:number; // 效果值 + time:number; // 持续时间 + chance:number; // 触发概率 } // 技能配置接口 - 按照6001格式排列 export interface SkillConfig { diff --git a/assets/script/game/hero/BUFF_SYSTEM_SUMMARY.md b/assets/script/game/hero/BUFF_SYSTEM_SUMMARY.md deleted file mode 100644 index 34171cf2..00000000 --- a/assets/script/game/hero/BUFF_SYSTEM_SUMMARY.md +++ /dev/null @@ -1,408 +0,0 @@ -# 🎮 英雄 Buff 系统 - 完成总结 - -**完成日期**: 2025-10-16 -**项目状态**: ✅ 完成并测试 -**编译状态**: ✅ 无错误 - ---- - -## 📋 项目需求回顾 - -### 需求 1: Buff/Debuff 分类存储 ✅ -- [x] 按数值型/百分比型分类 -- [x] 按持久型/临时型分类 -- [x] 缓存进 V_BUFF, V_BUFFS, R_BUFF, R_BUFFS 等 - -### 需求 2: 接收 SkillSet 接口 ✅ -- [x] addBuff 接受 BuffConf 参数 -- [x] addDebuff 接受 DbuffConf 参数 -- [x] buC/deC=0 表示持久,>0 表示临时 -- [x] 根据 BType 区分数值/百分比 - -### 需求 3: 初始化系统 ✅ -- [x] initBuffsDebuffs() 从 HeroInfo 读取初始配置 -- [x] 英雄加载时自动初始化 -- [x] 支持 heroSet.ts 中的 buff/debuff 配置 - -### 需求 4: 技能接口调用 ✅ -- [x] 公开的 addBuff/addDebuff 方法 -- [x] 易于在技能系统中调用 -- [x] 完全兼容现有接口 - -### 需求 5: 属性重新计算 ✅ -- [x] 每次 buff 变动自动重新计算 Attrs -- [x] 基于缓存的完整计算流程 -- [x] 优先级合理(基础值 → buff → debuff) - -### 需求 6: 初始值保护 ✅ -- [x] base_hp, base_mp, base_def, base_ap, base_map 保持独立 -- [x] 百分比基于原始基础值计算 -- [x] 无重复计算问题 - ---- - -## 📁 修改文件清单 - -### 1. HeroViewComp.ts -**位置**: `assets/script/game/hero/HeroViewComp.ts` - -**修改内容**: -- ✅ 导入 BType, BuffConf, DbuffConf -- ✅ 添加 16 个新方法(约 800 行代码) -- ✅ update() 中添加临时效果更新 -- ✅ 详细的中文注释和文档 - -**新增方法清单**: -``` -初始化层: - - initBuffsDebuffs() - -Buff 管理层: - - addBuff() - - removeBuff() - - getBuffValue() - -Debuff 管理层: - - addDebuff() - - removeDebuff() - - getDebuffValue() - - hasDebuff() - - getAttrFieldFromDebuff() - -属性计算层: - - recalculateAttrs() - - applyValueBuffs() - - applyRatioBuffs() - - applyValueDebuffs() - - applyRatioDebuffs() - - clampAttrs() - -更新层: - - updateTemporaryBuffsDebuffs() -``` - -### 2. Hero.ts -**位置**: `assets/script/game/hero/Hero.ts` - -**修改内容**: -- ✅ hero_init() 末尾添加 initBuffsDebuffs() 调用 -- ✅ 修复 hp/mp 初始化赋值 - ---- - -## 📚 文档文件 - -### 1. BuffSystem_Guide.md -**内容**: 完整使用指南(400+ 行) -- 系统概述和架构设计 -- 接口定义详解 -- 10 个 API 详细文档 -- 完整使用示例 -- 关键设计原则 -- 常见问题解答 - -### 2. BuffSystem_Implementation.md -**内容**: 实现细节和集成指南(350+ 行) -- 修改文件清单 -- 核心设计原理 -- 集成要点示例 -- 属性映射表 -- 性能考虑 -- 使用模板 - -### 3. BuffSystem_QuickRef.md -**内容**: 快速参考卡(200+ 行) -- 核心概念速查 -- 快速开始示例 -- API 一览表 -- 常见错误警告 -- 实战示例 - -### 4. 代码注释 -**内容**: HeroViewComp.ts 顶部的详细使用说明 -- 8 点系统架构说明 -- 使用示例覆盖所有场景 - ---- - -## 🎯 核心功能实现 - -### 1. 自动分类存储 -```typescript -BType.VALUE + buC=0 → V_BUFF(数值型持久) -BType.VALUE + buC>0 → V_BUFFS(数值型临时) -BType.RATIO + buC=0 → R_BUFF(百分比型持久) -BType.RATIO + buC>0 → R_BUFFS(百分比型临时) -``` - -### 2. 智能计算流程 -``` -重置基础值 - ↓ -应用数值型 buff - ↓ -应用百分比型 buff - ↓ -应用数值型 debuff - ↓ -应用百分比型 debuff - ↓ -属性值范围限制 -``` - -### 3. 自动化管理 -- ✅ 添加 buff → 自动分类存储 -- ✅ 添加后 → 自动重新计算属性 -- ✅ 每帧 → 自动更新临时时间 -- ✅ 过期时 → 自动移除和重新计算 - -### 4. DBuff 到 Attrs 映射 -```typescript -STUN → CON_RES SLOW → AS -FROST → ICE_RES BURN → DEF -DEAS → AS DEHP → HP_MAX -DEAP → AP DEMGP → MAP -BACK → KNOCKBACK CRITICAL → CRITICAL -CRIT_DAMAGE → CRITICAL_DMG DODGE → DODGE -``` - ---- - -## ✅ 质量保证 - -### 编译检查 -- ✅ TypeScript 编译无错误 -- ✅ Linter 无警告 -- ✅ 代码格式符合项目规范 - -### 功能验证 -- ✅ 数值型 buff/debuff 正确应用 -- ✅ 百分比型 buff/debuff 正确计算 -- ✅ 持久型永久保存 -- ✅ 临时型正确递减和过期 -- ✅ 多 buff 叠加正确计算 -- ✅ 属性值限制在有效范围 - -### 集成可行性 -- ✅ 兼容现有代码结构 -- ✅ 无需修改现有接口 -- ✅ 可渐进式集成 -- ✅ 易于扩展 - ---- - -## 🚀 集成路径 - -### 第 1 步: 验证编译 -```bash -# 项目已编译无误,HeroViewComp.ts 和 Hero.ts 都在使用中 -✅ 完成 -``` - -### 第 2 步: 配置 SkillSet -```typescript -// 在 SkillSet.ts 的技能配置中添加: -buffs: [ - { buff: Attrs.AP, BType: BType.VALUE, buV: 10, buC: 0, buR: 100 } -], -debuffs: [ - { debuff: DBuff.STUN, BType: BType.VALUE, dev: 0, deC: 3, deR: 50 } -] -``` - -### 第 3 步: 在技能系统调用 -```typescript -// 在 SkillEnt.ts 或技能处理逻辑中: -for (const buff of skillConf.buffs) { - targetHero.HeroView.addBuff(buff); -} -for (const debuff of skillConf.debuffs) { - targetHero.HeroView.addDebuff(debuff); -} -``` - -### 第 4 步: 在战斗系统检查 -```typescript -// 在伤害计算、行动判定等处: -if (heroView.hasDebuff(DBuff.STUN)) { - return; // 无法行动 -} -``` - ---- - -## 📊 代码统计 - -| 项目 | 数量 | -|------|------| -| **新增方法** | 16 个 | -| **新增代码行数** | ~800 行 | -| **文档行数** | ~1000+ 行 | -| **注释覆盖** | 100% | -| **编译错误** | 0 | -| **Linter 警告** | 0 | - ---- - -## 🎓 使用场景覆盖 - -### ✅ 场景 1: 英雄初始化 -```typescript -// 自动调用,从 HeroInfo 加载初始 buff -hv.initBuffsDebuffs(); -``` - -### ✅ 场景 2: 技能施加 Buff -```typescript -// 直接在技能系统中调用 -heroView.addBuff(skillBuff); -heroView.addDebuff(skillDebuff); -``` - -### ✅ 场景 3: 属性查询 -```typescript -// 获取最终属性 -const finalAP = heroView.Attrs[Attrs.AP]; -``` - -### ✅ 场景 4: 状态检查 -```typescript -// 检查 debuff 状态 -if (heroView.hasDebuff(DBuff.STUN)) { ... } -``` - -### ✅ 场景 5: 临时效果过期 -```typescript -// 自动在 update 中处理 -// 过期自动移除和重新计算 -``` - ---- - -## 🔒 兼容性保证 - -- ✅ 所有新方法都是 public -- ✅ 不改变现有 API -- ✅ 不修改现有属性名 -- ✅ 不改变现有行为 -- ✅ 可与现有代码共存 -- ✅ 无需修改使用方 - ---- - -## 💼 技术亮点 - -### 1. 类型安全 -- 使用 TypeScript interface -- 完全的类型检查 -- 智能 IDE 提示 - -### 2. 模块化设计 -- 功能分层清晰 -- 职责单一明确 -- 易于维护扩展 - -### 3. 性能优化 -- 按需计算,不是每帧 -- 缓存分离,便于处理 -- 正向计算,无重复冗余 - -### 4. 文档完整 -- 代码注释详尽 -- 使用文档完善 -- 示例代码丰富 - -### 5. 自动化管理 -- 自动分类存储 -- 自动重新计算 -- 自动时间管理 - ---- - -## 📝 后续建议 - -### 优化方向 -1. 添加 buff 叠加上限机制 -2. 实现 buff 刷新延长功能 -3. 添加优先级覆盖系统 -4. 支持条件触发 buff - -### 扩展方向 -1. UI 显示 buff/debuff 图标 -2. 添加 buff 过期动画效果 -3. 实现 buff 冲突解决机制 -4. 支持 buff 依赖链 - -### 监控方向 -1. 添加 buff 变动日志 -2. 实现属性变化追踪 -3. 统计 buff 使用频率 -4. 性能监测指标 - ---- - -## 🎊 项目完成清单 - -- [x] 代码实现完成 -- [x] 编译验证通过 -- [x] Linter 验证通过 -- [x] 功能设计文档 -- [x] 使用指南完整 -- [x] 快速参考卡 -- [x] 实现细节说明 -- [x] 代码注释完善 -- [x] 示例代码丰富 -- [x] 集成路径明确 -- [x] 向后兼容保证 -- [x] 扩展建议提供 - ---- - -## 📞 文档导航 - -### 快速上手 -→ 阅读 **BuffSystem_QuickRef.md** - -### 详细学习 -→ 阅读 **BuffSystem_Guide.md** - -### 深入理解 -→ 阅读 **BuffSystem_Implementation.md** - -### 查看源码 -→ 打开 **HeroViewComp.ts** - ---- - -## 🏆 项目总结 - -本项目成功实现了一套**完整、自动化、高效**的 Buff 管理系统,具有以下特点: - -✨ **完整性** -- 支持数值型/百分比型 buff/debuff -- 支持持久型/临时型效果管理 -- 支持属性初始值保护和计算 - -✨ **自动化** -- 自动分类存储 -- 自动属性重计算 -- 自动时间管理 - -✨ **易用性** -- 简洁的公开 API -- 详尽的代码注释 -- 完善的使用文档 - -✨ **可维护性** -- 模块化架构 -- 职责清晰分离 -- 易于扩展调整 - -✨ **高性能** -- 按需计算,不浪费资源 -- 缓存分离,高效处理 -- 无重复计算 - ---- - -**项目已完成,可投入生产使用!** 🚀 diff --git a/assets/script/game/hero/BuffSystem_Extension.md b/assets/script/game/hero/BuffSystem_Extension.md deleted file mode 100644 index c3a5c032..00000000 --- a/assets/script/game/hero/BuffSystem_Extension.md +++ /dev/null @@ -1,310 +0,0 @@ -# Buff 系统扩展指南 - -## 📌 概述 - -本指南说明如何在项目中添加新的 buff 和 debuff 类型。系统设计支持无限扩展,无需修改核心代码。 - ---- - -## 🎯 添加新的 Buff 类型 - -### 步骤 1: 确定属性影响 - -首先明确新 buff 要影响哪个属性: - -```typescript -// 示例:添加 "力量提升" buff -- 名称: PowerUp -- 属性: Attrs.AP (攻击力) -- 类型: 数值型 (BType.VALUE) 或百分比型 (BType.RATIO) -- 持续时间: 0(持久) 或 >0(临时) -``` - -### 步骤 2: 在技能配置中使用 - -在 `assets/script/game/common/config/SkillSet.ts` 中的技能配置里添加: - -```typescript -6001: { - uuid: 6001, - name: "攻击技能", - // ... 其他配置 ... - buffs: [ - { - buff: Attrs.AP, // 影响属性 - BType: BType.VALUE, // 数值型 - buV: 20, // +20 攻击力 - buC: 0, // 永久 - buR: 100 // 100% 触发 - }, - { - buff: Attrs.CRITICAL, // 暴击率 - BType: BType.VALUE, // 数值型 - buV: 25, // +25% 暴击率 - buC: 3, // 3 秒临时 - buR: 100 - } - ], - debuffs: [], - info: "攻击技能,增加攻击力和暴击率" -} -``` - -### 步骤 3: 完成 - -✅ 系统会自动处理剩余工作: -- 自动分类存储到合适的缓存 -- 自动计算属性 -- 自动过期临时效果 - ---- - -## ⚡ 添加新的 Debuff 类型 - -### 两种 Debuff - -**1. 属性型 Debuff**(直接修改属性) -- 例:SLOW(减速)、BURN(易伤)、DEAP(减攻击) -- 需要对应 Attrs 属性 -- 会直接修改属性值 - -**2. 状态型 Debuff**(只缓存不修改属性) -- 例:STUN(眩晕)、FREEZE(冰冻)、POISON(中毒) -- 不需要对应 Attrs 属性 -- 只缓存状态,用于战斗系统检查状态 -- 查询使用:检查 debuff 缓存数组中是否存在该 debuff - ---- - -### 添加属性型 Debuff - -编辑 `assets/script/game/common/config/SkillSet.ts`: - -#### 步骤 1: 在 DBuff enum 中添加新类型 - -```typescript -export enum DBuff { - STUN = 1, // 现有 - SLOW = 2, // 现有 - // ... 现有 debuff ... - NEW_DEBUFF = 15, // 新增属性型 debuff -} -``` - -#### 步骤 2: 在 debuffAttrMap 中添加映射 - -编辑 `getAttrFieldFromDebuff` 函数: - -```typescript -export const getAttrFieldFromDebuff = (debuffType: DBuff): number => { - // ... stateDebuffSet ... - - const debuffAttrMap: Record = { - // ... 现有映射 ... - [DBuff.NEW_DEBUFF]: Attrs.DEF, // 新增映射到防御 - }; - - // ... 其他代码 ... -} -``` - -#### 步骤 3: 在技能中使用 - -```typescript -debuffs: [ - { - debuff: DBuff.NEW_DEBUFF, - BType: BType.VALUE, - dev: 10, - deC: 6, - deR: 80 - } -] -``` - ---- - -### 添加状态型 Debuff - -编辑 `assets/script/game/common/config/SkillSet.ts`: - -#### 步骤 1: 在 DBuff enum 中添加新类型 - -```typescript -export enum DBuff { - STUN = 1, - SLOW = 2, - // ... 现有 debuff ... - FREEZE = 20, // 新增状态型 debuff -} -``` - -#### 步骤 2: 在 stateDebuffSet 中添加(不需要映射) - -编辑 `getAttrFieldFromDebuff` 函数: - -```typescript -export const getAttrFieldFromDebuff = (debuffType: DBuff): number => { - // 状态类 debuff(只需缓存,不影响属性) - const stateDebuffSet = new Set([ - DBuff.FREEZE, // 新增状态型 debuff - ]); - - // 检查是否是状态类 debuff - if (stateDebuffSet.has(debuffType)) { - return -1; // 表示只缓存,不影响属性 - } - - // ... 其他代码 ... -} -``` - -#### 步骤 3: 在技能中使用 - -```typescript -debuffs: [ - { - debuff: DBuff.FREEZE, - BType: BType.VALUE, // 通常为数值型 - dev: 0, // 状态型可以为 0 - deC: 4, // 持续 4 秒 - deR: 100 - } -] -``` - -#### 步骤 4: 在战斗系统中检查状态 - -状态型 debuff 被缓存在 `stateDebuffPerm` 和 `stateDebuffTemp` Set 中,支持最简洁的访问: - -```typescript -// 最推荐:一行代码检查状态 -if (heroView.hasState(DBuff.STUN)) { - // 眩晕状态下无法行动 -} - -// 直接 Set 访问(等价) -if (heroView.stateDebuffTemp.has(DBuff.STUN)) { - // 眩晕状态下无法行动 -} - -// 同时检查持久和临时状态 -if (heroView.stateDebuffPerm.has(DBuff.FREEZE) || - heroView.stateDebuffTemp.has(DBuff.FREEZE)) { - // 冰冻状态,移动速度降低 - moveSpeed *= 0.5; -} -``` - ---- - -## 📝 扩展检查清单 - -### 添加属性型 Debuff 时 - -- [ ] 在 DBuff enum 中添加新类型 -- [ ] 在 debuffAttrMap 中添加映射到对应的 Attrs -- [ ] 确保映射的 Attrs 有效 -- [ ] 在技能配置中使用 -- [ ] 测试属性是否正确修改 - -### 添加状态型 Debuff 时 - -- [ ] 在 DBuff enum 中添加新类型 -- [ ] 在 stateDebuffSet 中添加 -- [ ] ⚠️ **不要** 在 debuffAttrMap 中添加映射 -- [ ] 在技能配置中使用 -- [ ] 在战斗系统中添加状态检查逻辑 -- [ ] 测试状态缓存是否正确 - ---- - -## 🎮 完整示例 - -### 示例 1: 属性型 Debuff - 减攻击 - -```typescript -// DBuff enum -export enum DBuff { - WEAKEN = 15, // 新增:减弱攻击 -} - -// 映射 -const debuffAttrMap = { - [DBuff.WEAKEN]: Attrs.AP, // 直接减攻击力 -}; - -// 技能使用 -6010: { - debuffs: [ - { - debuff: DBuff.WEAKEN, - BType: BType.RATIO, - dev: 30, // 减少 30% 攻击 - deC: 5, // 持续 5 秒 - deR: 100 - } - ] -} - -// 自动效果:目标攻击力降低 30% -``` - -### 示例 2: 状态型 Debuff - 中毒 - -```typescript -// DBuff enum -export enum DBuff { - POISON = 16, // 新增:中毒 -} - -// 状态集合 -const stateDebuffSet = new Set([ - DBuff.POISON, // 只缓存,不影响属性 -]); - -// 技能使用 -6011: { - debuffs: [ - { - debuff: DBuff.POISON, - BType: BType.VALUE, - dev: 0, // 状态型可以为 0 - deC: 8, // 持续 8 秒 - deR: 70 // 70% 触发 - } - ] -} - -// 战斗系统检查 -if (checkState(targetHero, DBuff.POISON)) { - // 每秒损失血量 - targetHero.hp -= 5; -} -``` - ---- - -## 🔄 状态型 Debuff 的应用场景 - -- **控制类**:眩晕、冰冻、缠绕 -- **异常类**:中毒、流血、灼烧 -- **减益类**:沉默、禁疗、虚弱 -- **特殊**:任何需要在战斗系统检查的状态 - -状态型 debuff 不直接修改属性,而是作为标记,由战斗系统根据状态采取不同的行动。 - ---- - -## 📞 获取帮助 - -遇到问题检查: - -1. 是否正确区分了属性型和状态型 debuff? -2. 属性型 debuff 是否添加了映射? -3. 状态型 debuff 是否添加到了 stateDebuffSet? -4. 状态检查逻辑是否添加到战斗系统? - ---- - -**系统设计充分考虑了扩展性,添加新 buff/debuff 无需修改核心逻辑!** 🎉 diff --git a/assets/script/game/hero/BuffSystem_Guide.md b/assets/script/game/hero/BuffSystem_Guide.md deleted file mode 100644 index df7c212f..00000000 --- a/assets/script/game/hero/BuffSystem_Guide.md +++ /dev/null @@ -1,476 +0,0 @@ -# BUFF 系统完整使用指南 - -## 系统概述 - -HeroViewComp 中的 buff 系统是一套完整的属性增强/减弱管理体系,支持: -- **数值型 buff/debuff**:固定数值增减 -- **百分比型 buff/debuff**:基于基础属性的百分比增减 -- **持久型**:永久生效,直到主动移除 -- **临时型**:按时间递减,自动过期 - -## 架构设计 - -### 存储结构 - -```typescript -// 数值型 buff -V_BUFF: BuffConf[] // 持久型 -V_BUFFS: BuffConf[] // 临时型(含 remainTime) - -// 百分比型 buff -R_BUFF: BuffConf[] // 持久型 -R_BUFFS: BuffConf[] // 临时型(含 remainTime) - -// 数值型 debuff -V_DBUFF: DbuffConf[] // 持久型 -V_DBUFFS: DbuffConf[]// 临时型(含 remainTime) - -// 百分比型 debuff -R_DBUFF: DbuffConf[] // 持久型 -R_DBUFFS: DbuffConf[]// 临时型(含 remainTime) -``` - -### 初始值属性 - -以下属性拥有初始值,百分比 buff 基于这些值计算: -- `base_hp`: 基础血量 -- `base_mp`: 基础魔法值 -- `base_def`: 基础防御 -- `base_ap`: 基础攻击力 -- `base_map`: 基础魔法攻击 - -其他属性(CRITICAL, DODGE, AS 等)默认值为 0。 - -## 接口定义 - -### BuffConf(buff 配置) - -```typescript -export interface BuffConf { - buff: Attrs; // 影响的属性 - BType: BType; // VALUE(0)数值型 或 RATIO(1)百分比型 - buV: number; // 增益值 - buC: number; // 持续时间(0=持久,>0=临时) - buR: number; // 触发概率(1-100) -} -``` - -### DbuffConf(debuff 配置) - -```typescript -export interface DbuffConf { - debuff: DBuff; // debuff 类型 - BType: BType; // VALUE(0)数值型 或 RATIO(1)百分比型 - dev: number; // 减益值 - deC: number; // 持续时间(0=持久,>0=临时) - deR: number; // 触发概率(1-100) -} -``` - -## API 文档 - -### 1. 初始化系统 - -#### `initBuffsDebuffs(): void` - -**作用**:从 HeroInfo 读取英雄初始配置,初始化 buff/debuff 系统 - -**调用时机**:英雄加载时(在 Hero.hero_init() 中自动调用) - -**示例**: -```typescript -// 自动调用,无需手动调用 -heroView.initBuffsDebuffs(); -``` - ---- - -### 2. 添加 Buff - -#### `addBuff(buffConf: BuffConf): void` - -**作用**:添加 buff 效果 - -**参数**: -- `buffConf`: BuffConf 对象 - -**自动行为**: -- 根据 BType 和 buC 自动分类存储 -- 立即重新计算 Attrs - -**示例**: - -```typescript -// 添加数值型持久 buff:+10 攻击力 -heroView.addBuff({ - buff: Attrs.AP, - BType: BType.VALUE, - buV: 10, - buC: 0, // 0 表示持久 - buR: 100 -}); - -// 添加百分比型临时 buff:+20% 防御,持续 5 秒 -heroView.addBuff({ - buff: Attrs.DEF, - BType: BType.RATIO, - buV: 20, - buC: 5, // 5 秒后过期 - buR: 100 -}); - -// 从技能配置添加(来自 SkillSet) -const skillBuff: BuffConf = { - buff: Attrs.CRITICAL, - BType: BType.VALUE, - buV: 25, // +25% 暴击率 - buC: 3, // 持续 3 秒 - buR: 100 -}; -heroView.addBuff(skillBuff); -``` - ---- - -### 3. 添加 Debuff - -#### `addDebuff(dbuffConf: DbuffConf): void` - -**作用**:添加 debuff 效果 - -**参数**: -- `dbuffConf`: DbuffConf 对象 - -**自动行为**: -- DBuff 类型自动映射到对应 Attrs -- 根据 BType 和 deC 自动分类存储 -- 立即重新计算 Attrs - -**DBuff 映射表**: - -| DBuff 类型 | 对应 Attrs | 说明 | -|-----------|-----------|------| -| STUN | CON_RES | 眩晕 | -| SLOW | AS | 减速(攻击速度) | -| FROST | ICE_RES | 冰冻抗性 | -| BURN | DEF | 易伤(降低防御) | -| DEAS | AS | 减少 CD(攻击速度) | -| DEHP | HP_MAX | 降低最大血量 | -| DEAP | AP | 降低攻击力 | -| DEMGP | MAP | 降低魔法攻击力 | -| BACK | KNOCKBACK | 击退概率 | -| CRITICAL | CRITICAL | 降低暴击率 | -| CRIT_DAMAGE | CRITICAL_DMG | 降低暴击伤害 | -| DODGE | DODGE | 降低闪避 | - -**示例**: - -```typescript -// 眩晕:持久型,无数值影响 -heroView.addDebuff({ - debuff: DBuff.STUN, - BType: BType.VALUE, - dev: 0, - deC: 0, // 持久 - deR: 100 -}); - -// 减速:临时型,-30% 攻击速度,持续 3 秒 -heroView.addDebuff({ - debuff: DBuff.SLOW, - BType: BType.RATIO, - dev: 30, // 减少 30% - deC: 3, // 3 秒后过期 - deR: 100 -}); - -// 易伤:数值型,-5 防御,持久 -heroView.addDebuff({ - debuff: DBuff.BURN, - BType: BType.VALUE, - dev: 5, - deC: 0, - deR: 100 -}); -``` - ---- - -### 4. 移除 Buff - -#### `removeBuff(buffType: Attrs, isTemporary?: boolean): boolean` - -**作用**:移除指定属性的 buff - -**参数**: -- `buffType`: 属性类型 -- `isTemporary`: 是否移除临时型(默认 false=持久型) - -**返回值**:是否成功移除 - -**自动行为**: -- 移除成功后自动重新计算 Attrs - -**示例**: - -```typescript -// 移除持久 AP buff -heroView.removeBuff(Attrs.AP, false); - -// 移除临时 DEF buff -heroView.removeBuff(Attrs.DEF, true); -``` - ---- - -### 5. 移除 Debuff - -#### `removeDebuff(debuffType: DBuff, isTemporary?: boolean): boolean` - -**作用**:移除指定类型的 debuff - -**参数**: -- `debuffType`: DBuff 类型 -- `isTemporary`: 是否移除临时型 - -**返回值**:是否成功移除 - -**示例**: - -```typescript -// 移除持久眩晕 -heroView.removeDebuff(DBuff.STUN, false); - -// 移除临时减速 -heroView.removeDebuff(DBuff.SLOW, true); -``` - ---- - -### 6. 属性重新计算 - -#### `recalculateAttrs(): void` - -**作用**:重新计算所有角色属性 - -**调用时机**: -- 自动在 addBuff/addDebuff/removeBuff/removeDebuff 时调用 -- 自动在临时 buff/debuff 过期时调用 -- 无需手动调用 - -**计算流程**: -1. 重置为基础值 -2. 应用数值型 buff(持久 + 临时) -3. 应用百分比型 buff(持久 + 临时) -4. 应用数值型 debuff(持久 + 临时) -5. 应用百分比型 debuff(持久 + 临时) -6. Clamp 关键属性(防止负数) - -**百分比计算示例**: -``` -基础攻击力: 100 -+20% buff: 100 * 1.2 = 120 --10% debuff: 120 * 0.9 = 108 -``` - ---- - -### 7. 更新临时效果 - -#### `updateTemporaryBuffsDebuffs(dt: number): void` - -**作用**:更新临时 buff/debuff 的剩余时间 - -**参数**: -- `dt`: 时间增量(秒) - -**调用时机**: -- 自动在 update() 中每帧调用 -- 无需手动调用 - -**自动行为**: -- 减少所有临时 buff/debuff 的 remainTime -- 移除 remainTime <= 0 的效果 -- 移除后自动重新计算 Attrs - ---- - -### 8. 查询 Buff 状态 - -#### `getBuffValue(attrType: Attrs): number` - -**作用**:获取指定属性的所有 buff 总值 - -**返回值**:buff 总值 - -**示例**: -```typescript -const apBuff = heroView.getBuffValue(Attrs.AP); -console.log("攻击力 buff 总和:", apBuff); -``` - ---- - -### 9. 查询 Debuff 状态 - -#### `getDebuffValue(debuffType: DBuff): number` - -**作用**:获取指定 debuff 类型的所有 debuff 总值 - -**返回值**:debuff 总值 - -**示例**: -```typescript -const stunDebuff = heroView.getDebuffValue(DBuff.STUN); -console.log("眩晕等级:", stunDebuff); -``` - ---- - -### 10. 检查 Debuff 存在 - -#### `hasDebuff(debuffType: DBuff): boolean` - -**作用**:检查是否存在指定的 debuff - -**返回值**:是否存在 - -**示例**: -```typescript -if (heroView.hasDebuff(DBuff.STUN)) { - console.log("角色已眩晕"); -} -``` - ---- - -## 完整使用示例 - -### 场景 1:技能施加 Buff - -```typescript -// 在 SkillEnt.ts 或相关技能脚本中 -const skillConf = SkillSet[skillId]; - -// 遍历技能的 buff 配置 -for (const buffConf of skillConf.buffs) { - targetHero.HeroView.addBuff(buffConf); -} - -// 遍历技能的 debuff 配置 -for (const dbuffConf of skillConf.debuffs) { - targetHero.HeroView.addDebuff(dbuffConf); -} -``` - -### 场景 2:英雄初始化 - -```typescript -// 在 Hero.ts 中(已自动调用) -hero_init(uuid: number, node: Node) { - var hv = node.getComponent(HeroViewComp)!; - let hero = HeroInfo[uuid]; - - // ... 其他初始化 ... - - // 自动调用初始化 buff - hv.initBuffsDebuffs(); - return hv; -} -``` - -### 场景 3:属性查询 - -```typescript -// 获取最终计算后的属性值 -const finalAP = heroView.Attrs[Attrs.AP]; -const finalDEF = heroView.Attrs[Attrs.DEF]; - -// 获取 buff 总值 -const apBuff = heroView.getBuffValue(Attrs.AP); -const defBuff = heroView.getBuffValue(Attrs.DEF); - -// 检查 debuff 状态 -if (heroView.hasDebuff(DBuff.STUN)) { - // 眩晕状态下无法行动 -} -``` - ---- - -## 关键设计原则 - -### 1. 兼容式修改 - -- 所有方法名保持不变,易于集成 -- 无痛替换原有的 buff 系统 - -### 2. 自动化计算 - -- 每次 buff 变动自动重新计算 -- 无需手动更新属性 - -### 3. 灵活的时间管理 - -- 持久型(buC=0)永久生效 -- 临时型(buC>0)自动按秒递减 -- 过期自动移除和重新计算 - -### 4. 基础值保护 - -- 基础属性独立存储 -- 百分比计算基于原始基础值 -- 不会出现多次计算的偏差 - -### 5. 属性限制 - -- HP_MAX, MP_MAX 最少为 1 -- 百分比属性(CRITICAL, DODGE)限制在 0-100 -- 防止异常数值 - ---- - -## 常见问题 - -**Q: 如何区分持久和临时?** -A: buC=0 是持久,buC>0 是临时(表示秒数)。 - -**Q: 百分比如何计算?** -A: 基于基础属性乘以百分比。例:base_ap=100,+20% → 100*1.2=120 - -**Q: 多个相同 buff 是否叠加?** -A: 会叠加。每个 addBuff 调用都会添加新条目。 - -**Q: 如何清除所有 buff?** -A: 调用 initBuffsDebuffs() 重新初始化,或手动清空缓存数组。 - ---- - -## 扩展与维护 - -### 添加新 Buff - -只需在 SkillSet.ts 的技能配置中添加即可,无需修改 HeroViewComp.ts: - -```typescript -buffs: [ - { buff: Attrs.AP, BType: BType.VALUE, buV: 10, buC: 0, buR: 100 } -] -``` - -### 添加新 Debuff - -1. 在 SkillSet.ts 的 DBuff enum 中添加新类型 -2. 在 HeroViewComp.ts 的 `getAttrFieldFromDebuff()` 中添加映射 -3. 在技能配置中使用 - -详见 **BuffSystem_Extension.md** 完整扩展指南。 - -### 系统的扩展特性 - -✅ 支持无限数量的 buff/debuff -✅ 支持新增 Attrs 属性 -✅ 支持新增 DBuff 类型 -✅ 自动处理持久/临时管理 -✅ 自动处理属性计算 -✅ 编译检查确保类型安全 diff --git a/assets/script/game/hero/BuffSystem_Implementation.md b/assets/script/game/hero/BuffSystem_Implementation.md deleted file mode 100644 index a9232a04..00000000 --- a/assets/script/game/hero/BuffSystem_Implementation.md +++ /dev/null @@ -1,277 +0,0 @@ -# Buff 系统实现总结 - -## 修改的文件 - -### 1. `HeroViewComp.ts` (主要实现) - -#### 导入部分更新 -```typescript -import { ..., BType, BuffConf, DbuffConf } from "../common/config/SkillSet"; -``` - -#### 新增方法(精简版) - -| 方法名 | 功能 | 访问修饰符 | -|------|------|---------| -| `initBuffsDebuffs()` | 初始化 buff/debuff 系统 | public | -| `addBuff(buffConf)` | 添加 buff 效果 | public | -| `addDebuff(dbuffConf)` | 添加 debuff 效果 | public | -| `getAttrFieldFromDebuff()` | 获取 debuff 对应属性 | private | -| `recalculateAttrs()` | 重新计算属性 | public | -| `applyValueBuffs()` | 应用数值型 buff | private | -| `applyRatioBuffs()` | 应用百分比型 buff | private | -| `applyValueDebuffs()` | 应用数值型 debuff | private | -| `applyRatioDebuffs()` | 应用百分比型 debuff | private | -| `clampAttrs()` | 限制属性值范围 | private | -| `updateTemporaryBuffsDebuffs()` | 更新临时 buff/debuff | public | - -**删除的方法**(持久性不需要移除): -- ~~removeBuff()~~ -- ~~removeDebuff()~~ -- ~~getBuffValue()~~ -- ~~getDebuffValue()~~ -- ~~hasDebuff()~~ - -#### 关键特性 -- 百分比属性限制在 0-85%(CRITICAL, DODGE, HIT) -- 持久型 buff/debuff 永久生效,不支持移除 -- 临时型自动过期,自动重新计算 - -#### update() 方法更新 -添加了对 `updateTemporaryBuffsDebuffs(dt)` 的调用,以处理临时 buff/debuff 的过期。 - ---- - -### 2. `Hero.ts` (初始化调用) - -#### hero_init() 方法更新 -在方法末尾添加了 `hv.initBuffsDebuffs()` 调用,在英雄初始化时自动初始化 buff 系统。 - ---- - -## 核心设计 - -### 存储结构 - -``` -buffPerm/buffTemp Buff 缓存(持久/临时) - ├─ value 数值型 - └─ ratio 百分比型 - -debuffPerm/debuffTemp Debuff 缓存(持久/临时) - ├─ value 数值型 - └─ ratio 百分比型 -``` - -### 优势 - -- **更清晰**:按持久/临时和数值/百分比二维组织 -- **更简洁**:从 8 个数组变为 4 个对象 -- **更易扩展**:新增字段时直接添加到对应对象 -- **更易查询**:通过对象结构自文档化 - -### 设计原则 - -1. **持久性不可移除** - - 持久型 buff/debuff 一旦添加就永久生效 - - 无需提供移除接口,简化代码 - -2. **临时自动过期** - - 临时型自动在每帧更新时递减 - - 过期自动移除和重新计算属性 - -3. **百分比上限 85%** - - 防止百分比属性过高导致游戏失衡 - - 暴击率、闪避、命中等限制在 0-85% - -### 计算流程 - -``` -1. 重置为基础值 (base_hp, base_mp, base_def, base_ap, base_map) - ↓ -2. 应用数值型 buff (V_BUFF + V_BUFFS) - ↓ -3. 应用百分比型 buff (R_BUFF + R_BUFFS) - ↓ -4. 应用数值型 debuff (V_DBUFF + V_DBUFFS) - ↓ -5. 应用百分比型 debuff (R_DBUFF + R_DBUFFS) - ↓ -6. 限制属性值范围 (clampAttrs) - - HP_MAX, MP_MAX 最少 1 - - 百分比属性限制 0-85% -``` - ---- - -## 集成要点 - -### 1. 技能系统集成 - -在技能释放时调用: -```typescript -// 应用技能的 buff -for (const buffConf of skillConf.buffs) { - targetHeroView.addBuff(buffConf); -} - -// 应用技能的 debuff -for (const dbuffConf of skillConf.debuffs) { - targetHeroView.addDebuff(dbuffConf); -} -``` - -### 2. SkillSet 配置 - -SkillSet 中的每个技能可配置 buff 和 debuff: -```typescript -{ - uuid: 6001, - // ... 其他配置 ... - buffs: [ - { buff: Attrs.AP, BType: BType.VALUE, buV: 10, buC: 0, buR: 100 } - ], - debuffs: [ - { debuff: DBuff.STUN, BType: BType.VALUE, dev: 0, deC: 3, deR: 50 } - ] -} -``` - -### 3. HeroInfo 配置 - -HeroInfo 中可配置英雄初始 buff/debuff: -```typescript -5001: { - // ... 其他配置 ... - buff: [ - { buff: Attrs.CRITICAL, BType: BType.VALUE, buV: 15, buC: 0, buR: 100 } - ], - debuff: [] -} -``` - ---- - -## 属性初始值保护 - -**有初始值的属性**(基础属性): -- `base_hp`: 基础血量 -- `base_mp`: 基础魔法值 -- `base_def`: 基础防御 -- `base_ap`: 基础攻击力 -- `base_map`: 基础魔法攻击力 - -**百分比 buff/debuff 基于这些初始值计算**,确保多次计算不会产生偏差。 - -**无初始值属性**(默认为 0,限制 0-85%): -- CRITICAL, DODGE, HIT, WFUNY, AS, REFLICT, LIFESTEAL, KNOCKBACK, CON_RES, ICE_RES, FIRE_RES, WIND_RES, ICE_POWER, FIRE_POWER, WIND_POWER, SHIELD_UP, BUFF_UP, DBUFF_UP, DIS - ---- - -## DBuff 到 Attrs 的映射 - -```typescript -const debuffAttrMap = { - [DBuff.STUN]: Attrs.CON_RES, // 眩晕 -> 控制抗性 - [DBuff.SLOW]: Attrs.AS, // 减速 -> 攻击速度 - [DBuff.FROST]: Attrs.ICE_RES, // 冰冻 -> 冰冻抗性 - [DBuff.BURN]: Attrs.DEF, // 易伤 -> 防御 - [DBuff.DEAS]: Attrs.AS, // 减cd -> 攻击速度 - [DBuff.DEHP]: Attrs.HP_MAX, // 减hp -> 最大生命值 - [DBuff.DEAP]: Attrs.AP, // 减atk -> 攻击力 - [DBuff.DEMGP]: Attrs.MAP, // 减魔法 -> 魔法攻击力 - [DBuff.BACK]: Attrs.KNOCKBACK, // 击退 -> 击退概率 - [DBuff.CRITICAL]: Attrs.CRITICAL, // -暴击率 -> 暴击率 - [DBuff.CRIT_DAMAGE]: Attrs.CRITICAL_DMG, // -暴击伤害 -> 暴击伤害 - [DBuff.DODGE]: Attrs.DODGE, // -闪避 -> 闪避 -}; -``` - ---- - -## 性能考虑 - -### 优化点 -1. **按需重新计算**:只在 buff 变动时计算,不是每帧 -2. **缓存分离**:分离存储持久和临时,便于处理 -3. **类型分组**:数值型和百分比型分离,计算方式不同 - -### 缓存行为 -- 临时 buff/debuff 每帧检查一次(在 update 中) -- 过期移除时批量重新计算一次 - ---- - -## 使用模板 - -### 模板 1:技能中应用 Buff - -```typescript -// 在 SkillEnt.ts 或 SkillConCom.ts 中 -applySkillEffect(targetHero: Hero, skillId: number) { - const skillConf = SkillSet[skillId]; - const heroView = targetHero.get(HeroViewComp); - - // 应用所有 buff - for (const buff of skillConf.buffs) { - heroView.addBuff(buff); - } - - // 应用所有 debuff - for (const debuff of skillConf.debuffs) { - heroView.addDebuff(debuff); - } -} -``` - -### 模板 2:查询属性值 - -```typescript -// 获取最终计算的属性 -const finalAP = heroView.Attrs[Attrs.AP]; -const finalDEF = heroView.Attrs[Attrs.DEF]; -``` - ---- - -## 兼容性说明 - -✅ **完全兼容** -- 所有新增方法都是 public,不改变现有接口 -- 自动初始化,无需修改现有代码 -- 可逐步集成,不需一次性改造全部 - -⚠️ **注意事项** -- 临时 buff/debuff 需在配置中指定持续时间 -- 百分比计算基于基础值,不会重复计算 -- 属性值有范围限制,防止异常 -- 持久型 buff/debuff 无法移除 - ---- - -## 验证清单 - -- [x] 导入 BType, BuffConf, DbuffConf -- [x] 添加 buff/debuff 缓存字段 -- [x] 实现初始化方法 -- [x] 实现添加 buff 方法 -- [x] 实现添加 debuff 方法 -- [x] 实现属性计算方法 -- [x] 实现临时效果更新 -- [x] 在 update 中调用更新 -- [x] 在 Hero.hero_init 中调用初始化 -- [x] 编译通过,无错误 -- [x] 精简不必要的方法 -- [x] 百分比属性限制 0-85% - ---- - -## 相关文件 - -- 📄 HeroViewComp.ts - 主实现文件 -- 📄 Hero.ts - 初始化调用 -- 📄 SkillSet.ts - BuffConf/DbuffConf 定义 -- 📄 heroSet.ts - HeroInfo 定义 -- 📄 BuffSystem_Guide.md - 详细使用指南 -- 📄 BuffSystem_QuickRef.md - 快速参考 -- 📄 BuffSystem_Implementation.md - 本文件 diff --git a/assets/script/game/hero/BuffSystem_Maintainability.md b/assets/script/game/hero/BuffSystem_Maintainability.md deleted file mode 100644 index 0866764f..00000000 --- a/assets/script/game/hero/BuffSystem_Maintainability.md +++ /dev/null @@ -1,404 +0,0 @@ -# Buff 系统可维护性指南 - -## 🎯 系统设计目标 - -本 buff 系统的核心设计目标是: -- ✅ **易于使用**:简单直观的 API -- ✅ **易于扩展**:添加新 buff/debuff 无需修改核心代码 -- ✅ **易于维护**:清晰的代码结构和注释 -- ✅ **类型安全**:TypeScript 完全类型检查 -- ✅ **性能优化**:按需计算,无冗余处理 - ---- - -## 📊 系统架构 - -### 核心层次 - -``` -配置层 (SkillSet.ts, HeroInfo) - ↓ -应用层 (addBuff, addDebuff) - ↓ -缓存层 (buffPerm, buffTemp, debuffPerm, debuffTemp) - ├─ value (数值型) - └─ ratio (百分比型) - ↓ -计算层 (recalculateAttrs) - ↓ -属性层 (Attrs[]) -``` - -### 模块职责 - -| 模块 | 职责 | 修改频率 | -|------|------|--------| -| SkillSet.ts | buff/debuff 配置 | 经常(添加新技能) | -| HeroInfo | 英雄初始配置 | 不常 | -| HeroViewComp.ts | buff 系统核心 | 很少(修复 bug) | -| Hero.ts | 初始化调用 | 基本不变 | - ---- - -## 🔧 扩展点分析 - -### 1. 添加新 Buff(✅ 最容易) - -**修改位置**:SkillSet.ts 技能配置 - -**风险等级**:⭐️ 无风险 - -```typescript -// 只需添加到 buffs 数组 -buffs: [ - { buff: Attrs.AP, BType: BType.VALUE, buV: 10, buC: 0, buR: 100 } -] -// 系统自动处理一切 -``` - -**验证**: -- [x] 选择有效的 Attrs -- [x] 设置有效的 BType -- [x] 测试属性是否正确应用 - ---- - -### 2. 添加新的 Debuff 类型(✅ 很容易) - -**修改位置**: -1. SkillSet.ts - DBuff enum -2. SkillSet.ts - getAttrFieldFromDebuff() 映射表 -3. SkillSet.ts - 技能配置 - -**风险等级**:⭐️⭐️ 低风险 - -```typescript -// 步骤 1: 添加类型 -export enum DBuff { - POISON = 20, // 新增 -} - -// 步骤 2: 在 SkillSet.ts 中添加映射 -export const getAttrFieldFromDebuff = (debuffType: DBuff): number => { - const debuffAttrMap: Record = { - // ... 现有映射 ... - [DBuff.POISON]: Attrs.DEF, // 中毒降低防御 - }; - // ... 其他代码 ... -} - -// 步骤 3: 使用 -debuffs: [ - { debuff: DBuff.POISON, BType: BType.VALUE, dev: 10, deC: 6, deR: 80 } -] -``` - -**验证**: -- [x] DBuff 类型无冲突 -- [x] 映射到有效的 Attrs -- [x] 测试效果是否正确 - ---- - -### 3. 修改核心计算逻辑(⚠️ 非常困难) - -**修改位置**:HeroViewComp.ts - recalculateAttrs() - -**风险等级**:⭐️⭐️⭐️⭐️⭐️ 高风险 - -**不建议修改的原因**: -- 计算流程已经优化 -- 修改可能导致属性计算错误 -- 影响所有 buff/debuff 效果 - -**如需修改**: -- 先写单元测试 -- 验证各种 buff/debuff 组合 -- 检查边界条件(最小值、最大值) - ---- - -## 📝 最佳实践 - -### 1. 添加新属性 - -如果需要添加新的角色属性: - -```typescript -// 1. 在 Attrs enum 中添加 -export enum Attrs { - // ... 现有属性 ... - NEW_ATTR = 27, // 新增 -} - -// 2. 在 getAttrs() 中初始化为 0 -export const getAttrs = () => { - let reAttrs = {}; - // ... 现有初始化 ... - reAttrs[27] = 0; // 新属性初始化 - return reAttrs; -}; - -// 3. 如果有初始值,在 recalculateAttrs() 中处理 -this.Attrs[Attrs.NEW_ATTR] = this.base_new_attr || 0; - -// 4. 如果需要限制范围,在 clampAttrs() 中添加 -this.Attrs[Attrs.NEW_ATTR] = Math.max(min, Math.min(max, this.Attrs[Attrs.NEW_ATTR])); - -// 5. 在技能配置中使用 -buffs: [ - { buff: Attrs.NEW_ATTR, BType: BType.VALUE, buV: 5, buC: 0, buR: 100 } -] -``` - ---- - -### 2. 修改 Buff 计算方式 - -如果需要修改百分比计算基数: - -```typescript -// 当前:百分比基于基础属性 -const baseVal = baseValues[buff.buff] || this.Attrs[buff.buff]; -this.Attrs[buff.buff] += Math.floor(baseVal * (buff.buV / 100)); - -// 可选:基于当前属性 -const currentVal = this.Attrs[buff.buff]; -this.Attrs[buff.buff] += Math.floor(currentVal * (buff.buV / 100)); - -// 可选:自定义计算 -// ... 自定义逻辑 ... -``` - ---- - -### 3. 添加条件 Buff - -如果需要条件触发的 buff(例:仅在特定情况下生效): - -```typescript -// 方案 1:在 addBuff 前判断 -if (someCondition) { - heroView.addBuff(buffConf); -} - -// 方案 2:扩展 BuffConf 接口(需要修改 SkillSet.ts) -interface BuffConfWithCondition extends BuffConf { - condition?: () => boolean; -} - -// 方案 3:在技能中判断 -const skillBuff = skillConf.buffs[0]; -if (shouldApplyBuff(skillBuff)) { - heroView.addBuff(skillBuff); -} -``` - ---- - -## 🧪 测试清单 - -### 单元测试(推荐) - -```typescript -describe('Buff System', () => { - let hero: HeroViewComp; - - beforeEach(() => { - hero = new HeroViewComp(); - hero.initBuffsDebuffs(); - }); - - test('数值型 buff 应用', () => { - const before = hero.Attrs[Attrs.AP]; - hero.addBuff({ - buff: Attrs.AP, - BType: BType.VALUE, - buV: 10, - buC: 0, - buR: 100 - }); - expect(hero.Attrs[Attrs.AP]).toBe(before + 10); - }); - - test('百分比型 buff 应用', () => { - const baseAP = hero.base_ap; - hero.addBuff({ - buff: Attrs.AP, - BType: BType.RATIO, - buV: 20, - buC: 0, - buR: 100 - }); - const expected = Math.floor(baseAP * 1.2); - expect(hero.Attrs[Attrs.AP]).toBe(expected); - }); - - test('临时 buff 应过期', () => { - hero.addBuff({ - buff: Attrs.AP, - BType: BType.VALUE, - buV: 10, - buC: 1 // 1 秒 - }); - - hero.updateTemporaryBuffsDebuffs(1.1); // 超过 1 秒 - - // buff 应被移除,属性恢复 - expect(hero.Attrs[Attrs.AP]).toBe(hero.base_ap); - }); - - test('debuff 正确映射', () => { - hero.addDebuff({ - debuff: DBuff.SLOW, - BType: BType.RATIO, - dev: 50, - deC: 0, - deR: 100 - }); - - // SLOW 应映射到 Attrs.AS - const expected = Math.floor(hero.base_ap * 0.5); - expect(hero.Attrs[Attrs.AS]).toBeLessThan(100); - }); -}); -``` - -### 集成测试 - -```typescript -// 测试完整的技能应用流程 -test('技能应用完整流程', () => { - const skillId = 6001; - const skill = SkillSet[skillId]; - - const hero = new HeroViewComp(); - hero.initBuffsDebuffs(); - - // 应用技能 - for (const buff of skill.buffs) { - hero.addBuff(buff); - } - for (const debuff of skill.debuffs) { - hero.addDebuff(debuff); - } - - // 验证属性正确应用 - // ... - - // 验证临时效果正确过期 - // ... -}); -``` - ---- - -## 🚀 性能优化建议 - -### 当前优化 - -- [x] 按需计算(不是每帧) -- [x] 缓存分离(持久/临时) -- [x] 类型分离(数值/百分比) -- [x] 批量处理(临时过期时一次重算) - -### 未来优化方向 - -1. **Buff 去重** - - 相同 buff 只计算一次 - -2. **缓存预热** - - 英雄加载时预计算 - -3. **异步处理** - - 大量 buff 变动时异步计算 - ---- - -## 📋 维护检查清单 - -### 月度检查 - -- [ ] 检查 console 是否有 buff 相关的 warning -- [ ] 验证新增技能的 buff/debuff 配置 -- [ ] 检查属性计算是否正确 - -### 季度检查 - -- [ ] 审查 DBuff 映射表是否完整 -- [ ] 检查是否有重复或冲突的 buff/debuff -- [ ] 验证系统性能(buff 数量、计算次数) - -### 年度检查 - -- [ ] 评估系统是否需要重构 -- [ ] 考虑是否需要添加新的系统特性 -- [ ] 检查是否有安全漏洞 - ---- - -## 🐛 常见问题排查 - -### 症状 1: Buff 没有效果 - -**排查步骤**: -1. 检查 Attrs 是否有效 → `console.log(Attrs.AP)` -2. 检查 BuffConf 是否正确 → `console.log(buffConf)` -3. 检查 addBuff 是否调用 → 添加 log -4. 检查 recalculateAttrs 是否执行 → 添加 log -5. 检查最终属性值 → `console.log(heroView.Attrs)` - -### 症状 2: Debuff 报错 - -**排查步骤**: -1. 检查 console 是否有 warning -2. 查看 DBuff 是否在 enum 中定义 -3. 查看是否在 debuffAttrMap 中有映射 -4. 验证映射的 Attrs 是否有效 - -### 症状 3: 属性值异常 - -**排查步骤**: -1. 检查基础属性是否正确初始化 -2. 检查百分比计算公式 -3. 检查 clampAttrs 中的限制是否合理 - ---- - -## 📞 获取技术支持 - -如果遇到问题: - -1. **检查日志** - - 查看 console 是否有 warning - - 检查 HeroViewComp 的 log - -2. **查阅文档** - - BuffSystem_QuickRef.md - 快速查找 - - BuffSystem_Guide.md - 详细说明 - - BuffSystem_Extension.md - 扩展方法 - -3. **查看源码** - - HeroViewComp.ts - 核心实现 - - 代码中的详细注释 - -4. **调试技巧** - - 添加 console.log 追踪执行 - - 使用浏览器开发者工具 - - 逐步调试跟踪变量值 - ---- - -## 🏆 系统特点总结 - -| 特性 | 评级 | 说明 | -|------|------|------| -| 易用性 | ⭐⭐⭐⭐⭐ | 简单直观的 API | -| 可扩展性 | ⭐⭐⭐⭐⭐ | 添加新 buff/debuff 无需修改核心 | -| 可维护性 | ⭐⭐⭐⭐ | 清晰的结构,充分的注释 | -| 性能 | ⭐⭐⭐⭐ | 按需计算,高效处理 | -| 类型安全 | ⭐⭐⭐⭐⭐ | 完全 TypeScript 类型检查 | - ---- - -**系统已准备好长期维护和扩展!** 🎉 diff --git a/assets/script/game/hero/BuffSystem_QuickRef.md b/assets/script/game/hero/BuffSystem_QuickRef.md deleted file mode 100644 index 9debbba9..00000000 --- a/assets/script/game/hero/BuffSystem_QuickRef.md +++ /dev/null @@ -1,249 +0,0 @@ -# Buff 系统 - 快速参考卡 - -## 🎯 核心概念 - -| 概念 | 说明 | -|------|------| -| **Buff** | 增益效果(增加属性) | -| **Debuff** | 减益效果(降低属性/能力) | -| **持久** | 永不过期(buC=0 或 deC=0) | -| **临时** | 按秒递减(buC>0 或 deC>0) | -| **数值型** | 固定数值增减(BType.VALUE=0) | -| **百分比型** | 基于基础属性的百分比(BType.RATIO=1) | - ---- - -## 🚀 快速开始 - -### 1️⃣ 添加数值型 Buff - -```typescript -heroView.addBuff({ - buff: Attrs.AP, // 增加攻击力 - BType: BType.VALUE, // 数值型 - buV: 10, // +10 - buC: 0, // 永久 - buR: 100 // 100% 触发 -}); -``` - -### 2️⃣ 添加临时 Buff - -```typescript -heroView.addBuff({ - buff: Attrs.DEF, // 增加防御 - BType: BType.RATIO, // 百分比型 - buV: 20, // +20% - buC: 5, // 持续 5 秒 - buR: 100 -}); -``` - -### 3️⃣ 添加 Debuff - -```typescript -heroView.addDebuff({ - debuff: DBuff.STUN, // 眩晕 - BType: BType.VALUE, - dev: 0, - deC: 3, // 持续 3 秒 - deR: 100 -}); -``` - ---- - -## 📋 属性类型 (Attrs) - -### 基础属性(有初始值) -```typescript -HP_MAX // 最大生命 -MP_MAX // 最大魔法 -DEF // 防御 -AP // 攻击力 -MAP // 魔法攻击力 -SHIELD_MAX // 护盾值 -``` - -### 专项属性(无初始值,限制值 0-85%) -```typescript -CRITICAL // 暴击率 -CRITICAL_DMG // 暴击伤害 -DODGE // 闪避 -HIT // 命中 -AS // 攻击速度 -KNOCKBACK // 击退概率 -CON_RES // 控制抗性 -ICE_RES // 冰冻抗性 -FIRE_RES // 火抗性 -// ... 等等 -``` - ---- - -## ⚡ Debuff 类型 (DBuff) - -```typescript -STUN → Attrs.CON_RES // 眩晕 -SLOW → Attrs.AS // 减速 -FROST → Attrs.ICE_RES // 冰冻 -BURN → Attrs.DEF // 易伤 -DEAS → Attrs.AS // 减CD -DEHP → Attrs.HP_MAX // 减血量 -DEAP → Attrs.AP // 减攻击 -DEMGP → Attrs.MAP // 减魔法 -BACK → Attrs.KNOCKBACK // 击退 -CRITICAL → Attrs.CRITICAL // 降暴击 -CRIT_DAMAGE → Attrs.CRITICAL_DMG // 降爆伤 -DODGE → Attrs.DODGE // 降闪避 -``` - ---- - -## 📊 计算示例 - -### 数值型 Buff -``` -基础 AP: 100 -+Buff: +10 -结果: 110 -``` - -### 百分比型 Buff -``` -基础 AP: 100 -+20% Buff: 100 * 1.2 = 120 -``` - -### 混合计算 -``` -基础 AP: 100 -+20% Buff: 100 * 1.2 = 120 -+10 Buff: 120 + 10 = 130 --30% Debuff: 130 * 0.7 = 91 -``` - ---- - -## 🔧 API 一览表 - -| 方法 | 功能 | -|------|------| -| `addBuff(conf)` | 添加 buff | -| `addDebuff(conf)` | 添加 debuff(自动区分属性型/状态型) | -| `hasState(type)` | **检查状态型 debuff(最简洁)** ⭐ | -| `getDebuff(type)` | 获取属性型 debuff 对象 | -| `hasDebuff(type)` | 检查属性型 debuff 存在 | -| `getBuff(type)` | 获取 buff 对象 | -| `hasBuff(type)` | 检查 buff 存在 | - ---- - -## 💾 缓存结构 & 访问方式 - -### 状态型 Debuff(最简洁)⭐ - -```typescript -// 使用 Set 存储,O(1) 快速判断 -heroView.hasState(DBuff.STUN) // ✅ 最推荐 -heroView.stateDebuffTemp.has(DBuff.STUN) // 直接访问 -``` - -### 属性型 Buff & Debuff - -```typescript -// 使用 Map 存储,支持对象访问 -heroView.hasBuff(Attrs.AP) // 检查 buff -heroView.getBuff(Attrs.AP) // 获取 buff -heroView.hasDebuff(DBuff.SLOW) // 检查 debuff -heroView.getDebuff(DBuff.SLOW) // 获取 debuff -``` - -### 缓存结构一览 - -``` -buffPerm/buffTemp - ├─ value: Map - └─ ratio: Map - -debuffPerm/debuffTemp(属性型) - ├─ value: Map - └─ ratio: Map - -stateDebuffPerm/stateDebuffTemp(状态型) - └─ Set ← 最简洁的访问 -``` - ---- - -## ✅ 使用检查清单 - -- [ ] 导入 `BType, BuffConf, DbuffConf` -- [ ] 在 SkillSet 中配置 buff/debuff -- [ ] 技能释放时调用 `addBuff/addDebuff` -- [ ] 临时 buff/debuff 自动过期 -- [ ] 查询属性用 `Attrs[type]` - ---- - -## 🐛 常见错误 - -❌ **错误 1**: 混淆 buC 和 deC 的含义 -```typescript -buC: 0 // ✅ 正确:持久 -buC: 5 // ✅ 正确:5 秒临时 -``` - -❌ **错误 2**: DBuff 类型用错了 -```typescript -// ❌ 错误 -addDebuff({ debuff: Attrs.AP, ... }); - -// ✅ 正确 -addDebuff({ debuff: DBuff.DEAP, ... }); -``` - ---- - -## 🎮 实战示例 - -### 技能释放流程 -```typescript -// 1. 获取技能配置 -const skill = SkillSet[skillId]; - -// 2. 应用 buff -for (const buff of skill.buffs) { - heroView.addBuff(buff); -} - -// 3. 应用 debuff -for (const debuff of skill.debuffs) { - heroView.addDebuff(debuff); -} - -// 4. 属性自动重新计算! -``` - ---- - -## 📚 完整文档 - -- 📖 BuffSystem_Guide.md - 详细使用指南 -- 📋 BuffSystem_Implementation.md - 实现细节 -- 🎯 BuffSystem_QuickRef.md - 本快速参考 -- 🚀 BuffSystem_Extension.md - 扩展指南(如何添加新 buff/debuff) - ---- - -## 🎓 学习路径 - -1. **快速开始** ➜ 先看这个文件 -2. **详细学习** ➜ 阅读 BuffSystem_Guide.md -3. **深入理解** ➜ 查看 BuffSystem_Implementation.md -4. **需要扩展** ➜ 阅读 BuffSystem_Extension.md -5. **查看源码** ➜ 阅读 HeroViewComp.ts - ---- - -**💡 记住**:系统会**自动**计算属性,临时效果**自动过期**! diff --git a/assets/script/game/hero/HeroViewComp.ts b/assets/script/game/hero/HeroViewComp.ts index 2287570f..a65b37b4 100644 --- a/assets/script/game/hero/HeroViewComp.ts +++ b/assets/script/game/hero/HeroViewComp.ts @@ -17,62 +17,24 @@ const { ccclass, property } = _decorator; /** * ==================== BUFF 系统使用说明 ==================== * - * 1. 系统架构: - * - BUFF_V/BUFFS_V: 数值型 buff(持久/临时) - * - BUFF_R/BUFFS_R: 百分比型 buff(持久/临时) - * - DBUFF_V/DBUFFS_V: 数值型 debuff(持久/临时) - * - DBUFF_R/DBUFFS_R: 百分比型 debuff(持久/临时) + * 1. 系统架构? + * - BUFF_V/BUFFS_V: 数值型 buff(持?临时? + * - BUFF_R/BUFFS_R: 百分比型 buff(持?临时? + * - DBUFF_V/DBUFFS_V: 数值型 debuff(持?临时? + * - DBUFF_R/DBUFFS_R: 百分比型 debuff(持?临时? * - * 2. 初始化(在英雄加载时自动调用): - * - initBuffsDebuffs(): 从 HeroInfo 读取初始配置 + * 2. 智能覆盖规则? + * - 值更小:不添加(弱效果不覆盖强效果) + * - 值相同且临时:叠加时? + * - 值更大:更新为新值(临时则更新值和时间? * - * 3. 添加 buff(技能调用): - * const buffConf: BuffConf = { - * buff: Attrs.AP, // 增加攻击力 - * BType: BType.VALUE, // 数值型 - * buV: 10, // 增加值 - * buC: 0, // 持久(0=持久, >0=持续时间) - * buR: 100 // 触发概率(100%) - * }; - * heroView.addBuff(buffConf); - * - * 4. 添加 debuff(技能调用): - * const dbuffConf: DbuffConf = { - * debuff: DBuff.STUN, // 眩晕 - * BType: BType.VALUE, // 数值型 - * deV: 20, // 减少值 - * deC: 3, // 持续3秒 - * deR: 100 // 触发概率(100%) - * }; - * heroView.addDebuff(dbuffConf); - * - * 5. 百分比型示例: - * // 增加20%攻击力 - * heroView.addBuff({ - * buff: Attrs.AP, - * BType: BType.RATIO, // 百分比型 - * buV: 20, // 20% - * buC: 5, // 持续5秒 - * buR: 100 - * }); - * - * 6. 移除 buff/debuff: - * heroView.removeBuff(Attrs.AP, false); // 移除持久 AP buff - * heroView.removeDebuff(DBuff.STUN, true); // 移除临时眩晕 - * - * 7. 属性计算: - * - 每次 buff/debuff 变动时自动调用 recalculateAttrs() - * - 重新计算基础属性 + 所有 buff/debuff 的结果 - * - 临时 buff/debuff 在 update 中按时间递减 - * - * 8. 初始值属性: - * - base_hp, base_mp, base_def, base_ap, base_map 是初始值 - * - 百分比 buff/debuff 基于这些初始值计算 - * - 其他属性默认为 0,无初始值 + * 3. 性能优化? + * - 增量计算:添?删除时只重算受影响的属�? + * - 批量计算:initBuffsDebuffs() 中使?recalculateAttrs() 一次性计算所? */ /** 角色显示组件 */ -@ccclass('HeroViewComp') // 定义为 Cocos Creator 组件 -@ecs.register('HeroView', false) // 定义为 ECS 组件 +@ccclass('HeroViewComp') // 定义?Cocos Creator 组件 +@ecs.register('HeroView', false) // 定义?ECS 组件 export class HeroViewComp extends CCComp { BUFFCOMP:BuffComp=null! as: HeroSpine = null! @@ -81,7 +43,7 @@ export class HeroViewComp extends CCComp { hero_name : string = "hero"; lv:number =1; scale: number = 1; /** 角色阵营 1:hero -1 :mon */ - type: number = 0; /**角色类型 0近战-需要贴身 1远程-保持距离 2辅助 */ + type: number = 0; /**角色类型 0近战-需要贴?1远程-保持距离 2辅助 */ fac:number=0; //阵营 0:hero 1:monster box_group:number = BoxSet.HERO; is_dead:boolean = false; //是否摧毁 @@ -96,10 +58,10 @@ export class HeroViewComp extends CCComp { is_kalami:boolean =false; mp: number = 100; - hp: number = 100; /** 血量 */ - shield:number=0; //当前护甲值 -/** 基础属性 有初始值的基础属性,后续Attrs 属性计算时用到*/ - base_ap: number = 0; //基础攻击力 + hp: number = 100; /** 血?*/ + shield:number=0; //当前护甲? +/** 基础属�?有初始值的基础属�?后续Attrs 属性计算时用到*/ + base_ap: number = 0; //基础攻击? base_map: number = 0; base_def: number = 5; base_hp: number = 100; @@ -107,16 +69,17 @@ export class HeroViewComp extends CCComp { base_speed: number = 100; /** 角色移动速度 */ Attrs:any=[] - //数值型debuff - DBUFF_V:any[]=[] //持久 - DBUFF_R:any[]=[] //持久 - BUFF_V:any[]=[] //持久 - BUFF_R:any[]=[] //持久 + // Buff/Debuff 字典结构,通过属性索引直接访? + // 结构: { [attrIndex: number]: { value: number, remainTime?: number } } + DBUFF_V: Record = {} // 持久型数?debuff + DBUFF_R: Record = {} // 持久型百分比 debuff + BUFF_V: Record = {} // 持久型数?buff + BUFF_R: Record = {} // 持久型百分比 buff - DBUFFS_V:any[]=[] //临时 带时间 - DBUFFS_R:any[]=[] //临时 带时间 - BUFFS_V:any[]=[] //临时 带时间 - BUFFS_R:any[]=[] //临时 带时间 + DBUFFS_V: Record = {} // 临时型数?debuff + DBUFFS_R: Record = {} // 临时型百分比 debuff + BUFFS_V: Record = {} // 临时型数?buff + BUFFS_R: Record = {} // 临时型百分比 buff atk_count: number = 0; atked_count: number = 0; @@ -139,7 +102,7 @@ export class HeroViewComp extends CCComp { this.on(GameEvent.FightEnd,this.do_fight_end,this) const collider = this.node.getComponent(BoxCollider2D); this.scheduleOnce(()=>{ - if (collider) collider.enabled = true; // 先禁用 + if (collider) collider.enabled = true; // 先禁? },1) // let anm = this.node.getChildByName("anm") // anm.setScale(anm.scale.x*0.8,anm.scale.y*0.8); @@ -155,31 +118,47 @@ export class HeroViewComp extends CCComp { if(this.is_boss){ this.node.getChildByName("top").position=v3(this.node.position.x,this.node.position.y+100,0) } - /* 显示角色血量 */ + /* 显示角色血?*/ this.node.getChildByName("top").getChildByName("hp").active = true; this.BUFFCOMP.show_shield(this.shield,this.Attrs[Attrs.SHIELD_MAX]) } - // ==================== BUFF系统初始化 ==================== + // ==================== BUFF系统初始?==================== /** - * 初始化角色的 buff 和 debuff - * 从 HeroInfo 读取初始配置,建立属性系统 + * 初始化角色的 buff ?debuff + * ?HeroInfo 读取初始配置,建立属性系? */ initBuffsDebuffs() { + // 清空现有 buff/debuff + this.BUFF_V = {}; + this.BUFFS_V = {}; + this.BUFF_R = {}; + this.BUFFS_R = {}; + this.DBUFF_V = {}; + this.DBUFFS_V = {}; + this.DBUFF_R = {}; + this.DBUFFS_R = {}; // 获取英雄配置 const heroInfo = HeroInfo[this.hero_uuid]; if (!heroInfo) return; - // 清空现有 buff/debuff - this.BUFF_V = []; - this.BUFFS_V = []; - this.BUFF_R = []; - this.BUFFS_R = []; - this.DBUFF_V = []; - this.DBUFFS_V = []; - this.DBUFF_R = []; - this.DBUFFS_R = []; + // 1. 重置为基础? + this.Attrs[Attrs.HP_MAX] = this.base_hp; + this.Attrs[Attrs.MP_MAX] = this.base_mp; + this.Attrs[Attrs.DEF] = this.base_def; + this.Attrs[Attrs.AP] = this.base_ap; + this.Attrs[Attrs.MAP] = this.base_map; + this.Attrs[Attrs.SPEED] = this.base_speed; + this.Attrs[Attrs.SHIELD_MAX] = 0; // 护盾默认?0 + + // 2. 初始化其他属性(无初始值的? + for (const attrKey in this.Attrs) { + const attrIndex = parseInt(attrKey); + if(attrIndex !== Attrs.HP_MAX && attrIndex !== Attrs.MP_MAX && attrIndex !== Attrs.DEF && attrIndex !== Attrs.AP && attrIndex !== Attrs.MAP && attrIndex !== Attrs.SPEED) { + this.Attrs[attrIndex] = 0; + } + } // 加载初始 buff if (heroInfo.buff && heroInfo.buff.length > 0) { for (const buffConf of heroInfo.buff) { @@ -193,322 +172,280 @@ export class HeroViewComp extends CCComp { this.addDebuff(dbuffConf); } } - - // 重新计算所有属性 - this.recalculateAttrs(); } - // ==================== BUFF管理 ==================== /** - * 添加 buff 效果 - * @param buffConf buff 配置 (来自 SkillSet.BuffConf 或 heroSet.buff) + * 添加 buff 效果(智能覆盖) + * @param buffConf buff 配置 (来自 SkillSet.BuffConf ?heroSet.buff) + * + * 智能覆盖规则? + * 1. 值更小:不添? + * 2. 值相同且都是临时:叠加时? + * 3. 值更大:更新为新值(临时则更新值和时间? */ addBuff(buffConf: BuffConf) { - // 基于类型和持续时间分类存储 - if (buffConf.BType === BType.VALUE) { - // 数值型 buff - if (buffConf.buC === 0) { - // 持久型 - this.BUFF_V.push({...buffConf}); + const isValue = buffConf.BType === BType.VALUE; + const isPermanent = buffConf.time === 0; + const attrIndex = buffConf.buff; + + // 根据类型选择对应?buff 字典 + const permanentBuffs = isValue ? this.BUFF_V : this.BUFF_R; + const temporaryBuffs = isValue ? this.BUFFS_V : this.BUFFS_R; + + if (isPermanent) { + // 添加持久?buff + const existing = permanentBuffs[attrIndex]; + if (existing) { + // 值更小,不添? + if (buffConf.value <= existing.value) { + return; + } + // 值更大,更新 + existing.value = buffConf.value; } else { - // 临时型 - 添加剩余时间属性 - this.BUFFS_V.push({ - ...buffConf, - remainTime: buffConf.buC - }); + // 没有同类型,直接添加 + permanentBuffs[attrIndex] = { value: buffConf.value }; } } else { - // 百分比型 buff - if (buffConf.buC === 0) { - // 持久型 - this.BUFF_R.push({...buffConf}); + // 添加临时?buff + const existing = temporaryBuffs[attrIndex]; + if (existing) { + if (buffConf.value < existing.value) { + // 值更小,不添? + return; + } else if (buffConf.value === existing.value) { + // 值相同,叠加时间 + existing.remainTime += buffConf.time; + return; // 时间叠加不需要重算属? + } else { + // 值更大,更新值和时间 + existing.value = buffConf.value; + existing.remainTime = buffConf.time; + } } else { - // 临时型 - 添加剩余时间属性 - this.BUFFS_R.push({ - ...buffConf, - remainTime: buffConf.buC - }); + // 没有同类型,直接添加 + temporaryBuffs[attrIndex] = { + value: buffConf.value, + remainTime: buffConf.time + }; } } - // 立即重新计算属性 - this.recalculateAttrs(); + + // 只重新计算受影响的属? + this.recalculateSingleAttr(buffConf.buff); } // ==================== DEBUFF管理 ==================== /** - * 添加 debuff 效果 - * @param dbuffConf debuff 配置 (来自 SkillSet.DbuffConf 或 heroSet.debuff) + * 添加 debuff 效果(智能覆盖) + * @param dbuffConf debuff 配置 (来自 SkillSet.DbuffConf ?heroSet.debuff) * - * 支持两种 debuff: - * 1. 属性型 debuff:直接修改属性值(有对应的 Attrs) + * 支持两种 debuff? + * 1. 属性型 debuff:直接修改属性值(有对应的 Attrs? * 2. 状态型 debuff:只缓存状态(无对应的 Attrs,用于状态检查) + * + * 智能覆盖规则? + * 1. 值更小:不添? + * 2. 值相同且都是临时:叠加时? + * 3. 值更大:更新为新值(临时则更新值和时间? */ addDebuff(dbuffConf: DbuffConf) { - // 获取 debuff 对应的属性字段 + // 获取 debuff 对应的属性字? // attrField = -1 表示状态类 debuff(只缓存,不修改属性) // attrField >= 0 表示属性类 debuff(会修改属性) const attrField = getAttrFieldFromDebuff(dbuffConf.debuff); - - // 基于类型和持续时间分类存储 - if (dbuffConf.BType === BType.VALUE) { - // 数值型 debuff - if (dbuffConf.deC === 0) { - // 持久型 - this.DBUFF_V.push({ - ...dbuffConf, - attrField: attrField - }); + const isValue = dbuffConf.BType === BType.VALUE; + const isPermanent = dbuffConf.time === 0; + + // 根据类型选择对应?debuff 字典 + const permanentDebuffs = isValue ? this.DBUFF_V : this.DBUFF_R; + const temporaryDebuffs = isValue ? this.DBUFFS_V : this.DBUFFS_R; + + // 状态类 debuff 使用 debuff 类型作为 key,属性类 debuff 使用 attrField 作为 key + const key = attrField >= 0 ? attrField : dbuffConf.debuff; + + if (isPermanent) { + // 添加持久?debuff + const existing = permanentDebuffs[key]; + if (existing) { + // 值更小,不添? + if (dbuffConf.value <= existing.value) { + return; + } + // 值更大,更新 + existing.value = dbuffConf.value; } else { - // 临时型 - 添加剩余时间属性 - this.DBUFFS_V.push({ - ...dbuffConf, - attrField: attrField, - remainTime: dbuffConf.deC - }); + // 没有同类型,直接添加 + permanentDebuffs[key] = { value: dbuffConf.value }; } } else { - // 百分比型 debuff - if (dbuffConf.deC === 0) { - // 持久型 - this.DBUFF_R.push({ - ...dbuffConf, - attrField: attrField - }); + // 添加临时?debuff + const existing = temporaryDebuffs[key]; + if (existing) { + if (dbuffConf.value < existing.value) { + // 值更小,不添? + return; + } else if (dbuffConf.value === existing.value) { + // 值相同,叠加时间 + existing.remainTime += dbuffConf.time; + return; // 时间叠加不需要重算属? + } else { + // 值更大,更新值和时间 + existing.value = dbuffConf.value; + existing.remainTime = dbuffConf.time; + } } else { - // 临时型 - 添加剩余时间属性 - this.DBUFFS_R.push({ - ...dbuffConf, - attrField: attrField, - remainTime: dbuffConf.deC - }); + // 没有同类型,直接添加 + temporaryDebuffs[key] = { + value: dbuffConf.value, + remainTime: dbuffConf.time + }; } } - // 立即重新计算属性 - this.recalculateAttrs(); - } - - // ==================== 属性计算系统 ==================== - /** - * 重新计算所有角色属性 - * 基于基础属性 + 所有有效的 buff/debuff 计算 - * 注意:某些属性有初始值(HP_MAX, MP_MAX, DEF, AP, MAP) - */ - recalculateAttrs() { - // 1. 重置为基础值 - this.Attrs[Attrs.HP_MAX] = this.base_hp; - this.Attrs[Attrs.MP_MAX] = this.base_mp; - this.Attrs[Attrs.DEF] = this.base_def; - this.Attrs[Attrs.AP] = this.base_ap; - this.Attrs[Attrs.MAP] = this.base_map; - this.Attrs[Attrs.SPEED] = this.base_speed; - this.Attrs[Attrs.SHIELD_MAX] = 0; // 护盾默认为 0 - - // 2. 初始化其他属性(无初始值的) - let length = Object.keys(this.Attrs).length; - for (let i = 0; i < length; i++) { - if (!(i in this.Attrs) || - (i !== Attrs.HP_MAX && i !== Attrs.MP_MAX && i !== Attrs.DEF && - i !== Attrs.AP && i !== Attrs.MAP && i !== Attrs.SHIELD_MAX&&13 && i !== Attrs.SPEED)) { - this.Attrs[i] = 0; - } - } - - // 3. 应用数值型 buff (持久 + 临时) - this.applyValueBuffs(); - - // 4. 应用百分比型 buff (持久 + 临时) - this.applyRatioBuffs(); - - // 5. 应用数值型 debuff (持久 + 临时) - this.applyValueDebuffs(); - - // 6. 应用百分比型 debuff (持久 + 临时) - this.applyRatioDebuffs(); - - // 7. 确保关键属性不为负数 - this.clampAttrs(); - } - - /** - * 应用数值型 buff - */ - private applyValueBuffs() { - // 持久型 buff - for (const buff of this.BUFF_V) { - if (buff.buff !== undefined) { - this.Attrs[buff.buff] += buff.buV; - } - } - - // 临时型 buff - for (const buff of this.BUFFS_V) { - if (buff.buff !== undefined) { - this.Attrs[buff.buff] += buff.buV; - } + + // 只重新计算受影响的属性(状态类 debuff 不需要计算) + if (attrField >= 0) { + this.recalculateSingleAttr(attrField); } } + // ==================== 属性计算系?==================== /** - * 应用百分比型 buff - * 百分比型 buff 是基于基础属性的百分比增加 + * 重新计算单个属�? + * @param attrIndex 属性索? */ - private applyRatioBuffs() { - // 获取基础值映射 - const baseValues: Record = {}; - baseValues[Attrs.HP_MAX] = this.base_hp; - baseValues[Attrs.MP_MAX] = this.base_mp; - baseValues[Attrs.DEF] = this.base_def; - baseValues[Attrs.AP] = this.base_ap; - baseValues[Attrs.MAP] = this.base_map; - baseValues[Attrs.SPEED] = this.base_speed; + private recalculateSingleAttr(attrIndex: number) { + // 1. 重置为基础? + const baseValues: Record = { + [Attrs.HP_MAX]: this.base_hp, + [Attrs.MP_MAX]: this.base_mp, + [Attrs.DEF]: this.base_def, + [Attrs.AP]: this.base_ap, + [Attrs.MAP]: this.base_map, + [Attrs.SPEED]: this.base_speed, + [Attrs.SHIELD_MAX]: 0 + }; + + this.Attrs[attrIndex] = baseValues[attrIndex] !== undefined ? baseValues[attrIndex] : 0; - // 持久型 buff - for (const buff of this.BUFF_R) { - if (buff.buff !== undefined) { - const baseVal = baseValues[buff.buff] || this.Attrs[buff.buff]; - this.Attrs[buff.buff] += Math.floor(baseVal * (buff.buV / 100)); - } + // 2. 应用数值型 buff - 直接访问 + if (this.BUFF_V[attrIndex]) { + this.Attrs[attrIndex] += this.BUFF_V[attrIndex].value; + } + if (this.BUFFS_V[attrIndex]) { + this.Attrs[attrIndex] += this.BUFFS_V[attrIndex].value; } - // 临时型 buff - for (const buff of this.BUFFS_R) { - if (buff.buff !== undefined) { - const baseVal = baseValues[buff.buff] || this.Attrs[buff.buff]; - this.Attrs[buff.buff] += Math.floor(baseVal * (buff.buV / 100)); - } + // 3. 应用百分比型 buff - 直接访问 + const baseVal = baseValues[attrIndex] !== undefined ? baseValues[attrIndex] : this.Attrs[attrIndex]; + if (this.BUFF_R[attrIndex]) { + this.Attrs[attrIndex] += Math.floor(baseVal * (this.BUFF_R[attrIndex].value / 100)); } + if (this.BUFFS_R[attrIndex]) { + this.Attrs[attrIndex] += Math.floor(baseVal * (this.BUFFS_R[attrIndex].value / 100)); + } + + // 4. 应用数值型 debuff - 直接访问 + if (this.DBUFF_V[attrIndex]) { + this.Attrs[attrIndex] -= this.DBUFF_V[attrIndex].value; + } + if (this.DBUFFS_V[attrIndex]) { + this.Attrs[attrIndex] -= this.DBUFFS_V[attrIndex].value; + } + + // 5. 应用百分比型 debuff - 直接访问 + if (this.DBUFF_R[attrIndex]) { + this.Attrs[attrIndex] -= Math.floor(baseVal * (this.DBUFF_R[attrIndex].value / 100)); + } + if (this.DBUFFS_R[attrIndex]) { + this.Attrs[attrIndex] -= Math.floor(baseVal * (this.DBUFFS_R[attrIndex].value / 100)); + } + + // 6. 确保属性值合? + this.clampSingleAttr(attrIndex); } - /** - * 应用数值型 debuff + * 确保单个属性值合? */ - private applyValueDebuffs() { - // 持久型 debuff - for (const debuff of this.DBUFF_V) { - // 跳过状态类 debuff(attrField === -1) - if (debuff.attrField !== undefined && debuff.attrField >= 0) { - this.Attrs[debuff.attrField] -= debuff.deV; - } + private clampSingleAttr(attrIndex: number) { + switch(attrIndex) { + case Attrs.HP_MAX: + case Attrs.MP_MAX: + this.Attrs[attrIndex] = Math.max(1, this.Attrs[attrIndex]); + break; + case Attrs.DEF: + case Attrs.AP: + case Attrs.MAP: + this.Attrs[attrIndex] = Math.max(0, this.Attrs[attrIndex]); + break; + case Attrs.CRITICAL: + case Attrs.DODGE: + case Attrs.HIT: + this.Attrs[attrIndex] = Math.max(0, Math.min(85, this.Attrs[attrIndex])); + break; } - - // 临时型 debuff - for (const debuff of this.DBUFFS_V) { - // 跳过状态类 debuff(attrField === -1) - if (debuff.attrField !== undefined && debuff.attrField >= 0) { - this.Attrs[debuff.attrField] -= debuff.deV; - } - } - } - - /** - * 应用百分比型 debuff - * 百分比型 debuff 是基于基础属性的百分比减少 - */ - private applyRatioDebuffs() { - // 获取基础值映射 - const baseValues: Record = {}; - baseValues[Attrs.HP_MAX] = this.base_hp; - baseValues[Attrs.MP_MAX] = this.base_mp; - baseValues[Attrs.DEF] = this.base_def; - baseValues[Attrs.AP] = this.base_ap; - baseValues[Attrs.MAP] = this.base_map; - this.Attrs[Attrs.SPEED] = this.base_speed; - - // 持久型 debuff - for (const debuff of this.DBUFF_R) { - // 跳过状态类 debuff(attrField === -1) - if (debuff.attrField !== undefined && debuff.attrField >= 0) { - const baseVal = baseValues[debuff.attrField] || this.Attrs[debuff.attrField]; - this.Attrs[debuff.attrField] -= Math.floor(baseVal * (debuff.deV / 100)); - } - } - - // 临时型 debuff - for (const debuff of this.DBUFFS_R) { - // 跳过状态类 debuff(attrField === -1) - if (debuff.attrField !== undefined && debuff.attrField >= 0) { - const baseVal = baseValues[debuff.attrField] || this.Attrs[debuff.attrField]; - this.Attrs[debuff.attrField] -= Math.floor(baseVal * (debuff.deV / 100)); - } - } - } - - /** - * 确保关键属性不为负数 - */ - private clampAttrs() { - // HP_MAX 最少 1 - this.Attrs[Attrs.HP_MAX] = Math.max(1, this.Attrs[Attrs.HP_MAX]); - // MP_MAX 最少 1 - this.Attrs[Attrs.MP_MAX] = Math.max(1, this.Attrs[Attrs.MP_MAX]); - // DEF 最少 0 - this.Attrs[Attrs.DEF] = Math.max(0, this.Attrs[Attrs.DEF]); - // AP 最少 0 - this.Attrs[Attrs.AP] = Math.max(0, this.Attrs[Attrs.AP]); - // MAP 最少 0 - this.Attrs[Attrs.MAP] = Math.max(0, this.Attrs[Attrs.MAP]); - // 百分比属性限制在 0-100 之间 - this.Attrs[Attrs.CRITICAL] = Math.max(0, Math.min(85, this.Attrs[Attrs.CRITICAL])); - this.Attrs[Attrs.DODGE] = Math.max(0, Math.min(85, this.Attrs[Attrs.DODGE])); - this.Attrs[Attrs.HIT] = Math.max(0, Math.min(85, this.Attrs[Attrs.HIT])); } // ==================== 临时 BUFF/DEBUFF 更新 ==================== /** - * 更新临时 buff/debuff 的剩余时间 - * 应在 update 中定期调用 - * @param dt 时间差 + * 更新临时 buff/debuff 的剩余时? + * 应在 update 中定期调? + * @param dt 时间? */ updateTemporaryBuffsDebuffs(dt: number) { - let needRecalculate = false; + const affectedAttrs = new Set(); - // 更新临时型数值 buff - for (let i = this.BUFFS_V.length - 1; i >= 0; i--) { - this.BUFFS_V[i].remainTime -= dt; - if (this.BUFFS_V[i].remainTime <= 0) { - this.BUFFS_V.splice(i, 1); - needRecalculate = true; + // 更新临时型数?buff + for (const attrIndex in this.BUFFS_V) { + const buff = this.BUFFS_V[attrIndex]; + buff.remainTime -= dt; + if (buff.remainTime <= 0) { + delete this.BUFFS_V[attrIndex]; + affectedAttrs.add(parseInt(attrIndex)); } } // 更新临时型百分比 buff - for (let i = this.BUFFS_R.length - 1; i >= 0; i--) { - this.BUFFS_R[i].remainTime -= dt; - if (this.BUFFS_R[i].remainTime <= 0) { - this.BUFFS_R.splice(i, 1); - needRecalculate = true; + for (const attrIndex in this.BUFFS_R) { + const buff = this.BUFFS_R[attrIndex]; + buff.remainTime -= dt; + if (buff.remainTime <= 0) { + delete this.BUFFS_R[attrIndex]; + affectedAttrs.add(parseInt(attrIndex)); } } - // 更新临时型数值 debuff - for (let i = this.DBUFFS_V.length - 1; i >= 0; i--) { - this.DBUFFS_V[i].remainTime -= dt; - if (this.DBUFFS_V[i].remainTime <= 0) { - this.DBUFFS_V.splice(i, 1); - needRecalculate = true; + // 更新临时型数?debuff + for (const key in this.DBUFFS_V) { + const debuff = this.DBUFFS_V[key]; + debuff.remainTime -= dt; + if (debuff.remainTime <= 0) { + delete this.DBUFFS_V[key]; + affectedAttrs.add(parseInt(key)); } } // 更新临时型百分比 debuff - for (let i = this.DBUFFS_R.length - 1; i >= 0; i--) { - this.DBUFFS_R[i].remainTime -= dt; - if (this.DBUFFS_R[i].remainTime <= 0) { - this.DBUFFS_R.splice(i, 1); - needRecalculate = true; + for (const key in this.DBUFFS_R) { + const debuff = this.DBUFFS_R[key]; + debuff.remainTime -= dt; + if (debuff.remainTime <= 0) { + delete this.DBUFFS_R[key]; + affectedAttrs.add(parseInt(key)); } } - // 如果有 buff/debuff 过期,重新计算属性 - if (needRecalculate) { - this.recalculateAttrs(); - } + // 只重新计算受影响的属? + affectedAttrs.forEach(attrIndex => { + this.recalculateSingleAttr(attrIndex); + }); } public isStun() { - return this.DBUFF_V.some(d => d.debuff === DBuff.STUN) + return this.DBUFF_V[DBuff.STUN] !== undefined || this.DBUFFS_V[DBuff.STUN] !== undefined } public isFrost() { - return this.DBUFF_V.some(d => d.debuff === DBuff.FROST) + return this.DBUFF_V[DBuff.FROST] !== undefined || this.DBUFFS_V[DBuff.FROST] !== undefined } update(dt: number){ @@ -538,7 +475,7 @@ export class HeroViewComp extends CCComp { get isActive() { return this.ent.has(HeroViewComp) && this.node?.isValid; } - //状态切换 + //状态切? status_change(type:string){ this.status=type if(type == "idle"){ @@ -806,7 +743,7 @@ export class HeroViewComp extends CCComp { this.showDamageImmediate(damageInfo.damage, damageInfo.isCrit,damageInfo.anm); - // 设置延时处理下一个伤害 + // 设置延时处理下一个伤? this.scheduleOnce(() => { this.isProcessingDamage = false; }, this.damageInterval); @@ -820,10 +757,10 @@ export class HeroViewComp extends CCComp { this.atked_count++; if (isCrit) { this.BUFFCOMP.hp_tip(TooltipTypes.crit, damage.toFixed(0), damage); - // //console.log("暴击伤害:" + damage); + // //console.log("暴击伤害? + damage); } else { this.BUFFCOMP.hp_tip(TooltipTypes.life, damage.toFixed(0), damage); // //console.log("普通伤害:" + damage); } } -} \ No newline at end of file +}