62 lines
4.2 KiB
Markdown
62 lines
4.2 KiB
Markdown
# Combat
|
||
|
||
Combat 模块提供不依赖具体角色类的伤害、韧性、战斗属性、标准 Ability 原型与移动适配。游戏仍负责角色
|
||
实体、动画和输入映射;模块不会创建通用 Actor 根类。
|
||
|
||
脚本入口 `eve.Combat()` 提供 `getName`,并可通过 `newRuntime()` 创建一个 Squirrel-owned
|
||
`CombatRuntime`。`registerFighter`、
|
||
`setMoveIntent`、`navigateTo`、`stop`、`advance`、`applyDamage`、`applyTimelineDamage` 和 `state`
|
||
全部返回统一 Result 投影;`applyTimelineDamage` 直接消费 Montage runtime event 的 payload JSON,并复用
|
||
`ActionDamageBinding` 校验,不会在示例脚本中复制伤害字段解析规则。
|
||
runtime 内部复用下述 C++ 权威实现,不在脚本层复制生命值或移动状态。runtime 随脚本对象 GC 销毁,
|
||
`ownership()` 返回 `owned`。
|
||
|
||
同一个 runtime 还内建并注册 `standardCombatAbilities()` 的 20 个定义。`grantAbility`、
|
||
`activateAbility`、`advanceAbilities`、`cancelAbility`、`abilityGrant` 和 `matchingAbilities` 直接投影
|
||
`AbilityRuntime`;冷却与 Action phase 只使用调用者注入的 tick/delta,不读取墙钟。`advanceAbilities`
|
||
推进所有活跃 execution、递减冷却并同步终态链接,脚本不应另外保存 active/cooldown 状态。
|
||
`registerTimelineAbility` 接收 `ActionTimelineEditor.snapshotJson()` 的规范 schema,将 timeline 的 actionId、
|
||
总时长和 physical split 映射为同一个 `ActionDefinition` 的 phase timing;同时显式设置 cooldown、
|
||
instancing、activation group 和可选 gameplay-event trigger。注册失败不会留下部分 definition。
|
||
`replaceTimelineAbility` 使用相同参数事务式热替换已有定义:grant、per-owner instance 与剩余冷却保持不变;
|
||
已激活 execution 继续持有提交时的旧快照,下一次激活才读取新的 timeline 与 actionId。
|
||
已有 grant 时不能热切换 instancing policy,避免悄悄改变 instance 身份语义。
|
||
|
||
## 角色移动与导航
|
||
|
||
`CombatLocomotionRuntime` 以 `SubjectRef` 注册角色,并唯一拥有水平位置、速度、朝向、移动意图和导航目标:
|
||
|
||
```cpp
|
||
DirectCombatNavigationProvider navigation;
|
||
CombatLocomotionRuntime locomotion(navigation);
|
||
locomotion.registerSubject({fighter, "fighter:player", {0.0, 0.0}, 5.0, 18.0});
|
||
locomotion.setMoveIntent(fighter, {1.0, 0.0}, 1.0);
|
||
locomotion.advance({tick, fixedDelta});
|
||
```
|
||
|
||
方向不要求预先归一化,速度比例必须位于 `[0,1]`。玩家或 AI 的直接移动会清除该角色旧导航目标;
|
||
`navigateTo` 则要求安装 `ICombatNavigationProvider`。内置 `DirectCombatNavigationProvider` 适合无障碍 arena。
|
||
启用 2D/3D profile 时,可选 `combat_navigation` 卫星提供 `PathfinderCombatNavigationProvider`:
|
||
|
||
```cpp
|
||
map::Pathfinder pathfinder(width, height);
|
||
auto navigation = combat::navigation::PathfinderCombatNavigationProvider::create(
|
||
pathfinder, {{worldOriginX, worldOriginZ}, cellSize});
|
||
CombatLocomotionRuntime locomotion(*navigation.value());
|
||
```
|
||
|
||
它把世界 X/Z 投影到地图格,每步调用 canonical `Pathfinder` 取得下一 waypoint;不会缓存 Path,因此地图阻挡、
|
||
TileLayer revision 或代价改变会在下一步重新规划。不可达目标返回 `NotFound`,并由 locomotion 的整帧事务语义保证
|
||
所有角色都不发生部分移动。`Pathfinder` 必须比 provider 活得更久。
|
||
|
||
整帧更新具有原子语义:运行时先复制全部状态,再依次取得导航 steering、限制加速度并积分,全部成功后才
|
||
发布。Provider 失败、返回非有限值或非法比例时,没有任何角色移动。Provider 是借用对象,必须比运行时活得
|
||
更久,或者在销毁前调用 `clearNavigationProvider`;若清除时仍有活动目标,后续 `advance` 会明确失败,目标不会
|
||
被悄悄丢弃。到达目标会返回 owning `CombatLocomotionEventKind::Arrived` 事件。
|
||
|
||
## 组合边界
|
||
|
||
移动状态应由表现层投射到 Scene/Physics,由 Ability Active 阶段决定冲刺、闪避等动作何时写入移动意图。
|
||
Ability 生命周期仍由 `AbilityRuntime`/`ActionRuntime` 唯一拥有,伤害仍通过 `DamageRuntime` 或
|
||
`CombatActionDamageSink` 提交;不要在角色 Controller 中复制冷却、动作阶段或生命值。
|