# 战斗总览 战斗在数据端完成:怪物先被计算成「计算后怪物」,再由伤害计算器根据怪物与勇士的属性算出伤害与回合数,最后经过战前脚本、战后脚本与状态钩子结算。本篇串起这条主线,各环节的细节见对应文档。 ## 伤害大致怎么算 一次战斗的伤害可以写成 `f(enemy, hero)`:`enemy` 是计算后的怪物对象,`hero` 是勇士属性对象。计算器读取双方的 `hp`、`atk`、`def`、`mdef` 等属性,返回: - `damage`:本次战斗勇士会损失的生命值; - `turn`:战斗持续多少回合。 数据端不逐帧模拟战斗,只根据公式给出这两个值。公式的实现与替换见[伤害计算](./enemy-calculator.md)。 ## 计算后怪物:buildup 的四个阶段 怪物在数据里保存的是基础属性与特殊属性。进入战斗前,怪物上下文会把每个怪物重建为「计算后怪物」(`enemyContext.buildup()`),分四步: 1. **光环与特殊查询**:把特殊属性转换成光环视图,按优先级执行会修改特殊属性的效果,确定每个怪物最终拥有哪些特殊属性; 2. **普通光环**:执行修改基础属性的光环效果; 3. **常规查询**:允许读取上下文(周围怪物、位置等),并修改自身基础属性; 4. **最终效果**:不再查询上下文,只对自身基础属性做收尾调整。 前三步都可能受优先级影响;光环与查询共用同一套优先级,见[怪物光环](./enemy-aura.md)与[怪物查询](./enemy-query.md)。最终效果见[最终属性效果](./enemy-final.md)。 ## 战斗流程 ```mermaid graph TD A[怪物基础数据] --> B[光环 / 查询 / 最终] B --> C[伤害计算 f(enemy, hero)] C --> D[战前脚本 before] D -->|返回 false| X[放弃战斗] D -->|返回 true| E[战斗结算 damage / turn] E --> F[战后脚本 after] F --> G[战后钩子与状态钩子] ``` - **基础数据**:怪物模板的属性与特殊属性,来自怪物数据; - **光环 / 查询 / 最终**:由 `enemyContext.buildup()` 生成计算后怪物; - **伤害计算**:`IDamageCalculator.calculate` 返回 `{ damage, turn }`; - **战前脚本**:`ICombatScript.before` 返回 `false` 时放弃战斗; - **战斗结算**:按 `damage` 扣血,按 `turn` 记录回合数; - **战后脚本**:`ICombatScript.after` 结算经验、金币等内容; - **战后钩子与状态钩子**:处理中毒、衰弱、重生等持续状态。 战斗流程本身由 `state.combat`(`ICombatFlow`)驱动,`battle(view)` 返回本次战斗的伤害信息。脚本见[战斗脚本](./enemy-combat-script.md),状态钩子见[状态钩子](./enemy-status-hooks.md)。 ## 流程步骤与对应文档 | 步骤 | 做什么 | 对应文档 | |------|--------|----------| | 特殊属性 | 定义怪物的机制与参数 | [特殊属性](./enemy-specials.md) | | 光环 | 影响周围怪物的基础属性或特殊属性 | [怪物光环](./enemy-aura.md) | | 查询 | 读取上下文后调整自身 | [怪物查询](./enemy-query.md) | | 最终效果 | 只调整自身基础属性 | [最终属性效果](./enemy-final.md) | | 伤害计算 | 实现 `f(enemy, hero)` | [伤害计算](./enemy-calculator.md) | | 地图伤害 | 勇士移动时按位置结算伤害 | [地图伤害](./enemy-map-damage.md) | | 战前 / 战后脚本 | 拦截战斗、结算奖励 | [战斗脚本](./enemy-combat-script.md) | | 状态钩子 | 处理中毒、衰弱、重生等状态 | [状态钩子](./enemy-status-hooks.md) | 勇士一侧的属性读写见[勇士属性](./hero-attribute.md)。