update docs

This commit is contained in:
SepComet 2026-03-12 09:36:24 +08:00
parent 09ebe6e3f3
commit d34af661b9
4 changed files with 277 additions and 588 deletions

View File

@ -1,6 +1,6 @@
# CodeX TODO # CodeX TODO
最后更新2026-03-10 最后更新2026-03-12
> 目标:基于当前仓库现状,为 `docs/TODO.md` 的 M1 收口补一份更可执行的补充顺序。 > 目标:基于当前仓库现状,为 `docs/TODO.md` 的 M1 收口补一份更可执行的补充顺序。
> 原则:先收主流程,再补硬规则,最后统一文档与验收口径。 > 原则:先收主流程,再补硬规则,最后统一文档与验收口径。
@ -66,10 +66,10 @@
- `ProcedureMain + NodeMapForm` 已能创建固定 10 节点 Run并驱动战斗 / 事件 / 商店三类节点的主流程入口。 - `ProcedureMain + NodeMapForm` 已能创建固定 10 节点 Run并驱动战斗 / 事件 / 商店三类节点的主流程入口。
- `RunState`、`FixedRunNodeSequenceBuilder`、`RunStateAdvanceService` 与对应 Editor 测试已存在,说明 Run 模型、固定序列、节点推进基础能力已经落地。 - `RunState`、`FixedRunNodeSequenceBuilder`、`RunStateAdvanceService` 与对应 Editor 测试已存在,说明 Run 模型、固定序列、节点推进基础能力已经落地。
- 战斗节点已有结算、奖励选择、失败返回;事件和商店节点也会发出 `NodeEnterEventArgs / NodeCompleteEventArgs`,主流程闭环已能稳定走通。 - 战斗节点已有结算、奖励选择、失败返回;事件和商店节点也会发出 `NodeEnterEventArgs / NodeCompleteEventArgs`,主流程闭环已能稳定走通。
- `P0-10 ~ P0-12` 不是纯空白 - `P0-10 ~ P0-12` 已完成当前 M1 口径收口
- 出战前已有“参与区至少有 1 座塔”的最低门槛 - 出战前已按“三组件完整且未损坏”的统一规则校验合法参战塔
- 品质 / Tag 已在组装、商店、展示链路中分散使用 - 品质 / Tag 已完成统一生成、汇总、展示与首发 7 个 Tag 的战斗生效
- 耐久已有字段、展示与扣减入口 - 耐久已完成“每场固定扣 1、归零失效、自动移出参战区”的最小闭环
### M1 目标状态 ### M1 目标状态
@ -198,11 +198,17 @@
- `Crit`、`Execution`、`Shatter` 已通过数值修正链路生效;`Shatter` 当前按“目标已减速时增伤”收口。 - `Crit`、`Execution`、`Shatter` 已通过数值修正链路生效;`Shatter` 当前按“目标已减速时增伤”收口。
- `Inferno``AbsoluteZero` 已不再是独立状态效果,而是分别在 `Fire` / `Ice` 生效时读取同次命中的强化 Tag 层数,增强 DOT 时长/伤害与减速时长/强度。 - `Inferno``AbsoluteZero` 已不再是独立状态效果,而是分别在 `Fire` / `Ice` 生效时读取同次命中的强化 Tag 层数,增强 DOT 时长/伤害与减速时长/强度。
### S4 后续执行计划 ### S4 审计结论2026-03-12
1. `S4-07` 已完成,当前不再继续围绕三表命名与职责拆分新任务。 - `S4-02 ~ S4-07` 的 M1 闭环已完成,当前不回滚其完成状态。
2. 后续如果要继续配置化更深层 Tag 元数据,应作为新的增强项单独立项,不回挂到当前 M1。 - 但本轮对 Tag 系统的静态审查确认:当前实现还存在 5 个会放大后续返工成本的结构问题。
3. `BurnSpread`、`IgniteBurst`、`FreezeMask`、`Pierce`、`Overpenetrate` 继续留在后续扩展阶段,不因为 `S4-07` 完成而提前进入当前迭代。 - 这些问题分别是:
- 配置真相源与 DataTable 加载顺序仍不稳定,`IsImplemented` 的最终结果会受加载先后影响。
- 组件 Tag 随机口径还没有把 `RunSeed` 作为正式输入,当前“同 Run 可复现、跨 Run 可区分”的合同未完全落地。
- `AttackPayload + HitContext` 还不是稳定的统一战斗上下文,数值类 Tag 仍依赖散装参数扩展。
- `TagConfig.txt` 中一部分字段已进入配置层,但还没有成为运行时真实消费字段,存在“表能改、逻辑不跟”的风险。
- `TagSystemDesign.md` 里仍混有旧的 12 Tag / 流派草稿,正式口径与历史预案没有彻底拆开。
- 因此,`S4` 后续不再继续扩展新 Tag 功能,而是先进入新的审计整改阶段,优先修掉上述结构问题。
## 阶段 S5 - 收口耐久规则 ## 阶段 S5 - 收口耐久规则
@ -255,7 +261,7 @@
1. `S5-01 ~ S5-04` 已按当前 M1 口径完成,不再作为 `P0-12` 的主阻塞项。 1. `S5-01 ~ S5-04` 已按当前 M1 口径完成,不再作为 `P0-12` 的主阻塞项。
2. 当前未实现的是长期设计里的维修、自动销毁、耐久折价、连续属性衰减,这些后续若要恢复,应作为新的增强项重新拆分,而不是回滚当前 MVP 口径。 2. 当前未实现的是长期设计里的维修、自动销毁、耐久折价、连续属性衰减,这些后续若要恢复,应作为新的增强项重新拆分,而不是回滚当前 MVP 口径。
3. `CodeX-TODO``TODO` 当前已经同步到同一执行口径;后续文档收尾应优先处理 `MVP-Scope`、`GameDesign` 等仍保留旧表述的设计文档。 3. `CodeX-TODO`、`TODO`、`MVP-Scope`、`GameDesign`、`TagSystemDesign` 当前已经同步到同一执行口径;后续若继续调整 M1 / M2 边界,应同步回写这些设计文档。
## 阶段 S6 - 回归与文档收尾 ## 阶段 S6 - 回归与文档收尾
@ -276,19 +282,75 @@
> >
> 2026-03-11 更新:`S6-04` 已完成。`MVP-Scope.md`、`GameDesign.md`、`TODO.md`、`CodeX-TODO.md` 与 `TagSystemDesign.md` 现已统一回写到当前真实实现口径:战斗奖励改为“敌人概率掉落 + 结算金币 + 满血额外 3 选 1”商店改为“当前 M1 只保留基础购买”并移除了“开局二选三组件组两塔”“M1 不做耐久 / 红色品质”“组件/配件混写”等已过期描述。当前 docs 下未再发现会误导 M1 开发的主冲突项,剩余内容仅保留明确标注为后续阶段的设计预案。 > 2026-03-11 更新:`S6-04` 已完成。`MVP-Scope.md`、`GameDesign.md`、`TODO.md`、`CodeX-TODO.md` 与 `TagSystemDesign.md` 现已统一回写到当前真实实现口径:战斗奖励改为“敌人概率掉落 + 结算金币 + 满血额外 3 选 1”商店改为“当前 M1 只保留基础购买”并移除了“开局二选三组件组两塔”“M1 不做耐久 / 红色品质”“组件/配件混写”等已过期描述。当前 docs 下未再发现会误导 M1 开发的主冲突项,剩余内容仅保留明确标注为后续阶段的设计预案。
## 阶段 S7 - Tag 系统审计整改
| 状态 | ID | 任务 | 交付物路径 | 验收标准 |
|-----|-------|------------------------------|---------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------|
| [ ] | S7-01 | 收口 Tag 配置真相源与加载顺序 | `Assets/GameMain/Scripts/Procedure/`<br>`Assets/GameMain/Scripts/Definition/Tag/`<br>`Assets/Tests/EditMode/` | `IsImplemented`、默认值与运行时定义不再受 DataTable 加载顺序影响 |
| [ ] | S7-02 | 补齐组件 Tag 随机上下文与 `RunSeed` 合同 | `Assets/GameMain/Scripts/Definition/Tag/Generation/`<br>`Assets/GameMain/Scripts/UI/Shop/`<br>`Assets/GameMain/Scripts/CustomComponent/CombatNode/`<br>`Assets/Tests/EditMode/` | 同 Run 可复现、跨 Run 可区分,且掉落 / 商店 / 种子共用同一随机合同 |
| [ ] | S7-03 | 收口 `AttackPayload / HitContext` 结算合同 | `Assets/GameMain/Scripts/Definition/DataStruct/`<br>`Assets/GameMain/Scripts/Definition/Tag/Combat/`<br>`Assets/GameMain/Scripts/Entity/`<br>`Assets/Tests/EditMode/` | Tag 结算统一只读上下文对象,不再继续靠散装参数扩展 |
| [ ] | S7-04 | 对齐 `TagConfig` 字段与运行时真实消费 | `Assets/GameMain/DataTables/TagConfig.txt`<br>`Assets/GameMain/Scripts/Definition/Tag/Metadata/`<br>`Assets/GameMain/Scripts/Definition/Tag/Combat/`<br>`Assets/Tests/EditMode/` | 保留字段要么真实生效,要么明确标注为占位且不会误导配置方 |
| [ ] | S7-05 | 清理 Tag 设计文档中的过期草稿 | `docs/TagSystemDesign.md`<br>`docs/CodeX-TODO.md` | 正式口径、当前实现、后续预案三者分层清晰 |
### S7 立项原因
- 当前 Tag 系统已经满足 M1 最小闭环,但还没有达到“可稳定继续扩展第二批 Tag”的结构状态。
- 如果现在直接继续做 `BurnSpread`、`Pierce`、`Overpenetrate` 一类高侵入 Tag会把当前加载顺序、随机上下文和命中结算接口里的隐患一起放大。
- 因此 `S7` 的目标不是新增玩法,而是先把 Tag 系统的配置真相源、随机合同、战斗上下文合同与文档口径收稳。
### S7-01 整改口径
- `Tag.txt`、`TagConfig.txt`、registry 默认值三处不能再各自持有一份“是否首发 / 是否启用”的真相。
- `ProcedurePreload``Tag``TagConfig` 的加载完成顺序不能再影响 `TagDefinitionRegistry` 最终状态。
- 至少补一组 EditMode 测试覆盖“先加载 `Tag` 再加载 `TagConfig`”与“先加载 `TagConfig` 再加载 `Tag`”两种顺序,确认结果一致。
- 本项完成后,`ComponentTagGenerationService` 的首发过滤与展示 / 战斗的定义读取必须共享同一份最终状态。
### S7-02 整改口径
- `ComponentTagGenerationService` 需要正式接收并消费 `RunSeed` 或等价的显式随机上下文,而不是只依赖 `rarity + sourceType + itemInstanceId + configId`
- 掉落、商店、初始种子、事件奖励四条链路必须明确各自如何构造同构的 Tag 随机上下文。
- `EnemyDropResolver` 当前按 `Reset()` 把掉落实例 Id 重置为 `1` 的做法,只能作为局部实现细节,不能继续承担跨 Run 区分责任。
- 本项通过标准是:同一 Run 下同一实例上下文结果稳定;不同 Run 即使出现相同配置与实例序号,也能由 `RunSeed` 拉开结果空间。
### S7-03 整改口径
- `HitContext` 需要补齐当前文档已经承诺的统一结算上下文职责,例如目标状态、击杀结果、攻击来源与后续第二批 Tag 需要的命中信息。
- `TagEffectResolver.ResolveBeforeHit` 不再继续新增 `targetCurrentHealth`、`targetHasSlowStatus` 这类散装参数。
- 数值类、状态类、攻击形态类 Tag 统一从上下文对象读取所需信息,避免每补一个 Tag 就再改一轮函数签名。
- 本项优先级高于第二批 Tag 落地;在 `S7-03` 完成前,不推进 `BurnSpread`、`Pierce`、`Overpenetrate` 的真实战斗效果。
### S7-04 整改口径
- `TagConfig.txt` 中当前保留的字段必须逐项确认:哪些已经是正式运行时字段,哪些只是占位。
- 例如 `Fire.MaxEffectiveStack` 这类已经进入表与配置类、但尚未参与实际结算的字段,需要二选一:
- 要么接入真实逻辑;
- 要么从当前正式口径中移除,避免形成“表能改、逻辑不跟”的假配置。
- `Inferno`、`AbsoluteZero` 这类强化 Tag 也需要明确:它们是继续走独立 `TriggerPhase` 路由,还是正式定义为“依附主状态 Tag 的修饰器”。
- 本项完成后,`TagConfig.txt`、`TagDefinitionRegistry`、`TagEffectResolver` 与实际战斗行为必须一一对应。
### S7-05 整改口径
- `docs/TagSystemDesign.md` 需要把“当前正式口径”“已实现状态”“后续预案 / 历史草稿”彻底拆开。
- 当前正式口径只保留 M1 已收口与 `S7` 审计确认后的内容,不再在同一文件主路径里混写旧的 12 Tag 流派设计草稿。
- `CodeX-TODO.md` 继续只记录执行顺序与整改项,不重复承担大段玩法设计说明。
- 本项完成后,后续继续改 Tag 时,开发与策划应能只看文档主干就拿到当前真实执行口径。
## 推荐执行顺序 ## 推荐执行顺序
1. `S1 ~ S3` 已完成,不再作为当前主阻塞项。 1. `S1 ~ S3` 已完成,不再作为当前主阻塞项。
2. `S4` 已完成,当前不再把三表方案作为 M1 主阻塞项。 2. `S4` 已完成,当前不再把三表方案作为 M1 主阻塞项。
3. `S5` 已完成,当前无需继续按旧耐久设计拆任务。 3. `S5` 已完成,当前无需继续按旧耐久设计拆任务。
4. `S6` 转入“测试补强 + 旧文档清理”收尾;重点不再是补主功能,而是把现状固化并避免后续继续按旧口径推进。 4. `S6` 已完成本轮“测试补强 + 文档清理”收尾。
5. `S6` 完成后,再决定是否把维修、自动销毁、耐久折价、更多 Tag 元数据配置化等长期设计拆成新的增强阶段。 5. 当前优先进入 `S7-01 ~ S7-03`,先收口 Tag 的配置真相源、随机合同与战斗上下文合同。
6. 再推进 `S7-04 ~ S7-05`,把配置字段与文档口径收稳。
7. `S7` 完成前,不提前展开 `BurnSpread`、`IgniteBurst`、`FreezeMask`、`Pierce`、`Overpenetrate` 的真实战斗效果。
8. 后续若继续推进维修、自动销毁、耐久折价、更多 Tag 元数据配置化等长期设计,应作为新的增强阶段单独拆项。
## 本周建议开工顺序 ## 本周建议开工顺序
1. 先补 `S6-01 ~ S6-02` 的主链路 / 规则回归测试,把当前 M1 口径固化下来 1. 先`S7-01`,把 `Tag.txt / TagConfig.txt / registry` 的真相源与加载顺序问题收掉
2. 再继续处理 `S6-04`,清理 `MVP-Scope`、`GameDesign` 等仍保留旧范围描述的文档 2. 再`S7-02 ~ S7-03`,补齐 `RunSeed` 随机合同和命中上下文合同
3. 最后再决定是否开启新的增强阶段,而不是回头重开 `S4-07` 3. 然后做 `S7-04 ~ S7-05`,把配置字段与设计文档统一回写
## 备注 ## 备注

View File

@ -32,11 +32,11 @@
- 关卡开始有一些资源用于布置防御塔,击杀敌人获取资源来布置或升级防御塔。 - 关卡开始有一些资源用于布置防御塔,击杀敌人获取资源来布置或升级防御塔。
- 敌人会选择最短路径由出怪口向玩家基地前进;道路阻挡与更复杂的路径改写机制保留到后续阶段 - 敌人会选择最短路径由出怪口向玩家基地前进;道路阻挡与更复杂的路径改写机制保留到后续阶段
2. 击杀敌人除了获取关卡内使用的资源外,还有概率掉落防御塔组件;每个小关卡结束后也会奖励组件与金币用于后续节点 2. 击杀敌人除了获取关卡内使用的资源外,还有概率掉落防御塔组件;每个小关卡结束后也会奖励组件与金币用于后续节点
3. 关卡内设定一个胜利波次,当玩家存活的波次达到后会根据基地生命产生不同的事件 3. 关卡内设定一个胜利波次,当玩家存活的波次达到后会根据基地生命产生不同的结算
- = 100% :获得额外 30% 的金币,以及额外 1 次组件 3 选 1 - = 100% :获得额外 30% 的金币,以及额外 1 次组件 3 选 1
- >= 80% :获得额外 10% 的金币 - >= 80% :获得额外 10% 的金币
- >= 50% :无加成 - >= 50% :无加成
- < 50%损失携带防御塔耐久 - < 50%当前 M1 不再追加额外耐久惩罚耐久已按每场战斗结算后对本场参战塔固定扣 1收口
4. “胜利后继续挑战”保留到后续阶段,当前 M1 以正常结算回流节点地图为准 4. “胜利后继续挑战”保留到后续阶段,当前 M1 以正常结算回流节点地图为准
#### 2. 事件节点 #### 2. 事件节点
@ -60,4 +60,4 @@
- 品质计算每个组件提供一定的品质权重1绿2345比如三个组件是 2 绿 1 白,那么防御塔的品质是 (2+2+1)/3=1.67,四舍五入后为 2 也就是绿色品质。 - 品质计算每个组件提供一定的品质权重1绿2345比如三个组件是 2 绿 1 白,那么防御塔的品质是 (2+2+1)/3=1.67,四舍五入后为 2 也就是绿色品质。
- 各品质的配件槽与更深的配件系统保留到后续阶段 - 各品质的配件槽与更深的配件系统保留到后续阶段
- 组件 Tag 当前正式采用 `Tag.txt + RarityTagBudget.txt + TagConfig.txt` 三表方案:`Tag.txt` 负责基础字典、生成门槛、权重与启用态,`RarityTagBudget.txt` 负责按品质的 Tag 数量预算,`TagConfig.txt` 负责触发阶段、描述与效果参数 - 组件 Tag 当前正式采用 `Tag.txt + RarityTagBudget.txt + TagConfig.txt` 三表方案:`Tag.txt` 负责基础字典、生成门槛、权重与启用态,`RarityTagBudget.txt` 负责按品质的 Tag 数量预算,`TagConfig.txt` 负责触发阶段、描述与效果参数
2. 拆解与耐久:当前 M1 只保留最小耐久闭环,即战斗后按参战塔真实扣减、`0` 耐久失效并拦截参战 / 战斗入口;连续属性衰减、自动销毁与维修系统保留到后续阶段 2. 拆解与耐久:当前 M1 只保留最小耐久闭环,即每场战斗结算后按本场参战塔真实扣减 `1` 点耐久、`0` 耐久失效并拦截参战 / 战斗入口;连续属性衰减、自动销毁与维修系统保留到后续阶段

View File

@ -80,12 +80,7 @@
| [ ] | D-07 | P1 | 主题地图反制机制(每主题至少 2 个可用对策) | `Assets/GameMain/Scripts/Entity/`<br>`Assets/GameMain/Scripts/Scene/`<br>`Assets/GameMain/DataTables/*.txt` | 火山与山地都存在明确反制构筑UI 有可读提示 | | [ ] | D-07 | P1 | 主题地图反制机制(每主题至少 2 个可用对策) | `Assets/GameMain/Scripts/Entity/`<br>`Assets/GameMain/Scripts/Scene/`<br>`Assets/GameMain/DataTables/*.txt` | 火山与山地都存在明确反制构筑UI 有可读提示 |
| [ ] | D-08 | P0 | 先定义数值预算(经济/敌强/掉落)再调参 | `docs/NumericBudget.md`<br>`Assets/GameMain/DataTables/*.txt` | 关键曲线有目标区间3 局测试结果可与目标对比复盘 | | [ ] | D-08 | P0 | 先定义数值预算(经济/敌强/掉落)再调参 | `docs/NumericBudget.md`<br>`Assets/GameMain/DataTables/*.txt` | 关键曲线有目标区间3 局测试结果可与目标对比复盘 |
## 小目标 ## 当前收尾重点
1. CombatNodeComponent战斗节点的逻辑补全 1. 继续补 `Assets/Tests/` 的主链路回归,优先覆盖跨节点流程编排与更完整的 PlayMode 场景验证
- 完整塔防流程:初始硬币,敌人掉落硬币数量、基地生命与失败设计 2. 继续同步 `docs/MVP-Scope.md`、`docs/GameDesign.md` 等旧设计文档,避免后续按过期口径推进
- 敌人随机掉落局外资源(金币、组件) 3. 将“维修系统”“商店出售与复杂定价”“更多 Tag / 主题地图机制”等长期设计拆回后续阶段,不再混入当前 M1 已收口范围
- 无限波次下敌人血量、资源爆率的增加
- 基地血量满足一定条件的额外奖励
2. ShopNodeComponent商店节点的逻辑补全
3. RepoForm仓库的逻辑补全
- 组装防御塔逻辑的落实

View File

@ -1,107 +1,91 @@
# Tag System Design # Tag System Design
最后更新2026-03-11 最后更新2026-03-12
> 目标:固定 GeometryTD 当前 M1 的 Tag 系统正式口径,明确三表配置职责、实际消费链,以及后续增强边界。 > 目标:这是 GeometryTD 当前 Tag 系统的唯一正式口径。
> 本文档只记录当前真实实现、已确认的问题与后续整改边界。
> 历史流派草稿不再作为主文档内容。
## 1. 当前现状 ## 1. 当前范围
当前仓库已经形成 M1 所需的 Tag 最小闭环: M1 已完成 Tag 最小闭环:
- `TagType` 已定义 12 个 Tag`Assets/GameMain/Scripts/Definition/Enum/TagType.cs` - 组件实例 Tag 已统一生成,不再直接复制 `PossibleTag`
- `Tag.txt` 已定义 Tag 名称、`MinRarity`、`Weight`、`IsImplemented` - 塔级 Tag 已统一汇总为 `TagRuntimeData[]`
- `MuzzleComp.txt`、`BearingComp.txt`、`BaseComp.txt` 已定义 `PossibleTag` - UI 展示已优先消费 `TagRuntimes`
- `RarityTagBudget.txt` 已定义按品质的 Tag 数量预算 - 首发 7 个 Tag 已进入战斗实际生效
- `TagConfig.txt` 已定义触发阶段、描述与首发 Tag 的核心参数
- 组件实例、塔实例、UI 展示链路都已接入统一的生成、汇总与说明消费口径
当前 `S4-07` 收尾只处理三件事 当前正式首发 7 个 Tag
- 明确三表就是 M1 的正式配置方案,不再保留 `TagRule` 作为当前未决项 - `Fire`
- 统一默认值、运行时加载与文档描述,避免回退到旧口径 - `Ice`
- 把未首发 Tag 保持为占位扩展,而不是误判为当前必须实现的功能缺口 - `Crit`
- `Execution`
- `Shatter`
- `Inferno`
- `AbsoluteZero`
## 2. 设计目标 当前明确后移的 5 个 Tag
Tag 系统需要同时满足四个目标: - `BurnSpread`
- `IgniteBurst`
- `FreezeMask`
- `Pierce`
- `Overpenetrate`
1. 组件实例上的 Tag 来源统一,不能继续由不同链路各自硬编码 当前不展开:
2. Tag 随机结果可复现,掉落、商店、初始种子、存档读档后口径一致
3. 塔由三组件组装后Tag 汇总结果可解释,重复 Tag 的处理规则清晰
4. 战斗中的 Tag 生效有统一挂载点,不把效果分散塞进子弹、敌人、塔控制器各处
## 3. 核心设计问题 - 高级传播 / 多命中 / 击杀链式效果
- 复杂流派激活矩阵
- Tag 等级成长
- `TagGroup` 运行时规则
### 3.1 Tag 类型混杂 ## 2. 正式决策
当前 `TagType` 同时混了三类语义: 1. Tag 在组件实例创建时随机;组塔阶段只汇总,不重新随机。
2. 组件表的 `PossibleTag` 只表示候选池,不代表实例最终持有结果。
3. 组塔后重复 Tag 不丢弃,而是转为塔级 `Stack`
4. 配置层正式采用 `Tag.txt + RarityTagBudget.txt + TagConfig.txt` 三表结构。
5. 战斗中的 Tag 统一挂在 `AttackPayload -> HitContext -> TagEffectResolver` 链路上。
6. 新逻辑应优先使用 `TagRuntimes``Tags` 只保留兼容投影职责。
7. `TagGroup` 当前只作为展示元数据,不进入生成、汇总或战斗规则。
- 状态类:`Fire`、`Ice` ## 3. 配置模型
- 数值修正类:`Crit`、`Execution`、`Shatter`
- 攻击形态类:`BurnSpread`、`Pierce`、`Overpenetrate`
这三类 Tag 的触发时机不同: ### 3.1 三表职责
- 有的在命中前生效 `Tag.txt`
- 有的在命中时生效
- 有的在命中后挂状态
- 有的在击杀后触发
如果后续继续只用一个 `TagType[]` 直接驱动所有逻辑代码会迅速失控。后续实现必须引入“Tag 元数据 + 触发阶段”的概念。 - 负责基础字典与生成规则
- 当前字段:`TagType`、`Name`、`TagGroup`、`MinRarity`、`Weight`、`IsImplemented`
### 3.2 候选 Tag 不等于实例 Tag `RarityTagBudget.txt`
组件表中的 `PossibleTag` 应理解为“这个组件可能产出的 Tag 候选池”,不是实例最终持有的 Tag 列表。 - 负责按品质定义组件实例本次可抽取的 Tag 数量预算
- 当前字段:`Rarity`、`MinCount`、`MaxCount`
正确关系应为: `TagConfig.txt`
- DataTable给候选池 - 负责战斗与展示相关配置
- 实例生成器:按规则从候选池里抽 Tag - 当前字段:`TriggerPhase`、`Description`、`ParamJson`
- 组件实例:保存最终抽出的 Tag 结果
- 塔实例:组装时汇总三组件 Tag
### 3.3 重复 Tag 如何处理 ### 3.2 当前消费链
三组件组塔后,同一个 Tag 很可能在多个组件上重复出现。这里必须明确规则,否则后续实现会反复返工。 - `Tag.txt -> DRTag -> TagGenerationRuleRegistry`
- 当前负责 `MinRarity``Weight`
- `Tag.txt -> DRTag -> TagDefinitionRegistry.ApplyTagRows`
- 当前负责把 `IsImplemented` 同步到定义层
- `RarityTagBudget.txt -> DRRarityTagBudget -> RarityTagBudgetRuleRegistry`
- 当前负责按品质读取 `MinCount / MaxCount`
- `TagConfig.txt -> DRTagConfig -> TagDefinitionRegistry`
- 当前负责 `TriggerPhase`、`Description` 与各 Tag 参数配置
固定规则: ### 3.3 运行时结构
- 同一组件内不允许重复同一个 Tag - 组件实例保存 `TagType[]`
- 不同组件之间允许重复 - 塔实例保存 `TagRuntimeData[]`
- 组塔时不直接丢弃重复 Tag而是转成 `Stack` - 塔实例同时保留 `Tags` 作为兼容投影
- 战斗载荷保存塔级 `TagRuntimeData[]`
也就是说,最终塔上的 Tag 结果不应该只是简单 `TagType[]`而应该是“Tag + 层数”。
## 4. 推荐的数据模型
### 4.1 配置层
当前实现固定采用“`Tag.txt + RarityTagBudget.txt + TagConfig.txt`”三层结构,而不是继续把所有规则硬塞进现有 `Tag.txt`
- `Tag.txt`
- 保留 `TagType`、`Name` 等基础字典与按 Tag 的生成规则
- 当前实际承载:`MinRarity`、`Weight`
- `RarityTagBudget.txt`
- 承载按品质的数量预算
- 当前实际承载:`Rarity`、`MinCount`、`MaxCount`
- `TagConfig.txt`
- 承载战斗与展示相关配置
- 当前实际承载:`TriggerPhase`、`Description`、`ParamJson`
用途:
- `MinRarity`:该 Tag 最低可出现品质
- `Weight`:同一候选池内抽取权重
- `MinCount / MaxCount`:该品质组件本次可抽取的 Tag 数量预算
- `TriggerPhase`:用于战斗结算路由
- `ParamJson`:承载伤害倍率、持续时间、范围等效果参数
### 4.2 运行时结构
当前 M1 运行时结构固定为两层:
- 组件实例继续保存 `TagType[]`
- 塔实例保存汇总后的 `TagRuntimeData[]`
```csharp ```csharp
public sealed class TagRuntimeData public sealed class TagRuntimeData
@ -111,544 +95,192 @@ public sealed class TagRuntimeData
} }
``` ```
职责划分: ### 3.4 当前最小战斗结构
- 组件实例保存 `TagType[]` - `AttackPayload`
- 塔实例保存汇总后的 `TagRuntimeData[]` - 当前字段:`BaseDamage`、`AttackPropertyType`、`TagRuntimes`
- UI 展示可以继续只展示 Tag 名称,但底层不再丢失层数信息 - `HitContext`
- 当前字段:`AttackPayload`、`FinalDamage`、`IsCriticalHit`、`IsKilled`
- 这套结构已经足够承载首发 7 个 Tag
- 但还不足以稳定承载第二批攻击形态类 Tag详见第 7 节审计问题
## 5. 组件上如何随机生成 Tag ## 4. 组件 Tag 生成
### 5.1 随机时机 ### 4.1 当前流程
Tag 随机应发生在“组件实例创建时”,而不是组塔时。
包括以下来源:
- 初始种子生成组件
- 战斗掉落生成组件
- 商店刷新生成组件
- 事件奖励生成组件
这样做的好处:
- 玩家拿到手的组件就是确定结果
- 背包展示、组装预览、商店预览都能直接展示真实 Tag
- 存档不需要二次重算
### 5.2 候选池构建
单个组件实例的候选池按以下规则生成:
1. 读取组件配置的 `PossibleTag` 1. 读取组件配置的 `PossibleTag`
2. 读取 Tag 表 2. 读取 `Tag.txt` 中对应的生成规则
3. 过滤掉 `MinRarity > 组件品质` 的 Tag 3. 过滤掉 `None`、非法枚举、当前未首发支持的 Tag
4. 只保留同时存在于 `PossibleTag` 与 Tag 表允许范围内的 Tag 4. 过滤掉 `MinRarity > 当前组件品质` 的 Tag
5. 根据 `RarityTagBudget.txt` 决定本次抽取数量
6. 在候选池内按 `Weight` 抽取
7. 单组件内不重复抽取同一 Tag
8. 候选池不足时允许少于预算,不强行补满
结果: ### 4.2 当前统一入口
- `PossibleTag` 决定这个组件系列“能出什么” - `InventorySeedUtility`
- `MinRarity` 决定当前品质“允许出到什么档位” - `ShopFormUseCase`
- `EnemyDropResolver`
- 事件奖励后续如生成组件,也必须走同一入口
- 当前统一入口是 `ComponentTagGenerationService`
### 5.3 Tag 数量预算 ### 4.3 可复现合同
每个品质都保留独立的 Tag 数量预算,并由 `RarityTagBudget.txt` 驱动,而不是按概率硬编码在代码里。 - 设计目标要求 Tag 结果对同一 Run 可复现,并在存档读档后保持一致
当前正式默认值: 正式随机上下文应包含:
| 品质 | 推荐数量 |
|------|----------|
| White | `0~1` |
| Green | `0~2` |
| Blue | `1~3` |
| Purple | `1~3` |
| Red | `2~4` |
### 5.4 随机规则
固定抽取流程:
1. 先根据品质决定本组件本次要抽几个 Tag
2. 从候选池中按 `Weight` 抽取
3. 单组件内不重复抽同一个 Tag
4. 候选池不足时允许少于目标数量,不强行补 Tag
### 5.5 可复现要求
Tag 随机必须可复现。
统一随机种子来源:
- `RunSeed` - `RunSeed`
- `ItemInstanceId` - `ItemInstanceId`
- `ConfigId` - `ConfigId`
- `SourceType`(掉落 / 商店 / 初始 / 事件) - `SourceType`
原则 当前实现已经使用:
- 同一个组件实例只生成一次 Tag - `Rarity`
- 存档与读档不重新随机 - `SourceType`
- 商店刷新前后只有新实例才会有新结果 - `ItemInstanceId`
- `ConfigId`
- 当前实现尚未把 `RunSeed` 作为显式输入接进 `ComponentTagGenerationService`
- 这是当前已确认的问题,不应视为已完成能力
## 6. 组塔后的 Tag 汇总规则 ## 5. 塔级汇总与展示
组塔阶段不再随机,只做汇总。 ### 5.1 汇总规则
固定流程: - 同一组件内不允许重复同一个 Tag
- 不同组件之间允许重复
- 组塔时不做重新随机
- 汇总时按 `TagType` 分组并累加 `Stack`
1. 收集三组件的 `TagType[]` ### 5.2 展示规则
2. 按 `TagType` 分组
3. 累加 `Stack`
4. 输出塔级别的 `TagRuntimeData[]`
示例: - 组件展示仍显示组件实例自己的 `Tags`
- 塔展示优先显示 `TagRuntimes`
- 若缺少 `TagRuntimes`,允许通过 `Tags` 回退构建兼容结果
- 重复 Tag 以 `xN` 文本显示,例如 `Fire x2`
- 枪口:`Fire x1` ### 5.3 兼容边界
- 轴承:`Fire x1`, `BurnSpread x1`
- 底座:`Inferno x1`
组塔后: - `TowerStatsData.Tags` 不是新的真相源
- 它只用于兼容旧展示链路与旧数据
- 后续新增逻辑应优先读取 `TagRuntimes`
- `Fire x2` ## 6. 战斗模型
- `BurnSpread x1`
- `Inferno x1`
这比简单去重更合理,因为后续战斗效果可以基于层数增强,而不是浪费重复结果。 ### 6.1 分类与触发阶段
## 7. 战斗中如何生效 | 分类 | 说明 | 当前主触发阶段 |
|------|------|----------------|
| `Status` | 命中后在敌人身上形成可持续状态 | `OnAfterHit` |
| `NumericModifier` | 命中前修正最终伤害 | `OnBeforeHit` |
| `AttackShape` | 穿透、传播、爆炸等攻击形态变化 | `OnHit` / `OnKill` |
| `StatusModifier` | 强化同次命中的状态类 Tag但不独立生成敌人持有状态 | 当前随主状态一起消费 |
### 7.1 现有链路限制 ### 6.2 当前已实现的首发 7 Tag
当前战斗链路是: | Tag | 分类 | 配置阶段 | 当前真实行为 |
|-----|------|----------|--------------|
| `Fire` | `Status` | `OnAfterHit` | 命中后施加燃烧 DOT |
| `Ice` | `Status` | `OnAfterHit` | 命中后施加减速 |
| `Crit` | `NumericModifier` | `OnBeforeHit` | 按概率暴击并放大伤害 |
| `Execution` | `NumericModifier` | `OnBeforeHit` | 对低血量目标增伤 |
| `Shatter` | `NumericModifier` | `OnBeforeHit` | 对已减速目标增伤 |
| `Inferno` | `StatusModifier` | `OnAfterHit` | 强化同次命中的 `Fire` 时长与伤害 |
| `AbsoluteZero` | `StatusModifier` | `OnAfterHit` | 强化同次命中的 `Ice` 时长与减速强度 |
- `TowerController` 取塔属性 ### 6.3 当前已后移的 5 Tag
- `BasicBaseComp` 发起攻击
- `ShooterMuzzleComp` 创建子弹
- `ShooterBullet` 命中后调用 `IDamageReceiver.TakeDamage(int damage, AttackPropertyType attackPropertyType)`
这条链路只够表达: | Tag | 分类 | 当前状态 |
|-----|------|----------|
| `BurnSpread` | `AttackShape` | 仅保留元数据与占位路由,未实际生效 |
| `IgniteBurst` | `AttackShape` | 仅保留元数据与占位路由,未实际生效 |
| `FreezeMask` | `AttackShape` | 仅保留元数据与占位路由,未实际生效 |
| `Pierce` | `AttackShape` | 仅保留元数据与占位路由,未实际生效 |
| `Overpenetrate` | `AttackShape` | 仅保留元数据与占位路由,未实际生效 |
- 伤害数值 ### 6.4 当前运行时边界
- 伤害属性
不够表达: - 数值类 Tag 当前在 `ResolveBeforeHit` 阶段生效
- 状态类 Tag 当前通过 `EnemyTagStatusRuntime` 管理敌人持有状态
- `Inferno``AbsoluteZero` 当前不是独立状态,而是在 `FireTagEffect`、`IceTagEffect` 中读取同次命中的强化层数
- 攻击形态类 Tag 当前只有路由骨架,没有真实战斗效果
- 暴击 ## 7. 已确认审计问题
- 斩杀
- 燃烧 DOT
- 冻结层数
- 穿透与连锁
- 命中后爆炸
所以 Tag 不能直接继续依附在 `TakeDamage(int, AttackPropertyType)` 上。 ### 7.1 配置真相源与加载顺序不稳定
### 7.2 推荐挂载点 - `IsImplemented` 当前同时存在于 `Tag.txt` 与定义层默认值
- `Tag``TagConfig` 的 DataTable 加载先后会影响 `TagDefinitionRegistry` 最终状态
- 这意味着“Tag 是否首发启用”还没有成为稳定的唯一真相源
后续战斗入口固定引入统一的命中载荷与结算器: ### 7.2 Tag 随机合同未完整落地
```csharp - 文档口径要求随机上下文包含 `RunSeed`
AttackPayload - 当前 `ComponentTagGenerationService` 还没有显式接收 `RunSeed`
``` - 当前掉落链路的实例 Id 也会在局部重置,不能继续承担跨 Run 区分责任
至少包含: ### 7.3 战斗上下文合同仍偏弱
- `BaseDamage` - `HitContext` 当前只够承载首发数值修正与最小状态挂载
- `AttackPropertyType` - 数值类 Tag 仍依赖 `targetCurrentHealth`、`targetHasSlowStatus` 这类散装参数
- `TagRuntimeData[]` - 如果直接继续做 `Pierce`、`BurnSpread` 等第二批 Tag函数签名会继续膨胀
- 攻击来源信息
命中时再构造: ### 7.4 配置字段与真实行为还没有完全对齐
```csharp - 当前 `TagConfig.txt` 里的部分字段已经进入表与配置类
HitContext - 但并非所有字段都成为真实运行时行为
``` - 例如 `Fire.MaxEffectiveStack` 当前并未进入实际结算
- 这类字段要么接入运行时,要么移出当前正式口径
至少包含: ### 7.5 主文档曾混入历史草稿
- `Attacker` - 本文件过去同时包含正式收口口径与旧的 12 Tag 流派草稿
- `Target` - 这种写法会让“当前真实实现”和“历史预案”混淆
- `AttackPayload` - 从本次更新开始,主文档只保留当前正式口径
- 是否击杀
- 命中位置
统一由: ## 8. 审计整改顺序
```csharp ### S7-01 收口配置真相源与加载顺序
TagEffectResolver
```
处理 Tag 逻辑。 - 统一 `IsImplemented` 的最终真相源
- 保证 `Tag.txt``TagConfig.txt` 的加载顺序不再影响最终定义结果
- 补加载顺序相关 EditMode 测试
### 7.3 触发阶段 ### S7-02 补齐随机上下文与 `RunSeed`
Tag 触发阶段固定拆成四段: - 给 `ComponentTagGenerationService` 增加显式随机上下文
- 把 `RunSeed` 纳入正式输入
- 统一掉落、商店、种子、事件奖励四条链路的上下文构造方式
1. `OnBeforeHit` ### S7-03 收口 `AttackPayload / HitContext` 合同
- 例:`Crit`、`Execution`
2. `OnHit`
- 例:直接附加伤害、穿透判定
3. `OnAfterHit`
- 例:施加燃烧、减速、冻结层数
4. `OnKill`
- 例:击杀爆炸、传播
这样可以避免把所有效果都堆进一个巨大 `switch` 里。 - 把当前散装战斗输入收回统一上下文对象
- 为第二批攻击形态类 Tag 预留稳定上下文
- 在本项完成前,不推进第二批 Tag 的真实战斗效果
## 8. 当前 12 个 Tag 的效果定位 ### S7-04 对齐 `TagConfig` 与运行时真实消费
### 8.1 第一批优先落地 - 清点每个 `ParamJson` 字段是否真的被运行时消费
- 已保留字段必须真实生效,或明确标记为占位
- 明确 `StatusModifier` 的正式消费方式
这些效果与当前伤害模型更兼容,适合作为第一批战斗 Tag ### S7-05 保持文档主干单一口径
| Tag | 首发定位 | - `TagSystemDesign.md` 只保留当前真实实现与整改边界
|-----|----------| - 新的长期预案应进入独立文档,而不是回写到本文件主干
| `Fire` | 命中附加燃烧 DOT |
| `Ice` | 命中附加减速 |
| `Crit` | 命中前按概率暴击 |
| `Execution` | 对低血量目标增伤或直接处决 |
| `Shatter` | 对已减速 / 已冻结目标增伤 |
| `Inferno` | 强化燃烧伤害或持续时间 |
| `AbsoluteZero` | 强化减速,或提高冻结触发速度 |
这些效果主要需要: ## 9. 当前默认边界
- 命中前倍率修正 - 在 `S7-01 ~ S7-04` 完成前,不新增第二批 Tag 的真实战斗效果
- 敌人状态容器 - 在配置真相源收稳前,不继续增加新的“是否启用”字段来源
- DOT / Slow 的 runtime tick - 在 `HitContext` 收稳前,不继续依赖更多散装参数扩展 Tag 逻辑
- 在 `TagConfig` 消费对齐前,不继续向 `ParamJson` 追加没有运行时消费者的字段
对当前战斗架构侵入相对可控。 ## 10. 非当前范围
### 8.2 第二批再落地 - `BurnSpread`、`IgniteBurst`、`FreezeMask`、`Pierce`、`Overpenetrate` 的真实战斗实现
- 更复杂的多 Tag 联动与流派激活矩阵
这些效果需要更完整的弹道 / 范围 / 状态系统,固定放到后续阶段实现: - 冻结积累条、击杀爆炸传播链、多命中弹道系统
- Tag 等级成长、TagGroup 运行时规则、额外 Tag 元数据扩展表
| Tag | 后续定位 |
|-----|----------|
| `BurnSpread` | 燃烧向邻近敌人传播 |
| `IgniteBurst` | 燃烧结束或击杀时爆炸 |
| `FreezeMask` | 冻结积累条 / 冻结面具机制 |
| `Pierce` | 子弹贯穿多个目标 |
| `Overpenetrate` | 贯穿后保留部分伤害继续飞行 |
这些效果会牵动:
- 子弹多命中
- 范围查询
- 击杀后触发
- 敌人持续状态传播
不适合在最早版本一次性塞进当前命中链路。
## 9. 推荐的分阶段实施方案
### Phase 1规则入口
目标:
- 补齐 Tag 配置模型
- 实现组件实例随机生成 Tag
- 统一掉落 / 商店 / 初始种子 / 事件奖励入口
交付重点:
- `TagGenerationService`
- `TagGenerationResult`
- 组件实例保存最终 Tag 结果
### Phase 2塔级汇总
目标:
- 组塔时把三组件 Tag 汇总成塔级结果
- 不再简单去重,而是保留层数
交付重点:
- `TowerTagAggregationService`
- 塔实例保存 `TagRuntimeData[]`
### Phase 3战斗载荷
目标:
- 把塔的 Tag 结果传到子弹 / 命中链路
- 引入统一结算入口
交付重点:
- `AttackPayload`
- `HitContext`
- `TagEffectResolver`
### Phase 4第一批战斗效果
正式首发集合固定为:
- `Fire`
- `Ice`
- `Crit`
- `Execution`
- `Shatter`
- `Inferno`
- `AbsoluteZero`
这批做完后Tag 系统就从“展示字段”升级成“有实际战斗意义的最小闭环”。
### Phase 5高级联动
后续再做:
- 传播
- 爆炸
- 冻结积累
- 穿透与多命中
- 更复杂的多 Tag 联动
## 10. 与当前 MVP 范围的关系
当前 `docs/TODO.md` 已把 `P0-11` 收口为“规则最小闭环”。本设计文档与该口径保持一致:
- M1 最低要求是统一 Tag 来源与汇总规则
- M1 不强制要求一次做完全部高级联动
- 若要在 M1 内让 Tag 进入战斗,只做第一批效果,不同时展开高级传播 / 贯穿体系
同时需要注意,`docs/MVP-Scope.md` 里写了:
- 基础 Tag 系统只保留 `6~8`
- 不做高级 Tag 联动
- 不做复杂触发矩阵
因此后续真正实施时MVP 正式首发集合固定为以下 7 个:
- `Fire`
- `Ice`
- `Crit`
- `Execution`
- `Shatter`
- `Inferno`
- `AbsoluteZero`
`BurnSpread`、`Pierce`、`Overpenetrate`、`FreezeMask`、`IgniteBurst` 都作为后续扩展,不属于当前 `S4` 首发范围。
## 11. 当前收口结论
1. `S4-07` 已确认采用 `Tag.txt + RarityTagBudget.txt + TagConfig.txt` 三层表结构作为正式方案
2. `ComponentTagGenerationService` 已收口组件实例生成,不再直接复制 `PossibleTag`
3. `TowerTagAggregationService` 已收口塔级汇总,重复 Tag 会转为 `TagRuntimeData.TotalStack`
4. `AttackPayload + HitContext + TagEffectResolver` 已成为当前战斗内的统一 Tag 挂载点
5. 首发只实现固定 7 个基础 Tag避免超出 `MVP-Scope`
## 12. 默认决策
若没有额外设计变更,后续默认按以下决策推进:
- Tag 在组件实例创建时随机,不在组塔时随机
- `PossibleTag` 是候选池,不是最终实例值
- 塔级 Tag 汇总保留 `Stack`
- 配置层正式采用 `Tag.txt + RarityTagBudget.txt + TagConfig.txt` 分层结构
- 第一批战斗效果优先做状态类与数值修正类,不优先做穿透 / 爆炸 / 传播
- MVP 正式首发集合固定为 `Fire`、`Ice`、`Crit`、`Execution`、`Shatter`、`Inferno`、`AbsoluteZero`
- `BurnSpread` 明确后移,不作为当前首发集合成员
- `TagGroup` 当前只作为分类展示元数据,不进入运行时生成、汇总或战斗规则链
# 总体结构
我们设计 3 个流派方向:
1. 🔥 元素爆发流AOE清场
2. ❄ 控制叠层流(减速控制)
3. 🎯 穿透暴击流(单体爆发)
每个流派 4 个 Tag其中
- 2 个基础属性 Tag
- 1 个机制 Tag
- 1 个高阶稀有Tag
总 Tag 数 = 12
## 一、🔥 元素爆发流
核心定位:
> 中等频率攻击 + 元素叠层 + 击杀爆炸清场
## 4 个 Tag
### 1⃣ Fire基础
效果:
- 攻击附带灼烧(持续伤害)
- 可叠加 3 层
### 2⃣ BurnSpread机制
触发:
- 目标死亡时将灼烧传播给周围 2 个敌人
### 3⃣ IgniteBurst组合触发
触发条件:
- 同一塔 ≥2 Fire Tag
效果:
- 满层灼烧爆炸小范围AOE
4⃣ Inferno稀有
品质限定:紫及以上
效果:
爆炸伤害 ×2
灼烧叠层上限 +2
流派触发逻辑
条件 效果
1 Fire 基础DOT
2 Fire IgniteBurst 激活
Fire + BurnSpread 爆炸后传播
Inferno + 2 Fire 大范围爆炸
二、❄ 控制叠层流
核心定位:
降速 + 冻结 + 稳定推进
4 个 Tag
1⃣ Ice基础
效果:
攻击附带减速
可叠加 5 层
2⃣ FreezeMark机制
触发:
目标叠满 5 层冻结 1 秒
3⃣ Shatter组合触发
触发:
冻结目标受到暴击时额外伤害
4⃣ AbsoluteZero稀有
品质限定:紫及以上
效果:
冻结时间 +50%
冻结爆裂产生小范围伤害
流派触发逻辑
条件 效果
1 Ice 减速
Ice + FreezeMark 满层冻结
冻结 + Shatter 爆裂伤害
AbsoluteZero 群控升级
三、🎯 穿透暴击流
核心定位:
低频高伤 + 直线穿透 + 单体爆发
4 个 Tag
1⃣ Pierce基础
效果:
子弹穿透 2 个敌人
2⃣ Crit基础
效果:
+15% 暴击率
3⃣ Overpenetrate机制
触发:
穿透第一个敌人后伤害提升 30%
4⃣ Execution稀有
品质限定:紫及以上
效果:
暴击对生命低于30%目标伤害 ×2
流派触发逻辑
条件 效果
Pierce 直线清场
Crit 随机爆发
Pierce + Crit Overpenetrate 激活
Execution 斩杀强化
四、品质与 Tag 关系设计
建议规则:
品质 Tag 数量
白 1
绿 1
蓝 2
紫 2 + 稀有概率
红 3含稀有
这样:
低品质仍有存在价值
高品质增加构筑复杂度
稀有 Tag 不会泛滥
五、组合系统可视化建议
在组装界面显示:
🔥 元素爆发(已激活)
灼烧爆炸
传播效果
❄ 冰霜控制(未激活)
需要 FreezeMark
这样玩家会有“完成拼图”的感觉。
六、数值安全机制(防止爆炸)
每个机制必须有:
触发冷却0.5~1秒
最大叠层限制
爆炸不触发爆炸(防无限连锁)
群体上限目标数
例如:
BurnSpread 最多传播 3 次。
否则后期怪物多时会帧率爆炸。