跳到主要内容

战斗

单一不可变快照

战斗排在移动、Beacon 和 Worker 动作之后,但在 HP 恢复、修盾和生产之前。引擎会冻结 一份不可变快照,然后完全照着它算:

  1. 所有锁定攻击都基于同一份快照校验。
  2. 累计全部合法攻击的伤害。
  3. 把累计的伤害同时应用。
  4. 到这一步才移除死亡的 Unit 和被摧毁的 Core。

移除结束后,仍存活的 Unit 可以恢复 HP,然后仍存活的 Core 才能恢复 HP、修盾或生产。 所以致死伤害无法恢复,刚修好的护盾不能替你吸收刚结束的这轮伤害,新生产的 Unit 也不会 在出生 Tick 被攻击。

因为校验和结算用的都是这张定格的画面,战斗中被杀死的对象仍然能打出它此前锁定的 合法攻击,同归于尽也就成了很常见的结果。谁都拿不到先手:请求到达的顺序、完成的 顺序、数据库行的顺序,以及计划来自 Manual 还是 Agent,全都不算。

v0.1 没有随机伤害、闪避、暴击、护甲、自动反击、体力、等级和装备。

Vanguard 横扫

{"type": "SWEEP", "direction": "UP"}

引擎看的是战斗快照里那一格相邻格的样子:

  • 格子里每个敌方 Unit 各受 1 伤害;
  • 格子里的敌方 Core 受 1 伤害;
  • 友方对象不受伤害。

几个横扫指向同一个目标,伤害就叠起来。

Ranger 射击

{
"type": "SHOOT",
"expected_cell": [120, 85]
}

Ranger 可以射击横线、竖线或 45° 斜线上距离 1-3 格的任意格子,即使命令提交时该格 还是空的。移动先结算;服务端命中届时格内 HP 最低的敌方对象,HP 相同时按 UUID 原始 字节序。相对位置 (3, 3) 算 3 格,(2, 1) 不在合法直线上。只有射线实际经过的中间格 障碍物会挡住射线。Unit 和 Core 无论敌我都不阻挡,斜线两侧的障碍物也不阻挡。

旧客户端仍可带 target_id。这种精准模式只会命中仍为敌方且仍在 expected_cell 的 指定对象,不会改打同格的其他对象。

接口只检查结构,别的一概不管。所有动态失败都推迟到结算,统一变成 SHOT_MISSED

  • 格子为空,或精准目标不存在、是友军、已经移开;
  • 目标格不在八条射击直线上,或者超出射程;
  • 射线被障碍物挡住。

这种含糊是故意的。按格射击落空时不带 target_id;命中时会报告服务端实际选中的对象。

Core 伤害

伤害永远先扣护盾,再扣 HP。全部战斗伤害合并之后 Core 的 HP 归零,它的舰队才会被 移除——但在那之前,它那些还活着的 Unit 在快照里打出的攻击一样算数。

这里没有独占的「最后一击」统计。同一个 Tick 里多名玩家一起打掉同一个目标,所有人 都获得摧毁参与。被摧毁 Core 的资源单独判断:本 Tick 对该 Core 总伤害最高者获得容量 内的资源,伤害相同时按玩家 UUID 原始字节序。详见摧毁与重生

公开的伤害榜会计算每次合法命中,包括护盾伤害和同 Tick 超过目标剩余护盾与 HP 的 过量伤害。公开的 Core 摧毁参与榜会给摧毁 Tick 内每名伤害过该 Core 的玩家增加 1。 详见排行榜 API

返回结果

战斗结果出现在下一条 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]
}

普通可见状态里的敌方 Core 会带公开的 owner_username,但没有内部 owner ID; 敌方 Unit 不带所属玩家的 username。