405 lines
9.1 KiB
Markdown
405 lines
9.1 KiB
Markdown
# 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, number> = {
|
||
// ... 现有映射 ...
|
||
[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 类型检查 |
|
||
|
||
---
|
||
|
||
**系统已准备好长期维护和扩展!** 🎉
|