Files
bl/docs/fight-multi-battle-refactor-task-2026-04-04.md
2026-04-04 07:06:00 +08:00

328 lines
10 KiB
Go
Raw Permalink 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.

# 战斗多单位模式改造交接文档2026-04-04
## 0. 2026-04-04 本轮完成情况
本轮已完成以下落地项
- 动作提交改为按 `playerID + actorIndex` 去重同一玩家同回合的多个上场位动作不会再互相覆盖
- 主循环已从双动作入口改为动作列表入口`resolveRound` 现接收并处理 `[]action.BattleActionI`
- 回合结算增加了基于优先级和速度的统一排序并按跨阵营动作对子顺序执行保留现有 `enterturn(first, second)` 兼容层
- 技能和道具的目标选择已接入 `targetIndex`不再固定打对面 `0` 号位
- 切宠同步改为携带 `actorIndex`同一玩家多上场位的切宠播报不再冲突
- 开战同步结构新增当前战斗位数组同时保留 `Info1/Info2` 兼容旧结构
- `FightI` 已补充 `UseSkillAt/ChangePetAt/UseItemAt/GetCurrPETAt`
- `NewFight` 已改为包装 `NewFightWithOptions(...)`创建阶段开始支持 option/builder 扩展
- `Ctx` 已拆分为 `LegacySides + EffectBinding`effect 本体上挂载上下文并补充 `Source/Carrier/Target`
- 核心执行链已开始迁移到真实 source/target 语义`AddEffect``Exec``Damage``SetProp`主技能结算流程会注入实际对手上下文
- 已迁移一批公共/高复用 effect 到新语义包括状态基类击败触发物攻附加状态`1097-1101``680-690`部分魂印基础逻辑
- 本轮继续完成了 `1263-1287``1288-1312``1448-1472``1473-1497` 四组 effect 的迁移已不再直接依赖 `Ctx().Our/Opp`统一改为 `CarrierInput()/OpponentInput()` 访问当前承载侧与对位侧
- 增加了动作队列的基础单测覆盖同玩家不同槽位保留同槽位动作替换
本轮仍保留的限制
- `enterturn` 和大量 `effect/node` 逻辑仍是双动作上下文因此当前实现采用动作列表排序 + 跨阵营配对兼容执行的过渡方案而不是一次性重写所有效果系统
- `NewFight` 仍按现有建房流程创建双方 1 个战斗位本轮打通的是多战斗位结算骨架和接口不是外部建房入口的全量切换
- 大量具体 effect 仍在使用旧的 `Ctx().Our/Opp` 语义当前已迁移的是上下文承载方式执行链和部分公共基类具体 effect 仍需继续分批迁移
### 0.1 effect 迁移增量记录
本轮新增完成
- `logic/service/fight/effect/1263_1287.go`
- `logic/service/fight/effect/1288_1312.go`
- `logic/service/fight/effect/1448_1472.go`
- `logic/service/fight/effect/1473_1497.go`
这两组文件当前迁移策略是
- 旧语义中的 `Our` 统一视为当前执行/承载该 effect 的输入侧迁移为 `CarrierInput()`
- 旧语义中的 `Opp` 统一迁移为当前结算上下文里的对位输入侧 `OpponentInput()`
- 暂不在这一轮强行把所有 effect 重写成纯 `Source/Target/Carrier` 三元语义先保证 hostile sub-effect回合类 effect挂在对手身上的限制类 effect 都不再依赖 legacy 字段访问
### 0.2 下一批待迁移队列
高密度遗留文件已继续向后推进`1448-1497` 这两个分段本轮已清理完成
下一轮继续迁移时建议直接对 effect 包执行一次全量扫描仍包含 `Ctx().Our/Opp` grouped file继续往后收口而不是再只盯固定编号段
## 1. 任务目标
将当前战斗系统从每回合双方各 1 个动作的模型改造成支持多上场位多操作者的统一回合模型最终支持以下 3 种战斗模式
1. `1玩家:N精灵:1上场 VS 1玩家:N精灵:1上场`
2. `N玩家:N精灵:N上场 VS N玩家:N精灵:N上场`
3. `1玩家:N精灵:N上场 VS 1玩家:N精灵:N上场`
当前代码只完整支持模式 1模式 2 和模式 3 只做了结构铺垫还没有真正打通
---
## 2. 当前已完成的基础改造
以下结构改造已经落地
- `FightC.Our/Opp` 已改成数组表示战场单位数组不再是单对象
- `input.Input.CurrentPet` 已改成 `CurPet`并且是数组
- `FightC.OurPlayers/OppPlayers` 已加入用于表达操作者数组
- 战斗单位与操作者已解耦
- `Our/Opp` 表示战斗位
- `OurPlayers/OppPlayers` 表示操作这些战斗位的玩家
- `BattlePetEntity` 已支持绑定控制者`ControllerUserID`
- 动作模型已支持
- `ActorIndex`
- `TargetIndex`
- 已提供 indexed 入口
- `UseSkillAt(c, skillID, actorIndex, targetIndex)`
- `ChangePetAt(c, petID, actorIndex)`
- `UseItemAt(c, catchTime, itemID, actorIndex, targetIndex)`
当前默认行为仍等价于
- `actorIndex = 0`
- `targetIndex = 0`
也就是当前模式下仍然是操作和结算 `0` 号单位
---
## 3. 当前未完成的核心问题
### 3.1 回合模型仍然是双动作模型
目前主流程仍然是每回合只处理双方两个动作而不是处理一个动作列表
关键位置
- `logic/service/fight/loop.go`
- `collectPlayerActions(...)` 只收 2 个动作
- `resolveRound(p1Action, p2Action)` 只结算 2 个动作
这意味着
- 模式 2 无法支持双方多个操作者或多个上场位同时行动
- 模式 3 无法支持同一玩家控制多个上场位分别出手
### 3.2 动作提交仍按 `playerID` 去重
当前动作队列逻辑仍以 `playerID` 作为主要识别维度
关键位置
- `logic/service/fight/action.go`
- `submitAction(...)`
这会导致
- 同一玩家在同一回合给多个上场位下达动作时动作会互相覆盖或无法完整保留
这一点对模式 3 是直接阻塞对模式 2 也不够健壮
### 3.3 切宠和当前上场位逻辑仍大量默认使用 `CurPet[0]`
虽然 `CurPet` 已经是数组但主流程中不少逻辑仍固定操作 `0` 号位
典型影响
- 死亡换宠
- 主动换宠
- 当前出手单位检查
- 当前目标单位检查
这部分需要按 `actorIndex` 或上场槽位改造
### 3.4 开战协议仍然只有两个当前单位
当前开战下发协议仍然是双单位结构
关键位置
- `logic/service/fight/info/info.go`
- `FightStartOutboundInfo`
- 仍只有 `Info1` `Info2`
这不适合多上场位模式
### 3.5 公共接口仍是旧的单单位接口
关键位置
- `logic/service/common/fight.go`
- `FightI`
目前接口仍只有
- `UseSkill(c, id)`
- `ChangePet(c, id)`
- `UseItem(c, cacthid, itemid)`
indexed 版本只存在于具体实现 `FightC` 没有进入正式接口层
---
## 4. 当前实现与目标模式的对应关系
### 4.1 模式 1
`1玩家:N精灵:1上场 VS 1玩家:N精灵:1上场`
当前支持
原因
- 当前默认就是操作 `0` 号单位
- 当前默认就是攻击 `0` 号目标
- 当前回合系统仍是每边 1 个动作这与模式 1 一致
### 4.2 模式 2
`N玩家:N精灵:N上场 VS N玩家:N精灵:N上场`
当前不支持
直接原因
- 一回合只收 2 个动作
- 一回合只结算 2 个动作
- 协议仍只同步 2 个当前上场位
### 4.3 模式 3
`1玩家:N精灵:N上场 VS 1玩家:N精灵:N上场`
当前不支持
直接原因
- 同一玩家的多个动作无法作为同回合动作列表完整保留
- 主流程仍不是按动作列表统一排序和执行
---
## 5. 需要完成的工作
### 5.1 改造动作收集模型
将当前每边 1 个动作的模型改成每个可操作上场位 1 个动作的模型
至少需要做到
- 同一玩家可以在同一回合提交多个动作
- 每个动作能区分是哪个上场位发出的
- 每个动作能区分目标上场位
建议将动作唯一键至少扩为
- `playerID`
- `actorIndex`
### 5.2 改造回合结算模型
将当前
- `resolveRound(p1Action, p2Action)`
改成
- `resolveRound(actions []action.BattleActionI)`
并完成
- 动作列表排序
- 按优先级速度等规则统一排序
- 排序后逐个结算
注意
- 当前 effect/node 体系里仍有大量双动作接口不适合一次性全部重写
- 建议先在主流程做兼容层逐步过渡
### 5.3 按槽位处理切宠与死亡换宠
将当前固定 `CurPet[0]` 的逻辑改成按槽位处理
- 主动换宠
- 被动死亡换宠
- 死亡校验
- 出手资格判断
### 5.4 增加开战与战斗同步结构
将当前的双单位同步结构扩成可支持多上场位的结构但是保持协议结构不变现在是固定两个可以改成数组来实现
重点是
- 开战协议
- 当前上场位同步
- 切宠同步
- 可能的回合播报结构
### 5.5 补齐公共接口
indexed 版本能力补进接口层避免只能通过具体实现类型访问
建议新增类似接口
- `UseSkillAt(...)`
- `ChangePetAt(...)`
- `UseItemAt(...)`
---
## 6. 推荐实施顺序
建议按下面顺序推进避免一次性改动面过大
1. 先改动作队列和动作收集逻辑
2. 再改回合结算为动作列表
3. 再改切宠和死亡换宠按槽位处理
4. 最后改协议和正式接口
不建议一开始就全量重写 effect/node 接口因为当前大量效果实现仍假设双动作上下文
---
## 7. 建议重点查看文件
- `logic/service/fight/action.go`
- `logic/service/fight/loop.go`
- `logic/service/fight/fightc.go`
- `logic/service/fight/input.go`
- `logic/service/fight/input/input.go`
- `logic/service/fight/action/BattleAction.go`
- `logic/service/fight/info/info.go`
- `logic/service/common/fight.go`
---
## 8. 完成标准
至少满足以下条件才算这次改造完成
1. 同一玩家可以在同一回合给多个上场位分别提交动作动作不会互相覆盖
2. 双方多个上场位可以在同一回合统一排序并依次结算
3. 攻击目标位可选不再默认只能打对面 `0`
4. 切宠可以按上场槽位处理
5. 模式 1 不回归
6. 代码编译通过
---
## 9. 最低验证要求
至少执行
- `cd /workspace/logic && go build ./...`
- `cd /workspace/logic && go test ./service/fight/effect`
如果本轮改动较大建议再补一轮
- `cd /workspace/logic && go test ./...`
---
## 10. 额外提醒
- 当前仓库工作区可能是脏的不要回滚无关修改
- 这次改造的真正核心不是结构字段改数组而是把回合系统从双动作模型改成动作列表模型
- 已有 `ActorIndex/TargetIndex` 只是入口铺垫不代表多单位模式已经完成