diff --git a/docs/PLAYING.md b/docs/PLAYING.md index 19b12245..29f02be4 100644 --- a/docs/PLAYING.md +++ b/docs/PLAYING.md @@ -81,6 +81,7 @@ - **生命回复不是治疗**(与官方一致):吟游者的特性(魔王、浊心斯卡蒂及其海嗣)、调香师的天赋、瑕光二技能、铃兰三技能、锡人炼金单元给友军的「每秒恢复生命」是提高对方的**生命回复速度**,不是治疗:收割者 / 不屈者 / 武者(如隐德来希、圣约送葬人、折桠)这类「无法被友方治疗」的干员和处于禁疗的干员也能吃到,治疗量加成(如「受到的治疗效果提升」)也不会放大它;铃兰三技能开启后的第一秒没有回复。直接治疗(医疗干员的治疗、技能的「恢复…生命」)仍然对这些干员无效。 - **元素损伤条**在单位自己的血条正下方:左边是元素图标,白条是剩余的元素值,只有真正爆发时才会耗尽;爆发后条变成元素的颜色、图标闪烁,在冷却期间慢慢回满(这段时间不会再积累元素损伤)。 - **敌人**:远程敌人的射程按官方从干员的碰撞体积(半径 0.25 格)算起,比数据上的攻击范围半径远 0.25 格——例如萨卡兹枯朽战车(射程 2.2)能打到中心 2.45 格以内、站在低地的干员。没被阻挡的远程敌人每次攻击都会站定、播完攻击动作,两次攻击之间才继续前进。它的第一下攻击就是「秽蚀轰击」(在目标处留下半径 1.7、持续 10 秒的污染区:低地每秒 50、高台 25 点真实伤害,同名不叠加),被阻挡时普通攻击伤害翻倍。“萨科塔之翼”等血量第一次低于一半时会在原地小范围乱飞 5 秒(官方叫「恐惧」);叙拉古、妮芙等干员造成的恐惧会让敌人朝远离干员的方向逃跑。隐匿的敌人只有被阻挡(或被揭示)时才能被选为攻击目标,溅射、技能的圆形范围伤害也打不到没被挡住的隐匿敌人(和官方一样);阻挡解除后 3 秒内它仍然可以被选中(官方页面注明 0 秒或 1 秒的敌人按页面),之后才重新隐匿:深池逐火战士每次被击倒后先重生 1 秒,然后变成继续往前走的隐匿「余烬」(需要 5 次伤害击倒,护卫的「火灰」10 次),一般要用干员挡住它才能选中(挡住时它不再半透明;被阻挡时被击倒的,重生结束后约 2 秒内也能用远程或范围伤害补刀),10 秒内没打掉就满血站起来;敌人重生时身上的减速、恐惧等状态会被清空、技能冷却从头开始,被恐惧的逐火战士变成余烬后也能被挡住;转译基底·α 原始形态受到的伤害全部无效,受到第 4 次物理伤害、第 4 次法术伤害或被阻挡时花 2 秒变成寻仇者、特战术师或幽灵,之后才能被击倒。 +- **复活**(策略「埃芒加德」的前 3 次、M3茧甲)与官方一致:算作一次被击倒,紧接着在倒下的位置免费立即再部署——干员「被击倒时」和「部署时」的效果都会触发(例如砾的不屈 / 卡西米尔层数、瑕光的层数、卡西米尔盟约的部署攻击力),技力和身上的增益像普通再部署一样重置。 - **策略「鸭爵」(“神秘顾客”)**:从第 5 回合起,你和队友的每场作战(**最终攻势和隐秘核心也算**,联防不另外替换)有 0–2 名地面敌人(不含领袖及其部件、悬赏敌人)被替换为特殊版本的鸭爵、高普尼克、流泪小子或圆仔,出现在被替换敌人的时间和路线上(两人同场的领袖战里,各自只替换走向自己保护目标点的敌人);击倒者获得 1 资金(联防中的队友也算),漏进保护目标点照常扣 1 点目标生命值。鸭爵和圆仔**不攻击、无法被阻挡**:鸭爵受到伤害后移动速度 +300%;圆仔始终面向我方干员较多的一侧,来自正面的物理 / 法术伤害 −80%。流泪小子隐匿(被阻挡时才能被选中),攻击使目标晕眩 3.5 秒;高普尼克免疫晕眩、冻结和浮空。 - 右上角 🔍▶▶ 可以查看本回合即将来袭的敌人(预览区),左上角 🔍 查看本局信息(禁用盟约、禁用干员、策略)。 diff --git a/docs/SIM.md b/docs/SIM.md index 54f8c767..03e18828 100644 --- a/docs/SIM.md +++ b/docs/SIM.md @@ -774,11 +774,11 @@ registration order. `battle.off(handle)` / `battle.off(name, fn)` / `battle.offO | `damaged` | `{ source, target, amount, type, dmg, credit }` | after application (`amount` may be 0 when shielded); element fills too (with their source); 无来源: `source` null, `credit` set | | `hpDamage` | `{ source, target, amount, dmg, credit }` | a damage instance after shields, before the HP loss (§4; not a 流失): lower `amount` only (a raise is ignored) — HP floors / reductions ordered after a barrier (kits/ops/op-huang.js, op-zuole.js) | | `heal` | `{ source, target, amount, opts }` | mutable `amount` | -| `fatal` | `{ unit, source, credit, dmg, amount, prevented }` | HP would reach 0 — set `prevented` (substitutes, kit savers, 不死 / 复活 items, 埃芒加德; 不屈 is a `death` hook). Fired by every HP loss of a unit without a boss pool — hits of any type, element bursts, 无来源 damage, `loseHp` 流失. Order: kits' own savers (10 … −60) → items' 不死 (坚固维式重锤 — once per deployment: `items/battle.js deploymentOf`, a key every deploy changes and an in-place 复活 changes too; one battle-level hook holds the running windows (`holdsUndying`), so a window outlasts a lend, DESIGN §21.21 — the lock `PRIO_REVIVE` −100 after the substitutes (−100, registered first), the running windows `PRIO_UNDYING_HELD` −99 before them: a 傀儡师 holding 不死 does not switch, PRTS 分支特性信息 傀儡师 "未持有不死的情况下", DESIGN §22.11) → 淬羽赫默 S3's 不死 (−100.5: PRTS 衍生生命 "无畏者协议提供的不死效果仅在目标没有不死效果时才会触发"; its running windows held at −99 like the hammer's) → items' 复活 (M3茧甲, `PRIO_RESPAWN` −101: PRTS "复活" acts on a knock-out, which a 不死 prevents) → 埃芒加德 (−110); both 复活 revive in place and call `revivedInPlace` (a new deployment for the lock) | +| `fatal` | `{ unit, source, credit, dmg, amount, prevented }` | HP would reach 0 — set `prevented` (substitutes, kit savers, 不死 items; the 复活 — M3茧甲, 埃芒加德 — and 不屈 are `death` hooks). Fired by every HP loss of a unit without a boss pool — hits of any type, element bursts, 无来源 damage, `loseHp` 流失. Order: kits' own savers (10 … −60) → items' 不死 (坚固维式重锤 — once per deployment: `items/battle.js deploymentOf`, a key every deploy changes (a 复活's redeploy too); one battle-level hook holds the running windows (`holdsUndying`), so a window outlasts a lend, DESIGN §21.21 — the lock `PRIO_REVIVE` −100 after the substitutes (−100, registered first), the running windows `PRIO_UNDYING_HELD` −99 before them: a 傀儡师 holding 不死 does not switch, PRTS 分支特性信息 傀儡师 "未持有不死的情况下", DESIGN §22.11) → 淬羽赫默 S3's 不死 (−100.5: PRTS 衍生生命 "无畏者协议提供的不死效果仅在目标没有不死效果时才会触发"; its running windows held at −99 like the hammer's). The 复活 act on the knock-out after this step (PRTS "复活" acts on a knock-out, which a 不死 prevents): `death`, below | | `dollSwitch` | `{ unit, reason, done }` | content switches a 傀儡师 to its <替身> now (归溟幽灵鲨 S2 "技能结束后立刻切换为<替身>": no lethal HP loss); its trait does it unless it already is one or is not on the field, and sets `done` | | `dollSwap` | `{ unit, form }` | a 傀儡师 starts a switch — to its <替身> (`form` `'doll'`) or back to its <本体> (`null`); not when it is knocked out as the 替身 (不屈 rolls on it: "切换<替身>与<本体>时") | | `kill` | `{ killer, victim }` | victim HP reached 0 (a handler may revive by restoring HP) | -| `death` | `{ unit, reason:'killed'|'leak'|'retreat'|'merchant'|'expired'|'forcedExit', killer, dying }` | unit removed (`'forcedExit'`: an operator entering 联防 knocked out, §1.1; `dying`: a `retreat` that plays the death animation — 史尔特尔's 余烬, 骑士戒律 + 竞技旗) | +| `death` | `{ unit, reason:'killed'|'leak'|'retreat'|'merchant'|'expired'|'forcedExit', killer, dying, revivedBy? }` | unit removed (`'forcedExit'`: an operator entering 联防 knocked out, §1.1; `dying`: a `retreat` that plays the death animation — 史尔特尔's 余烬, 骑士戒律 + 竞技旗). Revives of a knock-out redeploy the operator inside it, free, where it lies — PRTS "“复活”的实现方式为:受益者因移动之外的原因退场时下次部署的再部署时间和费用归零", so the 被击倒时 and 部署时 effects both run: M3茧甲 (`PRIO_RESPAWN` 13) → 埃芒加德 (`PRIO_BAND_REVIVE` 12) — `items/battle.js reviveNow`, which sets `revivedBy` ('item' / 'band'; 阿戈尔 5 does not count such a knock-out as the member's first) — → 阿戈尔 5 (11) → 不屈 (10); until 0.2.0 the two 复活 were `fatal` savers that kept the unit standing | | `skillStart` / `skillEnd` | `{ unit, skill, reason }` | mutate `skill.ammoLeft` / `skill.timeLeft` in skillStart (bullets added there raise `skill.ammoMax`, the ammo bar's full mark) | | `ammoUsed` | `{ unit, left, skill }` | per ammo consumed | | `spGain` | `{ unit, amount, reason:'time'|'attack'|'hurt'|'init'|…, skill }` | mutable `amount` (time gains fire every tick) | diff --git a/docs/design/engine.md b/docs/design/engine.md index 7e12458b..533a3640 100644 --- a/docs/design/engine.md +++ b/docs/design/engine.md @@ -100,9 +100,9 @@ Base stats (from data): `maxHp, atk, def, res` (0–100), `aspd` (100 base), `ba | `hit` | `{ source, target, dmg }` | before mitigation; mutate `dmg` (DamageInfo) | | `damaged` | `{ source, target, amount, type, dmg }` | after application | | `heal` | `{ source, target, amount }` | before application (mutable amount) | -| `fatal` | `{ unit, source, credit, dmg, amount, prevented }` | HP would reach 0 — fired by every HP loss of a unit without a boss pool (hits of any type, element bursts, 无来源 damage, `loseHp`); set `prevented`. Order: kits' own savers (10 … −60) → items' 不死 (坚固维式重锤, once per deployment) `PRIO_REVIVE` −100 → items' 复活 (M3茧甲) `PRIO_RESPAWN` −101 → 埃芒加德 −110; the two 复活 revive in place and open a new deployment for the lock (§21.21); a running 坚固 window's hook sits at `PRIO_UNDYING_HELD` −99, before a 傀儡师's switch to its 替身 (−100, ahead of the lock — a 本体 holding 不死 does not switch, §22.11) | +| `fatal` | `{ unit, source, credit, dmg, amount, prevented }` | HP would reach 0 — fired by every HP loss of a unit without a boss pool (hits of any type, element bursts, 无来源 damage, `loseHp`); set `prevented`. Order: kits' own savers (10 … −60) → items' 不死 (坚固维式重锤, once per deployment) `PRIO_REVIVE` −100; a running 坚固 window's hook sits at `PRIO_UNDYING_HELD` −99, before a 傀儡师's switch to its 替身 (−100, ahead of the lock — a 本体 holding 不死 does not switch, §22.11). The 复活 are no `fatal` savers since 0.2.0: they answer the knock-out (`death`, below) | | `kill` | `{ killer, victim }` | victim hp reached 0; a `killed` ability that keeps the enemy alive (a knock-out into a 重生 / form change, §21.4) hides it from every later handler, the kill count, credit and the bounty | -| `death` | `{ unit }` | unit removed (ops may redeploy later); the `die` event and the death hooks fire only on removal | +| `death` | `{ unit }` | unit removed (ops may redeploy later); the `die` event and the death hooks fire only on removal. Knock-out revives redeploy the operator at once inside it, free, where it lies (PRTS "“复活”的实现方式为:…下次部署的再部署时间和费用归零": the 被击倒时 and 部署时 effects both run): items' 复活 (M3茧甲) `PRIO_RESPAWN` 13 → 埃芒加德 `PRIO_BAND_REVIVE` 12 (both `items/battle.js reviveNow`, ctx `revivedBy`) → 阿戈尔 5's first-knock-out revive 11 → 不屈 10 | | `skillStart` / `skillEnd` | `{ unit, skill }` | | | `ammoUsed` | `{ unit, left }` | per ammo consumed | | `spGain` | `{ unit, amount }` | mutable | diff --git a/docs/research/04-items.md b/docs/research/04-items.md index 97805f6c..6e92c1ee 100644 --- a/docs/research/04-items.md +++ b/docs/research/04-items.md @@ -215,7 +215,7 @@ Param names below are the keys of `items[].normal.params` / `items[].golden.para params: `hp_ratio=0.7/0.4`; buff keys: `env_gbuff_new_with_verify` - **护盾无人机** (`chess_item_4_11_e_a`, TIV, 2) - Each heal the carrier performs: prob chance to give the healed target 1 shield layer (max max_stack_cnt layers; 1 layer blocks one instance of damage). params: `prob=0.1/0.15, max_stack_cnt=1.0`; buff keys: `env_gbuff_new_with_verify` -- **M3茧甲** (`chess_item_4_12_e_a`, TIV, 3) - When the carrier is defeated during the battle phase: revive immediately in place at full HP [ASSUMED full HP] up to max_respawn_cnt times per battle. +- **M3茧甲** (`chess_item_4_12_e_a`, TIV, 3) - When the carrier is defeated during the battle phase: revive immediately at full HP up to max_respawn_cnt times per battle — PRTS 备注 "“复活”的实现方式为:受益者因移动之外的原因退场时下次部署的再部署时间和费用归零": since 0.2.0 the knock-out stands and the carrier redeploys at once, free, where it lies (its 被击倒时 and 部署时 effects run; in place before). params: `max_respawn_cnt=1.0/2.0`; buff keys: `env_gbuff_new_with_verify` ### SP - 技力 SP gain diff --git a/server/sim/content/bands/battle.js b/server/sim/content/bands/battle.js index 2f11d47e..77a02cc3 100644 --- a/server/sim/content/bands/battle.js +++ b/server/sim/content/bands/battle.js @@ -7,8 +7,12 @@ // act1autochess_band2_buff 阿米娅 众志合一 ≥ value_i active bonds (highest i) ⇒ every operator ATK +atk_i, // HP +max_hp_i (直接乘算 — support directMods —, bonds snapshot at combat start) // act1autochess_band28_buff 埃芒加德 命结之秘 the first max_respawn_cnt operator knock-downs of the battle revive at -// once at full HP (runs after every other death saver, items included; -// a new deployment for 坚固维式重锤's lock — items revivedInPlace) +// once — PRTS 备注 "“复活”的实现方式为:受益者因移动之外的原因退场时下次部署 +// 的再部署时间和费用归零": the knock-out stands (被击倒时 effects run) and the +// operator redeploys at once, free, where it lies (部署时 effects run, SP +// reset): items reviveNow, a `death` hook after M3茧甲's and before 阿戈尔 +// 5 / 不屈 (in place until 0.2.0, community report 「…砾和瑕光这种死亡和部 +// 署的叠层效果,如果有艾芒加德的3次复活似乎是无法触发」) // act1autochess_band13_buff 克莱门莎 崇高牺牲 a operator knocked down ⇒ +its tier (等阶) layers // (bond_add_type by_charlevel; no "已激活" in the text ⇒ requireActive false) // act1autochess_band16_buff 大帝 加急调派 "每次部署后再部署时间减少50%": every deployment of an operator stacks one @@ -37,12 +41,15 @@ import { num, buffsOf, bandRecord, isOp, onField, isElite, tierOf, unitBonds, activeBondIds, playerOps, passiveBuff, fxOn, matchBands, gainLayers, alliesAround, N4, baseChessId, isGroundOp, directMods, } from '../support/index.js'; -import { weaknessRetype, addShieldLayer, PRIO_REVIVE, revivedInPlace } from '../items/battle.js'; +import { weaknessRetype, addShieldLayer, PRIO_RESPAWN, reviveNow } from '../items/battle.js'; import { spawnMapChar } from '../tokens.js'; export const AMEDIC_BAND = 'band_amedic'; -/** 'fatal' priority of 埃芒加德: after the operators' own items (PRIO_REVIVE / PRIO_RESPAWN) and every talent / skill saver. */ -export const PRIO_BAND_REVIVE = PRIO_REVIVE - 10; +/** + * 'death' priority of 埃芒加德's revive: a knock-out (so after every `fatal` saver — kits', 坚固维式重锤's 不死), after the + * operator's own M3茧甲 (PRIO_RESPAWN 13), before 阿戈尔 5's first-knock-out revive (11) and 不屈 (10). + */ +export const PRIO_BAND_REVIVE = PRIO_RESPAWN - 1; const keyOf = (bandId, part = '') => `band:${bandId}${part ? `:${part}` : ''}`; const deployedOps = (battle, pid) => playerOps(battle, pid, { fieldOnly: true }); @@ -68,13 +75,10 @@ const BY_KEY = { const max = Math.floor(num(p.max_respawn_cnt, 3)); if (!(max > 0)) return; let used = 0; - battle.on('fatal', (c) => { + battle.on('death', (c) => { const u = c.unit; - if (c.prevented || used >= max || !isOp(u) || u.ownerId !== ps.playerId || !u.alive) return; + if (used >= max || !isOp(u) || u.ownerId !== ps.playerId || !reviveNow(battle, c, 'band')) return; used++; - c.prevented = true; - u.hp = u.s.maxHp; - revivedInPlace(u); // in place for PRTS's 0-time / 0-cost redeploy: a new deployment for 坚固维式重锤's lock (items) fxOn(battle, 'revive', u, keyOf(bandId), bandId, { left: max - used }); }, { priority: PRIO_BAND_REVIVE }); }, diff --git a/server/sim/content/bonds/core.js b/server/sim/content/bonds/core.js index 34baa1df..dc37388a 100644 --- a/server/sim/content/bonds/core.js +++ b/server/sim/content/bonds/core.js @@ -424,7 +424,7 @@ function devour(battle, pid, bb, members) { const amount = num(bb.damage_value, 0); const layered = new Set(); // a target knocked out during the pass = off the field, or in another deployment than when the marks were placed (items - // deploymentOf: the 5-tier revive and 不屈 redeploy it, 埃芒加德 / M3茧甲 revive it in place) — a revived member was + // deploymentOf: the 5-tier revive, 不屈 and the 复活 of 埃芒加德 / M3茧甲 redeploy it) — a revived member was // standing again when its pending marks used to knock it out a second time and spend every revive at t = 0 (GitHub #33) const dep = new Map(); for (const [, t] of marks) if (!dep.has(t)) dep.set(t, items.deploymentOf(t)); @@ -457,10 +457,12 @@ function installEgir(battle, pid, bb, members) { // other, so the eaten food usually takes them at t = 0 and survivors = uneaten members + 3. A member takes at most one // slot, on its first knock-out ('killed') in the battle: its later knock-outs never take one, and a first knock-out // after the 3 are gone stays down. However many members mark it, its pending marks are cancelled once it is knocked - // out (devour), so a multi-devoured member spends one slot at most. Its own saver acts first: every kit, item or band - // revive that prevents or replaces the knock-out is a `fatal` hook (斯卡蒂's DRE-Y −50, kit savers 10 … −60, 坚固维式 - // 重锤 PRIO_REVIVE −100, M3茧甲 PRIO_RESPAWN −101, 埃芒加德 −110), so the unit is never knocked out and no slot is used — - // the slot waits for its first real knock-out [ASSUMED for 埃芒加德, a band: as M3茧甲, the item revive the owner named]. + // out (devour), so a multi-devoured member spends one slot at most. Its own saver acts first: a kit or item saver that + // prevents the knock-out is a `fatal` hook (斯卡蒂's DRE-Y −50, kit savers 10 … −60, 坚固维式重锤 PRIO_REVIVE −100), so the + // unit is never knocked out and no slot is used; a 复活 (M3茧甲 13, 埃芒加德 12 — items reviveNow, a knock-out and a free + // redeploy since 0.2.0) answers the knock-out before this hook and marks it `revivedBy`: that knock-out is not the + // member's first either — the slot waits for its first unanswered knock-out (the owner's decision of 2026-10-05: an + // operator's own revive uses no slot; [ASSUMED] for 埃芒加德, a band, as for M3茧甲, the item revive the owner named). // An operator entering 联防 down (FORCED_EXIT) is not knocked out either; a 调和 member counts like any other. Each // battle (normal, 联防, boss) counts its own. PRTS: the knocked-out unit's next deployment has 0 redeploy time and 0 // cost, i.e. it IS knocked out (被击倒 triggers, 克莱门莎, 幽灵鲨 … fire) and redeploys at once where it lies (the @@ -478,7 +480,7 @@ function installEgir(battle, pid, bb, members) { let revives = 0; battle.on('death', (c) => { const u = c.unit; - if (c.reason !== 'killed' || !memberOps.has(u) || knockedOut.has(u)) return; + if (c.reason !== 'killed' || c.revivedBy || !memberOps.has(u) || knockedOut.has(u)) return; knockedOut.add(u); if (revives >= max || u.alive || u.removed) return; if (!battle.redeploy(u, { free: true })) return; diff --git a/server/sim/content/items/battle.js b/server/sim/content/items/battle.js index 8874e265..e88da4e8 100644 --- a/server/sim/content/items/battle.js +++ b/server/sim/content/items/battle.js @@ -23,12 +23,15 @@ // use 10 … −60) never wastes a charge: 坚固维式重锤's lock (异常效果 不死, once per deployment — deploymentOf) at // PRIO_REVIVE −100 and its running windows, held by one battle-level hook, at PRIO_UNDYING_HELD −99 — before a 傀儡师's // switch to its 替身 (professions.js, −100: PRTS 分支特性信息 傀儡师 "受到足以致命的伤害且未持有不死的情况下"), while the -// lock itself still comes after that switch (as in 0.1.1); then the M3茧甲 revive at PRIO_RESPAWN −101 — PRTS -// 卫戍协议:盟约 下半/PRTS盟约记录 备注 "“复活”的实现方式为:受益者因移动之外的原因退场时下次部署的再部署时间和费用归零": a -// revive acts on a knock-out, which a 不死 prevents, so the lock always comes first whatever the equip order (player -// report F1 after 0.1.0: with the 茧甲 equipped first the revive ran first and the first lethal hit showed no lock); -// 埃芒加德's band revive follows (bands/battle.js PRIO_BAND_REVIVE −110). Both revives stand in place for that redeploy, -// so each opens a new deployment for the lock (revivedInPlace). +// lock itself still comes after that switch (as in 0.1.1). The 复活 — M3茧甲 here, 埃芒加德's band (bands/battle.js) — +// act on the knock-out itself: PRTS 卫戍协议:盟约 下半/PRTS盟约记录 备注 "“复活”的实现方式为:受益者因移动之外的原因退场时下 +// 次部署的再部署时间和费用归零" — the unit IS knocked out (its `death` hooks, every 被击倒时 effect, run) and its next +// deployment, at once, free, where it lies, is a deployment like any other (部署时 effects, SP reset, a new lock): a +// `death` hook at PRIO_RESPAWN 13, then 埃芒加德 12 (PRIO_BAND_REVIVE), ahead of 阿戈尔 5's first-knock-out revive (11) +// and 不屈 (10) — reviveNow. A 不死 prevents the knock-out, so the lock always comes first whatever the equip order (player +// report F1 after 0.1.0: with the 茧甲 equipped first the revive ran first and the first lethal hit showed no lock). Until +// 0.2.0 both revived in place (`fatal` savers at −101 / −110): no 被击倒时 / 部署时 effect fired (community report +// 「像砾和瑕光这种死亡和部署的叠层效果,如果有艾芒加德的3次复活似乎是无法触发」). // 骑士戒律's free in-skill undying runs early (20). Flat damage reduction 'hit' −10 (after the other damage modifiers). // Proc damage dealt by items carries the tag 'item' and never re-triggers item procs. // @@ -69,8 +72,11 @@ const ENEMY_RECORD = /^enemy_/; export const PRIO_REVIVE = -100; /** A running 坚固 window (不死 held): before a 傀儡师's switch to its 替身 at −100 — see header. */ export const PRIO_UNDYING_HELD = PRIO_REVIVE + 1; -/** The items' 复活 (M3茧甲): acts on a knock-out, so after every 不死 (PRIO_REVIVE) — see header. */ -export const PRIO_RESPAWN = PRIO_REVIVE - 1; +/** + * 'death' priority of the items' 复活 (M3茧甲): it acts on the knock-out, so after every `fatal` saver (不死 included) — + * before 埃芒加德 (12), 阿戈尔 5's revive (11) and 不屈 (10). See header and reviveNow. + */ +export const PRIO_RESPAWN = 13; const PRIO_FREE_UNDYING = 20; /** Stat keys of a stat buff → mods (直接乘算, see header). */ @@ -238,16 +244,30 @@ function hammerState(battle, rt, u) { // 娜仁图亚's 60 s lend) follows the same rule as an owner. /** - * The deployment `u` is in: every deploy bumps `deploySeq` (the redeploy after a knock-out, a 突袭 retreat + redeploy - * [ASSUMED a deployment], 阿戈尔's 立刻复活), and an in-place 复活 (M3茧甲, 埃芒加德: revivedInPlace) opens a new one too - * [ASSUMED] — PRTS (M3茧甲 / 埃芒加德 / 阿戈尔 备注) "“复活”的实现方式为:受益者因移动之外的原因退场时下次部署的再部署时间和 - * 费用归零": officially a revive is a 0-time / 0-cost redeploy; the remake keeps the unit standing instead. - * Also read by 阿戈尔's devour (bonds/core.js): a unit whose deployment changed during the pass was knocked out. + * The deployment `u` is in: every deploy bumps `deploySeq` — the redeploy after a knock-out, a 突袭 retreat + redeploy + * [ASSUMED a deployment], 阿戈尔's 立刻复活 and every 复活 (M3茧甲, 埃芒加德: reviveNow — PRTS "“复活”的实现方式为:受益者因移动 + * 之外的原因退场时下次部署的再部署时间和费用归零", a 0-time / 0-cost redeploy; in place until 0.2.0, when an extra counter + * opened the new deployment). Also read by 阿戈尔's devour (bonds/core.js): a unit whose deployment changed during the + * pass was knocked out. */ -export function deploymentOf(u) { return `${u.deploySeq}:${u.mem.revives | 0}`; } +export function deploymentOf(u) { return `${u.deploySeq}`; } -/** An in-place 复活 (M3茧甲, 埃芒加德) happened: a new deployment for the once-per-deployment lock (deploymentOf). */ -export function revivedInPlace(u) { if (u && u.mem) u.mem.revives = (u.mem.revives | 0) + 1; } +/** + * A 复活 answering a knock-out — call from a `death` hook (M3茧甲 PRIO_RESPAWN, 埃芒加德 PRIO_BAND_REVIVE). PRTS 备注 + * "“复活”的实现方式为:受益者因移动之外的原因退场时下次部署的再部署时间和费用归零": the operator was knocked out (this death; + * its 被击倒时 effects run) and redeploys at once, free, where it lies (Battle.redeploy: full HP, SP reset, `deploy` — + * its 部署时 effects run). True when it stands again; the ctx then carries `revivedBy`, so 阿戈尔 5 does not count the + * knock-out as the member's first (the owner's decision of 2026-10-05: an operator's own revive uses no slot; 埃芒加德 + * [ASSUMED] alike, DESIGN §24.3). A redeploy that cannot happen (its tile taken) spends nothing [ASSUMED]. + * @param {object} battle @param {{ unit: object, reason: string, revivedBy?: string }} c the `death` ctx @param {string} by + */ +export function reviveNow(battle, c, by) { + const u = c && c.unit; + if (!u || c.reason !== 'killed' || c.revivedBy || !isOp(u) || u.alive || u.removed) return false; + if (!battle.redeploy(u, { free: true })) return false; + c.revivedBy = by; + return true; +} /** * Does `u` hold 坚固维式重锤's 不死 right now — a window started in this deployment that has not run out? The window lives @@ -602,21 +622,18 @@ const BY_ITEM = { if (addShieldLayer(battle, c.target, SHIELD_KEY, cap)) fxOn(battle, 'shield', c.target, 'item:chess_item_4_11_e', rec.id); }); }, - // M3茧甲: knocked down in battle ⇒ revive at full HP (max_respawn_cnt per battle), in place — PRTS's form (退场, then a - // 0-time / 0-cost redeploy) is not modelled, but it counts as a new deployment for 坚固维式重锤's lock (revivedInPlace) + // M3茧甲: knocked down in battle ⇒ 立刻复活 (max_respawn_cnt per battle) — PRTS's form: the knock-out stands (its + // 被击倒时 effects run) and the carrier redeploys at once, free, where it lies (reviveNow; in place until 0.2.0) chess_item_4_12_e(battle, u, rec, S) { const p = bp(rec, 'act1autochess_equip_acarm068_global_buff'); const max = p ? Math.floor(num(p.max_respawn_cnt, 1)) : 0; if (!(max > 0)) return; let used = 0; - S.on('fatal', (c) => { - if (c.unit !== u || c.prevented || used >= max) return; + S.on('death', (c) => { + if (c.unit !== u || used >= max || !reviveNow(battle, c, 'item')) return; used++; - c.prevented = true; - u.hp = u.s.maxHp; - revivedInPlace(u); fxOn(battle, 'revive', u, 'item:chess_item_4_12_e', rec.id, { left: max - used }); - }, PRIO_RESPAWN); // after the hammer's 不死 lock, whatever the equip order (header) + }, PRIO_RESPAWN); // a knock-out: after every 不死 (the hammer's lock), whatever the equip order (header) }, // 催泪瓦斯: on attack prob ⇒ 1 麻痹 stack chess_item_5_01_e(battle, u, rec, S) { diff --git a/server/sim/content/kits/ops/op-slent2.js b/server/sim/content/kits/ops/op-slent2.js index 56efaac8..b42972a1 100644 --- a/server/sim/content/kits/ops/op-slent2.js +++ b/server/sim/content/kits/ops/op-slent2.js @@ -55,13 +55,13 @@ // once per cast the first operator of her range taking lethal damage (not its own — CheckEntitySuicide; not while it already // holds 不死 — "_dontConsumeWhenUndeadable") keeps ≥ 1 HP and holds 不死 for grave_duration s (slent2_shallow_grave, buff // flag `undying`; it outlasts her leaving). Order of the `fatal` step (items/battle.js): after the kits' own savers, a -// 傀儡师's switch and 坚固维式重锤's lock (PRIO_REVIVE −100), before the 复活 (PRIO_RESPAWN −101); the window it opens is -// held like the hammer's (PRIO_UNDYING_HELD −99). +// 傀儡师's switch and 坚固维式重锤's lock (PRIO_REVIVE −100) — the 复活 (M3茧甲, 埃芒加德) act on the knock-out after the +// whole `fatal` step; the window it opens is held like the hammer's (PRIO_UNDYING_HELD −99). // Statuses: none applied to enemies. Damage: arts normal attacks only. import { num, up, traitBb, moduleBb, talentBb, skillRec, once, holdProtect } from '../shared/tier1.js'; import { releaseSkillSummon } from '../../tokens.js'; -import { holdsUndying, PRIO_UNDYING_HELD, PRIO_REVIVE, PRIO_RESPAWN } from '../../items/battle.js'; +import { holdsUndying, PRIO_UNDYING_HELD, PRIO_REVIVE } from '../../items/battle.js'; import { absoluteRangeKeys } from '../../../targeting.js'; import { COLS } from '../../../constants.js'; @@ -79,8 +79,8 @@ const REGEN_IV = 1; export const MAXHP_KEY = 'slent2:maxhp'; /** S3's 不死 (slent2_shallow_grave). */ export const GRAVE_KEY = 'slent2:grave'; -/** S3's place in the `fatal` step: after the items' 不死 lock (−100), before their 复活 (−101) — see the header. */ -const PRIO_GRAVE = (PRIO_REVIVE + PRIO_RESPAWN) / 2; +/** S3's place in the `fatal` step: right after the items' 不死 lock (−100) — see the header. */ +const PRIO_GRAVE = PRIO_REVIVE - 0.5; /** 夜灯's area when its record carries no grid: its tile and the 8 around (x-4). */ const X4 = Object.freeze([[1, -1], [1, 0], [1, 1], [0, -1], [0, 0], [0, 1], [-1, -1], [-1, 0], [-1, 1]]); /** 【莱茵生命】 (character_table groupId "rhine": every member, so a 自选 pick counts too). */ diff --git a/test/content/bands.test.js b/test/content/bands.test.js index 7fb879d7..40e9f070 100644 --- a/test/content/bands.test.js +++ b/test/content/bands.test.js @@ -8,7 +8,7 @@ import { makeMatch, give, giveItem, DATA } from '../match/harness.js'; import { createRegistry } from '../../server/match/effectsMeta.js'; import { hasBattlePart, amedicCharsFor, PRIO_BAND_REVIVE } from '../../server/sim/content/bands/battle.js'; import { bandMetaHandler, duckReplace } from '../../server/sim/content/bands/meta.js'; -import { PRIO_REVIVE } from '../../server/sim/content/items/battle.js'; +import { PRIO_RESPAWN } from '../../server/sim/content/items/battle.js'; import * as bands from '../../server/sim/content/bands.js'; const QUIET = { warn() {}, error() {}, info() {} }; @@ -532,9 +532,12 @@ test('阿米娅 众志合一: 3 / 4 / ≥ 5 active bonds ⇒ every operator ATK cover('band_amiya'); }); -test('埃芒加德 命结之秘: the first 3 knock-downs of the battle revive at full HP (after the operators\' own revive items)', () => { +test('埃芒加德 命结之秘: the first 3 knock-downs of the battle revive at full HP (after the operators\' own revive items) — a knock-out and a free redeploy', () => { const ops = { t_op: op('t_op'), t_b: op('t_b') }; const h = fight({ band: 'band_ermengard', ops, units: [{ chessId: 't_op', row: 10, col: 4, items: [A('4_12')] }, { chessId: 't_b', row: 11, col: 4 }], foes: [[10, 9]] }); + const log = []; + h.b.on('death', (c) => log.push(['death', c.unit.defId, c.revivedBy ?? null]), { priority: -1000 }); + h.b.on('deploy', (c) => { if (!c.initial && c.unit.side === 'ally') log.push(['deploy', c.unit.defId]); }, { priority: -1000 }); h.step(1); const [a, b] = [h.unit('t_op'), h.unit('t_b')]; const kill = (u) => h.b.dealDamage(foe(h), u, { amount: 1e6, type: 'true' }); @@ -543,9 +546,13 @@ test('埃芒加德 命结之秘: the first 3 knock-downs of the battle revive at kill(a); kill(b); kill(b); // band revives 1, 2, 3 assert.ok(a.alive && b.alive); close(b.hp, 2000, 'full HP'); + // PRTS 备注 "“复活”的实现方式为:受益者因移动之外的原因退场时下次部署的再部署时间和费用归零": each revive is a knock-out + // (death hooks — 被击倒时 effects) and an immediate free redeploy where it lies (deploy hooks — 部署时 effects) + assert.deepEqual(log.filter((x) => x[0] === 'death').map((x) => x.slice(1)), [['t_op', 'item'], ['t_op', 'band'], ['t_b', 'band'], ['t_b', 'band']]); + assert.deepEqual(log.filter((x) => x[0] === 'deploy').map((x) => x[1]), ['t_op', 't_op', 't_b', 't_b'], 'each knock-out redeployed at once'); kill(a); assert.equal(a.alive, false, '4th knock-down of the band: dies'); - assert.ok(PRIO_BAND_REVIVE < PRIO_REVIVE); + assert.ok(PRIO_BAND_REVIVE < PRIO_RESPAWN, 'the band after the item revive (both death hooks, after every fatal saver)'); cover('band_ermengard'); }); diff --git a/test/content/bonds_core.test.js b/test/content/bonds_core.test.js index d0492fa0..a5d4bb27 100644 --- a/test/content/bonds_core.test.js +++ b/test/content/bonds_core.test.js @@ -542,7 +542,7 @@ test('阿戈尔 5: a member devoured by several 阿戈尔 spends one slot at mos checkInvariants(t.b); }); -test('阿戈尔 5: an operator\'s own save uses no slot (斯卡蒂\'s DRE-Y, M3茧甲, 埃芒加德 [ASSUMED for the band]); the slot waits for its first real knock-out', () => { +test('阿戈尔 5: an operator\'s own save or revive uses no slot (斯卡蒂\'s DRE-Y, M3茧甲, 埃芒加德 [ASSUMED for the band]); the slot waits for its first unanswered knock-out', () => { // 斯卡蒂 (elite, module DRE-Y by default) enters 联防 at half HP in front of 乌尔比安: his mark is lethal, DRE-Y saves her // (PRTS: once per deployment, full HP with max HP −60 %) — no knock-out, so no slot const SKADI = 'chess_char_3_05_b', ULPIA = 'chess_char_5_05_a', GHOST = 'chess_char_2_07_a', HN = 'chess_char_3_09_a', DEEP = 'chess_char_1_04_a'; @@ -568,20 +568,23 @@ test('阿戈尔 5: an operator\'s own save uses no slot (斯卡蒂\'s DRE-Y, M3 const list = [['g0_a', ['egirShip']], ['g1_a', ['egirShip']], ['g2_a', ['egirShip']], ['g3_a', ['egirShip']], ['g4_a', ['egirShip']]]; const units = (it = {}) => list.map(([chessId], i) => ({ chessId, row: 9 + (i % 2) * 3, col: 3 + i, items: it[i] })); const killed = (b, id) => { const u = b.unit(id); b.b.dealDamage(null, u, { amount: 1e9, type: 'true' }); return u; }; - // M3茧甲 (an item 复活, in place): g0 is saved, the 3 slots go to g1, g2, g3; g4 stays down + // M3茧甲 (an item 复活 — since 0.2.0 PRTS's form: a knock-out answered by a free redeploy, items reviveNow): g0 is knocked + // out and back at once, the 3 slots go to g1, g2, g3; g4 stays down const hi = makeBattle({ defs: defsOf(list), autoFinish: false, timeLimit: 60, hooks: ['death', 'deploy'], units: units({ 0: ['chess_item_4_12_e_a'] }), bonds: { egirShip: bondOn(5, 0, null, [3, 5]) } }); hi.step(1); const g0 = killed(hi, 'g0_a'); - assert.ok(g0.alive && hi.hooksOf('death').filter((c) => c.unit === g0).length === 0, 'item: saved in place (no knock-out)'); - assert.deepEqual(['g1_a', 'g2_a', 'g3_a', 'g4_a'].map((id) => killed(hi, id).alive), [true, true, true, false], 'item: three slots left after the save'); + assert.ok(g0.alive && hi.hooksOf('death').filter((c) => c.unit === g0 && c.reason === 'killed').length === 1, 'item: knocked out and revived'); + assert.equal(hi.hooksOf('death').find((c) => c.unit === g0).revivedBy, 'item'); + assert.deepEqual(['g1_a', 'g2_a', 'g3_a', 'g4_a'].map((id) => killed(hi, id).alive), [true, true, true, false], 'item: three slots left after the revive'); checkInvariants(hi.b); - // 埃芒加德 (命结之秘: the battle's first 3 knock-downs revive in place — its own count, unchanged): g0, g1, g2 saved by it; - // the 阿戈尔 slots then go to g3, g4 and g0's first real knock-out; g1's real one finds none + // 埃芒加德 (命结之秘: the battle's first 3 knock-downs revive at once — its own count, unchanged): g0, g1, g2 revived by it; + // the 阿戈尔 slots then go to g3, g4 and g0's next knock-out (its first unanswered one); g1's finds none const hb = makeBattle({ defs: defsOf(list), autoFinish: false, timeLimit: 60, hooks: ['death', 'deploy'], units: units(), bandId: 'band_ermengard', bonds: { egirShip: bondOn(5, 0, null, [3, 5]) } }); hb.step(1); for (const id of ['g0_a', 'g1_a', 'g2_a']) { const u = killed(hb, id); - assert.ok(u.alive && hb.hooksOf('death').filter((c) => c.unit === u).length === 0, `band: ${id} saved in place`); + const deaths = hb.hooksOf('death').filter((c) => c.unit === u); + assert.ok(u.alive && deaths.length === 1 && deaths[0].revivedBy === 'band', `band: ${id} knocked out and revived by the band`); } assert.deepEqual(hb.eventsOf('fx').filter((x) => x[1] === 'revive' && x[4] && x[4].left != null).map((x) => x[4].left), [2, 1, 0], '埃芒加德 spent its 3'); assert.deepEqual(['g3_a', 'g4_a', 'g0_a', 'g1_a'].map((id) => killed(hb, id).alive), [true, true, true, false], 'band: the 阿戈尔 slots are untouched'); diff --git a/test/content/feedback1f-hammer.test.js b/test/content/feedback1f-hammer.test.js index b99b52d1..74e2ff3c 100644 --- a/test/content/feedback1f-hammer.test.js +++ b/test/content/feedback1f-hammer.test.js @@ -156,7 +156,8 @@ test('F1 坚固维式重锤 in front of an 阿戈尔: the battle-start devour sp }); test('F1 坚固维式重锤 + M3茧甲: the lock comes before the revive whatever the equip order (PRTS: a revive acts on 退场)', () => { - assert.ok(PRIO_RESPAWN < PRIO_REVIVE && PRIO_RESPAWN > PRIO_BAND_REVIVE, 'revive items: after every 不死, before 埃芒加德'); + // revive items: a `death` hook (after every 不死 — a fatal saver), before 埃芒加德's + assert.ok(Number.isFinite(PRIO_REVIVE) && PRIO_RESPAWN > PRIO_BAND_REVIVE, 'revive items before 埃芒加德'); for (const items of [[M3, HAMMER], [HAMMER, M3]]) { const c = carrier(items); const log = fxLog(c.h, c.u); diff --git a/test/content/feedback5-revive-redeploy.test.js b/test/content/feedback5-revive-redeploy.test.js new file mode 100644 index 00000000..0203b936 --- /dev/null +++ b/test/content/feedback5-revive-redeploy.test.js @@ -0,0 +1,80 @@ +// Community report of 2026-10-06 (items 9 / 37) 「卡西米尔和艾芒加德策略似乎有BUG:像砾和瑕光这种死亡和部署的叠层效果,如果有 +// 艾芒加德的3次复活似乎是无法触发…只有最后一次真的死了没站起来才叠层了」: 埃芒加德's 命结之秘 (and M3茧甲) revived in place — a +// `fatal` saver — so no 被击倒时 and no 部署时 effect fired. PRTS (卫戍协议:盟约 下半/PRTS盟约记录, 埃芒加德 and M3茧甲 备注): +// "“复活”的实现方式为:受益者因移动之外的原因退场时下次部署的再部署时间和费用归零" — the knock-out stands and the operator +// redeploys at once, free: items/battle.js reviveNow, a `death` hook. + +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { makeBattle, enemyRec } from '../helpers/battleHarness.js'; +import { hasGeneratedData } from '../../server/sim/simdata.js'; + +const REAL = { skip: !hasGeneratedData() }; +const GRAVEL = 'chess_char_2_12_a'; // 砾: <部署时>已激活的【卡西米尔】+1, <被击倒时>已激活的【不屈】+2 +const BLEMISH = 'chess_char_3_12_a'; // 瑕光: <部署时>自身已激活的盟约 +4 (每场作战至多12层) + +function setup({ band = 'band_ermengard', items = {} } = {}) { + const h = makeBattle({ + units: [{ chessId: GRAVEL, row: 9, col: 4, items: items[GRAVEL] }, { chessId: BLEMISH, row: 11, col: 4, items: items[BLEMISH] }], + bonds: { + kazimierzShip: { count: 3, layers: 1, active: true, tier: 1 }, + indomShip: { count: 2, layers: 1, active: true, tier: 1 }, + raidShip: { count: 2, layers: 1, active: true, tier: 1 }, + }, + bandId: band, + enemies: [{ key: 'enemy_far', time: 0, route: 0 }], + defs: { enemies: { enemy_far: enemyRec({ key: 'enemy_far', hp: 1e9, atk: 0, bat: 99, speed: 0.0001 }) } }, + timeLimit: 120, seed: 3, + }); + const gains = []; + h.b.on('layerGain', (c) => gains.push([c.source?.defId, c.bondId, c.n]), { priority: -1000 }); + h.step(); + const kill = (id) => { const u = h.unit(id); h.b.dealDamage(h.b.enemies[0], u, { amount: 1e7, type: 'true', canDodge: false }); return u; }; + const sum = (id, bond) => gains.filter(([s, b]) => s === id && b === bond).reduce((a, [, , n]) => a + n, 0); + return { h, kill, sum, gains }; +} + +test('埃芒加德: each of the 3 revives is a knock-out and a deployment — 砾 gains 不屈 +2 and 卡西米尔 +1 every time', REAL, () => { + const { h, kill, sum } = setup(); + assert.equal(sum(GRAVEL, 'kazimierzShip'), 1, 'the battle-start deployment'); + for (let i = 1; i <= 3; i++) { + const u = kill(GRAVEL); + assert.ok(u.alive, `revive ${i}: standing again`); + assert.equal(sum(GRAVEL, 'indomShip'), 2 * i, `revive ${i}: <被击倒时> 不屈 +2 (the parent: 0 until the 4th)`); + assert.equal(sum(GRAVEL, 'kazimierzShip'), 1 + i, `revive ${i}: <部署时> 卡西米尔 +1`); + h.run(0.5); + } + assert.deepEqual(h.eventsOf('fx').filter((e) => e[1] === 'revive' && e[4] && e[4].left != null).map((e) => e[4].left), [2, 1, 0], 'the band\'s 3'); +}); + +test('埃芒加德: 瑕光\'s <部署时> +4 to her own active bonds fires on a revive, up to its 12 per battle', REAL, () => { + const { kill, sum } = setup(); + assert.equal(sum(BLEMISH, 'kazimierzShip'), 4); + kill(BLEMISH); + assert.equal(sum(BLEMISH, 'kazimierzShip'), 8, 'first revive'); + assert.equal(sum(BLEMISH, 'raidShip'), 8); + kill(BLEMISH); + assert.equal(sum(BLEMISH, 'kazimierzShip'), 12, 'second revive: the cap'); + kill(BLEMISH); + assert.equal(sum(BLEMISH, 'kazimierzShip'), 12, 'third revive: still 12 (max_add_count_per_battle)'); +}); + +test('埃芒加德: a revive resets the operator like a redeploy (SP back to its initial value, a new deployment)', REAL, () => { + const { h, kill } = setup(); + const u = h.unit(BLEMISH); + u.skill.gainSp(3, 'test'); + const seq = u.deploySeq; + assert.ok(u.skill.sp > u.skill.initSp + 1e-6, `SP charged (${u.skill.sp})`); + kill(BLEMISH); + assert.ok(u.deploySeq > seq, 'a new deployment'); + assert.ok(Math.abs(u.skill.sp - u.skill.initSp) < 1e-6, `SP reset to ${u.skill.initSp}, got ${u.skill.sp}`); + assert.equal(Math.round(u.hp), Math.round(u.s.maxHp), 'full HP'); +}); + +test('M3茧甲: the same 复活 — a knock-out (砾 不屈 +2) and a deployment (卡西米尔 +1), once per battle', REAL, () => { + const { kill, sum } = setup({ band: null, items: { [GRAVEL]: ['chess_item_4_12_e_a'] } }); + const u = kill(GRAVEL); + assert.ok(u.alive); + assert.equal(sum(GRAVEL, 'indomShip'), 2); + assert.equal(sum(GRAVEL, 'kazimierzShip'), 2); +}); diff --git a/test/content/op_lessng.test.js b/test/content/op_lessng.test.js index b0a41b98..be0e6300 100644 --- a/test/content/op_lessng.test.js +++ b/test/content/op_lessng.test.js @@ -8,6 +8,7 @@ import { test } from 'node:test'; import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; +import { deploymentOf } from '../../server/sim/content/items/battle.js'; import { makeBattle, enemyRec, chessRec, checkInvariants } from '../helpers/battleHarness.js'; import { KITTED_CHARS, OPERATOR_KITS, KITS } from '../../server/sim/content/kits/index.js'; import { DUEL_KEY, OATH_KEY, PAIN_KEY, REBORN_KEY } from '../../server/sim/content/kits/ops/op-lessng.js'; @@ -327,7 +328,7 @@ test('DRE-Y “苦修者的抗压训练”: the first lethal hit of a deployment done(h); // a running 不死 (坚固维式重锤's window) holds him instead: the module is not used const r = field({ tier, elite: true, mod: DREY }); - r.u.mem.undyingAt = `${r.u.deploySeq}:0`; + r.u.mem.undyingAt = deploymentOf(r.u); r.u.mem.undyingUntil = r.h.b.time + 5; const hammer = r.h.b.on('fatal', (c) => { if (c.unit === r.u && !c.prevented) c.prevented = true; }, { priority: -99 }); const f = r.h.spawn('enemy_dummy', { pos: [11, 8] }); diff --git a/test/content/op_zuole.test.js b/test/content/op_zuole.test.js index 485e05aa..1a8fff90 100644 --- a/test/content/op_zuole.test.js +++ b/test/content/op_zuole.test.js @@ -8,6 +8,7 @@ import { test } from 'node:test'; import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; +import { deploymentOf } from '../../server/sim/content/items/battle.js'; import { makeBattle, enemyRec, checkInvariants } from '../helpers/battleHarness.js'; import { KITTED_CHARS, OPERATOR_KITS, KITS } from '../../server/sim/content/kits/index.js'; import { diyPool, validateDiyPicks } from '../../shared/diy.js'; @@ -350,7 +351,7 @@ test('SBL-Y (stages 1 and 3): knocked out ⇒ he stays and heals 30 % max HP, on // a running 不死 (坚固维式重锤's window) keeps him up instead h.b.redeploy(u); const r = field({ tier, elite: true, mod: SBLY, skill: 1 }); - r.u.mem.undyingAt = `${r.u.deploySeq}:0`; + r.u.mem.undyingAt = deploymentOf(r.u); r.u.mem.undyingUntil = r.h.b.time + 5; const hammer = r.h.b.on('fatal', (c) => { if (c.unit === r.u && !c.prevented) c.prevented = true; }, { priority: -99 }); const f = r.h.spawn('enemy_dummy', { pos: [10, 6] }); diff --git a/test/docs-consistency.test.js b/test/docs-consistency.test.js index 3f8b16be..e604e53d 100644 --- a/test/docs-consistency.test.js +++ b/test/docs-consistency.test.js @@ -718,9 +718,12 @@ test('player feedback after 0.1.0 (DESIGN §21, v0.1.1): every report mapped, th test('batch 6 after 0.1.0 (DESIGN §21.21–§21.25): the hammer per deployment, 起飞, fenced tiles, bodies, the PR fixes — code and docs agree', async () => { const sec = (n) => DESIGN.slice(DESIGN.indexOf(`## ${n}.`), DESIGN.indexOf(`## ${n + 1}.`) > 0 ? DESIGN.indexOf(`## ${n + 1}.`) : undefined); // F1: 不死 before 复活, once per deployment (§5.4 = SIM = items/battle.js) + // (0.2.0: the 复活 answer the knock-out — `death` hooks ahead of 阿戈尔 5 (11) and 不屈 (10), community report on 埃芒加德) const { PRIO_REVIVE, PRIO_RESPAWN } = await import('../server/sim/content/items/battle.js'); - assert.equal(PRIO_RESPAWN, PRIO_REVIVE - 1); - assert.match(sec(5), /\| `fatal` \|[^\n]*坚固维式重锤, once per deployment\) `PRIO_REVIVE` −100 → items' 复活 \(M3茧甲\) `PRIO_RESPAWN` −101 → 埃芒加德 −110/); + const { PRIO_BAND_REVIVE } = await import('../server/sim/content/bands/battle.js'); + assert.ok(PRIO_REVIVE < 0 && PRIO_RESPAWN > PRIO_BAND_REVIVE && PRIO_BAND_REVIVE > 11); + assert.match(sec(5), /\| `fatal` \|[^\n]*坚固维式重锤, once per deployment\) `PRIO_REVIVE` −100/); + assert.match(sec(5), /\| `death` \|[^\n]*items' 复活 \(M3茧甲\) `PRIO_RESPAWN` 13 → 埃芒加德 `PRIO_BAND_REVIVE` 12/); assert.match(SIM, /坚固维式重锤 — once per deployment/); assert.match(PLAYING, /\*\*每次部署一次\*\*/); // F2: onBuy = a shop purchase (§6.4 = META) @@ -764,11 +767,11 @@ test('batch 6 QA residuals (DESIGN §21.21–§21.25): the lock per deployment f const sub = (n) => { const a = DESIGN.indexOf(`### 21.${n} `); const b = DESIGN.indexOf('\n### 21.', a + 5); return DESIGN.slice(a, b > 0 ? b : DESIGN.indexOf('\n## 22.') > 0 ? DESIGN.indexOf('\n## 22.') : undefined); }; // F1: the lock belongs to the deployment (deploymentOf), its window to the battle (holdsUndying); revives open one const IB = await import('../server/sim/content/items/battle.js'); - for (const f of ['holdsUndying', 'revivedInPlace']) assert.equal(typeof IB[f], 'function', f); + for (const f of ['holdsUndying', 'reviveNow']) assert.equal(typeof IB[f], 'function', f); const items = doc('server/sim/content/items/battle.js'); assert.match(items, /function deploymentOf\(u\)/); assert.ok(!/S\.on\('deploy', \(c\) => \{\s*if \(c\.unit !== u \|\| c\.initial\) return;\s*hs\.undyingUsed/.test(items), 'no per-grant re-arm hook'); - assert.match(doc('server/sim/content/bands/battle.js'), /revivedInPlace\(u\)/); + assert.match(doc('server/sim/content/bands/battle.js'), /reviveNow\(battle, c, 'band'\)/); // since 0.2.0 a redeploy, no longer in place assert.match(doc('server/sim/content/kits/ops/chess_char_4_01-rmixer.js'), /if \(holdsUndying\(battle, unit\)\) return;/); assert.match(sub(21), /\*\*QA after the integration, fixed\*\*: \(1\) the lock lived in the hooks of the carrier's hammer grants/); assert.match(sub(21), /both in-place revives now call `revivedInPlace`/); diff --git a/test/golden/fields.json b/test/golden/fields.json index 13850933..8cf7547e 100644 --- a/test/golden/fields.json +++ b/test/golden/fields.json @@ -667,64 +667,64 @@ "time": 200, "ticks": 6000, "reason": "forced", - "killed": 4, + "killed": 5, "total": 6, "unspawned": 0, - "bossHpLeft": 6954318, - "rngDraws": 552, + "bossHpLeft": 6839827, + "rngDraws": 487, "errors": {"count":0,"kinds":[]}, "players": { - "p1": {"killed":4,"total":6,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":847634,"bossDmg":395229,"heal":818,"deaths":7,"layerGains":{}}, - "p2": {"killed":0,"total":0,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":1162932,"bossDmg":610453,"heal":1435,"deaths":14,"layerGains":{}} + "p1": {"killed":5,"total":6,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":931502,"bossDmg":476637,"heal":0,"deaths":5,"layerGains":{}}, + "p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":1243058,"bossDmg":643537,"heal":3926,"deaths":16,"layerGains":{}} }, "units": [ - ["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",3907,1,3,2,137783,0,0,32,2], + ["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",3907,1,3,2,107043,0,0,26,3], ["p1",2,"op","chess_char_4_01_b",2,"uniequip_002_rmixer",3537,1,1,0,0,0,0,0,0], - ["p1",3,"op","chess_char_5_14_b",1,"none",1994,1,5,0,55921,0,0,0,14], + ["p1",3,"op","chess_char_5_14_b",1,"none",1994,1,5,0,49913,0,0,0,12], ["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",4654.6,1,11,0,0,0,0,0,1], - ["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",1170,1,7,0,262312,0,0,69,10], - ["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",1382,1,13,0,182427,0,0,73,6], - ["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",1629,1,55,2,34515,1629,0,47,2], - ["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",0,0,56,0,121284,4833,0,40,12], - ["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",0,0,57,0,1934,5648,818,2,1], - ["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",1695,1,9,0,51458,0,0,38,2], - ["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",2644,1,43,0,0,12182,281,0,1], - ["p2",12,"op","chess_char_4_04_b",1,"uniequip_002_ines",0,0,50,0,185732,9124,851,264,6], + ["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",1170,1,7,1,308827,0,0,73,11], + ["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",1382,1,13,0,199158,0,0,73,6], + ["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",1629,1,15,1,28304,0,0,41,2], + ["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",0,0,40,0,176110,3222,0,44,15], + ["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",0,0,56,0,8257,4830,0,0,0], + ["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",1695,1,9,0,53890,0,0,41,2], + ["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",2644,1,44,0,4798,9594,208,10,1], + ["p2",12,"op","chess_char_4_04_b",1,"uniequip_002_ines",0,0,49,0,225342,9308,1035,271,6], ["p2",13,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",2383,1,6,0,0,0,0,0,0], - ["p2",14,"op","chess_char_4_16_b",2,"uniequip_002_texas2",0,0,58,0,61676,11022,256,126,7], - ["p2",15,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",2777.6,1,14,0,215990,0,0,116,6], - ["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,8,0,472573,0,0,132,2], + ["p2",14,"op","chess_char_4_16_b",2,"uniequip_002_texas2",0,0,55,0,72175,10989,223,130,7], + ["p2",15,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",2777.6,1,14,0,230782,0,0,117,6], + ["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,8,1,414404,0,0,114,2], ["p2",17,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1664,1,12,0,0,0,0,0,0], - ["p2",18,"op","chess_char_4_12_b",2,"uniequip_002_glady",2232,1,52,0,34831,2232,0,103,4], - ["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",0,0,48,0,93427,3978,0,86,22], - ["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",0,0,40,0,98701,3299,47,36,7], + ["p2",18,"op","chess_char_4_12_b",2,"uniequip_002_glady",0,0,16,0,80528,3398,1166,113,4], + ["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",0,0,18,0,136215,3232,1243,127,33], + ["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",0,0,54,0,78815,4930,52,27,4], ["p2",21,"token","token_10041_cathy_catsld",null,null,100,1,21,0,0,0,0,0,null], ["p2",22,"token","token_10041_cathy_catsld",null,null,100,1,22,0,0,0,0,0,null] ], "enemies": { - "enemy_10028_vtswd": [3,3,0,0,0], + "enemy_10028_vtswd": [5,5,0,0,0], "enemy_10029_vtshld": [3,3,0,0,0], - "enemy_10030_vtwand": [5,5,0,0,0], - "enemy_10085_hllevi_2": [2,0,2,0,804272], - "enemy_1010_demon": [4,4,0,13032,200612], - "enemy_9032_aclionk": [1,0,0,40914,1005682] + "enemy_10030_vtwand": [2,2,0,0,0], + "enemy_10085_hllevi_2": [2,1,1,0,853774], + "enemy_1010_demon": [4,4,0,10445,200612], + "enemy_9032_aclionk": [1,0,0,39059,1120173] }, - "hooks": [1,57,6000,1150,1168,2101,2112,1078,36,40,105,103,0,33986,1087,3,18,2,1,29,0,2,0], - "events": {"atk":1223,"deploy":39,"die":38,"dmg":2065,"engage":13,"fx":576,"heal":2,"leak":2,"skill":208,"spawn":40,"status":1110}, + "hooks": [1,55,6000,1195,1208,2168,2182,2342,36,39,115,113,0,36555,1375,7,17,1,1,28,0,3,0], + "events": {"atk":1268,"deploy":38,"die":38,"dmg":2165,"engage":14,"fx":588,"leak":1,"skill":228,"spawn":39,"status":1225}, "fx": { - "aoe": 32, + "aoe": 34, "appear": 4, "blink": 2, - "burst": 2, - "crit": 80, + "burst": 3, + "crit": 68, "dilemma": 6, "disappear": 4, "displace": 19, - "equip": 16, - "explosion": 7, - "frostNova": 22, + "equip": 12, + "explosion": 4, + "frostNova": 33, "garrisonGrant": 1, - "iceSpike": 40, + "iceSpike": 32, "overclock": 1, "pull": 4, "quadShot": 2, @@ -733,20 +733,20 @@ "sentry": 3, "shadowWeave": 3, "shield": 1, - "soul": 2, - "sp": 11, + "soul": 3, + "sp": 12, "stealth": 6, - "sword": 2, - "swordRain": 38, + "sword": 4, + "swordRain": 41, "swordStorm": 7, - "telegraph": 18, + "telegraph": 17, "tornado": 4, "tornadoPulse": 20, "vest": 3, "weightless": 6, - "zone": 190 + "zone": 209 }, - "snaps": "8a1f8d78 5887f6a8 75e7640c ee72be7c 45aaf338 72646e9d 5400e843 875b0bdd a5255fb2 4f28c0d0 da0a87a1 653af3cb 41cc724c ce76236e 751fd07f 20c538c4 0edfbcee 916abbd9 6371a2f1 9937cd28" + "snaps": "8a1f8d78 5887f6a8 75e7640c 6c1fa52f 3d0715d7 13a9bc85 01f2f99f 6ec63e95 79471033 6a9046a9 bce9f51f 7f9907c6 9448ee2c e5c0b958 3ee5cd84 bc474e74 1c886f0b caaecafa 265a6885 50b105cd" }, "boss-boss_6-solo": { "about": "阿利斯泰尔,帝国余晖 solo pool 3980000: chess_char_4_17_b chess_char_4_18_b chess_char_4_23_b chess_char_4_19_b chess_char_4_22_b chess_char_4_20_b chess_char_4_21_b chess_char_4_24_b chess_char_4_25_b chess_char_4_26_b", @@ -928,48 +928,48 @@ "killed": 13, "total": 18, "unspawned": 0, - "bossHpLeft": 12721869, + "bossHpLeft": 12722981, "rngDraws": 595, "errors": {"count":0,"kinds":[]}, "players": { - "p1": {"killed":13,"total":18,"perfect":false,"leaks":2,"leaksUncounted":0,"coins":0,"dmg":1807554,"bossDmg":894991,"heal":43213,"deaths":18,"layerGains":{}}, - "p2": {"killed":0,"total":0,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":973750,"bossDmg":782556,"heal":3433,"deaths":25,"layerGains":{}} + "p1": {"killed":13,"total":18,"perfect":false,"leaks":2,"leaksUncounted":0,"coins":0,"dmg":1799509,"bossDmg":894991,"heal":43213,"deaths":20,"layerGains":{}}, + "p2": {"killed":0,"total":0,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":978836,"bossDmg":781444,"heal":3433,"deaths":25,"layerGains":{}} }, "units": [ - ["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",5080.92,1,77,2,48613,25521,344,19,2], - ["p1",2,"op","chess_char_4_01_b",2,"uniequip_002_rmixer",8067.66,1,76,0,378,9736,453,3,2], - ["p1",3,"op","chess_char_5_14_b",1,"none",3988,1,86,1,48666,12855,2175,24,9], - ["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",0,0,83,0,35959,29785,8006,59,3], - ["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",89.23,1,80,2,849513,4961,12341,98,11], - ["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",0,0,70,1,72754,10765,201,19,2], - ["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",3258,1,89,1,288403,6516,0,12,1], - ["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",0,0,72,1,98794,6444,0,9,5], - ["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",3220,1,90,0,0,11772,19693,17,2], - ["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",801.14,1,79,2,364473,10638,0,24,2], - ["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",0,0,73,0,0,6071,137,0,1], - ["p2",12,"op","chess_char_4_04_b",1,"uniequip_002_ines",0,0,82,1,8212,12720,5,56,4], - ["p2",13,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",4170.25,1,92,0,1799,9948,1608,2,2], - ["p2",14,"op","chess_char_4_16_b",2,"uniequip_002_texas2",974.55,1,88,0,92340,16538,16,44,9], - ["p2",15,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",0,0,67,0,77253,8291,204,21,3], - ["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",0,0,85,2,597129,3122,0,130,2], + ["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",5080.92,1,79,2,40568,26519,344,15,2], + ["p1",2,"op","chess_char_4_01_b",2,"uniequip_002_rmixer",8067.66,1,78,0,378,9736,453,3,2], + ["p1",3,"op","chess_char_5_14_b",1,"none",3988,1,88,1,48666,12855,2175,24,9], + ["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",0,0,85,0,35959,29785,8006,59,3], + ["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",89.23,1,82,2,849513,4961,12341,98,11], + ["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",0,0,72,1,72754,10765,201,19,2], + ["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",3258,1,91,1,288403,6516,0,12,1], + ["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",0,0,74,1,98794,6444,0,9,5], + ["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",3220,1,92,0,0,11772,19693,17,2], + ["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",801.14,1,81,2,364473,10638,0,24,2], + ["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",0,0,75,0,0,6071,137,0,1], + ["p2",12,"op","chess_char_4_04_b",1,"uniequip_002_ines",0,0,84,1,8212,12720,5,56,4], + ["p2",13,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",4170.25,1,94,0,1799,9948,1608,2,2], + ["p2",14,"op","chess_char_4_16_b",2,"uniequip_002_texas2",974.55,1,90,0,92340,16538,16,44,9], + ["p2",15,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",0,0,69,0,77253,8291,204,21,3], + ["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",0,0,87,2,597129,3122,0,130,2], ["p2",17,"op","chess_char_4_10_b",1,"uniequip_002_aroma",0,0,20,0,56567,7585,264,58,2], ["p2",18,"op","chess_char_4_12_b",2,"uniequip_002_glady",0,0,2,0,27214,2956,724,13,2], - ["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",0,0,64,0,27451,4162,184,37,11], - ["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",0,0,65,3,85785,3543,291,33,6], + ["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",0,0,66,1,30896,4162,184,41,12], + ["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",0,0,67,2,87426,3543,291,33,6], ["p2",21,"token","token_10041_cathy_catsld",null,null,100,1,21,0,0,0,0,0,null], ["p2",22,"token","token_10041_cathy_catsld",null,null,100,1,22,0,0,0,0,0,null] ], "enemies": { - "enemy_10027_vtsk": [6,1,3,136990,777594], + "enemy_10027_vtsk": [6,1,3,137988,776007], "enemy_1005_yokai": [4,4,0,0,1600], "enemy_1229_darmy_2": [8,8,0,3462,294231], - "enemy_9013_acstmk_2": [1,0,0,48118,1678131], + "enemy_9013_acstmk_2": [1,0,0,48118,1677019], "enemy_9014_acstma": [4,3,0,2847,23452], "enemy_9015_acstmb": [3,2,0,12510,31442], "enemy_9016_acstmr": [8,7,0,0,40] }, - "hooks": [1,90,6000,770,773,2560,2726,4023,68,73,81,79,3,18733,553,15,34,3,1,69,0,3,5], - "events": {"atk":856,"deploy":56,"die":70,"dmg":2725,"engage":17,"fx":600,"heal":101,"leak":3,"skill":160,"spawn":56,"status":553}, + "hooks": [1,92,6000,770,773,2562,2728,4023,70,75,82,80,3,18982,560,15,34,3,1,69,0,3,5], + "events": {"atk":856,"deploy":58,"die":72,"dmg":2727,"engage":17,"fx":601,"heal":101,"leak":3,"skill":162,"spawn":56,"status":559}, "fx": { "aoe": 23, "appear": 9, @@ -984,7 +984,7 @@ "dodge": 5, "explode": 6, "explosion": 6, - "frostNova": 11, + "frostNova": 12, "iceSpike": 12, "overclock": 1, "palsy": 1, @@ -1012,7 +1012,7 @@ "weightless": 2, "zone": 187 }, - "snaps": "1b4d1c90 5e89ae3a 18b0277b 5cb9694e 563cd78d c2934649 005a2898 7c68af78 029a7b80 184cf32b 943adc62 cc001f13 527719ca e6dd0c82 6bc82008 833dee21 e6dd7990 4c3331ac 7e1c1ac9 63fe7c16" + "snaps": "1b4d1c90 5e89ae3a 18b0277b 5cb9694e 563cd78d c2934649 005a2898 3c77b766 04f89607 02eb8917 8e175305 f676cd83 a97f93f8 b59d1be9 3d859552 ffe9cc48 0faf2d10 044cbe2d f3bedb1c 7d4d8edd" }, "hidden-boss_8-solo": { "about": "假想敌:胄 solo pool 7200000: chess_char_4_17_b chess_char_4_18_b chess_char_4_23_b chess_char_4_19_b chess_char_4_22_b chess_char_4_20_b chess_char_4_21_b chess_char_4_24_b chess_char_4_25_b chess_char_4_26_b", @@ -1079,36 +1079,36 @@ "killed": 8, "total": 8, "unspawned": 0, - "bossHpLeft": 4049210, - "rngDraws": 1680, + "bossHpLeft": 4017610, + "rngDraws": 1624, "errors": {"count":0,"kinds":[]}, "players": { - "p1": {"killed":8,"total":8,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":1426827,"bossDmg":597682,"heal":13214,"deaths":5,"layerGains":{}}, - "p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":2554978,"bossDmg":913911,"heal":130784,"deaths":8,"layerGains":{}} + "p1": {"killed":8,"total":8,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":1645455,"bossDmg":671508,"heal":15048,"deaths":5,"layerGains":{}}, + "p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":2448666,"bossDmg":865308,"heal":101654,"deaths":17,"layerGains":{}} }, "units": [ - ["p1",1,"op","chess_char_6_03_b",2,"uniequip_002_yu",0,0,58,0,0,10883,4690,0,2], + ["p1",1,"op","chess_char_6_03_b",2,"uniequip_002_yu",0,0,61,0,0,10883,4678,0,2], ["p1",2,"op","chess_char_6_06_b",2,"uniequip_002_pepe",2939,1,11,0,23455,2258,0,35,1], ["p1",3,"op","chess_char_6_07_b",2,"uniequip_002_siege2",2990,1,17,0,52147,2547,0,50,2], - ["p1",4,"op","chess_char_6_01_b",2,"uniequip_002_lemuen",99.06,1,7,1,1043569,3226,0,57,8], - ["p1",5,"op","chess_char_6_02_b",2,"uniequip_002_sbell2",931.61,1,9,0,31824,10406,0,46,2], - ["p1",6,"op","chess_char_6_04_b",2,"uniequip_002_skadi2",745.66,1,52,0,8749,9134,562,0,4], + ["p1",4,"op","chess_char_6_01_b",2,"uniequip_002_lemuen",0,0,7,1,1261872,3759,0,54,8], + ["p1",5,"op","chess_char_6_02_b",2,"uniequip_002_sbell2",931.61,1,9,0,32004,10184,0,46,2], + ["p1",6,"op","chess_char_6_04_b",2,"uniequip_002_skadi2",745.66,1,55,0,8749,9239,728,0,4], ["p1",7,"op","chess_char_6_05_b",2,"uniequip_002_pasngr",2451.4,1,13,1,81581,0,0,0,11], - ["p1",8,"op","chess_char_6_08_b",2,"uniequip_002_reed2",1668,1,19,1,32005,0,7161,70,2], - ["p1",9,"op","chess_char_6_09_b",0,"uniequip_002_cello",0,0,21,1,131535,12922,0,27,27], - ["p1",10,"op","chess_char_6_11_b",2,"uniequip_002_mlyss",1893,1,56,0,14353,9097,349,78,2], + ["p1",8,"op","chess_char_6_08_b",2,"uniequip_002_reed2",1668,1,19,1,32038,0,8142,70,2], + ["p1",9,"op","chess_char_6_09_b",0,"uniequip_002_cello",0,0,21,1,131623,12992,0,27,27], + ["p1",10,"op","chess_char_6_11_b",2,"uniequip_002_mlyss",1893,1,23,0,14377,8316,349,84,2], ["p1",11,"token","token_10017_skadi2_dedant",null,null,0,0,28,0,0,130,0,0,null], ["p1",12,"token","token_10030_mlyss_wtrman",null,null,0,0,24,0,0,1614,292,4,1], - ["p2",13,"op","chess_char_6_15_b",2,"uniequip_002_qiubai",0,0,60,3,471039,50514,0,332,3], - ["p2",14,"op","chess_char_6_19_b",2,"uniequip_002_blkkgt",0,0,61,0,247360,13406,0,68,4], - ["p2",15,"op","chess_char_5_01_b",1,"uniequip_002_excu2",0,0,59,0,13275,9642,2640,45,2], - ["p2",16,"op","chess_char_6_17_b",2,"uniequip_002_nearl2",2458.52,1,62,1,509240,22200,0,58,2], - ["p2",17,"op","chess_char_6_12_b",1,"uniequip_002_rosmon",2886.8,1,8,0,264522,6236,0,75,3], - ["p2",18,"op","chess_char_6_13_b",1,"uniequip_002_angel2",2215,1,14,0,662969,6421,4283,285,6], - ["p2",19,"op","chess_char_6_14_b",2,"uniequip_002_lumen",2222.83,1,20,0,0,2781,19999,79,1], - ["p2",20,"op","chess_char_6_16_b",2,"uniequip_002_halo2",0,0,10,0,80392,3176,881,101,3], - ["p2",21,"op","chess_char_6_18_b",2,"uniequip_002_whitw2",1331,1,27,0,255595,5370,0,32,3], - ["p2",22,"op","chess_char_6_20_b",2,"uniequip_002_agoat2",0,0,25,0,0,17059,102981,70,2], + ["p2",13,"op","chess_char_6_15_b",2,"uniequip_002_qiubai",0,0,58,3,707548,33856,0,262,3], + ["p2",14,"op","chess_char_6_19_b",2,"uniequip_002_blkkgt",0,0,64,0,14341,15397,0,38,2], + ["p2",15,"op","chess_char_5_01_b",1,"uniequip_002_excu2",0,0,62,0,5592,6711,1711,34,2], + ["p2",16,"op","chess_char_6_17_b",2,"uniequip_002_nearl2",0,0,63,1,473437,22231,0,46,2], + ["p2",17,"op","chess_char_6_12_b",1,"uniequip_002_rosmon",0,0,8,0,261483,4750,0,72,3], + ["p2",18,"op","chess_char_6_13_b",1,"uniequip_002_angel2",0,0,14,0,615801,8646,2600,258,5], + ["p2",19,"op","chess_char_6_14_b",2,"uniequip_002_lumen",0,0,20,0,0,5004,9343,65,1], + ["p2",20,"op","chess_char_6_16_b",2,"uniequip_002_halo2",0,0,10,0,93740,3176,1402,116,3], + ["p2",21,"op","chess_char_6_18_b",2,"uniequip_002_whitw2",0,0,27,0,204164,10664,0,31,2], + ["p2",22,"op","chess_char_6_20_b",2,"uniequip_002_agoat2",0,0,25,0,0,14139,86599,66,2], ["-","~1","device","trap_1105_accrate",null,null,100,1,1,0,0,0,0,0,null], ["-","~2","device","trap_1105_accrate",null,null,100,1,2,0,0,0,0,0,null], ["-","~3","device","trap_1105_accrate",null,null,100,1,3,0,0,0,0,0,null], @@ -1118,40 +1118,39 @@ ["p2","~1","token","token_10019_nearl2_sword",null,null,3924.87,0,46,0,6538,3899,0,8,null], ["p1","~1","token","token_10030_mlyss_wtrman",null,null,0,0,47,0,1339,2034,0,23,1], ["p1","~2","token","token_10030_mlyss_wtrman",null,null,131.08,0,48,0,1401,2025,0,19,null], - ["p1","~3","token","token_10030_mlyss_wtrman",null,null,0,0,49,0,120,1322,0,2,null], - ["p1","~1","token","token_10040_siege2_vlion",null,null,3722.5,0,50,0,4750,277,0,10,null], - ["p2","~2","token","token_10019_nearl2_sword",null,null,3093.17,0,53,0,44047,4069,0,25,null], - ["p1","~2","token","token_10040_siege2_vlion",null,null,3933.26,0,55,0,0,81,0,0,null], - ["p1","~4","token","token_10030_mlyss_wtrman",null,null,1322,1,57,0,0,180,160,0,1] + ["p1","~3","token","token_10030_mlyss_wtrman",null,null,0,0,50,0,120,1322,0,2,null], + ["p1","~1","token","token_10040_siege2_vlion",null,null,3722.5,0,51,0,4750,277,0,10,null], + ["p2","~2","token","token_10019_nearl2_sword",null,null,0,0,56,0,66023,6528,0,4,null], + ["p1","~4","token","token_10030_mlyss_wtrman",null,null,1322,1,57,0,0,840,859,0,1], + ["p1","~2","token","token_10040_siege2_vlion",null,null,3980.14,0,60,0,0,26,0,0,null] ], "enemies": { "enemy_1267_nhpbr_2": [6,6,0,2895,141894], - "enemy_9007_acelem": [2,2,0,23398,309587], - "enemy_9017_achunt_2": [2,0,0,59262,1550790], - "enemy_9018_actrpa": [1,0,0,43264,577004], - "enemy_9019_actrpb": [1,0,0,21943,535849], - "enemy_9020_actrpc": [1,0,0,24229,938579] + "enemy_9007_acelem": [2,2,0,13327,309587], + "enemy_9017_achunt_2": [2,0,0,54993,1582390], + "enemy_9018_actrpa": [1,0,0,40542,615292], + "enemy_9019_actrpb": [1,0,0,26197,568492], + "enemy_9020_actrpc": [1,0,0,27710,967163] }, - "hooks": [1,60,6000,1767,1767,7110,13865,2612,25,35,93,88,317,45858,2401,14,13,0,1,29,0,17,0], - "events": {"atk":2141,"deploy":41,"die":35,"dmg":13390,"engage":22,"fx":2180,"heal":905,"skill":181,"spawn":49,"status":750}, + "hooks": [1,62,6000,1591,1591,6920,13591,2927,35,43,89,87,292,42200,2590,16,13,0,1,55,0,17,0], + "events": {"atk":2132,"deploy":43,"die":43,"dmg":13198,"engage":22,"fx":2025,"heal":843,"skill":176,"spawn":49,"status":768}, "fx": { - "airstrike": 99, - "beam": 24, + "airstrike": 91, + "beam": 21, "blessing": 1, - "blink": 5, - "bombard": 72, - "bombardShell": 72, + "blink": 4, + "bombard": 69, + "bombardShell": 69, "burst": 17, "camouflage": 1, "copy": 3, "dash": 24, - "displace": 6, "dp": 2, - "drone": 331, - "droneLock": 11, - "drones": 3, - "extraAttack": 15, - "finale": 4, + "drone": 235, + "droneLock": 7, + "drones": 2, + "extraAttack": 11, + "finale": 2, "firewall": 2, "garrisonGrant": 1, "lightning": 126, @@ -1163,19 +1162,20 @@ "revive": 3, "scorchBurst": 3, "shieldBreak": 9, - "slash": 44, + "slash": 22, "snow": 28, "split": 2, - "steal": 6, + "steal": 5, "storm": 11, "summon": 4, - "sunBurst": 4, + "sunBurst": 2, "talent": 4, "tide": 4, + "undying": 1, "wanted": 6, "zone": 6 }, - "snaps": "9797dd57 d3ba8d58 32d06887 bf42877c 1994874a e5491557 66d383f3 1312fd65 b74b9f4a 2f28845d ead771e6 c391a1a4 f923753b 23bee15f caa10968 93e7fa5f 8c6cfd06 4d79d333 2710458e 1a607645" + "snaps": "9797dd57 d3ba8d58 32d06887 bf42877c 1994874a c004c813 a0ce0809 99f52693 2d52f767 6e0096e0 c26a60f1 b9832509 290e1478 b7c46bbb 46636ff6 a278a6e4 cf1fe33e d7ceb1e8 e4323815 e22fb1a3" }, "hidden-boss_9-solo": { "about": "假想敌:铳 solo pool 2800000: chess_char_5_08_b chess_char_5_11_b chess_char_5_05_b chess_char_5_06_b chess_char_5_13_b chess_char_5_07_b chess_char_5_02_b chess_char_5_03_b chess_char_5_10_b chess_char_5_12_b", diff --git a/test/golden/matches.json b/test/golden/matches.json index a6e19d08..a9a40a7a 100644 --- a/test/golden/matches.json +++ b/test/golden/matches.json @@ -99,7 +99,7 @@ "combat": "client", "boost": null, "setup": {"stageId":"act1autochess_m03","bossId":"boss_5","hiddenBossId":"boss_8","factions":["TIMES","DOT","INVISIBLE"]}, - "end": {"victory":false,"roundsPassed":13,"hiddenReached":false,"hiddenCleared":false,"reason":"defeat","teamLp":0,"bossPoolLeft":93088,"virtualMs":106900}, + "end": {"victory":false,"roundsPassed":13,"hiddenReached":false,"hiddenCleared":false,"reason":"defeat","teamLp":0,"bossPoolLeft":94160,"virtualMs":106900}, "rng": {"setup":25,"shop":207,"waves":0,"draft":10,"bots":8483,"meta":14}, "errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0}, "rounds": [ @@ -134,11 +134,11 @@ }, { "round": 12, - "ai_0": [1,17,12,0,0,6,8,"03cea672",154,"arcaneShip 0/2, deputShip 0/8, emptyShip 0/4, kazimierzShip 0/8, kjeragShip 0/14, miraShip 1/9, preciShip 0/12, sargonShip 0/8, siracusaShip 2/105, soloShip 1/16, steadShip 0/6, suntShip 1/2, swiftShip 1/22",20,31,11,109] + "ai_0": [1,19,12,0,0,6,8,"03cea672",151,"arcaneShip 0/2, deputShip 0/8, emptyShip 0/4, kazimierzShip 0/8, kjeragShip 0/14, miraShip 1/8, preciShip 0/12, sargonShip 0/8, siracusaShip 2/103, soloShip 1/16, steadShip 0/6, suntShip 1/2, swiftShip 1/22",23,31,8,109] }, { "round": 13, - "ai_0": [1,17,12,0,0,6,8,"1cf42739",230,"arcaneShip 0/2, deputShip 2/12, emptyShip 1/8, kazimierzShip 0/16, kjeragShip 0/22, miraShip 1/13, preciShip 0/12, sargonShip 0/8, siracusaShip 1/129, soloShip 1/20, steadShip 0/6, suntShip 1/6, swiftShip 1/42",115,115,0,121] + "ai_0": [1,19,12,0,0,6,8,"1cf42739",227,"arcaneShip 0/2, deputShip 2/12, emptyShip 1/8, kazimierzShip 0/16, kjeragShip 0/22, miraShip 1/12, preciShip 0/12, sargonShip 0/8, siracusaShip 1/127, soloShip 1/20, steadShip 0/6, suntShip 1/6, swiftShip 1/42",115,115,0,121] } ], "players": { @@ -152,9 +152,9 @@ "title": {"id":"comment_2","name":"不朽盟约","picId":"comment_icon_2","text":"激活的盟约层数总和最高"}, "trophies": 0, "reward": 320, - "stats": {"activatedLayers":290,"bossDamage":296912,"dmgDealt":2081142,"gold":131,"itemsEquipped":23,"kills":383,"leaks":11,"lpLost":10,"merges":5,"perfectRounds":12,"refreshes":15}, + "stats": {"activatedLayers":287,"bossDamage":295840,"dmgDealt":2127405,"gold":131,"itemsEquipped":23,"kills":386,"leaks":8,"lpLost":8,"merges":5,"perfectRounds":12,"refreshes":15}, "lineup": ["2_14_a@12,5","5_10_a@12,7[4_07_e_a+3_08_e_b]","5_20_b@11,5[6_09_e_a+5_02_e_b]","3_20_b@11,8[3_06_e_a+4_08_e_a]","6_11_a@10,3[4_12_e_a+5_02_e_b]","3_18_a@10,8[2_04_e_b+4_05_e_b]","6_19_a@9,4[4_04_e_a+4_10_e_a]","1_08_a@9,5[1_01_e_a+1_02_e_a]"], - "bonds": ["arcaneShip 0/2","deputShip 1/14","emptyShip 1/10","kazimierzShip 0/16","kjeragShip 1/24","maniShip 1/2","miraShip 1/15","preciShip 0/12","sargonShip 0/8","siracusaShip 1/151","soloShip 1/22","steadShip 0/6","suntShip 1/8","swiftShip 1/44"] + "bonds": ["arcaneShip 0/2","deputShip 1/14","emptyShip 1/10","kazimierzShip 0/16","kjeragShip 1/24","maniShip 1/2","miraShip 1/14","preciShip 0/12","sargonShip 0/8","siracusaShip 1/149","soloShip 1/22","steadShip 0/6","suntShip 1/8","swiftShip 1/44"] } } }, @@ -243,7 +243,7 @@ "combat": "client", "boost": null, "setup": {"stageId":"act1autochess_m03","bossId":"boss_5","hiddenBossId":"boss_8","factions":["TIMES","DOT","INVISIBLE"]}, - "end": {"victory":false,"roundsPassed":13,"hiddenReached":false,"hiddenCleared":false,"reason":"defeat","teamLp":0,"bossPoolLeft":94716,"virtualMs":107800}, + "end": {"victory":false,"roundsPassed":13,"hiddenReached":false,"hiddenCleared":false,"reason":"defeat","teamLp":0,"bossPoolLeft":92859,"virtualMs":107800}, "rng": {"setup":25,"shop":201,"waves":0,"draft":42,"bots":8376,"meta":2}, "errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0}, "rounds": [ @@ -262,27 +262,27 @@ }, { "round": 8, - "ai_0": [1,23,11,0,0,4,8,"6960d5f9",66,"deputShip 1/6, emptyShip 1/2, kazimierzShip 0/8, kjeragShip 1/9, preciShip 0/5, sargonShip 0/8, siracusaShip 1/27, soloShip 1/7, steadShip 1/15, swiftShip 0/8",15,19,4,61] + "ai_0": [1,24,11,0,0,4,8,"6960d5f9",66,"deputShip 1/6, emptyShip 1/2, kazimierzShip 0/8, kjeragShip 1/9, preciShip 0/5, sargonShip 0/8, siracusaShip 1/27, soloShip 1/7, steadShip 1/15, swiftShip 0/8",16,19,3,61] }, { "round": 9, - "ai_0": [1,23,12,0,0,4,8,"ee973cc6",102,"arcaneShip 1/10, deputShip 1/8, emptyShip 1/4, kazimierzShip 0/8, kjeragShip 1/16, preciShip 1/14, sargonShip 0/8, siracusaShip 1/41, soloShip 1/9, steadShip 0/15, swiftShip 0/8",34,34,0,75] + "ai_0": [1,24,12,0,0,4,8,"ee973cc6",102,"arcaneShip 1/10, deputShip 1/8, emptyShip 1/4, kazimierzShip 0/8, kjeragShip 1/16, preciShip 1/14, sargonShip 0/8, siracusaShip 1/41, soloShip 1/9, steadShip 0/15, swiftShip 0/8",34,34,0,75] }, { "round": 10, - "ai_0": [1,23,12,0,0,5,8,"b4c89cd7",128,"arcaneShip 1/12, deputShip 1/10, emptyShip 1/6, kazimierzShip 0/8, kjeragShip 1/23, preciShip 1/21, sargonShip 0/8, siracusaShip 1/45, soloShip 1/11, steadShip 0/15, swiftShip 0/8",24,24,0,86] + "ai_0": [1,24,12,0,0,5,8,"b4c89cd7",128,"arcaneShip 1/12, deputShip 1/10, emptyShip 1/6, kazimierzShip 0/8, kjeragShip 1/23, preciShip 1/21, sargonShip 0/8, siracusaShip 1/45, soloShip 1/11, steadShip 0/15, swiftShip 0/8",24,24,0,86] }, { "round": 11, - "ai_0": [1,20,12,0,2,5,8,"1d52aad9",172,"arcaneShip 1/20, deputShip 1/12, emptyShip 1/8, kazimierzShip 0/8, kjeragShip 1/32, preciShip 1/28, sargonShip 0/8, siracusaShip 1/59, soloShip 1/13, steadShip 0/17, swiftShip 0/8",31,34,3,97] + "ai_0": [1,21,12,0,2,5,8,"1d52aad9",172,"arcaneShip 1/20, deputShip 1/12, emptyShip 1/8, kazimierzShip 0/8, kjeragShip 1/32, preciShip 1/28, sargonShip 0/8, siracusaShip 1/59, soloShip 1/13, steadShip 0/17, swiftShip 0/8",31,34,3,97] }, { "round": 12, - "ai_0": [1,10,14,0,0,6,8,"4dd4e915",196,"arcaneShip 0/20, deputShip 1/14, emptyShip 1/10, kazimierzShip 0/8, kjeragShip 1/39, preciShip 1/40, sargonShip 0/8, siracusaShip 1/63, soloShip 1/15, steadShip 0/17, swiftShip 1/15",12,31,19,111] + "ai_0": [1,11,14,0,0,6,8,"4dd4e915",196,"arcaneShip 0/20, deputShip 1/14, emptyShip 1/10, kazimierzShip 0/8, kjeragShip 1/39, preciShip 1/40, sargonShip 0/8, siracusaShip 1/63, soloShip 1/15, steadShip 0/17, swiftShip 1/15",11,31,20,111] }, { "round": 13, - "ai_0": [1,10,12,0,2,6,8,"42f17176",230,"arcaneShip 1/26, deputShip 0/14, emptyShip 1/10, kazimierzShip 0/8, kjeragShip 1/39, preciShip 2/45, sargonShip 0/8, siracusaShip 1/75, soloShip 1/15, steadShip 0/17, swiftShip 1/20",115,115,0,126] + "ai_0": [1,11,12,0,2,6,8,"42f17176",230,"arcaneShip 1/26, deputShip 0/14, emptyShip 1/10, kazimierzShip 0/8, kjeragShip 1/39, preciShip 2/45, sargonShip 0/8, siracusaShip 1/75, soloShip 1/15, steadShip 0/17, swiftShip 1/20",115,115,0,126] } ], "players": { @@ -296,7 +296,7 @@ "title": {"id":"comment_2","name":"不朽盟约","picId":"comment_icon_2","text":"激活的盟约层数总和最高"}, "trophies": 0, "reward": 340, - "stats": {"activatedLayers":268,"bossDamage":685284,"dmgDealt":2251076,"gold":140,"itemsEquipped":16,"kills":391,"leaks":26,"lpLost":17,"merges":3,"perfectRounds":10,"refreshes":15}, + "stats": {"activatedLayers":268,"bossDamage":687141,"dmgDealt":2250488,"gold":140,"itemsEquipped":16,"kills":393,"leaks":26,"lpLost":16,"merges":3,"perfectRounds":10,"refreshes":15}, "lineup": ["6_12_a@12,5[5_01_e_a+5_02_e_a]","5_10_a@12,7[4_07_e_a+5_02_e_b]","4_14_a@11,8","3_11_a@10,3","5_14_a@9,4[3_08_e_a+3_11_e_a]","1_08_a@9,5[1_01_e_a+4_05_e_a]","6_02_a@9,6","4_10_a@9,8[4_08_e_a+4_10_e_b]"], "bonds": ["arcaneShip 1/30","deputShip 0/14","emptyShip 1/10","kazimierzShip 0/16","kjeragShip 1/51","preciShip 2/50","sargonShip 0/8","siracusaShip 1/79","soloShip 1/15","steadShip 0/21","swiftShip 1/33","visiShip 1/0"] } @@ -406,23 +406,23 @@ }, { "round": 8, - "ai_0": [1,21,11,0,0,4,8,"214665a0",70,"deputShip 1/6, emptyShip 1/2, kazimierzShip 0/8, kjeragShip 1/9, preciShip 0/5, sargonShip 0/8, siracusaShip 1/31, soloShip 1/7, steadShip 1/15, swiftShip 0/8",14,19,5,61] + "ai_0": [1,21,11,0,0,4,8,"214665a0",68,"deputShip 1/6, emptyShip 1/2, kazimierzShip 0/8, kjeragShip 1/9, preciShip 0/5, sargonShip 0/8, siracusaShip 1/29, soloShip 1/7, steadShip 1/15, swiftShip 0/8",14,19,5,61] }, { "round": 9, - "ai_0": [1,21,12,0,0,4,8,"b598a45c",106,"arcaneShip 1/10, deputShip 1/8, emptyShip 1/4, kazimierzShip 0/8, kjeragShip 1/16, preciShip 1/14, sargonShip 0/8, siracusaShip 1/45, soloShip 1/9, steadShip 0/15, swiftShip 0/8",34,34,0,75] + "ai_0": [1,21,12,0,0,4,8,"b598a45c",104,"arcaneShip 1/10, deputShip 1/8, emptyShip 1/4, kazimierzShip 0/8, kjeragShip 1/16, preciShip 1/14, sargonShip 0/8, siracusaShip 1/43, soloShip 1/9, steadShip 0/15, swiftShip 0/8",34,34,0,75] }, { "round": 10, - "ai_0": [1,11,12,0,0,5,8,"317b28ba",132,"arcaneShip 1/12, deputShip 1/10, emptyShip 1/6, kazimierzShip 0/8, kjeragShip 1/23, preciShip 1/21, sargonShip 0/8, siracusaShip 1/49, soloShip 1/11, steadShip 0/15, swiftShip 0/8",11,24,13,86] + "ai_0": [1,11,12,0,0,5,8,"317b28ba",130,"arcaneShip 1/12, deputShip 1/10, emptyShip 1/6, kazimierzShip 0/8, kjeragShip 1/23, preciShip 1/21, sargonShip 0/8, siracusaShip 1/47, soloShip 1/11, steadShip 0/15, swiftShip 0/8",12,24,12,86] }, { "round": 11, - "ai_0": [1,1,12,0,0,5,8,"e69c468d",176,"arcaneShip 1/20, deputShip 1/12, emptyShip 1/8, kazimierzShip 0/8, kjeragShip 1/32, preciShip 1/28, sargonShip 0/8, siracusaShip 1/63, soloShip 1/13, steadShip 0/17, swiftShip 0/8",18,34,16,97] + "ai_0": [1,1,12,0,0,5,8,"e69c468d",174,"arcaneShip 1/20, deputShip 1/12, emptyShip 1/8, kazimierzShip 0/8, kjeragShip 1/32, preciShip 1/28, sargonShip 0/8, siracusaShip 1/61, soloShip 1/13, steadShip 0/17, swiftShip 0/8",16,34,18,97] }, { "round": 12, - "ai_0": [0,0,12,0,0,6,0,"811c9dc5",0,"arcaneShip 0/22, deputShip 0/14, emptyShip 0/10, kazimierzShip 0/8, kjeragShip 0/39, preciShip 0/35, sargonShip 0/8, siracusaShip 0/67, soloShip 0/15, steadShip 0/17, swiftShip 0/8",9,31,22,109] + "ai_0": [0,0,12,0,0,6,0,"811c9dc5",0,"arcaneShip 0/22, deputShip 0/14, emptyShip 0/10, kazimierzShip 0/8, kjeragShip 0/39, preciShip 0/35, sargonShip 0/8, siracusaShip 0/65, soloShip 0/15, steadShip 0/17, swiftShip 0/8",7,31,24,109] } ], "players": { @@ -436,9 +436,9 @@ "title": {"id":"comment_4","name":"精英云集","picId":"comment_icon_4","text":"晋升精锐次数最多"}, "trophies": 0, "reward": 255, - "stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":1632814,"gold":109,"itemsEquipped":10,"kills":227,"leaks":57,"lpLost":36,"merges":2,"perfectRounds":7,"refreshes":9}, + "stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":1612455,"gold":109,"itemsEquipped":10,"kills":224,"leaks":60,"lpLost":36,"merges":2,"perfectRounds":7,"refreshes":9}, "lineup": [], - "bonds": ["arcaneShip 0/22","deputShip 0/14","emptyShip 0/10","kazimierzShip 0/8","kjeragShip 0/39","preciShip 0/35","sargonShip 0/8","siracusaShip 0/67","soloShip 0/15","steadShip 0/17","swiftShip 0/8"] + "bonds": ["arcaneShip 0/22","deputShip 0/14","emptyShip 0/10","kazimierzShip 0/8","kjeragShip 0/39","preciShip 0/35","sargonShip 0/8","siracusaShip 0/65","soloShip 0/15","steadShip 0/17","swiftShip 0/8"] } } }, diff --git a/test/golden/roster.json b/test/golden/roster.json index 8b113218..88b692e1 100644 --- a/test/golden/roster.json +++ b/test/golden/roster.json @@ -720,31 +720,31 @@ "round": 10, "seed": 1517795683, "waveId": "act1autochess_h03", - "time": 161.47, - "ticks": 4844, + "time": 162.33, + "ticks": 4870, "reason": "cleared", "killed": 99, "total": 100, "unspawned": 0, "bossHpLeft": null, - "rngDraws": 194, + "rngDraws": 175, "errors": {"count":0,"kinds":[]}, "players": { - "p1": {"killed":99,"total":100,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":10,"dmg":985546,"bossDmg":0,"heal":21845,"deaths":7,"layerGains":{"preciShip":8}} + "p1": {"killed":99,"total":100,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":10,"dmg":995615,"bossDmg":0,"heal":24822,"deaths":10,"layerGains":{"preciShip":8}} }, "units": [ ["p1",1,"op","chess_char_4_17_b",1,"uniequip_002_hsguma",3430.24,1,7,1,184,83,0,20,0], - ["p1",2,"op","chess_char_4_18_b",1,"uniequip_002_mudrok",6104,1,9,4,50229,1721,1721,31,6], - ["p1",3,"op","chess_char_4_11_b",1,"uniequip_002_cathy",2644,1,124,0,2731,3521,0,3,1], - ["p1",4,"op","chess_char_4_19_b",2,"uniequip_002_flamtl",0,0,104,3,52099,4236,0,53,4], - ["p1",5,"op","chess_char_4_22_b",2,"uniequip_002_svrash",2219,1,122,9,101389,5488,0,26,3], - ["p1",6,"op","chess_char_4_16_b",2,"uniequip_002_texas2",1619,1,113,2,4659,5745,362,27,3], + ["p1",2,"op","chess_char_4_18_b",1,"uniequip_002_mudrok",6104,1,9,7,64566,2767,2767,38,8], + ["p1",3,"op","chess_char_4_11_b",1,"uniequip_002_cathy",2644,1,127,0,2731,3521,0,3,1], + ["p1",4,"op","chess_char_4_19_b",2,"uniequip_002_flamtl",0,0,107,3,35806,4236,0,39,3], + ["p1",5,"op","chess_char_4_22_b",2,"uniequip_002_svrash",1487.95,1,125,7,100277,6219,0,26,3], + ["p1",6,"op","chess_char_4_16_b",2,"uniequip_002_texas2",1619,1,119,3,20363,8218,1742,32,7], ["p1",7,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1664,1,4,0,0,0,0,0,0], - ["p1",8,"op","chess_char_4_12_b",2,"uniequip_002_glady",2232,1,5,2,8753,557,557,14,2], - ["p1",9,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,11,22,185454,2255,0,90,38], - ["p1",10,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1526,1,13,43,489267,8101,0,55,23], - ["p1",11,"op","chess_char_4_20_b",2,"uniequip_002_fartth",0,0,6,13,90781,1419,0,28,5], - ["p1",12,"op","chess_char_4_21_b",1,"uniequip_002_plosis",1484,1,14,0,0,9049,19206,94,2], + ["p1",8,"op","chess_char_4_12_b",2,"uniequip_002_glady",2232,1,5,1,6718,557,557,13,2], + ["p1",9,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,11,19,183787,3355,0,88,36], + ["p1",10,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1526,1,13,46,493888,8151,0,58,23], + ["p1",11,"op","chess_char_4_20_b",2,"uniequip_002_fartth",0,0,6,12,87294,1419,0,26,4], + ["p1",12,"op","chess_char_4_21_b",1,"uniequip_002_plosis",1484,1,14,0,0,8449,19756,98,2], ["p1",13,"token","token_10041_cathy_catsld",null,null,100,1,17,0,0,0,0,0,null], ["p1",14,"token","token_10041_cathy_catsld",null,null,100,1,16,0,0,0,0,0,null], ["-","~1","device","trap_1105_accrate",null,null,100,0,1,0,0,0,0,0,null], @@ -760,19 +760,19 @@ "enemy_1183_mlasrt": [1,1,0,988,7488], "enemy_1207_sfji_2": [1,1,0,0,16128], "enemy_1208_msfji_2": [4,4,0,0,120], - "enemy_1267_nhpbr": [45,45,0,12900,233280], - "enemy_1267_nhpbr_2": [24,24,0,7500,152064], + "enemy_1267_nhpbr": [45,45,0,13100,233280], + "enemy_1267_nhpbr_2": [24,24,0,7525,152064], "enemy_1270_nhstlk": [1,1,0,0,13824], - "enemy_1270_nhstlk_2": [15,15,0,6314,276480], + "enemy_1270_nhstlk_2": [15,15,0,8416,276480], "enemy_1325_cbgpro_2": [1,1,0,0,5299], "enemy_1425_lrcmra_2": [1,1,0,718,28800], - "enemy_1525_blkswb": [1,0,1,11126,39216], + "enemy_1525_blkswb": [1,0,1,13598,49286], "enemy_2050_smsha": [1,1,0,2630,46080] }, - "hooks": [1,122,4844,474,474,1410,1409,514,107,110,87,86,0,15791,1515,23,100,1,1,121,1,0,2], - "events": {"atk":621,"bounty":5,"deploy":19,"die":109,"dmg":1401,"engage":10,"fx":242,"heal":206,"layer":1,"leak":1,"skill":175,"spawn":117,"status":1119}, - "fx": {"beam":6,"blink":2,"block":1,"displace":8,"dodge":2,"explode":4,"explosion":23,"featherArrow":5,"flame":4,"frostNova":38,"garrison":1,"garrisonGrant":1,"healField":2,"overclock":1,"palsy":1,"pull":2,"revive":4,"riposte":2,"rockslide":6,"shieldBreak":8,"slash":23,"summon":1,"swordRain":6,"swordStorm":3,"telegraph":4,"tornado":2,"tornadoPulse":10,"truesilver":3,"zone":69}, - "snaps": "a9c24b01 82cf2fda dbf7ac00 19d6e0fe bf0d6eef 39844f92 381970eb 0fff21ed d568b845 7e0b3bed 79bdef09 a61efdea d3ec023b 3898ceb9 a9d144b1 f7530a04 cdd5419c" + "hooks": [1,125,4870,486,486,1463,1462,531,111,113,89,88,0,16848,1524,31,100,1,1,121,1,0,2], + "events": {"atk":638,"bounty":5,"deploy":22,"die":112,"dmg":1450,"engage":10,"fx":278,"heal":221,"layer":1,"leak":1,"skill":179,"spawn":117,"status":1124}, + "fx": {"beam":6,"blink":2,"block":1,"displace":8,"dodge":2,"explode":6,"explosion":23,"featherArrow":4,"flame":3,"frostNova":36,"garrison":1,"garrisonGrant":1,"healField":2,"overclock":1,"palsy":1,"pull":2,"revive":4,"riposte":2,"rockslide":8,"shieldBreak":12,"slash":23,"summon":1,"swordRain":35,"swordStorm":7,"telegraph":3,"tornado":2,"tornadoPulse":10,"truesilver":3,"zone":69}, + "snaps": "a9c24b01 82cf2fda dbf7ac00 19d6e0fe bf0d6eef 39844f92 381970eb 0fff21ed d568b845 7e0b3bed 136fd57f 1d2e61ff 98f8e769 ac6a83ff 68395209 1b564b59 fa140621" }, "roster-013": { "about": "pass 0 band 5: chess_char_4_23_b chess_char_5_08_a chess_char_5_01_a chess_char_5_05_a chess_char_5_06_a chess_char_5_07_a chess_char_4_24_b chess_char_4_25_b chess_char_4_26_b chess_char_5_02_a chess_char_5_03_a chess_char_5_10_a", @@ -1624,32 +1624,32 @@ "total": 73, "unspawned": 0, "bossHpLeft": null, - "rngDraws": 164, + "rngDraws": 162, "errors": {"count":0,"kinds":[]}, - "players": {"p1":{"killed":15,"total":73,"perfect":false,"leaks":58,"leaksUncounted":0,"coins":6,"dmg":172523,"bossDmg":0,"heal":1327,"deaths":18,"layerGains":{}}}, + "players": {"p1":{"killed":15,"total":73,"perfect":false,"leaks":58,"leaksUncounted":0,"coins":6,"dmg":171592,"bossDmg":0,"heal":1327,"deaths":21,"layerGains":{}}}, "units": [ - ["p1",1,"op","chess_char_3_12_a",0,null,0,0,96,3,6989,4668,1327,19,3], + ["p1",1,"op","chess_char_3_12_a",0,null,0,0,99,3,6989,4668,1327,19,3], ["p1",2,"op","chess_char_3_16_a",0,null,0,0,6,0,3190,2173,0,11,1], - ["p1",3,"op","chess_char_3_18_a",0,null,0,0,93,1,4796,2962,0,4,3], + ["p1",3,"op","chess_char_3_18_a",0,null,0,0,96,1,4796,2962,0,4,3], ["p1",4,"op","chess_char_3_08_a",0,null,0,0,4,1,30700,1594,0,8,1], - ["p1",5,"op","chess_char_3_09_a",0,null,1267,1,99,2,14769,1267,0,22,3], - ["p1",6,"op","chess_char_3_10_a",0,null,0,0,86,1,26456,3300,0,17,4], + ["p1",5,"op","chess_char_3_09_a",0,null,1267,1,102,2,14769,1267,0,22,3], + ["p1",6,"op","chess_char_3_10_a",0,null,0,0,89,1,26456,3300,0,17,4], ["p1",7,"op","chess_char_3_11_a",0,null,0,0,7,1,11464,1316,0,7,1], - ["p1",8,"op","chess_char_3_13_a",0,null,0,0,10,0,4799,4736,0,27,1], - ["p1",9,"op","chess_char_3_14_a",0,null,0,0,75,0,5911,2502,0,7,0], - ["p1",10,"op","chess_char_3_17_a",0,null,938.6,1,95,3,38866,3553,0,52,10], - ["p1",11,"op","chess_char_3_19_a",0,null,0,0,79,1,16258,2878,0,29,0], - ["p1",12,"op","chess_char_3_20_a",0,null,0,0,97,0,3447,2684,0,18,1], + ["p1",8,"op","chess_char_3_13_a",0,null,0,0,54,0,3868,5140,0,25,0], + ["p1",9,"op","chess_char_3_14_a",0,null,0,0,78,0,5911,2502,0,7,0], + ["p1",10,"op","chess_char_3_17_a",0,null,938.6,1,98,3,38866,3553,0,52,10], + ["p1",11,"op","chess_char_3_19_a",0,null,0,0,82,1,16258,2878,0,29,0], + ["p1",12,"op","chess_char_3_20_a",0,null,0,0,100,0,3447,2684,0,18,1], ["p1",13,"token","token_10028_vigil_wolf",null,null,51.51,0,15,1,3733,828,0,6,null], ["-","~1","device","trap_1105_accrate",null,null,100,1,1,0,0,0,0,0,null], ["-","~2","device","trap_1105_accrate",null,null,100,1,2,0,0,0,0,0,null], ["-","~3","device","trap_1105_accrate",null,null,100,1,3,0,0,0,0,0,null], - ["p1","~1","token","token_10028_vigil_wolf",null,null,0,0,80,0,1145,1579,0,4,null] + ["p1","~1","token","token_10028_vigil_wolf",null,null,0,0,83,0,1145,1579,0,4,null] ], "enemies": { "enemy_10042_prtrop": [12,0,12,6413,21834], "enemy_10042_prtrop_2": [12,0,10,4427,15485], - "enemy_10043_sailor": [39,8,31,16646,159545], + "enemy_10043_sailor": [39,8,31,16904,158614], "enemy_1005_yokai_2": [1,1,0,68,2678], "enemy_10156_mncrer": [1,1,0,140,6912], "enemy_1116_liprr_2": [1,1,0,2415,15356], @@ -1657,13 +1657,13 @@ "enemy_1196_msfyin_2": [2,2,0,0,6], "enemy_1251_lysyta_2": [1,1,0,495,7925], "enemy_1355_mrfly_2": [1,0,1,0,5433], - "enemy_1513_dekght_2": [1,0,1,3473,1400], + "enemy_1513_dekght_2": [1,0,1,3619,1400], "enemy_9010_acpupp": [1,0,1,0,1540] }, - "hooks": [1,98,4200,354,354,1421,1482,9,34,91,28,28,0,8507,22,36,73,56,1,38,0,0,0], - "events": {"atk":413,"bounty":3,"deploy":22,"die":35,"dmg":1480,"engage":14,"fx":22,"heal":9,"leak":56,"skill":56,"spawn":90,"status":64}, + "hooks": [1,101,4200,353,353,1419,1480,9,37,94,27,27,0,8991,22,39,73,56,1,38,0,0,0], + "events": {"atk":412,"bounty":3,"deploy":25,"die":38,"dmg":1478,"engage":14,"fx":22,"heal":9,"leak":56,"skill":54,"spawn":90,"status":65}, "fx": {"dp":3,"explode":3,"liberate":1,"phase":1,"revive":4,"shield":2,"sp":2,"strike":1,"summon":2,"telegraph":2,"wolfShadowLost":1}, - "snaps": "eabc0c84 cc18ecdc 1266ee58 d2db745d d594c101 9c126fe9 207f1030 2cde0f2a d36f3786 a951fe8c 1df07ff6 2a7a28d7 440f50c1 e202f4c9" + "snaps": "eabc0c84 cc18ecdc 1266ee58 666fc8d3 26baaab7 d3a36a4b 25ba2a3b 47080865 27431ea4 dd4bd88b 236a99ed 70c9d9cf c92abc52 7537fbcd" }, "roster-027": { "about": "pass 1 band 4: chess_char_3_06_b chess_char_3_12_b chess_char_3_02_b chess_char_3_03_b chess_char_3_04_b chess_char_3_05_b chess_char_3_21_a chess_char_3_01_b chess_char_3_08_b chess_char_3_09_b chess_char_3_10_b chess_char_3_11_b", @@ -2010,64 +2010,64 @@ "round": 12, "seed": 3754088384, "waveId": "act1autochess_h05", - "time": 222.13, - "ticks": 6664, + "time": 223.13, + "ticks": 6694, "reason": "cleared", - "killed": 35, + "killed": 34, "total": 167, "unspawned": 0, "bossHpLeft": null, - "rngDraws": 474, + "rngDraws": 285, "errors": {"count":0,"kinds":[]}, "players": { "p1": { - "killed": 35, + "killed": 34, "total": 167, "perfect": false, - "leaks": 132, + "leaks": 133, "leaksUncounted": 0, "coins": 2, - "dmg": 346977, + "dmg": 292129, "bossDmg": 0, - "heal": 42114, - "deaths": 24, - "layerGains": {"indomShip":35} + "heal": 24904, + "deaths": 27, + "layerGains": {"indomShip":20} } }, "units": [ - ["p1",1,"op","chess_char_5_11_a",0,null,3628.8,1,198,2,15002,7551,4312,30,4], - ["p1",2,"op","chess_char_5_19_a",0,null,2167.52,1,196,3,36237,18040,49,14,3], - ["p1",3,"op","chess_char_5_13_a",0,null,0,0,193,5,70464,16349,83,31,1], - ["p1",4,"op","chess_char_5_14_a",0,null,1546.99,1,197,1,6713,5581,1527,20,3], - ["p1",5,"op","chess_char_5_06_b",0,"uniequip_003_etlchi",0,0,179,14,123248,17506,7085,33,8], - ["p1",6,"op","chess_char_5_17_a",0,null,89.06,1,195,0,5573,17040,199,14,2], - ["p1",7,"op","chess_char_5_12_a",1,null,0,0,3,3,14619,2983,75,13,2], - ["p1",8,"op","chess_char_5_15_a",0,null,0,0,4,3,25588,2074,18609,102,34], - ["p1",9,"op","chess_char_5_20_a",0,null,0,0,189,0,4867,4992,193,14,1], - ["p1",10,"op","chess_char_5_21_a",0,null,0,0,184,0,4231,6460,156,7,0], - ["p1",11,"op","chess_char_5_22_a",0,null,0,0,5,3,38526,3546,20,57,2], - ["p1",12,"op","chess_char_5_23_a",0,null,0,0,139,0,0,6556,9649,18,8], + ["p1",1,"op","chess_char_5_11_a",0,null,0,0,163,5,18173,8247,1009,34,1], + ["p1",2,"op","chess_char_5_19_a",0,null,0,0,175,2,21710,9416,9,12,1], + ["p1",3,"op","chess_char_5_13_a",0,null,0,0,178,3,58739,11515,0,24,1], + ["p1",4,"op","chess_char_5_14_a",0,null,1272.54,1,199,0,8585,6030,2107,25,3], + ["p1",5,"op","chess_char_5_06_b",0,"uniequip_003_etlchi",0,0,154,13,111471,13178,5457,30,7], + ["p1",6,"op","chess_char_5_17_a",0,null,1024.54,1,198,0,9393,20946,494,19,5], + ["p1",7,"op","chess_char_5_12_a",1,null,0,0,3,2,11238,1698,0,10,1], + ["p1",8,"op","chess_char_5_15_a",0,null,0,0,190,3,11272,2237,6845,46,18], + ["p1",9,"op","chess_char_5_20_a",0,null,1108,1,200,0,4975,3358,100,14,1], + ["p1",10,"op","chess_char_5_21_a",0,null,0,0,112,0,3973,5181,156,6,0], + ["p1",11,"op","chess_char_5_22_a",0,null,1237,1,201,5,30053,1682,0,46,1], + ["p1",12,"op","chess_char_5_23_a",0,null,0,0,140,0,0,5511,8570,16,6], ["-","~1","device","trap_1105_accrate",null,null,100,1,1,0,0,0,0,0,null], ["-","~2","device","trap_1105_accrate",null,null,100,1,2,0,0,0,0,0,null], - ["p1","~1","token","token_10015_dusk_drgn",null,null,1177.52,0,38,0,1910,976,157,6,null] + ["p1","~1","token","token_10015_dusk_drgn",null,null,1366.61,0,38,0,2547,787,157,8,null] ], "enemies": { - "enemy_1005_yokai_3": [1,0,1,5803,15478], - "enemy_1009_lurker": [72,14,58,515,85902], + "enemy_1005_yokai_3": [1,0,1,4737,7387], + "enemy_1009_lurker": [72,17,55,766,86048], "enemy_10159_mntrjn": [1,0,1,0,21757], - "enemy_1019_jshoot_2": [51,15,36,17451,115001], + "enemy_1019_jshoot_2": [51,12,39,14340,95258], "enemy_1118_lidbox_2": [1,1,0,39,14774], "enemy_1196_msfyin": [1,1,0,0,2], - "enemy_1252_lysytb_2": [1,0,1,307,9631], - "enemy_1364_spnaxe_2": [1,0,1,2528,4741], - "enemy_1404_msnip": [36,4,32,77857,127526], - "enemy_1516_jakill": [1,0,1,5154,1320], - "enemy_9011_acrefr": [1,0,1,0,1527] + "enemy_1252_lysytb_2": [1,0,1,202,9631], + "enemy_1364_spnaxe_2": [1,0,1,2054,3130], + "enemy_1404_msnip": [36,3,33,63431,102254], + "enemy_1516_jakill": [1,0,1,4217,1056], + "enemy_9011_acrefr": [1,0,1,0,592] }, - "hooks": [1,198,6664,961,961,3404,3432,2289,59,192,68,67,0,23204,206,88,167,132,1,65,7,0,3], - "events": {"atk":1050,"bounty":1,"deploy":29,"die":60,"dmg":3390,"engage":12,"fx":119,"heal":451,"layer":7,"leak":132,"skill":135,"spawn":182,"status":264}, - "fx": {"aoe":3,"dodge":3,"dollEnd":3,"garrison":7,"healAoe":4,"hpShare":1,"palsy":1,"phase":1,"reborn":3,"revive":6,"shield":39,"sp":10,"substitute":3,"summon":1,"zone":34}, - "snaps": "8b9c3026 e0f96062 a49bbfa8 29d89b05 0acdd66d 607a3e6e e487bee7 925b98be 8d6d2209 5c9e2d74 878a99ae 98ba61a3 429c3a4d 28fa2b80 5f6aa75e 47b6d9dc 12bc9401 62c44e64 d6f464bb de487d8c 7aaa2057 21893dc4 3ac24c00" + "hooks": [1,201,6694,779,779,2914,2928,2154,61,195,45,45,0,16024,151,77,167,133,1,63,4,0,7], + "events": {"atk":860,"bounty":1,"deploy":32,"die":62,"dmg":2905,"engage":12,"fx":77,"heal":195,"layer":4,"leak":133,"skill":90,"spawn":182,"status":198}, + "fx": {"aoe":3,"crit":2,"dodge":7,"dollEnd":2,"garrison":4,"healAoe":1,"hpShare":1,"palsy":1,"phase":1,"reborn":2,"revive":5,"shield":20,"sp":7,"substitute":2,"summon":1,"zone":18}, + "snaps": "8b9c3026 e0f96062 5bd2ea4f aa1681c2 f63b458e 8819a70c dbc211ee a33b4151 5d36531b e30ecd3d d3f615f0 d4cf7a96 42176da0 3492c4c9 c33d146c da0aee15 57018be8 1faef296 76622577 a7a9b09c 82ee5bcd 47d4838d 773e5245" }, "roster-034": { "about": "pass 1 band 6: chess_char_5_08_b chess_char_5_11_b chess_char_5_19_b chess_char_5_13_b chess_char_5_14_b chess_char_5_07_b chess_char_5_17_b chess_char_5_10_b chess_char_5_12_b chess_char_5_15_b chess_char_5_20_b chess_char_5_21_b", @@ -2441,47 +2441,47 @@ "time": 170, "ticks": 5100, "reason": "timeout", - "killed": 26, + "killed": 23, "total": 65, "unspawned": 0, "bossHpLeft": null, - "rngDraws": 280, + "rngDraws": 272, "errors": {"count":0,"kinds":[]}, - "players": {"p1":{"killed":26,"total":65,"perfect":false,"leaks":39,"leaksUncounted":0,"coins":2,"dmg":518926,"bossDmg":0,"heal":1130,"deaths":25,"layerGains":{}}}, + "players": {"p1":{"killed":23,"total":65,"perfect":false,"leaks":42,"leaksUncounted":0,"coins":4,"dmg":429762,"bossDmg":0,"heal":1172,"deaths":27,"layerGains":{}}}, "units": [ - ["p1",1,"op","chess_char_4_01_a",1,null,0,0,3,0,2428,2638,0,46,1], - ["p1",2,"op","chess_char_4_17_a",2,null,0,0,6,0,12763,2849,0,19,1], - ["p1",3,"op","chess_char_4_18_a",2,null,0,0,8,0,17529,3440,573,18,1], - ["p1",4,"op","chess_char_4_04_a",2,null,0,0,94,2,25834,7040,0,19,4], - ["p1",5,"op","chess_char_4_07_a",2,null,0,0,83,0,15765,7632,0,18,1], - ["p1",6,"op","chess_char_4_16_a",1,null,922.33,1,96,1,54471,7800,0,20,8], - ["p1",7,"op","chess_char_4_09_a",2,null,0,0,15,0,21707,1336,0,22,1], - ["p1",8,"op","chess_char_3_19_b",1,"none",0,0,4,3,51861,1648,0,61,1], - ["p1",9,"op","chess_char_3_21_b",1,"uniequip_004_archet",0,0,95,9,185226,3180,0,91,10], - ["p1",10,"op","chess_char_4_02_a",1,null,0,0,86,4,56749,2856,0,15,1], - ["p1",11,"op","chess_char_4_12_a",1,null,0,0,89,4,38365,4065,557,38,1], - ["p1",12,"op","chess_char_4_13_a",2,null,0,0,74,3,36228,3174,0,59,1], - ["p1",13,"token","token_10028_vigil_wolf",null,null,0,0,5,0,0,3541,0,0,null], + ["p1",1,"op","chess_char_4_01_a",1,null,0,0,3,0,2575,2639,0,53,1], + ["p1",2,"op","chess_char_4_17_a",2,null,0,0,6,1,24301,2849,0,31,1], + ["p1",3,"op","chess_char_4_18_a",2,null,0,0,8,0,17076,2867,0,15,1], + ["p1",4,"op","chess_char_4_04_a",2,null,0,0,90,2,18637,7040,0,16,4], + ["p1",5,"op","chess_char_4_07_a",2,null,0,0,86,0,9740,8690,0,22,1], + ["p1",6,"op","chess_char_4_16_a",1,null,1116.53,1,99,0,45090,7605,0,20,7], + ["p1",7,"op","chess_char_4_09_a",2,null,0,0,15,0,17764,1336,0,21,1], + ["p1",8,"op","chess_char_3_19_b",1,"none",0,0,4,7,50812,1648,0,68,1], + ["p1",9,"op","chess_char_3_21_b",1,"uniequip_004_archet",0,0,96,3,123167,3180,0,58,6], + ["p1",10,"op","chess_char_4_02_a",1,null,0,0,88,3,47171,2856,0,13,1], + ["p1",11,"op","chess_char_4_12_a",1,null,915.81,1,98,4,38898,3764,1172,39,1], + ["p1",12,"op","chess_char_4_13_a",2,null,0,0,77,3,34532,3174,0,56,1], + ["p1",13,"token","token_10028_vigil_wolf",null,null,0,0,5,0,0,2703,0,0,null], ["-","~1","device","trap_1105_accrate",null,null,100,1,1,0,0,0,0,0,null], ["-","~2","device","trap_1105_accrate",null,null,100,1,2,0,0,0,0,0,null] ], "enemies": { - "enemy_1005_yokai": [24,12,12,0,49267], - "enemy_1005_yokai_2": [27,10,12,7677,86315], - "enemy_1005_yokai_3": [6,1,4,20566,237116], + "enemy_1005_yokai": [24,11,13,0,49414], + "enemy_1005_yokai_2": [27,7,15,10447,66086], + "enemy_1005_yokai_3": [6,1,5,17540,184608], "enemy_10065_ftzlc": [1,1,0,0,16339], - "enemy_10162_mnctpt": [1,0,1,6114,39162], - "enemy_1119_vofsd": [1,0,1,1104,45721], + "enemy_10162_mnctpt": [1,0,1,5389,32651], + "enemy_1119_vofsd": [1,1,0,436,47298], "enemy_1196_msfyin_2": [1,1,0,0,3], - "enemy_1254_lypa_2": [1,0,1,8996,35711], - "enemy_1367_dseed": [1,0,1,0,2836], - "enemy_1517_xi": [1,0,1,5983,6446], + "enemy_1254_lypa_2": [1,0,1,9930,25245], + "enemy_1367_dseed": [1,0,1,0,3394], + "enemy_1517_xi": [1,0,1,6152,4716], "enemy_9016_acstmr": [1,1,0,0,8] }, - "hooks": [1,95,5100,625,625,1014,1053,834,53,86,31,31,18,8193,215,15,65,33,1,64,0,2,6], - "events": {"atk":711,"bounty":1,"deploy":28,"die":53,"dmg":1046,"engage":12,"fx":94,"heal":1,"leak":33,"skill":62,"spawn":80,"status":253}, - "fx": {"beam":4,"block":3,"buff":2,"burst":2,"coldWind":1,"dodge":6,"dp":1,"explode":1,"liberate":1,"overclock":1,"overload":1,"palsy":2,"phase":1,"revive":3,"ripple":1,"rockfall":1,"sentry":6,"shadowWeave":13,"shield":7,"shieldBreak":7,"stone":1,"swordStorm":8,"telegraph":3,"volley":10,"wake":1,"wolfShadow":2,"wolfShadowLost":4,"zone":1}, - "snaps": "f3440ee2 7da3be75 c96f2794 c9817d86 f4e4f99b 9be69905 48a68fda e1005cd1 ac1c74e4 d687c55f a47b29fc 90d6b228 4659af45 9df1748d 2e40f293 8372ceaf ff38b29e" + "hooks": [1,98,5100,629,629,941,979,808,51,89,26,26,18,8641,209,16,65,37,1,58,0,1,7], + "events": {"atk":722,"bounty":2,"deploy":31,"die":52,"dmg":972,"engage":12,"fx":86,"leak":37,"skill":52,"spawn":80,"status":239}, + "fx": {"beam":4,"block":3,"buff":2,"burst":1,"coldWind":1,"dodge":7,"dp":1,"explode":1,"overclock":1,"overload":1,"palsy":2,"phase":1,"revive":3,"ripple":1,"rockfall":1,"sentry":6,"shadowWeave":13,"shield":7,"shieldBreak":7,"stone":1,"swordStorm":7,"telegraph":3,"volley":6,"wake":1,"wolfShadow":1,"wolfShadowLost":3,"zone":1}, + "snaps": "f3440ee2 7da3be75 c96f2794 b353bd1c 4a6df4de 503d473c 91472bdb 1409d9fa 2311529b b078cd52 e92fd654 8c84b0e0 3c6c3d57 488a3c0a 61ca72e1 90784564 91926bb6" }, "roster-041": { "about": "pass 2 band 5: chess_char_4_23_a chess_char_4_01_b chess_char_4_19_a chess_char_4_22_a chess_char_4_04_b chess_char_4_07_b chess_char_4_09_b chess_char_4_20_a chess_char_4_24_a chess_char_4_25_a chess_char_4_02_b chess_char_4_12_b", @@ -2866,19 +2866,19 @@ "bossHpLeft": null, "rngDraws": 282, "errors": {"count":0,"kinds":[]}, - "players": {"p1":{"killed":54,"total":142,"perfect":false,"leaks":88,"leaksUncounted":0,"coins":6,"dmg":320902,"bossDmg":0,"heal":12345,"deaths":23,"layerGains":{}}}, + "players": {"p1":{"killed":54,"total":142,"perfect":false,"leaks":88,"leaksUncounted":0,"coins":6,"dmg":320902,"bossDmg":0,"heal":12345,"deaths":26,"layerGains":{}}}, "units": [ - ["p1",1,"op","chess_char_6_06_b",1,"none",0,0,147,3,39950,5278,0,20,1], - ["p1",2,"op","chess_char_6_15_b",1,"none",0,0,146,10,39140,4608,0,44,2], - ["p1",3,"op","chess_char_6_07_b",1,"none",0,0,114,0,14892,7056,0,12,0], + ["p1",1,"op","chess_char_6_06_b",1,"none",0,0,150,3,39950,5278,0,20,1], + ["p1",2,"op","chess_char_6_15_b",1,"none",0,0,149,10,39140,4608,0,44,2], + ["p1",3,"op","chess_char_6_07_b",1,"none",0,0,117,0,14892,7056,0,12,0], ["p1",4,"op","chess_char_6_17_b",1,"none",0,0,77,5,41945,4457,0,10,2], - ["p1",5,"op","chess_char_6_08_b",1,"none",1508,1,178,3,19446,5042,2565,15,1], - ["p1",6,"op","chess_char_6_09_b",2,"none",268,1,177,0,3424,3068,0,8,0], - ["p1",7,"op","chess_char_6_11_b",1,"none",0,0,163,1,3238,6231,0,9,0], - ["p1",8,"op","chess_char_6_12_b",2,"none",0,0,4,8,62955,9521,0,30,1], - ["p1",9,"op","chess_char_6_13_b",2,"uniequip_002_angel2",0,0,156,24,86408,7142,2712,38,2], - ["p1",10,"op","chess_char_6_14_b",1,"none",0,0,122,0,0,4723,7068,14,2], - ["p1",11,"op","chess_char_6_16_b",1,"uniequip_002_halo2",0,0,171,0,6370,4472,0,8,1], + ["p1",5,"op","chess_char_6_08_b",1,"none",1508,1,181,3,19446,5042,2565,15,1], + ["p1",6,"op","chess_char_6_09_b",2,"none",268,1,180,0,3424,3068,0,8,0], + ["p1",7,"op","chess_char_6_11_b",1,"none",0,0,166,1,3238,6231,0,9,0], + ["p1",8,"op","chess_char_6_12_b",2,"none",0,0,112,8,62955,10007,0,30,1], + ["p1",9,"op","chess_char_6_13_b",2,"uniequip_002_angel2",0,0,159,24,86408,7142,2712,38,2], + ["p1",10,"op","chess_char_6_14_b",1,"none",0,0,125,0,0,4723,7068,14,2], + ["p1",11,"op","chess_char_6_16_b",1,"uniequip_002_halo2",0,0,174,0,6370,4472,0,8,1], ["p1",12,"op","chess_char_6_18_b",1,"uniequip_002_whitw2",0,0,95,0,2720,4926,0,6,1], ["p1",13,"token","token_10030_mlyss_wtrman",null,null,0,0,15,0,413,1001,0,1,1], ["-","~1","device","trap_1105_accrate",null,null,100,1,1,0,0,0,0,0,null], @@ -2888,24 +2888,24 @@ ["p1","~1","token","token_10012_rosmon_shield",null,null,4293.6,0,59,0,0,706,0,0,null], ["p1","~2","token","token_10012_rosmon_shield",null,null,646.92,0,60,0,0,4353,0,0,null], ["p1","~1","token","token_10030_mlyss_wtrman",null,null,0,0,100,0,0,1865,0,0,0], - ["p1","~2","token","token_10030_mlyss_wtrman",null,null,0,0,164,0,0,1865,0,0,0] + ["p1","~2","token","token_10030_mlyss_wtrman",null,null,0,0,167,0,0,1865,0,0,0] ], "enemies": { "enemy_10067_ftsjc": [1,1,0,0,12480], "enemy_1017_defdrn": [1,1,0,0,3840], - "enemy_1019_jshoot_2": [57,15,42,12227,43974], + "enemy_1019_jshoot_2": [57,15,42,12178,43974], "enemy_1121_lifbos": [1,1,0,0,19200], "enemy_1197_sfshu": [1,1,0,0,2400], "enemy_1198_msfshu": [3,3,0,0,9], "enemy_1267_nhpbr": [1,1,0,400,4320], "enemy_1381_winman": [28,16,12,40,96129], - "enemy_1389_winbab_2": [48,15,33,57170,111670], + "enemy_1389_winbab_2": [48,15,33,57705,111670], "enemy_1525_blkswb": [1,0,1,5082,26880] }, - "hooks": [1,177,6433,727,719,831,938,109,80,172,14,14,75,10563,691,44,142,88,1,84,0,0,0], - "events": {"atk":733,"bounty":3,"deploy":32,"die":84,"dmg":851,"engage":12,"fx":60,"heal":25,"leak":88,"skill":28,"spawn":163,"status":186}, + "hooks": [1,180,6433,727,719,830,937,109,83,175,14,14,75,10563,691,44,142,88,1,84,0,0,0], + "events": {"atk":733,"bounty":3,"deploy":35,"die":87,"dmg":850,"engage":12,"fx":60,"heal":25,"leak":88,"skill":28,"spawn":163,"status":186}, "fx": {"airstrike":28,"anchor":1,"appear":1,"blink":1,"copy":1,"disappear":1,"ember":1,"explode":2,"garrisonGrant":2,"heal":2,"link":1,"revive":4,"strike":6,"summon":2,"summonStun":2,"sunBurst":1,"sword":2,"telegraph":1,"zone":1}, - "snaps": "ece6325d ebbd3de9 c30df90e b4f15c1c 94019924 1c9ec2f7 c9e16f6a ac507052 9ad73a7c 3b7cd673 730a9416 a0799dfb ffa923b0 8032fa00 126b697f b6f261e8 322ee407 3a29c4a7 db6b7ac2 4a24c1db 43f3735b 51aab483" + "snaps": "ece6325d ebbd3de9 c30df90e b4f15c1c 94019924 1c9ec2f7 c9e16f6a ac507052 9ad73a7c 73c57bf2 9baf1e8d 16b1fda0 af97763f 98adb61f 6818bdbc 5ed7a5e7 344d84fc c15d577c f610844d 48ba8f80 80020820 08d98134" }, "roster-048": { "about": "pass 2 band 7: chess_char_6_19_b chess_char_5_13_b chess_char_6_20_b chess_char_5_12_b chess_char_5_20_b chess_char_6_05_b", diff --git a/test/golden/standins.json b/test/golden/standins.json index 6171527d..52e7018e 100644 --- a/test/golden/standins.json +++ b/test/golden/standins.json @@ -375,7 +375,7 @@ "total": 80, "unspawned": 0, "bossHpLeft": null, - "rngDraws": 86, + "rngDraws": 82, "errors": {"count":0,"kinds":[]}, "players": { "p1": { @@ -385,46 +385,46 @@ "leaks": 71, "leaksUncounted": 0, "coins": 4, - "dmg": 124008, + "dmg": 125257, "bossDmg": 0, "heal": 0, - "deaths": 22, + "deaths": 25, "layerGains": {"preciShip":8,"sargonShip":18} } }, "units": [ ["p1",1,"op","chess_char_4_17_b",1,"none",0,0,3,0,210,3211,0,2,1], - ["p1",2,"op","chess_char_4_18_b",1,"none",0,0,83,0,30,9306,0,1,1], - ["p1",3,"op","chess_char_5_05_b",2,"none",0,0,97,0,1145,5816,0,2,1], - ["p1",4,"op","chess_char_4_19_b",1,"none",1847.63,1,107,0,230,3864,0,7,1], - ["p1",5,"op","chess_char_5_01_b",2,"none",1036.53,1,105,0,2197,3985,0,5,3], - ["p1",6,"op","chess_char_4_22_b",1,"none",3191,1,109,0,1178,15724,0,5,1], - ["p1",7,"op","chess_char_4_23_b",1,"none",0,0,68,0,3484,6865,0,8,1], + ["p1",2,"op","chess_char_4_18_b",1,"none",0,0,86,0,30,9306,0,1,1], + ["p1",3,"op","chess_char_5_05_b",2,"none",0,0,100,0,1145,5816,0,2,1], + ["p1",4,"op","chess_char_4_19_b",1,"none",1847.63,1,110,0,230,3864,0,7,1], + ["p1",5,"op","chess_char_5_01_b",2,"none",1036.53,1,108,0,2197,3985,0,5,3], + ["p1",6,"op","chess_char_4_22_b",1,"none",3191,1,112,0,959,14040,0,6,1], + ["p1",7,"op","chess_char_4_23_b",1,"none",0,0,71,0,3484,6865,0,8,1], ["p1",8,"op","chess_char_5_06_b",2,"uniequip_002_acguad",0,0,10,0,0,3820,0,0,0], - ["p1",9,"op","chess_char_4_20_b",1,"none",1255.06,1,106,2,14281,4581,0,27,1], - ["p1",10,"op","chess_char_4_24_b",1,"none",1007.59,1,108,0,5710,3072,0,19,1], - ["p1",11,"op","chess_char_5_02_b",2,"none",0,0,102,1,8684,4080,0,19,1], + ["p1",9,"op","chess_char_4_20_b",1,"none",1255.06,1,109,2,15749,4785,0,30,1], + ["p1",10,"op","chess_char_4_24_b",1,"none",1007.59,1,111,0,5710,3072,0,19,1], + ["p1",11,"op","chess_char_5_02_b",2,"none",0,0,105,1,8684,4080,0,19,1], ["p1",12,"op","chess_char_5_03_b",2,"uniequip_002_accast",0,0,4,6,86859,1749,0,10,1], ["-","~1","device","trap_1105_accrate",null,null,100,1,1,0,0,0,0,0,null], ["-","~2","device","trap_1105_accrate",null,null,100,1,2,0,0,0,0,0,null] ], "enemies": { - "enemy_1005_yokai_2": [18,3,15,3871,7232], - "enemy_1041_lazerd_2": [24,3,21,43406,32062], + "enemy_1005_yokai_2": [18,3,15,3206,7232], + "enemy_1041_lazerd_2": [24,3,21,43558,33530], "enemy_1042_frostd": [30,1,29,0,25469], - "enemy_1045_hammer": [1,1,0,2117,15552], - "enemy_1045_hammer_2": [1,0,1,5327,20514], + "enemy_1045_hammer": [1,1,0,2106,15552], + "enemy_1045_hammer_2": [1,0,1,5370,20295], "enemy_1046_agent": [1,1,0,72,3888], - "enemy_1050_lslime": [1,0,1,9701,0], + "enemy_1050_lslime": [1,0,1,8703,0], "enemy_1061_zomshd": [1,0,1,61,13862], "enemy_1062_rager_2": [1,0,1,1519,13929], "enemy_1067_snslime": [1,0,1,0,0], "enemy_1071_dftman": [1,0,1,0,0] }, - "hooks": [1,109,6707,301,301,585,576,545,31,102,13,13,0,8990,10,14,80,71,1,34,2,0,9], - "events": {"atk":327,"bounty":2,"deploy":27,"die":31,"dmg":576,"engage":11,"fx":23,"layer":2,"leak":71,"skill":26,"spawn":94,"status":111}, - "fx": {"aoe":1,"dodge":9,"dp":5,"garrison":2,"garrisonGrant":1,"palsy":2,"revive":3}, - "snaps": "801e90ec 5f30137a 56120166 3365328a cd10076b ddf2ae60 00e0a9a1 f0fbc83c 9a8e0ded c4876430 15bb6d00 e61302d2 75a24a51 0b7275b4 f728ca3f 437d1568 ed5e8b79 5a14602a ac144838 2dcf417a 7b12357a 77ef33ec ff8819ba" + "hooks": [1,112,6707,301,301,557,549,545,34,105,13,13,0,9357,10,15,80,71,1,34,2,0,8], + "events": {"atk":327,"bounty":2,"deploy":30,"die":34,"dmg":549,"engage":11,"fx":22,"layer":2,"leak":71,"skill":26,"spawn":94,"status":117}, + "fx": {"aoe":1,"dodge":8,"dp":5,"garrison":2,"garrisonGrant":1,"palsy":2,"revive":3}, + "snaps": "801e90ec 5f30137a 2f821a94 27817b68 c0d15f75 e321526a 89ad955e 577c467d e5ab6fc3 ea5ef327 c886e093 8fb8ee86 0bcd89de 3e0a3556 5a88da95 d1f4e3bf c043e923 9e51b0d0 951fd650 26d039ea c8dfac53 49a41bb2 1aba0cf1" }, "standin-08": { "about": "elite band 6 as stand-ins: chess_char_5_08_b→char_610_acfend chess_char_5_14_b→char_608_acpion chess_char_5_19_b→char_617_sharp2 chess_char_5_07_b→char_601_cguard chess_char_5_13_b→char_609_acguad chess_char_5_17_b→char_615_acspec chess_char_5_10_b→char_606_csuppo chess_char_5_11_b→char_613_acmedc chess_char_5_12_b→char_614_acsupo chess_char_5_15_b→char_603_csnipe chess_char_5_18_b→char_611_acnipe chess_char_5_20_b→char_614_acsupo",