战斗
单一不可变快照
战斗排在最后:移动、Beacon、Worker、生产和修盾都处理完之后,引擎才冻结一份不可变 快照,然后完全照着它算:
- 所有锁定攻击都基于同一份快照校验。
- 累计全部合法攻击的伤害。
- 把累计的伤害同时应用。
- 到这一步才移除死亡的 Unit 和被摧毁的 Core。
因为校验和结算用的都是这张定格的画面,战斗中被杀死的对象仍然能打出它此前锁定的 合法攻击,同归于尽也就成了很常见的结果。谁都拿不到先手:请求到达的顺序、完成的 顺序、数据库行的顺序,以及计划来自 Manual 还是 Agent,全都不算。
v0.1 没有随机伤害、闪避、暴击、护甲、自动反击、体力、等级和装备。
Vanguard 横扫
{"type": "SWEEP", "direction": "UP"}
引擎看的是战斗快照里那一格相邻格的样子:
- 格子里每个敌方 Unit 各受 1 伤害;
- 格子里的敌方 Core 受 1 伤害;
- 友方对象不受伤害。
几个横扫指向同一个目标,伤害就叠起来。
Ranger 射击
{
"type": "SHOOT",
"target_id": "175f47f4-f7de-4785-b45c-9a2d2289a8ea",
"expected_cell": [120, 85]
}
Ranger 打的是横线或竖线上距离 1-3 格的某一个具体对象。中间只要有东西——障碍、Unit 或 Core——射线就被挡住。目标格本身可以叠着另一个对象,这不会产生任何前后顺序。
接口只检查结构,别的一概不管。所有动态失败都推迟到结算,统一变成 SHOT_MISSED:
- 目标已经不在了;
- 目标是友军;
- 目标离开了
expected_cell; - 目标在斜线上或者超出射程;
- 射线被挡。
这种含糊是故意的,就是不让命令接口顺便变成一个查雾区的工具。
Core 伤害
伤害永远先扣护盾,再扣 HP。全部战斗伤害合并之后 Core 的 HP 归零,它的舰队才会被 移除——但在那之前,它那些还活着的 Unit 在快照里打出的攻击一样算数。
这里没有「最后一击」可争。同一个 Tick 里多名玩家一起打掉同一个目标,这次摧毁就是 共享的,不会按输入顺序判给某个人。
返回结果
战斗结果出现在下一条 state.events 里,形如:
{
"event_id": "e1841781-2a89-44e4-a5ce-d4bbc46d33a1",
"tick": 10583,
"event_type": "SHOT_HIT",
"actor_id": "9d3e4941-2816-4a39-a220-df8cd95e877d",
"target_id": "175f47f4-f7de-4785-b45c-9a2d2289a8ea",
"position": [120, 85]
}
普通可见状态里的敌方对象仍然不带 username 和 owner ID。