# 战斗多单位模式改造交接文档(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` 只是入口铺垫,不代表多单位模式已经完成。