# 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 类型检查 | --- **系统已准备好长期维护和扩展!** 🎉