128 lines
5.3 KiB
Markdown
128 lines
5.3 KiB
Markdown
## ADDED Requirements
|
||
|
||
### Requirement: 装备子类型与部位
|
||
|
||
系统 MUST 提供 4 种装备 EquipItemType:Material(1) / Equip(2) / Drawing(3) / DrawingMaterial(4)。完整成品装备(Equip)MUST 占用 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 类 ItemInfo(heroId=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 满足条件也不计入
|