128 lines
5.3 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: 装备子类型与部位
系统 MUST 提供 4 种装备 EquipItemTypeMaterial(1) / Equip(2) / Drawing(3) / DrawingMaterial(4)。完整成品装备EquipMUST 占用 8 个部位中的一个,由 `EquipSubType` 枚举Head(1) / BreastPlate(2) / Weapon(3) / Gloves(4) / Pants(5) / Accessories1(6) / Accessories2(7) / Shoes(8)。
#### Scenario: 装备数据结构
- **WHEN** `ItemConfig.itemType == Equipment`
- **THEN** 必须有关联的 `EquipConfig.subType` 字段8 个部位之一)
- **AND** 必须有 `EquipConfig.equipItemType`Material/Equip/Drawing/DrawingMaterial
### Requirement: 英雄穿戴装备
玩家 MUST 能为指定英雄穿戴成品装备EquipItemType == Equip。同部位已穿装备 MUST 自动卸下并回到背包未绑定状态。
#### Scenario: 穿戴空槽位装备
- **WHEN** 玩家发送 `C2G_HeroWearEquip { heroId, equipItemIndex }`
- **AND** 该装备类型为 Equip
- **AND** 英雄对应 SubType 槽位为空
- **THEN** 服务端将该装备 itemIndex 写入 `Hero.equipSlots[SubType]`
- **AND** 设置该装备 `ItemInfo.heroId = heroId`
- **AND** 推送 `Hero_HeroInfo` + `Item_ItemInfo`
#### Scenario: 替换已穿装备
- **WHEN** 玩家穿戴新装备,对应槽位已有装备
- **THEN** 服务端 MUST 先卸下旧装备(旧 ItemInfo.heroId = 0
- **AND** 穿戴新装备
- **AND** 推送两条 `Item_ItemInfo`(旧/新装备)+ 一条 `Hero_HeroInfo`
#### Scenario: 穿戴非装备道具
- **WHEN** 玩家发送 wear 请求但 itemIndex 对应的不是 Equip
- **THEN** 服务端 MUST 拒绝并返回 `NotEquipment`
### Requirement: 卸下装备
玩家 MUST 能从英雄身上卸下指定部位装备。卸下后装备 MUST 回到背包未绑定状态heroId = 0
#### Scenario: 卸下装备
- **WHEN** 玩家发送 `C2G_TakeOffEquip { heroId, subType }`
- **AND** 该英雄对应槽位有装备
- **THEN** 服务端清空 `Hero.equipSlots[SubType]`
- **AND** 该装备 `ItemInfo.heroId = 0`
- **AND** 推送 `Hero_HeroInfo` + `Item_ItemInfo`
#### Scenario: 卸下空槽位
- **WHEN** 该英雄对应槽位为空
- **THEN** 服务端 MUST 拒绝并返回 `EquipSlotEmpty`
### Requirement: 装备属性
每件装备 MUST 提供属性加成,由 `EquipConfig.attrTypes[] + attrNumbers[]` 定义。英雄装备总属性 MUST 等于所有已穿装备的属性总和。
#### Scenario: 计算英雄装备属性
- **WHEN** 客户端调用 `HeroExtensions.GetEquipAttr(hero)`
- **THEN** 返回字典 `{ AttrType -> 数值 }`,键值是 8 个部位装备属性累加
### Requirement: 装备品质排序
客户端 MUST 提供装备列表排序:
- HighQuality按品质降序
- LowQuality按品质升序
- Worn先显示已穿戴再未穿戴
- Exclusive只显示英雄专属`EquipConfig.exclusive` 字段)
#### Scenario: 按品质排序
- **WHEN** 客户端调用 `BagComponentExtensions.GetEquipItemsBySortType(EquipSortType.HighQuality)`
- **THEN** 返回所有 Equip 类道具
- **AND** 按 `EquipConfig.quality` 字段降序
### Requirement: 装备锻造(制作成品)
玩家 MUST 能用图纸Drawing + 图纸材料DrawingMaterial合成成品装备。每个图纸 MUST 在 `EquipConfig.requireMaterials[]` 定义所需材料和数量。
#### Scenario: 锻造成功
- **WHEN** 玩家发送 `C2G_MakeEquipment { drawingItemId }`
- **AND** 玩家持有该图纸 1 个 + 所有必需材料足够
- **THEN** 服务端扣除图纸 1 个 + 各材料数量
- **AND** 创建新 Equip 类 ItemInfoheroId=0
- **AND** 推送所有相关 `Item_ItemInfo` 变更
#### Scenario: 材料不足
- **WHEN** 玩家发送锻造请求但材料不够
- **THEN** 服务端拒绝并返回 `MaterialNotEnough`
- **AND** 不消耗任何道具
### Requirement: 装备分解
玩家 MUST 能分解未穿戴的成品装备,按 `EquipConfig.resolveRewards[]` 返还材料/碎片。
#### Scenario: 分解成功
- **WHEN** 玩家发送 `C2G_ResolveEquipment { itemIndex }`
- **AND** 该装备 `heroId == 0`(未穿戴)
- **THEN** 服务端删除该 itemIndex
- **AND** 按配置发放奖励道具
- **AND** 推送 `Item_ItemInfo` 多条
#### Scenario: 已穿戴装备不能分解
- **WHEN** 该装备 `heroId != 0`
- **THEN** 拒绝并返回 `EquipmentInUse`
### Requirement: 材料合成
玩家 MUST 能用低级材料合成高级材料,由 `MaterialDefine.mixRules[]` 定义规则(如 5 个 1 级材料 → 1 个 2 级材料)。
#### Scenario: 合成材料
- **WHEN** 玩家发送 `C2G_MixMaterial { sourceItemId, count }`
- **AND** 数量是合成倍数(如 5 / 10 / 15
- **AND** 玩家拥有足够数量
- **THEN** 服务端扣除源材料
- **AND** 增加目标材料 `count / mixRatio`
- **AND** 推送 `Item_ItemInfo`
### Requirement: 锻造红点
客户端 MUST 提供"有装备可锻造"红点:
- `HasEquipCanBeForged()` 返回是否任一图纸的材料齐全
- 玩家 MUST 能"忽略某图纸的红点"(本地存储),`AddForgeEquipIgnoreRedDot(drawingItemId)`
#### Scenario: 检测可锻造红点
- **WHEN** 玩家拥有图纸 A 和它的所有材料足够
- **AND** 调用 `HasEquipCanBeForged()`
- **THEN** 返回 true
#### Scenario: 忽略红点后不再提示
- **WHEN** 玩家忽略图纸 A 的红点
- **AND** 调用 `HasEquipCanBeForged()` 仅检测其他图纸
- **THEN** 即使图纸 A 满足条件也不计入