175 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## ADDED Requirements
### Requirement: Hero Entity 数据模型
系统 MUST 为每个英雄实例提供一个 `Hero` 实体,挂在玩家的 `HeroComponent` 下。每个 `Hero` 实体 MUST 持有以下基础字段:英雄 configId、当前等级、当前经验、当前星级、当前升星经验、招募时间、击杀数、技能等级数组5 个槽位、当前天赋页索引、3 套天赋树数据、8 个装备槽引用。
#### Scenario: 创建一个新英雄
- **WHEN** 服务端处理 `C2G_SummonHero` 成功后
- **THEN** 在玩家 `HeroComponent` 下创建一个新的 `Hero` Entity等级初始为 1、经验为 0、星级为 configId 对应 HeroConfig 的 `initStar`、所有技能等级为 1、装备槽为空
- **AND** 新 `Hero` Entity 的 Id 是分布式唯一 ID
- **AND** 服务端 MUST 推送 `Hero_HeroInfo` 给客户端
#### Scenario: 查询英雄数据
- **WHEN** 客户端通过 `HeroComponent.GetHero(heroId)` 查询
- **THEN** 返回对应 `Hero` Entity若不存在返回 null
### Requirement: 英雄招募
玩家 MUST 能通过消耗碎片道具招募一个新英雄。招募 MUST 满足以下条件:碎片数量 >= HeroConfig.getItemNum玩家未达到当前英雄招募上限HeroConfig.getLimit玩家未已持有该英雄每个英雄唯一
#### Scenario: 招募成功
- **WHEN** 玩家碎片足够且未持有该英雄
- **AND** 客户端发送 `C2G_SummonHero { configId }`
- **THEN** 服务端扣除 `HeroConfig.getItemNum` 数量的对应碎片
- **AND** 创建新 `Hero` Entity
- **AND** 返回 `R2C_SummonHero { error: 0, hero: HeroInfo }`
- **AND** 推送 `Item_ItemInfo` 同步碎片数量变化
#### Scenario: 碎片不足招募失败
- **WHEN** 玩家碎片数量 < HeroConfig.getItemNum
- **THEN** 服务端 MUST 拒绝并返回 `R2C_SummonHero { error: ItemNotEnough }`
- **AND** 不扣道具不创建英雄
#### Scenario: 重复招募已有英雄
- **WHEN** 玩家已持有该 configId 的英雄
- **THEN** 服务端 MUST 拒绝并返回 `R2C_SummonHero { error: HeroAlreadyOwned }`
### Requirement: 英雄经验升级
玩家 MUST 能消耗经验道具提升英雄等级系统 MUST 强制以下约束等级上限受当前星级约束`Hero.level <= StarConfig.starLimit`经验溢出 MUST 顺延到下一级满级时溢出经验 MUST 被丢弃
#### Scenario: 单次升级
- **WHEN** 玩家发送 `C2G_HeroAddExp { heroId, itemId, count }`
- **AND** 玩家拥有足够道具且英雄未到星级限定等级
- **THEN** 服务端按 `ItemConfig.exp * count` 累加经验
- **AND** 经验超过 `HeroLevelConfig.exp` 时升级可连升
- **AND** 推送更新后的 `Hero_HeroInfo` + `Item_ItemInfo`
#### Scenario: 满级丢弃溢出
- **WHEN** 英雄已达星级等级上限
- **THEN** 服务端 MUST 拒绝升级请求或保持经验不增长返回相应错误码
### Requirement: 英雄升星
玩家 MUST 能消耗"升星材料"道具提升英雄星级每次提交 MUST 累加升星经验 `Hero.starExp`达到阈值后升星并提供"幸运暴击"机制 `HeroStarExpConfig.lucky` 概率多算经验)。
#### Scenario: 升星积累经验
- **WHEN** 玩家发送 `C2G_HeroStarUp { heroId, itemId, count }`
- **THEN** 服务端按 `HeroStarExpConfig.exp` 计算经验值乘以幸运系数
- **AND** 累加到 `Hero.starExp`
- **AND** `starExp >= HeroStarConfig.starExpRequired` `star += 1``starExp -= 该阈值`
#### Scenario: 满星拒绝
- **WHEN** `Hero.star >= HeroConfig.star`最大星级
- **THEN** 服务端 MUST 拒绝升星请求并返回 `StarMaxLevel`
### Requirement: 英雄技能升级
每个英雄 MUST 5 个技能槽 4 个初始解锁 5 个需觉醒解锁)。玩家 MUST 能消耗指定材料按等级升级单个技能技能等级 MUST `HeroSkillConfig.maxLevel` 上限约束
#### Scenario: 升级第 1-4 技能
- **WHEN** 玩家发送 `C2G_HeroSkillUp { heroId, skillIndex }` skillIndex [0,3]
- **AND** 拥有 `HeroSkillLevelConfig.costItem`按英雄稀有度选择不同 costItem 字段
- **THEN** 服务端扣道具技能等级 +1
- **AND** 推送 `Hero_HeroInfo` 更新
#### Scenario: 升级第 5 技能要求觉醒
- **WHEN** 玩家发送 `C2G_HeroSkillUp { heroId, skillIndex: 4 }`
- **AND** `Hero.isAwakening == false`
- **THEN** 服务端 MUST 拒绝并返回 `NeedAwakening`
### Requirement: 英雄觉醒
玩家 MUST 在前 4 个技能全部满级时才能觉醒英雄觉醒后 `Hero.isAwakening = true`解锁第 5 个技能initial level = 1
#### Scenario: 觉醒成功
- **WHEN** 玩家发送 `C2G_HeroAwake { heroId }`
- **AND** Hero 4 个技能都达到 `HeroSkillConfig.maxLevel`
- **AND** 玩家拥有觉醒材料道具
- **THEN** 服务端扣道具设置 `Hero.isAwakening = true` 5 技能等级置 1
- **AND** 推送 `Hero_HeroInfo`
#### Scenario: 觉醒前置不满足
- **WHEN** 4 个技能未全部满级
- **THEN** 拒绝并返回 `SkillNotMaxBeforeAwake`
### Requirement: 天赋树
每个英雄 MUST 3 套天赋页pageIndex 0/1/2玩家 MUST 当前页学习/升级单个天赋切换当前页消耗道具或钻石重置某一页天赋返还点数)。
#### Scenario: 学习天赋
- **WHEN** 玩家发送 `C2G_TalentUp { heroId, pageIndex, talentNodeId }`
- **AND** 当前天赋页剩余点数 >= 该节点消耗
- **AND** 满足前置节点依赖(`HeroTalentDefine` 中定义)
- **THEN** 服务端扣减剩余点数,节点等级 +1
- **AND** 推送 `Hero_HeroInfo` 更新 talentTrees[pageIndex]
#### Scenario: 切换天赋页
- **WHEN** 玩家发送 `C2G_ChangeTalentIndex { heroId, targetIndex }`
- **THEN** 服务端按规则扣消耗(道具或钻石)
- **AND** 更新 `Hero.talentIndex = targetIndex`
#### Scenario: 重置天赋
- **WHEN** 玩家发送 `C2G_ResetTalent { heroId, pageIndex }`
- **THEN** 服务端清空该页所有节点等级
- **AND** 返还消耗的点数(或按规则按比例返还道具)
### Requirement: 英雄属性与战力计算
系统 MUST 提供英雄"总战力"计算,等于:`baseScore + levelScore + skillScore + talentScore + equipScore`。每个分项 MUST 可独立计算:
- baseScore = `HeroConfig.score`
- levelScore = `HeroLevelConfig(rareGroup, lv).score`
- skillScore = 5 个技能各自 `HeroSkillEffectConfig(skillId, level).score` 之和
- talentScore = 已学习天赋节点 score 之和
- equipScore = 已穿戴装备的属性折算 score`equipment-system` 提供接口)
#### Scenario: 计算单个英雄战力
- **WHEN** 客户端调用 `HeroExtensions.GetPower(hero)`
- **THEN** 返回 5 个分项之和
#### Scenario: 计算所有英雄总战力
- **WHEN** 客户端调用 `HeroComponentExtensions.GetTotalPower()`
- **THEN** 返回所有 `Hero` Entity 的战力之和
### Requirement: 英雄排序与筛选
客户端 MUST 提供英雄排序能力支持以下排序类型Rare稀有度/ Star星级/ Level等级/ Power战力/ Recomend推荐分。排序 MUST 输出三个分组:已拥有 / 可召唤(碎片够但未招募)/ 未集齐。
#### Scenario: 按战力排序已拥有列表
- **WHEN** 客户端调用 `HeroComponentExtensions.GetHerosBySort(SortType.Power)`
- **THEN** 返回 `(ownedList, canSummonList, fragmentList)` 三个列表
- **AND** ownedList 按战力降序排列
- **AND** canSummonList 包含所有 `碎片数 >= getItemNum && !已拥有 && !达到招募上限` 的英雄
### Requirement: 英雄红点
系统 MUST 提供以下红点接口(基于 `cn.etetet.yiuireddot` 包):
- 有英雄可招募
- 有英雄有技能可升级(道具足够升满)
- 有英雄装备可升级
- 有英雄天赋有剩余点数
#### Scenario: 检测可招募英雄红点
- **WHEN** 客户端访问 `HeroComponentExtensions.GetCanSummonHeroCount()`
- **THEN** 返回当前可立即招募的英雄数量
#### Scenario: 检测可升级技能红点
- **WHEN** 客户端访问 `HeroComponentExtensions.GetCanSkillUpHeroCount()`
- **THEN** 返回当前任一英雄存在"道具足够升一级且未满级"的技能时计数 + 1
### Requirement: 客户端英雄数据同步
客户端 `HeroComponent` MUST 持有服务端推送的全部英雄数据快照。任何 `Hero_HeroInfo` 推送 MUST若 heroId 已存在则更新;若不存在则创建新缓存。
#### Scenario: 全量同步(登录后)
- **WHEN** 玩家登录成功,服务端发送 `Hero_HeroInfoList { heroes }`
- **THEN** 客户端 `HeroComponent` 清空旧缓存
- **AND** 为每个 HeroInfo 创建客户端 `Hero` Entity 缓存
- **AND** 触发 `OnHeroListUpdated` 事件
#### Scenario: 增量同步
- **WHEN** 服务端推送 `Hero_HeroInfo { hero }`
- **THEN** 客户端找到对应缓存并更新
- **AND** 触发 `OnHeroUpdated(heroId)` 事件