diff --git a/CHANGELOG.md b/CHANGELOG.md index eec6af3e..45fc627d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ - 修复干员一次攻击后模型继续循环、多挥一次的问题,保留迟到消息的现有前摇同步方式。 - 自在重生后的无敌期不再被普攻或需要可选目标的自动技能锁定;修复 AI 托管遮罩挡住“在此页面继续”按钮。 - 驭械术师未释放的浮游改为本体攻击再加一份附加伤害(初始相当于攻击力 20%,同一目标每次 +15,上限 110%);技能放出的浮游仍造成技能伤害(PR #537,感谢 @Xinglan233)。 +- 只改普攻的技能保留干员自己的那一击。耶拉二技能(基础与隐藏)放出浮游时仍打出 100% 的普通攻击,寒冷对自身和浮游各判一次;荒芜拉普兰德一技能开启后仍是本体一击加两份未释放浮游。只由浮游出手的技能不另加这一击。 - 干员再部署时浮游倍率回到初始值,并清掉按目标记住的倍率;自由移动仍保留。已经飞出的浮游按命中时的倍率结算(PR #536,感谢 @Xinglan233)。 - 洛洛二技能放出的浮游在目标离开攻击范围后继续锁定,只在击杀或技能结束时返回;技能期间不再叠加未释放浮游的附加伤害(PR #535,感谢 @Xinglan233)。 - 受击格按官方四舍六入五成双取整,被挡在场地边缘的敌人留在边缘那一格(PR #520,感谢 @Cloudnyco)。 diff --git a/docs/SIM.md b/docs/SIM.md index 4ba20e73..4723d265 100644 --- a/docs/SIM.md +++ b/docs/SIM.md @@ -1351,7 +1351,7 @@ header of professions.js). | loopshooter | 回环射手 (user playtest #3): every attack throws a boomerang (`ai.js throwBoomerang`, projectile `'boomerang'`) out to the target at 15 tiles/s — it hits on arrival — and back to the thrower's current position at 3.75 tiles/s without damage (PRTS 跃跃 "投射物飞行速度15,返回时飞行速度3.75"); attacks only while holding it (every boomerang thrown caught — "必须回收全部回旋投掷物才可以进行下一次攻击", `unit.trait.boomerangsOut`) and with the attack cooldown ready, so the real interval is the longer of the two; a target dead mid-flight is not hit (it still flies to the last position and back); knocked out / withdrawn ⇒ lost, a redeployed thrower holds a fresh one; 跃跃 S2's extra boomerangs share the one flight (cnt hits); each catch fires `boomerangCaught`, and an attack profile's `boomerangOnward(ctx)` flies it on after the first hit before it turns back — ctx `hit` (a hit of the same attack), `comeBack(x, y)` once (a content error sends it back from the hit point): 娜仁图亚 S1 bounces, S2 dashes on and hits on its way back (kits/ops/op-narant.js) | | reaperrange | hits every enemy in range; ×1.5 (bb atk_scale) on the trait front grid (or its own line ahead) — both along its direction | | chain | chain N (trait text/bb max_target) with −15 % per jump (bb chain.atk_scale), 1.7-tile jumps (constants.js CHAIN_RADIUS, PRTS 溅射半径一览: 链术师 1.7; 1.8 until 0.1.1), sluggish on each hit | -| funnel | normal attack: one 100 % ATK body hit plus separate drone additional damage, 20 % → +15 %/hit on the same target → 110 % (bb init/delta/max; modules can change init/cap). `funnelMul` holds the drone ramp; `dmgMul` applies to both. Extra drones (`hits`) do not duplicate the body; an unreleased skill attack can set `funnelBodyHits` (至简 S2: two body hits and two additions). Body and additions share an `attackId`, but only the body is `isAttack`; additions carry `addition, funnel`. [ASSUMED] body instances first at the existing impact, one ramp per volley. Released-skill profiles keep their existing paths; this normal-attack correction does not settle their body behaviour. A normal deployment resets target, scale and any per-target ramp map to init, including revival against the same living target. A free move (`moveRedeploy`, the same carry as a 秘术师's stored energy and 乌尔比安 S3) keeps the ramp. An in-flight drone recomputes the ramp on impact. 洛洛 S2 detaches this multiplier from new body shots and inherits the trait ramp in an independent skill tick: `rockr:drone`, arts, `isSkill:true`, `isAttack:false`. Older projectiles cannot change its local ramp. A living selectable lock need not remain in body range; the drone returns on a kill or when the skill ends, and ending hands the ramp back and restores the normal multiplier (§30.19) | +| funnel | normal attack: one 100 % ATK body hit plus separate drone additional damage, 20 % → +15 %/hit on the same target → 110 % (bb init/delta/max; modules can change init/cap). `funnelMul` holds the drone ramp; `dmgMul` applies to both. Extra drones (`hits`) do not duplicate the body; an unreleased skill attack can set `funnelBodyHits` (至简 S2: two body hits and two additions). Body and additions share an `attackId`, but only the body is `isAttack`; additions carry `addition, funnel`. [ASSUMED] body instances first at the existing impact, one ramp per volley. A skill that only buffs or retargets the normal attack keeps the body; `isSkill` does not remove it. `funnelBodyHits: 0` is drone-only (荒芜拉普兰德 S2). 耶拉 S2 detaches `funnelMul`: one 100 % `isAttack` body in range, the unreleased addition off, and `1 + attack@cnt` arts skill drones (`kjera:drone`, `isSkill`, not `isAttack`) that keep the lock until the enemy dies or the skill ends. [ASSUMED] Those drones use the trait ramp; her blackboard has no drone scale. The base form continues the per-target ramp (one step per volley on a shared target) and writes it back; the hidden form restarts each drone at init and does not write the scales back. [ASSUMED] No flight delay; an untargetable lock is dropped and retargeted; stun and disarm do not pause the drones. 澄闪's skills and 荒芜拉普兰德 S3 stay on their own `dealDamage` paths. A normal deployment resets target, scale and any per-target ramp map to init, including revival against the same living target. A free move (`moveRedeploy`, the same carry as a 秘术师's stored energy and 乌尔比安 S3) keeps the ramp. An in-flight drone recomputes the ramp on impact. 洛洛 S2 detaches this multiplier from new body shots and inherits the trait ramp in an independent skill tick: `rockr:drone`, arts, `isSkill:true`, `isAttack:false`. Older projectiles cannot change its local ramp. A living selectable lock need not remain in body range; the drone returns on a kill or when the skill ends, and ending hands the ramp back and restores the normal multiplier (§30.19) | | mystic | 秘术师 (PRTS 分支特性信息 秘术师, GitHub #181): at its attack check (the attack ready, able to act, not disarmed) with no valid target — no target, or its kit's `canAttack` false (深靛 never picks a bound enemy) — it stores one energy (`storeEnergy`, up to bb times: 3, 深靛's MSC-X 4), an attack action: the attack interval restarts; a full store idles with the attack ready. The energies leave with its next attack that happens (`releaseEnergy` in `performAttack`, after `beforeAttack`: an attack cancelled before its shot keeps them) and land with the main hit, one arts attack hit each (`hitsFn` reads the hit's `info.energy`); a redeployment holds none [ASSUMED]. 维伊 / 黑键 plug their own `storeEnergy` (转置能量, elite energies) into the same check | | phalanx | no attack & DEF +200 %, RES +20 (bb) while the skill is off; while on, `rangeAoe`: each attack strikes every selectable enemy on its range at once (blocked enemies included; a stealthed one only when revealed or blocked), the same damage near and far, instant (`'beam'`) — "群体法术伤害" (secondary: Terra Wiki, Phalanx Caster: "attacks hit all enemies within their range"; supporting: PRTS 林 S3 备注 "单次普攻最多触发1次效果" — one normal attack can kill several — the same 锁定攻击范围 shape as the 轰击术师, and PRTS 溅射半径一览 documents no splash radius for it (it omits the 撼地者 too, so this is not proof); no primary source states a target cap; community report E3: it used to be one bolt + a 1.1 splash). 卡涅利安's charged S1 keeps the skill-off trait, 不攻击 included (kit `canAttack`, PRTS 备注) | | physician | heal the lowest HP% injured ally in range (a skill `targeting.maxTargets` widens any heal profile) | diff --git a/docs/design/engine.md b/docs/design/engine.md index 77cfb80c..8106d641 100644 --- a/docs/design/engine.md +++ b/docs/design/engine.md @@ -181,10 +181,11 @@ The engine keeps a 100 % ATK body instance and a separate drone instance, each t `funnelMul` holds only the drone ramp; the attack's `dmgMul` (至简's talent) is shared once. Extra attached drones raise `hits`, not the body count; 至简's charged S2 sets `funnelBodyHits` to two. Both share one `attackId`, attack hook and SP / charge use; additions have `addition` and `funnel` tags and do not count as `isAttack`. [ASSUMED] Body -instances precede additions at the existing projectile impact; consecutive hits keep one ramp per volley. This -correction covers ordinary attacks and unreleased skill attacks that set `funnelBodyHits`. Released skill paths retain -their existing behaviour; it does not establish whether those skills should also have body attacks (耶拉 S2, 澄闪 S1 -and S2 remain to be reconciled separately). +instances precede additions at the existing projectile impact; consecutive hits keep one ramp per volley. A skill +that only buffs or retargets the normal attack keeps the body; `isSkill` is not the switch. `funnelBodyHits === 0` +is drone-only (荒芜拉普兰德 S2): the ramp stays inside those hits. 耶拉 S2 detaches `funnelMul` the way 洛洛 S2 does: +one 100 % body inside her range, the unreleased addition off, and the released drones as separate skill hits that +keep the lock until the enemy dies or the skill ends (§30.17). 澄闪's skills stay on their own `dealDamage` paths. Funnel ramps return to the initial scale on a normal deployment, including automatic revival against the same living target (§30.18). The reset clears the current target, the scale and any per-target ramp map, and leaves other trait diff --git a/docs/history/0.2.5.md b/docs/history/0.2.5.md index c03b4ae1..c4137d78 100644 --- a/docs/history/0.2.5.md +++ b/docs/history/0.2.5.md @@ -286,15 +286,35 @@ an attack's `dmgMul` (至简's talent) is applied once to both. Extra attached d emitted as a normal attack. [ASSUMED] Body instances precede additions at the existing projectile impact, and a multi-hit volley takes one ramp -step. This covers ordinary attacks and unreleased skill attacks that set `funnelBodyHits`. Released skill paths that -do not set it (耶拉 S2, 澄闪 S1 while its own drones are out) keep their existing skill-damage path and do not gain a -second body. Whether those released skills should also have a body attack is not settled here. 澄闪 S3 and the -skill-drone simulator on 淬羽 stay on their own `dealDamage` paths. +step. Ordinary attacks and any skill that only buffs or retargets the normal attack keep the body. `info.isSkill` is +not the switch: every attack or targeting override sets it. `funnelBodyHits === 0` means the attack is drone-only +(the ramp stays inside those hits and no body is added). 荒芜拉普兰德 S2 sets that. 至简 S2 sets `funnelBodyHits` +to two, so two body hits and two additions still share one ramp step. + +耶拉 S2, base and hidden, follows the 洛洛 S2 split. `skchr_kjera_2` (docs/research/03-operators.md) says 自身与浮游单元 +攻击, and the lock lasts until the enemy dies or the skill ends. While it runs, `funnelMul` is detached, so her own +shot is one 100 % `isAttack` hit inside her range and the unreleased addition is off. `1 + attack@cnt` drones tick +on their own (`kjera:drone`, arts, `isSkill`, not `isAttack`) and may stay outside her range. Cold is rolled once +on the body and once on each drone hit. Ending the skill restores the multiplier. + +[ASSUMED] Those released drones use the trait ramp (20 % → +15 % on the same target → the cap). Her blackboard has +no drone scale; the branch page gives that ramp to drones that were not released. The base form continues its +per-target ramp, and two drones on one enemy in the same tick take one step. That map is written back when the skill +ends. The hidden form restarts each drone at the initial scale, and those scales are not written back onto the single +trait ramp. There is no flight delay. A lock that can no longer be targeted is dropped and the drone retargets. Stun +and disarm do not pause the released drones. An in-flight shot from before the skill can still step the live ramp; +the skill keeps its own copy, and a shot that lands after the skill ends can step the restored ramp. + +[ASSUMED] 荒芜拉普兰德 S1 says 释放浮游单元 and does not say she stops attacking. The toggle is read as a retarget of +the unreleased attack: one body hit plus the two additions, at the raised ATK. A 洛洛-style release is not used. +澄闪's skills and 荒芜拉普兰德 S3 stay on their own `dealDamage` paths. 澄闪 S3 and the skill-drone simulator on +淬羽 are unchanged. Kits that stored the ramp on `dmgMul` (至简, both 耶拉 forms, 澄闪 S2) now store it on `funnelMul`. -Tests: `test/sim/funnel-body.test.js`, and the funnel cases in `kits_t3`, `kits_t6`, `kits_alt_t6`, `kits_alt_t2` -and `op_gdglow`. +Tests: `test/sim/funnel-body.test.js`, and the funnel cases in `kits_t3`, `kits_t4`, `kits_t6`, `kits_alt_t6`, +`kits_alt_t2` and `op_gdglow`. The golden moves from this correction, measured against the candidate after §30.22, +are §30.23. ### 30.18 Redeploy resets the drone ramp @@ -397,3 +417,40 @@ and `solo-FUNNY-2` team LP 8 → 23, both still victories, with every settled ro team LP 26 → 27; `coop4-ABYSS-7` eliminated at round 12 → defeat at round 13, and its shop and bot draw counts change. The other matches keep the same end reason. `standin-04` is the only battle in this set with no funnel operator on the board. + +### 30.23 Golden changes after the skill-only funnel body correction + +All 287 scenarios were recomputed after the §30.17 correction (a skill that only buffs or retargets keeps the body; +耶拉 S2 uses the 洛洛 split) and compared with this candidate after §30.22 (`HEAD` `e0f37718`, +`git show HEAD:test/golden/*.json`). No scenario was added or removed. `fields`, `standins` and `diy` are unchanged +(澄闪 stays on `dealDamage`). 19 digests differ. They are additional to §30.9, §30.16 and §30.22. Seventeen of them +already moved in §30.22 and move again. `roster-038` and `coop2-NORMAL-14-standins` did not move in §30.22. + +Opening strategy ids do not change in any of the 20 match digests. No isolated counterfactual was re-run. The roster +and bond rows name the skill index the corpus assigns: 耶拉 index 1 is 心随意动, 荒芜拉普兰德 index 0 is 慵怠者悲鸣. +至简 is on two of those roster boards at index 1; her S2 already kept two body hits, and her totals move because the +fight around 耶拉 changed. + +| Cause | Changed scenarios | +|---|---| +| 耶拉 S2, base form, skill index 1. `roster-007` also fields 至简 S2 | `roster-007`, `roster-009` | +| 耶拉 S2, skill index 1. No 荒芜拉普兰德 on the board | `bond-emptyShip-low`, `bond-kjeragShip-high`, `bond-miraShip-low`, `bond-soloShip-low` | +| 荒芜拉普兰德 S1, skill index 0. The toggle keeps one body hit and both unreleased additions | `roster-036`, `roster-038` | + +Battle-total flips in that table: `roster-007` killed 132 → 137, leaks 41 → 37, coins 4 → 6, deaths 11 → 10, damage +234357 → 243212 (耶拉's own damage 9204 → 17443; 至简 8936 → 9558). `roster-009` keeps the same kills and leaks; +耶拉's damage 2 → 3 and 至简's kills 28 → 29, damage 7594 → 7168. `roster-036` killed 75 → 76, leaks 55 → 54, +damage 1160465 → 1189341 (荒芜拉普兰德 60604 → 99946, kills 2 → 3). `roster-038` damage 3467641 → 3468742 +(荒芜拉普兰德 kills 4 → 14, damage 106163 → 187571). The four bonds keep the same kills and leaks. `bond-emptyShip-low` +healing 381 → 362; 耶拉's damage 6585 → 11450 (kills 1 → 3), `bond-kjeragShip-high` 6927 → 16312, +`bond-miraShip-low` 10165 → 18617 (kills 2 → 4), `bond-soloShip-low` 1963 → 2764. + +Match end and the final lineup. A bot's chosen skill is not stored. Where the final lineup still contains 耶拉, her +default skill is S2, which is the skill this correction changes. + +| Final lineup | Changed scenarios and the recorded end | +|---|---| +| 耶拉, lineup unchanged | `solo-FUNNY-1` (`3_20_b`): victory, team LP 23 → 27; only round 8's bond layers move (steadShip 34 → 35). `solo-FUNNY-2` (`3_20_a`): victory, team LP 23 → 29; all eight stored round rows are identical, so the LP change is the boss round. `solo-NORMAL-1` (`3_20_b`): victory, team LP 2 → 11; first divergence round 10 (kjeragShip 13 → 14). `solo-HARD-1` (`3_20_a` and 至简 `3_13_a`): still a defeat, team LP 0, boss pool 215042 → 212054; first divergence round 8, the board hash. `coop2-NORMAL-8-serverrun` (ai_1 `3_20_a`): victory, team LP 27 → 37 (ai_0 LP 10 → 19, ai_1 LP 17 → 18); first divergence round 8, ai_1 killed 22 → 23, leaks 1 → 0. `coop2-NORMAL-5-coverage-diy` (ai_0 `3_20_a`): victory, team LP 33 → 34 (h_0 LP 27 → 28); first divergence round 13, ai_0's board hash, killed 26 → 21, leaks 17 → 22 | +| 耶拉 was on the pre-change lineup; that seat is then eliminated and the stored lineup is empty | `solo-ABYSS-1`: defeat at round 13 → eliminated at round 12, team LP 0 → null. The pre-change lineup had 耶拉 `3_20_a` and 至简 `3_13_a`. First divergence round 8: LP 27 → 18, killed 19 → 10, leaks 0 → 9. `coop4-ABYSS-7`: still a defeat at round 13, team LP 0, boss pool 4821366 → 3417504. ai_1 is eliminated at round 13; the pre-change lineup had 至简 `3_13_a` and 耶拉 `3_20_a`. First divergence round 8: ai_1 LP 19 → 20, killed 2 → 3, leaks 7 → 6. ai_0's lineup also changes and has no funnel chess id before or after | +| 耶拉 plus other funnel operators, lineup unchanged, same victory and the same team LP 130 | `coop4-FUNNY-6`: ai_0 耶拉 `3_20_a`, ai_1 荒芜拉普兰德 `6_18_a`, ai_3 洛洛 `2_10_a`. First divergence round 11, ai_0's kjeragShip layers 26 → 23 | +| No 耶拉 on the final lineup. The diverging round's pieces and skill choice are not stored | `coop2-NORMAL-1-coverage-standins`: still a defeat, team LP 0, boss pool 25040 unchanged. ai_0's final lineup includes 荒芜拉普兰德 `6_18_a`. First divergence round 7, the other seat's miraShip layer 5 → 6. `coop2-NORMAL-14-standins`: victory, team LP 31 → 40 (ai_0 LP 13 → 22). Neither final lineup contains a funnel chess id. First divergence round 10 bond layers (raidShip 26 → 28, steadShip 16 → 18); that round's board hash is unchanged | diff --git a/server/sim/ai.js b/server/sim/ai.js index c6f3d823..73178281 100644 --- a/server/sim/ai.js +++ b/server/sim/ai.js @@ -319,10 +319,12 @@ export function resolveHit(b, u, prof, target, info, x, y) { let mulT = skillMul; if (prof.dmgMul) { const m = typeof prof.dmgMul === 'function' ? prof.dmgMul(b, u, target) : prof.dmgMul; if (Number.isFinite(m)) mulT *= m; } const funnelMul = prof.funnelMul ? prof.funnelMul(b, u, target) : 1; - const attachedFunnel = !!prof.funnelMul && (!info.isSkill || prof.funnelBodyHits > 0); - // Unreleased drones are additional damage (PRTS 驭械术师), not a replacement for the caster's attack. A volley - // shares one talent roll and attackId; extra drones never duplicate the body. Released skill paths stay separate. + // Unreleased drones are additional damage on the caster's attack (PRTS 驭械术师), including a skill that only + // buffs or retargets that attack. `info.isSkill` is set for every attack or targeting override, so it must not + // decide this. `funnelBodyHits === 0` is the drone-only opt-out (the ramp stays inside the hits, no body). + // A volley shares one talent roll and attackId; extra drones never duplicate the body. // [ASSUMED] Body instances precede additions at the existing projectile impact; a multi-hit volley keeps one ramp. + const attachedFunnel = !!prof.funnelMul && prof.funnelBodyHits !== 0; if (!attachedFunnel) mulT *= funnelMul; const hits = prof.hitsFn ? prof.hitsFn(b, u, info) : Math.max(1, prof.hits || 1); // `hitDmgMul` (professions.js header): each instance's 伤害倍率 — the DamageInfo `mul`, after DEF / RES — and only the @@ -330,7 +332,7 @@ export function resolveHit(b, u, prof, target, info, x, y) { const split = Number.isFinite(prof.hitDmgMul) && prof.hitDmgMul > 0 ? prof.hitDmgMul : null; let dealtMain = 0; if (attachedFunnel && info.index === 0) { - const bodyHits = Math.max(1, prof.funnelBodyHits || 1); + const bodyHits = Math.max(1, prof.funnelBodyHits > 0 ? prof.funnelBodyHits : 1); for (let h = 0; h < bodyHits && target.alive; h++) { dealtMain += b.dealDamage(u, target, { amount: atk * scale * mulT, type: baseType, isAttack: true, isSkill: info.isSkill, tags: prof.tags || [], attackId }); diff --git a/server/sim/content/kits/ops/chess_char_3_20-kjera.js b/server/sim/content/kits/ops/chess_char_3_20-kjera.js index 67429268..ffe6e3cf 100644 --- a/server/sim/content/kits/ops/chess_char_3_20-kjera.js +++ b/server/sim/content/kits/ops/chess_char_3_20-kjera.js @@ -2,42 +2,136 @@ // Conventions of the tier-3 kits: ../shared/tier3.js; kit contract and rules: ../README.md. import { COLS } from '../../../constants.js'; +import { canTargetEnemy, sortEnemyTargets } from '../../../targeting.js'; import { num, defOf, talentBb, altSkills, statSkill, funnelMap, installFunnelPrune } from '../shared/tier3.js'; +export const DRONE_TAG = 'kjera:drone'; + +// One step of the per-target ramp. Two drones that hit the same enemy in the same tick share the step (funnelMap). +function stepMap(ramp, id, time, f) { + const prev = ramp.get(id); + if (prev && prev.t === time) return prev.s; + const s = prev == null ? f.init : Math.min(f.max, prev.s + f.delta); + ramp.set(id, { s, t: time }); + return s; +} + +function acquire(battle, unit, rel) { + const prof = unit.profile; + const ok = (e) => !!e && e.alive && canTargetEnemy(unit, e, prof); + const cands = battle.enemiesInKeys(unit.rangeKeys, unit, prof); + for (const e of battle.blockedTargets(unit, prof)) if (!cands.includes(e)) cands.push(e); + sortEnemyTargets(battle, unit, cands, prof.priority); + const usable = cands.filter(ok); + const held = new Set(); + for (const d of rel.drones) { + if (d.lock && ok(d.lock)) held.add(d.lock); + else { d.lock = null; d.scale = null; } + } + for (const d of rel.drones) { + if (d.lock) continue; + const e = usable.find((x) => !held.has(x)) ?? usable[0] ?? rel.drones.find((x) => x.lock)?.lock ?? null; + if (!e) continue; + held.add(e); + d.lock = e; + d.scale = null; + } +} + +/** + * 心随意动 (skchr_kjera_2, docs/research/03-operators.md): release `1 + attack@cnt` drones that stay locked until the + * enemy dies or the skill ends, ATK +, and a cold roll on her own attack and on each drone hit. The body keeps its + * ordinary attack inside her range; the unreleased addition is off while the drones are out. + * `restart` (hidden form): each drone begins at the trait's initial scale and is not written back. + * Otherwise the drones continue the per-target ramp and that map is restored when the skill ends. + * [ASSUMED] The released drones use the trait ramp (init / +delta / cap). Her blackboard has no drone scale. + * [ASSUMED] No flight delay. A lock that can no longer be targeted is dropped and the drone retargets. Stun and + * disarm do not pause the released drones (the skill tick still runs). + */ +export function kjeraRelease(bb, { restart = false, announce = false } = {}) { + const n = 1 + Math.max(0, Math.floor(num(bb['attack@cnt'], 0))); + const prob = num(bb['attack@prob'], 0), cold = num(bb['attack@cold'], 0); + return { + skill: { + kind: 'duration', + mods: { atkPct: num(bb.atk) }, + onStart({ battle, unit }) { + const key = typeof unit.profile.funnelMul === 'function' ? 'funnelMul' : 'dmgMul'; + const mul = unit.profile[key]; + unit.profile = { ...unit.profile, [key]: null }; + const ramp = restart ? null : new Map(); + if (ramp && unit.trait.funnelMap) { + for (const [id, v] of unit.trait.funnelMap) ramp.set(id, { s: v.s, t: v.t }); + } + unit.mem.kjeraRel = { + key, mul, restart, ramp, cd: 0, + target: unit.trait.funnelTarget ?? null, + scale: unit.trait.funnelScale, + drones: Array.from({ length: n }, () => ({ lock: null, scale: null })), + }; + if (announce) battle.fx('drones', { x: unit.x, y: unit.y, id: unit.id, n }); + }, + onTick({ battle, unit, dt }) { + const rel = unit.mem.kjeraRel; + if (!rel || !unit.alive || !unit.skill?.active) return; + rel.cd = Math.max(0, rel.cd - dt); + acquire(battle, unit, rel); + if (!rel.drones.some((d) => d.lock) || rel.cd > 1e-9) return; + rel.cd = unit.s.interval; + const f = unit.profile.funnel || { init: 0.2, delta: 0.15, max: 1.1 }; + for (const d of rel.drones) { + if (!d.lock || !d.lock.alive) continue; + const scale = rel.restart + ? (d.scale = d.scale == null ? f.init : Math.min(f.max, d.scale + f.delta)) + : stepMap(rel.ramp, d.lock.id, battle.time, f); + battle.fx('drone', { x: d.lock.x, y: d.lock.y, id: unit.id }); + battle.dealDamage(unit, d.lock, { + amount: unit.s.atk * unit.s.atkScaleMul * scale, type: 'arts', + isSkill: true, isAttack: false, tags: ['skill', 'drone', DRONE_TAG], + }); + if (d.lock.alive && cold > 0 && battle.rng.chance(prob)) { + battle.applyStatus(d.lock, 'cold', { duration: cold, source: unit }); + } + } + }, + onEnd({ unit }) { + const rel = unit.mem.kjeraRel; + unit.mem.kjeraRel = null; + if (!rel) return; + unit.trait.funnelTarget = rel.target; + unit.trait.funnelScale = rel.scale; + if (rel.ramp) unit.trait.funnelMap = rel.ramp; + if (unit.profile && rel.key) unit.profile = { ...unit.profile, [rel.key]: rel.mul }; + }, + }, + install(battle, unit) { + // 自身攻击: one cold roll on the ordinary body hit. Drone hits roll in onTick, so they are not rolled again. + battle.on('damaged', (ctx) => { + if (!unit.mem.kjeraRel || ctx.source !== unit || !ctx.target?.alive || !ctx.dmg) return; + if (!ctx.dmg.isAttack || ctx.dmg.isSkill) return; + const tags = ctx.dmg.tags || []; + if (tags.includes('addition') || tags.includes('funnel') || tags.includes(DRONE_TAG)) return; + if (!(cold > 0) || !battle.rng.chance(prob)) return; + battle.applyStatus(ctx.target, 'cold', { duration: cold, source: unit }); + }, { owner: unit }); + }, + }; +} + export default { // ---- 3_20 耶拉 · 驭械术师 — S2 心随意动: +1 drone (2 locks; a lone enemy gets both), ATK +, cold procs; 低眉: ATK + - // (more with ≥cnt ground tiles in range) + // (more with ≥cnt ground tiles in range). S1 攻击力强化·γ型: ATK + only (one unreleased drone, the trait ramp). chess_char_3_20_a: (bb, chess, def) => { const d = defOf(chess, def); const t0 = talentBb(d, 0); - const extra = Math.floor(num(bb['attack@cnt'], 0)); - const prob = num(bb['attack@prob'], 0), cold = num(bb['attack@cold'], 0); - const kit = { + const rel = kjeraRelease(bb, { restart: false }); + return { trait: { funnelMul: funnelMap }, - skill: { - kind: 'duration', - mods: { atkPct: num(bb.atk) }, - attack: { onHit({ battle, unit, target }) { - if (target && target.alive && cold > 0 && battle.rng.chance(prob)) battle.applyStatus(target, 'cold', { duration: cold, source: unit }); - } }, - }, - // S1 攻击力强化·γ型: ATK + (one drone, the trait ramp as usual) + skill: rel.skill, skills: altSkills(chess, d, bb, { 'skcom_atk_up[3]': statSkill }), install(battle, unit) { installFunnelPrune(battle, unit); - // "浮游单元+1": every drone locks an enemy — with fewer enemies in range than drones, the spare drone joins a - // lock (both attack it, each hit rolls the cold proc; they ramp in parallel, see funnelMap) - if (extra > 0) { - battle.on('beforeAttack', (ctx) => { - if (ctx.attacker !== unit || !unit.skill?.active || !ctx.targets.length) return; - const n = 1 + extra; - if (ctx.targets.length >= n) return; - const base = ctx.targets.slice(); - const out = base.slice(); - for (let i = 0; out.length < n; i++) out.push(base[i % base.length]); - ctx.targets = out; - }, { owner: unit, priority: -50 }); - } + rel.install(battle, unit); }, talents: [{ install(battle, unit) { battle.on('deploy', (ctx) => { @@ -52,7 +146,5 @@ export default { }, { owner: unit }); } }], }; - if (extra > 0) kit.skill.targeting = { maxTargets: 1 + extra }; - return kit; }, }; diff --git a/server/sim/content/kits/ops/chess_char_4_03-kjera.js b/server/sim/content/kits/ops/chess_char_4_03-kjera.js index 528689e1..cf9282ce 100644 --- a/server/sim/content/kits/ops/chess_char_4_03-kjera.js +++ b/server/sim/content/kits/ops/chess_char_4_03-kjera.js @@ -2,35 +2,18 @@ // Conventions of the tier-4 kits: ../shared/tier4.js; kit contract and rules: ../README.md. import { COLS } from '../../../constants.js'; -import { canTargetEnemy } from '../../../targeting.js'; -import { num, tbb, skillActive, withDefaults } from '../shared/tier4.js'; +import { num, tbb, withDefaults } from '../shared/tier4.js'; +import { kjeraRelease } from './chess_char_3_20-kjera.js'; export default withDefaults({ - // ===== 耶拉 (funnel, hidden) S2 心随意动 — +1 drone locking targets, ATK up, chance to chill; talent 低眉 + // ===== 耶拉 (funnel, hidden) S2 心随意动 — +1 drone locking targets, ATK up, chance to chill; talent 低眉. + // Each released drone restarts at the trait's initial scale (it does not continue the pre-skill ramp) and those + // scales are not written back onto the single trait ramp. The body stays an ordinary in-range attack. chess_char_4_03_a: (bb, chess, def) => { const t0 = tbb(def, 0); - const n = 1 + Math.max(0, Math.floor(num(bb['attack@cnt'], 1))); - const prob = num(bb['attack@prob'], 0), cold = num(bb['attack@cold'], 0); - const funnel = (unit) => unit.profile.funnel || { init: 0.2, delta: 0.15, max: 1.1 }; + const rel = kjeraRelease(bb, { restart: true, announce: true }); return { - skill: { - kind: 'duration', - mods: { atkPct: num(bb.atk) }, - targeting: { maxTargets: n }, - attack: { - // every drone ramps on its own locked target (trait init/delta/max): the multipliers are queued per target - // by the beforeAttack hook below (two drones on the same enemy ramp independently) - funnelMul: (battle, unit, target) => { - const q = unit.mem.kjeraQueue && unit.mem.kjeraQueue.get(target.id); - return q && q.length ? q.shift() : funnel(unit).init; - }, - onHit({ battle, unit, target }) { - if (target && target.alive && cold > 0 && battle.rng.chance(prob)) battle.applyStatus(target, 'cold', { duration: cold, source: unit }); - }, - }, - onStart({ battle, unit }) { unit.mem.kjeraDrones = []; unit.mem.kjeraQueue = new Map(); battle.fx('drones', { x: unit.x, y: unit.y, id: unit.id, n }); }, - onEnd({ unit }) { unit.mem.kjeraDrones = []; unit.mem.kjeraQueue = null; }, - }, + skill: rel.skill, talents: [{ install(battle, unit) { // 低眉: ATK +10 %, +16 % with ≥ 2 ground tiles in range battle.on('deploy', (c) => { if (c.unit !== unit) return; @@ -40,38 +23,7 @@ export default withDefaults({ battle.addBuff(unit, { key: 'kjera:t1', mods: { atkPct: v } }); }, { owner: unit }); } }], - install(battle, unit) { - // n drones, each locked on its enemy until that enemy dies (while at least one enemy is in her range). A free - // drone takes an enemy no other drone holds, else doubles up on the best target (a lone enemy/boss gets both). - battle.on('beforeAttack', (c) => { - if (c.attacker !== unit || !skillActive(unit)) return; - const ok = (e) => !!e && e.alive && canTargetEnemy(unit, e, { canHitFly: true }); - const cands = c.targets.filter(ok); - const drones = unit.mem.kjeraDrones || (unit.mem.kjeraDrones = []); - const held = new Set(); - for (let i = 0; i < n; i++) { if (drones[i] && ok(drones[i].e)) held.add(drones[i].e); else drones[i] = null; } - for (let i = 0; i < n; i++) { - if (drones[i]) continue; - const e = cands.find((x) => !held.has(x)) ?? cands[0] ?? drones.find((d) => d)?.e; - if (!e) continue; - held.add(e); - drones[i] = { e, scale: null }; - } - const f = funnel(unit); - const q = unit.mem.kjeraQueue || (unit.mem.kjeraQueue = new Map()); - const out = []; - for (const d of drones) { - if (!d) continue; - d.scale = d.scale == null ? f.init : Math.min(f.max, d.scale + f.delta); - out.push(d.e); - const l = q.get(d.e.id); - if (l) l.push(d.scale); else q.set(d.e.id, [d.scale]); - } - if (out.length) c.targets = out; - }, { owner: unit, priority: 10 }); - // queued multipliers of shots that never landed (target died mid-flight) are dropped with the target - battle.on('death', (c) => { if (c.unit.side === 'enemy' && unit.mem.kjeraQueue) unit.mem.kjeraQueue.delete(c.unit.id); }, { owner: unit }); - }, + install(battle, unit) { rel.install(battle, unit); }, }; }, }); diff --git a/server/sim/content/kits/ops/chess_char_6_18-whitw2.js b/server/sim/content/kits/ops/chess_char_6_18-whitw2.js index 454140c5..3144cdc0 100644 --- a/server/sim/content/kits/ops/chess_char_6_18-whitw2.js +++ b/server/sim/content/kits/ops/chess_char_6_18-whitw2.js @@ -124,8 +124,10 @@ function whitw2(bb, chess, def) { const skills = { // S1 慵怠者悲鸣: passive 浮游单元+1 (trait: one more hit per attack); toggled on: ATK +atk and the drones lock a random - // non-moving enemy anywhere on the field (re-locking when it moves or falls; install), else her range. The whole-field - // grid only selects those targets — no rangeId, no 攻击范围 in the text — so the card keeps her 3-1 (showOwnRange) + // non-moving enemy anywhere on the field (re-locking when it moves or falls; install), else her range. The toggle + // retargets her attack; the text does not say she stops attacking, so the body and both unreleased additions stay. + // The whole-field grid only selects those targets — no rangeId, no 攻击范围 in the text — so the card keeps her 3-1 + // (showOwnRange) skchr_whitw2_1: { kind: 'toggle', // [ASSUMED] her drones lock enemies only (install): 白铁's 铁钳号 alone does not open S1 / S2 (skills.js allyTargetsOk) @@ -143,6 +145,8 @@ function whitw2(bb, chess, def) { ...(skillGridW ? { targeting: { rangeGrid: skillGridW } } : {}), attack: { hits: 1, + // The skill names the released drones, not a second hit from her. 0 keeps the ramp inside these hits. + funnelBodyHits: 0, funnelMul(battle, unit, target) { const f = unit.profile?.funnel || { init: 0.2, delta: 0.15, max: 1.1 }; const m = unit.mem.hunt; diff --git a/server/sim/professions.js b/server/sim/professions.js index 61dacb23..14187e32 100644 --- a/server/sim/professions.js +++ b/server/sim/professions.js @@ -22,7 +22,8 @@ // noHeal bool (cannot be healed by others) blockFly bool onHitStatus {key, duration, value} // dmgMul(battle, unit, target) → number afterHit(battle, unit, target, {dealt,x,y}) // funnelMul(battle, unit, target) → number (drone ramp, separate from the caster's attack multiplier) -// funnelBodyHits n (an unreleased skill attack's body hit count; default normal attack: one, drones: `hits`) +// funnelBodyHits n (body hits kept beside that ramp. Omit it for one. 0: drone-only, ramp folded into the hits, +// no body — 荒芜拉普兰德 S2. >0: that many body hits — 至简 S2. Not keyed off the skill flag) // canAttack(battle, unit) → bool afterAttack(battle, unit, targets) // skipEnemy(enemy) → bool (an enemy the unit never selects — targeting.js canTargetEnemy; 嵯峨 "不攻击重伤单位") // healThrough(healer, ally) → bool (a healer that selects and heals that ally through its 禁疗 — Battle diff --git a/test/content/kits_t3.test.js b/test/content/kits_t3.test.js index c79c80f6..faa3a41b 100644 --- a/test/content/kits_t3.test.js +++ b/test/content/kits_t3.test.js @@ -794,12 +794,21 @@ test('3_20 耶拉: 低眉 ATK (ground tiles in range); 心随意动 +1 drone, AT assert.ok(first[1] > first[0], 'drone ramps on the same target'); fill(u); assert.ok(h.runUntil(() => u.skill.active, 5)); + const tOn = h.b.time; approx(u.s.atk, u.base.atk * (1 + t0['kjera_t_1[high].atk'] + bb.atk)); + const full = u.s.atk * u.s.atkScaleMul; h.runUntil(() => !u.skill.active, 30); - const sk = h.hooksOf('attack').filter((c) => c.attacker === u && c.isSkill); - assert.ok(sk.length > 5 && sk.every((c) => c.targets.length === 1 + bb['attack@cnt']), 'two drone locks'); + const during = (c) => c.t + 1e-9 >= tOn - h.b.dt && c.t + 1e-9 < h.b.time; + const atks = h.hooksOf('attack').filter((c) => c.attacker === u && during(c) && !c.isSkill); + assert.ok(atks.length > 5 && atks.every((c) => c.targets.length === 1), 'the body keeps a single in-range target'); + const drones = h.hooksOf('damaged').filter((c) => c.source === u && during(c) && c.dmg?.tags?.includes('kjera:drone')); + assert.ok(drones.length >= atks.length, 'released drones keep firing'); + const bodies = h.hooksOf('damaged').filter((c) => c.source === u && during(c) && c.dmg?.isAttack && !c.dmg.isSkill + && Math.abs(c.amount - full) < 1e-4); + assert.ok(bodies.length >= 2, 'her own hits stay at 100% ATK'); const colds = h.hooksOf('statusApplied').filter((c) => c.source === u && c.status === 'cold'); - assert.ok(colds.length >= 1 && colds.length < sk.length * 2, `cold procs (${colds.length}/${sk.length * 2})`); + const chances = bodies.length + drones.length; + assert.ok(colds.length >= 1 && colds.length < chances, `cold procs (${colds.length}/${chances})`); approx(colds[0].duration, bb['attack@cold']); done(h); }); @@ -1076,7 +1085,7 @@ test('3_19 伺夜: the pack never takes a later board unit’s tile; a 狼群 pi }); test('3_20 耶拉: 心随意动 with a single enemy — both drones lock it and ramp in parallel', () => { - const id = 'chess_char_3_20_b', bb = BB(id), tb = TR(id); + const id = 'chess_char_3_20_b', tb = TR(id); const h = makeBattle({ defs: { enemies: { enemy_a: dummy('enemy_a') } }, timeLimit: 80, hooks: ['damaged', 'attack'], captureNoisy: true, units: [{ chessId: id, row: 10, col: 2 }], enemies: [{ key: 'enemy_a', pos: [10, 4] }], @@ -1087,13 +1096,22 @@ test('3_20 耶拉: 心随意动 with a single enemy — both drones lock it and approx(plain[plain.length - 1], tb.max_atk_scale, 1e-6, 'module ramp cap'); fill(u); assert.ok(h.runUntil(() => u.skill.active, 5)); + const t0 = h.b.time; const n0 = h.hooksOf('damaged').length; h.run(8); - const sk = h.hooksOf('attack').filter((c) => c.attacker === u && c.isSkill); - assert.ok(sk.length >= 3 && sk.every((c) => c.targets.length === 1 + bb['attack@cnt'] && c.targets.every((t) => t.defId === 'enemy_a'))); - const hits = h.hooksOf('damaged').slice(n0).filter((c) => c.source === u && c.dmg?.isAttack); - assert.ok(hits.length >= 2 * (sk.length - 1)); - for (let i = 0; i + 1 < hits.length; i += 2) approx(hits[i].amount, hits[i + 1].amount, 1e-9, 'same volley, same scale'); + const atks = h.hooksOf('attack').filter((c) => c.attacker === u && c.t + 1e-9 >= t0 - h.b.dt && !c.isSkill); + assert.ok(atks.length >= 3 && atks.every((c) => c.targets.length === 1 && c.targets.every((t) => t.defId === 'enemy_a')), 'one body target'); + const drones = h.hooksOf('damaged').slice(n0).filter((c) => c.source === u && c.dmg?.tags?.includes('kjera:drone')); + assert.ok(drones.length >= 4, 'both drones stay on the lone enemy'); + const byT = new Map(); + for (const c of drones) (byT.get(c.t) ?? byT.set(c.t, []).get(c.t)).push(c); + const pairs = [...byT.values()].filter((v) => v.length === 2); + assert.ok(pairs.length >= 2, 'the two drones share a volley'); + for (const v of pairs) approx(v[0].amount, v[1].amount, 1e-9, 'same volley, same scale'); + const full = u.s.atk * u.s.atkScaleMul; + const body = h.hooksOf('damaged').slice(n0).filter((c) => c.source === u && c.dmg?.isAttack && !c.dmg.isSkill + && Math.abs(c.amount - full) < 1e-4); + assert.ok(body.length >= 2, 'body stays at 100% ATK while the drones ramp'); done(h); }); diff --git a/test/content/kits_t4.test.js b/test/content/kits_t4.test.js index a80fc021..d065983b 100644 --- a/test/content/kits_t4.test.js +++ b/test/content/kits_t4.test.js @@ -138,12 +138,16 @@ test('耶拉 S2: two drones ramp independently on two targets, ATK up; 低眉 +1 const n0 = dmgBy(h, u).length; h.run(8); const hits = dmgBy(h, u).slice(n0); - const onA = hits.filter((c) => c.target === a).map((c) => c.amount), onB = hits.filter((c) => c.target === b).map((c) => c.amount); + const drones = hits.filter((c) => c.dmg?.tags?.includes('kjera:drone')); + const onA = drones.filter((c) => c.target === a).map((c) => c.amount), onB = drones.filter((c) => c.target === b).map((c) => c.amount); assert.ok(onA.length >= 3 && onB.length >= 3, 'both locked targets attacked'); const atk = u.s.atk; approx(onA[0], atk * tr.init_atk_scale, 1e-6, 'ramp start'); approx(onA[1], atk * (tr.init_atk_scale + tr.delta_atk_scale), 1e-6, 'ramp +15 %'); + approx(onB[0], atk * tr.init_atk_scale, 1e-6, 'second drone starts its own ramp'); approx(onB[1], atk * (tr.init_atk_scale + tr.delta_atk_scale), 1e-6, 'second drone ramps on its own'); + const body = hits.filter((c) => c.dmg?.isAttack && !c.dmg.isSkill); + assert.ok(body.length >= 1 && body.some((c) => Math.abs(c.amount - atk) < 1e-4), 'her own hit stays at 100% ATK'); h.run(15); assert.ok(noisy(h, 'statusApplied').some((c) => c.source === u && c.status === 'cold' && c.duration === bb['attack@cold']), 'cold proc'); checkInvariants(h.b); @@ -1032,14 +1036,17 @@ test('耶拉 S2: against a lone enemy both drones lock it and ramp independently const n0 = dmgBy(h, u).length; h.run(4); const hits = dmgBy(h, u).slice(n0); + const drones = hits.filter((c) => c.dmg?.tags?.includes('kjera:drone')); const byT = new Map(); - for (const c of hits) (byT.get(c.t) ?? byT.set(c.t, []).get(c.t)).push(c.amount / u.s.atk); + for (const c of drones) (byT.get(c.t) ?? byT.set(c.t, []).get(c.t)).push(c.amount / u.s.atk); const volleys = [...byT.values()]; assert.ok(volleys.length >= 3); - assert.ok(volleys.every((v) => v.length === 2), 'two drone hits per attack'); + assert.ok(volleys.every((v) => v.length === 2), 'two drone hits per tick'); approx(volleys[0][0], tr.init_atk_scale, 1e-6); approx(volleys[0][1], tr.init_atk_scale, 1e-6, 'second drone starts its own ramp'); approx(volleys[1][1], tr.init_atk_scale + tr.delta_atk_scale, 1e-6); + const full = u.s.atk * u.s.atkScaleMul; + assert.ok(hits.some((c) => c.dmg?.isAttack && !c.dmg.isSkill && Math.abs(c.amount - full) < 1e-4), 'body at 100% ATK'); checkInvariants(h.b); }); diff --git a/test/golden/bonds.json b/test/golden/bonds.json index 9d679cf0..3f092257 100644 --- a/test/golden/bonds.json +++ b/test/golden/bonds.json @@ -264,24 +264,24 @@ "total": 17, "unspawned": 0, "bossHpLeft": null, - "rngDraws": 82, + "rngDraws": 97, "errors": {"count":0,"kinds":[]}, - "players": {"p1":{"killed":17,"total":17,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":90450,"bossDmg":0,"heal":381,"deaths":2,"layerGains":{}}}, + "players": {"p1":{"killed":17,"total":17,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":90450,"bossDmg":0,"heal":362,"deaths":2,"layerGains":{}}}, "units": [ ["p1",1,"op","chess_char_4_01_a",2,null,2901.8,1,4,0,1278,0,0,8,0], - ["p1",2,"op","chess_char_4_04_a",1,null,1936,1,6,1,11817,0,0,19,2], + ["p1",2,"op","chess_char_4_04_a",1,null,1936,1,6,1,11213,0,0,19,2], ["p1",3,"op","chess_char_2_14_a",1,null,1355.2,1,1,0,0,0,0,0,0], ["p1",4,"op","chess_char_3_10_a",1,null,1815,1,2,0,0,0,0,0,0], - ["p1",5,"op","chess_char_3_20_a",1,null,1233.1,1,3,1,6585,0,0,24,1], - ["p1",6,"op","chess_char_3_21_a",2,null,0,0,7,4,26578,1606,106,39,1], - ["p1",7,"op","chess_char_4_02_a",2,null,1570.8,1,5,5,25327,0,0,18,1], - ["p1",8,"op","chess_char_4_06_a",1,null,0,0,8,6,18864,1646,275,40,1] + ["p1",5,"op","chess_char_3_20_a",1,null,1233.1,1,3,3,11450,0,0,24,1], + ["p1",6,"op","chess_char_3_21_a",2,null,0,0,7,6,23766,1606,106,38,1], + ["p1",7,"op","chess_char_4_02_a",2,null,1570.8,1,5,4,23679,0,0,18,1], + ["p1",8,"op","chess_char_4_06_a",1,null,0,0,8,3,19064,1627,256,38,1] ], - "enemies": {"enemy_10042_prtrop":[4,4,0,1383,21600],"enemy_10042_prtrop_2":[2,2,0,1606,14400],"enemy_10043_sailor":[11,11,0,263,54450]}, - "hooks": [1,25,1928,166,166,238,238,360,19,19,6,5,0,7171,17,9,17,0,1,19,0,0,0], - "events": {"atk":194,"deploy":8,"die":19,"dmg":237,"engage":6,"fx":28,"skill":11,"spawn":25,"status":46}, - "fx": {"crit":6,"displace":5,"ripple":7,"shadowWeave":5,"shield":2,"shieldBreak":1,"stealth":2}, - "snaps": "6de03b40 bcb3ddb5 7e1399bb 66f4cf7b 64a5b833 c3944891 0a226983" + "enemies": {"enemy_10042_prtrop":[4,4,0,1429,21600],"enemy_10042_prtrop_2":[2,2,0,1606,14400],"enemy_10043_sailor":[11,11,0,197,54450]}, + "hooks": [1,25,1928,162,162,247,247,342,19,19,6,5,0,7171,19,8,17,0,1,19,0,0,0], + "events": {"atk":171,"deploy":8,"die":19,"dmg":246,"engage":6,"fx":65,"skill":11,"spawn":25,"status":48}, + "fx": {"crit":9,"displace":5,"drone":34,"ripple":7,"shadowWeave":5,"shield":2,"shieldBreak":1,"stealth":2}, + "snaps": "6de03b40 bcb3ddb5 0d638656 71757fb2 ed5fc1b0 be14aa0b 29f78bf7" }, "bond-emptyShip-high": { "about": "协防干员 high: tier 1 layers 999; chess_char_4_17_b chess_char_4_18_b chess_char_4_19_b chess_char_4_22_b chess_char_2_14_b chess_char_3_10_b chess_char_4_20_b chess_char_4_21_b", @@ -623,25 +623,25 @@ "total": 17, "unspawned": 0, "bossHpLeft": null, - "rngDraws": 9, + "rngDraws": 13, "errors": {"count":0,"kinds":[]}, "players": {"p1":{"killed":17,"total":17,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":177984,"bossDmg":0,"heal":2132,"deaths":0,"layerGains":{}}}, "units": [ ["p1",1,"op","chess_char_1_02_b",1,"uniequip_002_yak",4680.5,1,2,0,0,0,0,0,0], ["p1",2,"op","chess_char_5_11_b",1,"uniequip_002_demkni",6111.11,1,1,0,0,0,1531,0,4], ["p1",3,"op","chess_char_2_05_b",1,"uniequip_002_harold",17101.41,1,4,0,0,50,600,7,1], - ["p1",4,"op","chess_char_3_11_b",1,"uniequip_002_snhunt",2356.25,1,7,10,114435,1041,0,21,9], - ["p1",5,"op","chess_char_3_14_b",1,"uniequip_002_slbell",2170.63,1,5,1,3944,50,0,1,1], - ["p1",6,"op","chess_char_3_20_b",1,"uniequip_002_kjera",1993.75,1,8,0,6927,50,0,7,1], + ["p1",4,"op","chess_char_3_11_b",1,"uniequip_002_snhunt",2356.25,1,7,10,108776,1041,0,21,9], + ["p1",5,"op","chess_char_3_14_b",1,"uniequip_002_slbell",2170.63,1,5,1,840,50,0,1,1], + ["p1",6,"op","chess_char_3_20_b",1,"uniequip_002_kjera",1993.75,1,8,0,16312,50,0,7,1], ["p1",7,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",2684.88,1,3,1,1414,50,0,1,2], - ["p1",8,"op","chess_char_5_12_b",0,"uniequip_002_dusk",2407.13,1,6,5,48718,1141,0,10,10], + ["p1",8,"op","chess_char_5_12_b",0,"uniequip_002_dusk",2407.13,1,6,5,48094,1141,0,10,10], ["p1","~1","token","token_10015_dusk_drgn",null,null,0,0,12,0,2547,1997,0,8,null] ], "enemies": {"enemy_1267_nhpbr_2":[11,11,0,2135,69696],"enemy_1270_nhstlk_2":[4,4,0,0,73728],"enemy_1272_nhtank_2":[2,2,0,2243,34560]}, - "hooks": [1,26,2174,65,65,117,117,12,18,18,28,28,0,7475,1579,3,17,0,1,18,0,0,0], - "events": {"atk":69,"deploy":9,"die":18,"dmg":117,"engage":6,"fx":40,"heal":12,"skill":56,"spawn":26,"status":20}, - "fx": {"coldWind":2,"frostNova":2,"healAoe":4,"strike":9,"summon":1,"volley":9,"zone":13}, - "snaps": "cc4cf53b 9139c2c7 206b1332 d27de872 77344198 6c0c2544 4d5c5c01 c0ec8188" + "hooks": [1,26,2174,65,65,121,121,12,18,18,28,28,0,7475,1579,3,17,0,1,18,0,0,0], + "events": {"atk":65,"deploy":9,"die":18,"dmg":121,"engage":6,"fx":48,"heal":12,"skill":56,"spawn":26,"status":20}, + "fx": {"coldWind":2,"drone":8,"frostNova":2,"healAoe":4,"strike":9,"summon":1,"volley":9,"zone":13}, + "snaps": "cc4cf53b 9139c2c7 206b1332 d27de872 bcb0ffd8 0b210404 84dba741 37d26448" }, "bond-lateranoShip-low": { "about": "拉特兰 low: tier 1 layers 1; chess_char_3_06_a chess_char_3_05_a chess_char_1_01_a chess_char_2_01_a chess_char_3_01_a chess_char_3_08_a chess_char_3_09_a chess_char_3_10_a", @@ -810,24 +810,24 @@ "total": 17, "unspawned": 0, "bossHpLeft": null, - "rngDraws": 35, + "rngDraws": 55, "errors": {"count":0,"kinds":[]}, "players": {"p1":{"killed":17,"total":17,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":126144,"bossDmg":0,"heal":0,"deaths":0,"layerGains":{}}}, "units": [ ["p1",1,"op","chess_char_4_01_a",2,null,2901.8,1,3,0,0,0,0,0,0], ["p1",2,"op","chess_char_2_11_a",1,null,2257.29,1,6,0,0,0,0,0,0], ["p1",3,"op","chess_char_3_18_a",2,null,1629.1,1,8,0,0,0,0,0,0], - ["p1",4,"op","chess_char_3_01_a",2,null,1663.13,1,1,2,24227,0,0,22,1], - ["p1",5,"op","chess_char_3_17_a",1,null,2470.6,1,4,5,36116,0,0,30,3], - ["p1",6,"op","chess_char_3_20_a",1,null,913.22,1,5,2,10165,320,0,30,1], - ["p1",7,"op","chess_char_3_21_a",2,null,1500.4,1,2,6,20213,0,0,19,1], - ["p1",8,"op","chess_char_4_02_a",2,null,530.2,1,7,2,35423,1041,0,17,1] + ["p1",4,"op","chess_char_3_01_a",2,null,1663.13,1,1,2,24889,0,0,22,1], + ["p1",5,"op","chess_char_3_17_a",1,null,2470.6,1,4,3,34513,0,0,30,3], + ["p1",6,"op","chess_char_3_20_a",1,null,913.22,1,5,4,18617,320,0,30,1], + ["p1",7,"op","chess_char_3_21_a",2,null,1500.4,1,2,7,15387,0,0,19,1], + ["p1",8,"op","chess_char_4_02_a",2,null,264,1,7,1,32738,1307,0,17,1] ], - "enemies": {"enemy_1116_liprr":[11,11,0,620,69696],"enemy_1116_liprr_2":[4,4,0,741,34560],"enemy_1118_lidbox_2":[2,2,0,0,21888]}, - "hooks": [1,25,1569,126,126,281,281,0,17,17,7,5,0,4873,9,8,17,0,1,17,0,0,0], - "events": {"atk":156,"deploy":8,"die":17,"dmg":280,"engage":5,"fx":20,"skill":12,"spawn":25,"status":64}, - "fx": {"buff":1,"displace":8,"ripple":5,"shield":2,"shieldBreak":1,"volley":3}, - "snaps": "84698390 95c61d5c f771ae02 f28e626f 36ad45e1 faed645b" + "enemies": {"enemy_1116_liprr":[11,11,0,620,69696],"enemy_1116_liprr_2":[4,4,0,741,34560],"enemy_1118_lidbox_2":[2,2,0,266,21888]}, + "hooks": [1,25,1569,126,126,283,283,0,17,17,7,5,0,4873,12,7,17,0,1,17,0,0,0], + "events": {"atk":137,"deploy":8,"die":17,"dmg":283,"engage":5,"fx":55,"skill":12,"spawn":25,"status":62}, + "fx": {"buff":1,"displace":7,"drone":37,"ripple":5,"shield":2,"volley":3}, + "snaps": "84698390 95c61d5c f4fb1346 74a078bf f8644cfb 64bec820" }, "bond-miraShip-high": { "about": "奇迹 high: tier 1 layers 999; chess_char_4_01_b chess_char_2_11_b chess_char_4_04_b chess_char_4_07_b chess_char_3_01_b chess_char_5_22_b chess_char_4_02_b chess_char_4_06_b", @@ -1275,7 +1275,7 @@ "total": 17, "unspawned": 0, "bossHpLeft": null, - "rngDraws": 4, + "rngDraws": 6, "errors": {"count":0,"kinds":[]}, "players": { "p1": {"killed":17,"total":17,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":126144,"bossDmg":0,"heal":0,"deaths":2,"layerGains":{"siracusaShip":6}} @@ -1285,19 +1285,19 @@ ["p1",2,"op","chess_char_4_01_a",2,null,4077.11,1,5,2,8508,566,0,10,1], ["p1",3,"op","chess_char_1_08_a",1,null,0,0,6,1,7992,2615,0,13,1], ["p1",4,"op","chess_char_3_18_a",2,null,0,0,10,5,40927,2036,0,38,1], - ["p1",5,"op","chess_char_3_19_a",2,null,1978.63,1,7,4,9931,0,0,21,1], - ["p1",6,"op","chess_char_3_20_a",1,null,1541.38,1,9,0,1963,0,0,6,1], - ["p1",7,"op","chess_char_3_21_a",2,null,1875.5,1,11,1,18570,0,0,23,1], + ["p1",5,"op","chess_char_3_19_a",2,null,1978.63,1,7,3,9846,0,0,20,1], + ["p1",6,"op","chess_char_3_20_a",1,null,1541.38,1,9,0,2764,0,0,6,1], + ["p1",7,"op","chess_char_3_21_a",2,null,1875.5,1,11,2,17854,0,0,23,1], ["p1",8,"op","chess_char_4_02_a",2,null,1963.5,1,4,4,37037,0,0,7,1], ["p1",9,"token","token_10028_vigil_wolf",null,null,852.9,1,8,0,1216,27,0,2,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_1116_liprr":[11,11,0,41,69696],"enemy_1116_liprr_2":[4,4,0,297,34560],"enemy_1118_lidbox_2":[2,2,0,4906,21888]}, - "hooks": [1,28,1502,148,148,266,266,0,19,19,7,4,3,6742,29,17,17,0,1,20,3,0,0], - "events": {"atk":181,"deploy":9,"die":19,"dmg":264,"engage":8,"fx":39,"layer":3,"skill":11,"spawn":28,"status":92}, - "fx": {"aoe":1,"camouflage":1,"counter":3,"displace":16,"dp":2,"garrison":3,"liberate":2,"phase":3,"ripple":4,"sermon":1,"shield":2,"wolfShadow":1}, - "snaps": "44b7a79e a057c22e d6d91d94 68aa8562 55566a97" + "hooks": [1,28,1502,147,147,266,266,0,19,19,7,4,3,6742,29,17,17,0,1,20,3,0,0], + "events": {"atk":178,"deploy":9,"die":19,"dmg":264,"engage":8,"fx":43,"layer":3,"skill":11,"spawn":28,"status":92}, + "fx": {"aoe":1,"camouflage":1,"counter":3,"displace":16,"dp":2,"drone":4,"garrison":3,"liberate":2,"phase":3,"ripple":4,"sermon":1,"shield":2,"wolfShadow":1}, + "snaps": "44b7a79e a057c22e 1399d939 c2bd253f 9479758a" }, "bond-soloShip-high": { "about": "独行 high: tier 1 layers 999; chess_char_5_19_b chess_char_1_08_b chess_char_5_13_b chess_char_5_14_b chess_char_5_17_b chess_char_5_12_b chess_char_5_15_b chess_char_5_20_b", diff --git a/test/golden/matches.json b/test/golden/matches.json index 878750b5..c3f2f059 100644 --- a/test/golden/matches.json +++ b/test/golden/matches.json @@ -16,7 +16,7 @@ "combat": "client", "boost": null, "setup": {"stageId":"act1autochess_m01","bossId":"boss_5","hiddenBossId":null,"factions":["TIMES","DOT","INVISIBLE"]}, - "end": {"victory":true,"roundsPassed":9,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":23,"bossPoolLeft":0,"virtualMs":68100}, + "end": {"victory":true,"roundsPassed":9,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":27,"bossPoolLeft":0,"virtualMs":68100}, "rng": {"setup":16,"shop":87,"waves":0,"draft":0,"bots":5205,"meta":0}, "errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0}, "rounds": [ @@ -27,7 +27,7 @@ {"round":5,"ai_0":[1,27,8,0,0,3,8,"93b57353",25,"deputShip 2/6, indomShip 2/14, preciShip 0/2, sargonShip 0/4, steadShip 1/5",53,16,0,30]}, {"round":6,"ai_0":[1,27,9,0,0,4,8,"95660cdd",46,"deputShip 2/10, indomShip 1/22, preciShip 0/2, sargonShip 0/4, steadShip 2/14",28,28,0,38]}, {"round":7,"ai_0":[1,27,10,0,0,4,8,"00b23401",75,"deputShip 1/12, emptyShip 1/2, indomShip 1/37, preciShip 0/2, sargonShip 0/4, steadShip 2/24",27,27,0,48]}, - {"round":8,"ai_0":[1,27,11,0,0,4,8,"a344d4b9",115,"deputShip 2/16, emptyShip 1/6, indomShip 1/59, preciShip 0/2, sargonShip 0/4, steadShip 2/34",14,14,0,60]} + {"round":8,"ai_0":[1,27,11,0,0,4,8,"a344d4b9",116,"deputShip 2/16, emptyShip 1/6, indomShip 1/59, preciShip 0/2, sargonShip 0/4, steadShip 2/35",14,14,0,60]} ], "players": { "ai_0": { @@ -35,14 +35,14 @@ "victory": true, "roundsPassed": 9, "eliminatedRound": null, - "lp": 23, + "lp": 27, "bandId": "band_ermengard", "title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"}, "trophies": 0, "reward": 113, - "stats": {"activatedLayers":133,"bossDamage":200000,"dmgDealt":745611,"gold":72,"itemsEquipped":14,"kills":169,"leaks":0,"lpLost":0,"merges":3,"perfectRounds":8,"refreshes":5}, + "stats": {"activatedLayers":134,"bossDamage":200000,"dmgDealt":737575,"gold":72,"itemsEquipped":14,"kills":168,"leaks":0,"lpLost":0,"merges":3,"perfectRounds":8,"refreshes":5}, "lineup": ["2_17_b@12,8","1_13_b@11,8","3_20_b@10,3[5_02_e_b+3_07_e_a]","2_08_a@10,4[4_11_e_a+4_03_e_a]","1_12_a@10,7[3_05_e_a]","5_13_a@10,8[4_02_e_a]","3_16_a@9,4[2_04_e_a+5_02_e_b]","5_02_a@9,8[3_02_e_a+1_01_e_b]"], - "bonds": ["deputShip 1/18","emptyShip 0/6","indomShip 1/63","preciShip 0/2","sargonShip 1/6","steadShip 2/46"] + "bonds": ["deputShip 1/18","emptyShip 0/6","indomShip 1/63","preciShip 0/2","sargonShip 1/6","steadShip 2/47"] } } }, @@ -56,7 +56,7 @@ "combat": "client", "boost": null, "setup": {"stageId":"act1autochess_m01","bossId":"boss_5","hiddenBossId":null,"factions":["ELEMENT","DOT","REFLECTION"]}, - "end": {"victory":true,"roundsPassed":9,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":23,"bossPoolLeft":0,"virtualMs":68100}, + "end": {"victory":true,"roundsPassed":9,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":29,"bossPoolLeft":0,"virtualMs":68100}, "rng": {"setup":16,"shop":154,"waves":0,"draft":0,"bots":5211,"meta":39}, "errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0}, "rounds": [ @@ -81,7 +81,7 @@ "victory": true, "roundsPassed": 9, "eliminatedRound": null, - "lp": 23, + "lp": 29, "bandId": "band_ducklord", "title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"}, "trophies": 0, @@ -102,7 +102,7 @@ "combat": "client", "boost": null, "setup": {"stageId":"act1autochess_m03","bossId":"boss_5","hiddenBossId":"boss_8","factions":["TIMES","DOT","INVISIBLE"]}, - "end": {"victory":true,"roundsPassed":14,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":2,"bossPoolLeft":0,"virtualMs":106900}, + "end": {"victory":true,"roundsPassed":14,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":11,"bossPoolLeft":0,"virtualMs":106900}, "rng": {"setup":25,"shop":159,"waves":0,"draft":10,"bots":8211,"meta":1}, "errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0}, "rounds": [ @@ -129,19 +129,19 @@ }, { "round": 10, - "ai_0": [1,27,12,0,0,5,8,"e01e0f99",87,"deputShip 1/10, kazimierzShip 0/8, kjeragShip 1/13, miraShip 0/3, preciShip 0/5, sargonShip 0/8, soloShip 1/11, steadShip 1/25, suntShip 1/6, swiftShip 1/22, yanShip 0/6",24,24,0,86] + "ai_0": [1,27,12,0,0,5,8,"e01e0f99",88,"deputShip 1/10, kazimierzShip 0/8, kjeragShip 1/14, miraShip 0/3, preciShip 0/5, sargonShip 0/8, soloShip 1/11, steadShip 1/25, suntShip 1/6, swiftShip 1/22, yanShip 0/6",24,24,0,86] }, { "round": 11, - "ai_0": [1,26,12,0,2,5,8,"1df90477",113,"deputShip 1/12, kazimierzShip 0/8, kjeragShip 1/18, miraShip 0/3, preciShip 0/5, sargonShip 0/8, soloShip 1/13, steadShip 1/30, suntShip 1/8, swiftShip 1/32, yanShip 0/6",23,24,1,97] + "ai_0": [1,26,12,0,2,5,8,"1df90477",114,"deputShip 1/12, kazimierzShip 0/8, kjeragShip 1/19, miraShip 0/3, preciShip 0/5, sargonShip 0/8, soloShip 1/13, steadShip 1/30, suntShip 1/8, swiftShip 1/32, yanShip 0/6",23,24,1,97] }, { "round": 12, - "ai_0": [1,16,14,0,0,6,8,"436a1bec",143,"deputShip 1/14, kazimierzShip 0/8, kjeragShip 1/25, miraShip 0/3, preciShip 0/5, sargonShip 0/8, soloShip 1/15, steadShip 1/37, suntShip 1/10, swiftShip 1/42, yanShip 0/6",16,31,15,109] + "ai_0": [1,16,14,0,0,6,8,"436a1bec",140,"deputShip 1/14, kazimierzShip 0/8, kjeragShip 1/22, miraShip 0/3, preciShip 0/5, sargonShip 0/8, soloShip 1/15, steadShip 1/37, suntShip 1/10, swiftShip 1/42, yanShip 0/6",18,31,13,109] }, { "round": 13, - "ai_0": [1,10,12,0,0,6,8,"3be0fd4e",169,"deputShip 1/16, kazimierzShip 0/8, kjeragShip 1/32, miraShip 0/3, preciShip 0/5, sargonShip 0/8, skillfulShip 1/7, soloShip 1/17, steadShip 1/41, suntShip 1/12, swiftShip 1/44, yanShip 0/6",108,35,6,119] + "ai_0": [1,11,12,0,0,6,8,"f559af38",166,"deputShip 1/16, kazimierzShip 0/8, kjeragShip 1/29, miraShip 0/3, preciShip 0/5, sargonShip 0/8, skillfulShip 1/7, soloShip 1/17, steadShip 1/41, suntShip 1/12, swiftShip 1/44, yanShip 0/6",109,35,5,119] } ], "players": { @@ -150,14 +150,14 @@ "victory": true, "roundsPassed": 14, "eliminatedRound": null, - "lp": 2, + "lp": 11, "bandId": "band_ermengard", "title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"}, "trophies": 0, "reward": 400, - "stats": {"activatedLayers":176,"bossDamage":390000,"dmgDealt":2263237,"gold":130,"itemsEquipped":17,"kills":372,"leaks":22,"lpLost":17,"merges":3,"perfectRounds":10,"refreshes":9}, + "stats": {"activatedLayers":173,"bossDamage":390000,"dmgDealt":2233950,"gold":130,"itemsEquipped":17,"kills":373,"leaks":19,"lpLost":16,"merges":3,"perfectRounds":10,"refreshes":9}, "lineup": ["4_21_a@12,7","3_16_a@12,8[4_10_e_a+2_04_e_a]","6_05_a@11,5","4_13_a@11,8[3_06_e_a]","3_20_b@10,3[5_02_e_b+4_08_e_a]","1_19_b@10,8[4_11_e_a]","1_02_a@9,4[5_02_e_b+3_08_e_b]","6_03_a@9,5"], - "bonds": ["deputShip 1/18","kazimierzShip 0/8","kjeragShip 1/39","miraShip 0/3","preciShip 0/5","sargonShip 0/8","skillfulShip 1/14","soloShip 0/17","steadShip 2/45","suntShip 1/14","swiftShip 1/46","yanShip 0/6"] + "bonds": ["deputShip 1/18","kazimierzShip 0/8","kjeragShip 1/36","miraShip 0/3","preciShip 0/5","sargonShip 0/8","skillfulShip 1/14","soloShip 0/17","steadShip 2/45","suntShip 1/14","swiftShip 1/46","yanShip 0/6"] } } }, @@ -246,7 +246,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":215042,"virtualMs":107800}, + "end": {"victory":false,"roundsPassed":13,"hiddenReached":false,"hiddenCleared":false,"reason":"defeat","teamLp":0,"bossPoolLeft":212054,"virtualMs":107800}, "rng": {"setup":25,"shop":215,"waves":0,"draft":42,"bots":8070,"meta":1}, "errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0}, "rounds": [ @@ -265,7 +265,7 @@ }, { "round": 8, - "ai_0": [1,27,11,0,0,4,8,"82c473bd",58,"deputShip 2/10, kazimierzShip 0/8, kjeragShip 0/2, sargonShip 1/21, skillfulShip 1/8, soloShip 1/11, steadShip 0/9, suntShip 1/8, swiftShip 0/11",19,19,0,58] + "ai_0": [1,27,11,0,0,4,8,"66ac5818",58,"deputShip 2/10, kazimierzShip 0/8, kjeragShip 0/2, sargonShip 1/21, skillfulShip 1/8, soloShip 1/11, steadShip 0/9, suntShip 1/8, swiftShip 0/11",19,19,0,58] }, { "round": 9, @@ -281,11 +281,11 @@ }, { "round": 12, - "ai_0": [1,27,13,0,0,6,8,"3445b39c",168,"deputShip 2/22, kazimierzShip 0/16, kjeragShip 0/10, sargonShip 1/39, skillfulShip 1/24, soloShip 0/13, steadShip 0/11, suntShip 1/20, swiftShip 1/63",31,31,0,108] + "ai_0": [1,19,13,0,0,6,8,"3445b39c",168,"deputShip 2/22, kazimierzShip 0/16, kjeragShip 0/10, sargonShip 1/39, skillfulShip 1/24, soloShip 0/13, steadShip 0/11, suntShip 1/20, swiftShip 1/63",23,31,8,108] }, { "round": 13, - "ai_0": [1,25,12,0,2,6,8,"caf07ef9",229,"deputShip 1/24, kazimierzShip 1/26, kjeragShip 0/10, sargonShip 1/41, skillfulShip 1/26, soloShip 1/15, steadShip 0/11, suntShip 1/22, swiftShip 1/75",113,35,2,120] + "ai_0": [1,19,12,0,2,6,8,"bb4537a0",229,"deputShip 1/24, kazimierzShip 1/26, kjeragShip 0/10, sargonShip 1/41, skillfulShip 1/26, soloShip 1/15, steadShip 0/11, suntShip 1/22, swiftShip 1/75",115,35,0,120] } ], "players": { @@ -299,7 +299,7 @@ "title": {"id":"comment_2","name":"不朽盟约","picId":"comment_icon_2","text":"激活的盟约层数总和最高"}, "trophies": 0, "reward": 340, - "stats": {"activatedLayers":212,"bossDamage":564958,"dmgDealt":2432521,"gold":135,"itemsEquipped":16,"kills":415,"leaks":2,"lpLost":2,"merges":4,"perfectRounds":12,"refreshes":17}, + "stats": {"activatedLayers":212,"bossDamage":567946,"dmgDealt":2349477,"gold":135,"itemsEquipped":16,"kills":408,"leaks":8,"lpLost":8,"merges":4,"perfectRounds":12,"refreshes":17}, "lineup": ["3_13_a@12,5[1_01_e_b+3_08_e_a]","3_20_a@11,8[5_02_e_a]","4_13_a@10,3","6_19_a@10,5[1_02_e_a+3_11_e_a]","6_17_a@10,8[2_01_e_a+5_01_e_a]","2_08_a@9,3[4_02_e_a+3_07_e_b]","1_19_b@9,4","1_12_b@9,5[4_10_e_a]"], "bonds": ["deputShip 0/24","kazimierzShip 1/26","kjeragShip 1/15","sargonShip 1/41","skillfulShip 1/31","soloShip 0/15","steadShip 0/11","suntShip 1/22","swiftShip 1/77"] } @@ -384,8 +384,8 @@ "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":2871317,"virtualMs":107800}, - "rng": {"setup":25,"shop":215,"waves":0,"draft":42,"bots":8070,"meta":1}, + "end": {"victory":false,"roundsPassed":12,"hiddenReached":false,"hiddenCleared":false,"reason":"eliminated","teamLp":null,"bossPoolLeft":null,"virtualMs":101900}, + "rng": {"setup":25,"shop":184,"waves":0,"draft":42,"bots":7846,"meta":1}, "errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0}, "rounds": [ {"round":1,"ai_0":[1,27,4,0,0,1,2,"cc1bac8f",0,"sargonShip 0/2, soloShip 1/0",5,5,0,4]}, @@ -403,43 +403,43 @@ }, { "round": 8, - "ai_0": [1,27,11,0,0,4,8,"48fc92cc",58,"deputShip 2/10, kazimierzShip 0/8, kjeragShip 0/2, sargonShip 1/21, skillfulShip 1/8, soloShip 1/11, steadShip 0/9, suntShip 1/8, swiftShip 0/11",19,19,0,58] + "ai_0": [1,18,11,0,0,4,8,"48fc92cc",58,"deputShip 2/10, kazimierzShip 0/8, kjeragShip 0/2, sargonShip 1/21, skillfulShip 1/8, soloShip 1/11, steadShip 0/9, suntShip 1/8, swiftShip 0/11",10,19,9,58] }, { "round": 9, - "ai_0": [1,27,12,0,0,4,8,"4fb70cbc",81,"deputShip 1/12, kazimierzShip 0/8, kjeragShip 0/2, sargonShip 1/25, skillfulShip 1/10, soloShip 0/11, steadShip 1/11, suntShip 1/10, swiftShip 1/13",34,34,0,71] + "ai_0": [1,18,12,0,0,4,8,"4fb70cbc",81,"deputShip 1/12, kazimierzShip 0/8, kjeragShip 0/2, sargonShip 1/25, skillfulShip 1/10, soloShip 0/11, steadShip 1/11, suntShip 1/10, swiftShip 1/13",34,34,0,71] }, { "round": 10, - "ai_0": [1,27,12,0,0,5,8,"b380bd34",99,"deputShip 1/14, kazimierzShip 0/8, kjeragShip 0/2, sargonShip 1/29, skillfulShip 1/14, soloShip 1/13, steadShip 0/11, suntShip 1/12, swiftShip 1/17",24,24,0,84] + "ai_0": [1,18,12,0,0,5,8,"b380bd34",99,"deputShip 1/14, kazimierzShip 0/8, kjeragShip 0/2, sargonShip 1/29, skillfulShip 1/14, soloShip 1/13, steadShip 0/11, suntShip 1/12, swiftShip 1/17",24,24,0,84] }, { "round": 11, - "ai_0": [1,27,12,0,1,5,8,"b74ff3d8",133,"deputShip 2/18, kazimierzShip 0/16, kjeragShip 0/10, sargonShip 1/35, skillfulShip 1/20, soloShip 0/13, steadShip 0/11, suntShip 1/16, swiftShip 1/44",34,34,0,96] + "ai_0": [1,18,12,0,1,5,8,"b74ff3d8",133,"deputShip 2/18, kazimierzShip 0/16, kjeragShip 0/10, sargonShip 1/35, skillfulShip 1/20, soloShip 0/13, steadShip 0/11, suntShip 1/16, swiftShip 1/44",34,34,0,96] }, { "round": 12, - "ai_0": [1,17,13,0,0,6,8,"b64e6caf",168,"deputShip 2/22, kazimierzShip 0/16, kjeragShip 0/10, sargonShip 1/39, skillfulShip 1/24, soloShip 0/13, steadShip 0/11, suntShip 1/20, swiftShip 1/63",12,31,19,108] + "ai_0": [1,8,13,0,0,6,8,"b64e6caf",176,"deputShip 2/22, kazimierzShip 0/16, kjeragShip 0/10, sargonShip 1/39, skillfulShip 1/24, soloShip 0/13, steadShip 0/11, suntShip 1/20, swiftShip 1/71",13,31,18,108] }, { "round": 13, - "ai_0": [1,9,12,0,2,6,8,"4640459d",229,"deputShip 1/24, kazimierzShip 1/26, kjeragShip 0/10, sargonShip 1/41, skillfulShip 1/26, soloShip 1/15, steadShip 0/11, suntShip 1/22, swiftShip 1/75",107,35,8,120] + "ai_0": [0,0,12,0,0,6,0,"811c9dc5",0,"deputShip 0/24, kazimierzShip 0/26, kjeragShip 0/10, sargonShip 0/41, skillfulShip 0/26, soloShip 0/15, steadShip 0/11, suntShip 0/22, swiftShip 0/83",107,35,8,120] } ], "players": { "ai_0": { - "alive": true, + "alive": false, "victory": false, - "roundsPassed": 13, - "eliminatedRound": null, + "roundsPassed": 12, + "eliminatedRound": 13, "lp": 0, "bandId": "band_ermengard", - "title": {"id":"comment_2","name":"不朽盟约","picId":"comment_icon_2","text":"激活的盟约层数总和最高"}, + "title": {"id":"comment_4","name":"精英云集","picId":"comment_icon_4","text":"晋升精锐次数最多"}, "trophies": 0, - "reward": 340, - "stats": {"activatedLayers":212,"bossDamage":128683,"dmgDealt":2858357,"gold":135,"itemsEquipped":16,"kills":379,"leaks":27,"lpLost":18,"merges":4,"perfectRounds":11,"refreshes":17}, - "lineup": ["3_20_a@12,5[5_02_e_a]","4_13_a@11,8","3_13_a@10,3[1_01_e_b+3_08_e_a]","2_08_a@10,5[4_02_e_a+3_07_e_b]","6_17_a@10,8","1_12_b@9,4[4_10_e_a]","6_19_a@9,5[1_02_e_a+3_11_e_a]","1_19_b@9,9[2_01_e_a+5_01_e_a]"], - "bonds": ["deputShip 0/24","kazimierzShip 1/26","kjeragShip 1/15","sargonShip 1/41","skillfulShip 1/31","soloShip 0/15","steadShip 0/11","suntShip 1/22","swiftShip 1/77"] + "reward": 298, + "stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":2572124,"gold":120,"itemsEquipped":14,"kills":364,"leaks":35,"lpLost":27,"merges":3,"perfectRounds":10,"refreshes":14}, + "lineup": [], + "bonds": ["deputShip 0/24","kazimierzShip 0/26","kjeragShip 0/10","sargonShip 0/41","skillfulShip 0/26","soloShip 0/15","steadShip 0/11","suntShip 0/22","swiftShip 0/83"] } } }, @@ -958,21 +958,21 @@ }, { "round": 11, - "ai_0": [1,26,12,0,2,5,8,"9d2a55eb",169,"deputShip 2/33, kjeragShip 1/26, preciShip 2/75, sargonShip 0/11, steadShip 0/8, swiftShip 1/35, victoriaShip 0/21",28,28,0,98], + "ai_0": [1,26,12,0,2,5,8,"9d2a55eb",166,"deputShip 2/33, kjeragShip 1/23, preciShip 2/75, sargonShip 0/11, steadShip 0/8, swiftShip 1/35, victoriaShip 0/21",28,28,0,98], "ai_1": [1,45,12,0,0,5,8,"65f29644",72,"deputShip 0/2, emptyShip 1/0, preciShip 1/6, sargonShip 0/2, siracusaShip 1/61, steadShip 0/31, visiShip 1/5",28,28,0,97], "ai_2": [1,28,12,0,0,5,8,"81bc5ae1",140,"deputShip 1/18, kjeragShip 0/5, preciShip 2/89, sargonShip 1/33, yanShip 0/6",28,28,0,91], "ai_3": [1,31,16,2,0,5,7,"566cbb6d",147,"deputShip 0/10, emptyShip 0/6, preciShip 1/93, siracusaShip 0/6, swiftShip 0/17, victoriaShip 1/10, visiShip 1/44, yanShip 0/1",28,28,0,104] }, { "round": 12, - "ai_0": [1,26,14,0,0,6,8,"d3120fcb",207,"deputShip 2/37, kjeragShip 1/30, preciShip 2/91, sargonShip 0/11, steadShip 0/8, swiftShip 1/49, victoriaShip 0/21",46,46,0,110], + "ai_0": [1,26,14,0,0,6,8,"d3120fcb",206,"deputShip 2/37, kjeragShip 1/29, preciShip 2/91, sargonShip 0/11, steadShip 0/8, swiftShip 1/49, victoriaShip 0/21",46,46,0,110], "ai_1": [1,45,12,0,2,6,8,"f6b8e9a9",95,"deputShip 1/4, emptyShip 1/2, preciShip 1/12, sargonShip 0/2, siracusaShip 1/65, steadShip 0/31, visiShip 1/12",46,46,0,109], "ai_2": [1,28,12,0,0,6,8,"f8339ca2",177,"deputShip 2/22, kjeragShip 0/5, preciShip 2/108, sargonShip 1/47, yanShip 0/6",46,46,0,103], "ai_3": [1,31,16,0,0,6,7,"6c3799c7",188,"deputShip 0/10, emptyShip 1/6, preciShip 1/104, siracusaShip 0/6, swiftShip 1/22, victoriaShip 0/14, visiShip 1/56, yanShip 0/1",46,46,0,118] }, { "round": 13, - "ai_0": [1,26,12,0,0,6,8,"57172cf7",240,"deputShip 1/39, emptyShip 1/2, kjeragShip 1/33, preciShip 2/105, sargonShip 0/11, steadShip 0/8, swiftShip 1/61, victoriaShip 0/21",32,32,0,123], + "ai_0": [1,26,12,0,0,6,8,"57172cf7",239,"deputShip 1/39, emptyShip 1/2, kjeragShip 1/32, preciShip 2/105, sargonShip 0/11, steadShip 0/8, swiftShip 1/61, victoriaShip 0/21",32,32,0,123], "ai_1": [1,45,14,0,0,6,8,"ced5ebe3",146,"deputShip 0/4, emptyShip 1/2, preciShip 2/16, sargonShip 0/2, siracusaShip 1/97, steadShip 1/31, visiShip 0/12",32,32,0,124], "ai_2": [1,28,12,0,0,6,8,"d0aeb38e",201,"deputShip 1/24, kjeragShip 0/5, preciShip 2/124, sargonShip 1/53, yanShip 0/6",32,32,0,117], "ai_3": [1,31,14,0,0,6,7,"9015cc77",220,"deputShip 0/10, emptyShip 0/6, preciShip 2/119, siracusaShip 0/6, swiftShip 1/27, victoriaShip 1/14, visiShip 1/60, yanShip 0/1",32,32,0,132] @@ -989,9 +989,9 @@ "title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"}, "trophies": 3, "reward": 250, - "stats": {"activatedLayers":272,"bossDamage":509540,"dmgDealt":1935644,"gold":135,"itemsEquipped":22,"kills":291,"leaks":0,"lpLost":0,"merges":5,"perfectRounds":13,"refreshes":23}, + "stats": {"activatedLayers":271,"bossDamage":508388,"dmgDealt":1934491,"gold":135,"itemsEquipped":22,"kills":291,"leaks":0,"lpLost":0,"merges":5,"perfectRounds":13,"refreshes":23}, "lineup": ["4_25_a@11,3","1_06_b@11,6","6_12_a@11,7[2_01_e_a]","3_20_a@10,3[1_05_e_b]","5_14_a@10,4[3_08_e_a+5_02_e_a]","4_22_b@9,4[4_11_e_a+3_02_e_b]","4_14_b@9,8[2_01_e_b+3_01_e_a]","3_11_b@9,9[3_07_e_a+4_03_e_b]"], - "bonds": ["deputShip 1/41","emptyShip 1/4","kjeragShip 1/35","preciShip 2/119","sargonShip 0/11","steadShip 0/8","swiftShip 1/73","victoriaShip 0/21"] + "bonds": ["deputShip 1/41","emptyShip 1/4","kjeragShip 1/34","preciShip 2/119","sargonShip 0/11","steadShip 0/8","swiftShip 1/73","victoriaShip 0/21"] }, "ai_1": { "alive": true, @@ -1003,7 +1003,7 @@ "title": {"id":"comment_3","name":"坚若磐石","picId":"comment_icon_3","text":"目标生命值损失最少"}, "trophies": 3, "reward": 250, - "stats": {"activatedLayers":154,"bossDamage":247821,"dmgDealt":1660185,"gold":135,"itemsEquipped":16,"kills":283,"leaks":0,"lpLost":0,"merges":5,"perfectRounds":13,"refreshes":17}, + "stats": {"activatedLayers":154,"bossDamage":248974,"dmgDealt":1661338,"gold":135,"itemsEquipped":16,"kills":283,"leaks":0,"lpLost":0,"merges":5,"perfectRounds":13,"refreshes":17}, "lineup": ["6_12_a@11,7[2_04_e_b+4_03_e_a]","5_10_a@11,8[1_02_e_a]","6_18_a@10,3","4_10_b@10,4[4_08_e_a+4_03_e_b]","3_05_b@10,8[4_06_e_a+4_05_e_a]","1_10_b@9,4","6_05_a@9,8","6_05_a@9,9"], "bonds": ["deputShip 0/4","emptyShip 1/2","preciShip 1/16","sargonShip 0/2","siracusaShip 1/105","steadShip 1/31","visiShip 0/12"] }, @@ -1047,8 +1047,8 @@ "combat": "client", "boost": null, "setup": {"stageId":"act2autochess_m01","bossId":"boss_1","hiddenBossId":"boss_8","factions":["DOT","INVISIBLE","REFLECTION"]}, - "end": {"victory":false,"roundsPassed":13,"hiddenReached":false,"hiddenCleared":false,"reason":"defeat","teamLp":0,"bossPoolLeft":4821366,"virtualMs":138350}, - "rng": {"setup":25,"shop":838,"waves":0,"draft":57,"bots":23018,"meta":61}, + "end": {"victory":false,"roundsPassed":13,"hiddenReached":false,"hiddenCleared":false,"reason":"defeat","teamLp":0,"bossPoolLeft":3417504,"virtualMs":139500}, + "rng": {"setup":25,"shop":790,"waves":0,"draft":57,"bots":22692,"meta":66}, "errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0}, "rounds": [ { @@ -1103,43 +1103,43 @@ { "round": 8, "ai_0": [1,28,11,0,0,4,8,"c8fd6622",73,"arcaneShip 1/4, kazimierzShip 0/8, kjeragShip 1/12, preciShip 2/24, skillfulShip 0/5, suntShip 1/0, swiftShip 1/33",7,9,2,63], - "ai_1": [1,19,11,0,0,4,8,"9a145335",54,"arcaneShip 0/2, deputShip 1/2, kazimierzShip 0/7, kjeragShip 1/11, preciShip 0/2, sargonShip 1/26, siracusaShip 0/6, skillfulShip 1/7, soloShip 1/2, steadShip 1/6, swiftShip 0/13",2,9,7,60], + "ai_1": [1,20,11,0,0,4,8,"9a145335",54,"arcaneShip 0/2, deputShip 1/2, kazimierzShip 0/7, kjeragShip 1/11, preciShip 0/2, sargonShip 1/26, siracusaShip 0/6, skillfulShip 1/7, soloShip 1/2, steadShip 1/6, swiftShip 0/13",3,9,6,60], "ai_2": [1,20,13,0,0,4,8,"c394bdcb",119,"arcaneShip 1/8, deputShip 1/27, egirShip 0/6, kazimierzShip 0/2, kjeragShip 0/14, lateranoShip 0/2, raidShip 0/6, soloShip 1/12, steadShip 1/34, suntShip 1/2, swiftShip 0/4, victoriaShip 1/36, yanShip 0/10",8,9,1,66], "ai_3": [0,0,11,0,0,4,0,"811c9dc5",0,"arcaneShip 0/2, kjeragShip 0/5, preciShip 0/2, sargonShip 0/4, siracusaShip 0/7, skillfulShip 0/5, soloShip 0/12",0,9,9,59] }, { "round": 9, "ai_0": [1,28,12,0,2,4,8,"2ff9d045",108,"arcaneShip 1/8, kazimierzShip 0/8, kjeragShip 1/19, preciShip 2/33, skillfulShip 1/10, suntShip 1/0, swiftShip 1/38",9,19,10,74], - "ai_1": [1,19,12,0,0,4,8,"08726f68",81,"arcaneShip 0/2, deputShip 2/6, kazimierzShip 0/7, kjeragShip 1/15, preciShip 0/2, sargonShip 1/39, siracusaShip 0/6, skillfulShip 1/11, soloShip 0/2, steadShip 1/10, swiftShip 0/13",10,19,9,72], - "ai_2": [1,20,12,0,4,4,8,"5c0ea571",123,"arcaneShip 1/12, deputShip 0/27, egirShip 0/8, indomShip 1/12, kazimierzShip 0/2, kjeragShip 0/20, lateranoShip 0/4, raidShip 0/6, soloShip 1/12, steadShip 1/45, suntShip 1/2, swiftShip 0/4, victoriaShip 1/40, yanShip 0/10",19,19,0,78], + "ai_1": [1,20,12,0,3,4,8,"2b472f66",90,"arcaneShip 0/2, deputShip 2/6, kazimierzShip 0/7, kjeragShip 1/15, preciShip 0/2, sargonShip 1/48, siracusaShip 0/6, skillfulShip 1/11, soloShip 0/2, steadShip 1/10, swiftShip 0/13",16,19,3,72], + "ai_2": [1,20,12,0,1,4,8,"5c0ea571",123,"arcaneShip 1/12, deputShip 0/27, egirShip 0/8, indomShip 1/12, kazimierzShip 0/2, kjeragShip 0/20, lateranoShip 0/4, raidShip 0/6, soloShip 1/12, steadShip 1/45, suntShip 1/2, swiftShip 0/4, victoriaShip 1/40, yanShip 0/10",19,19,0,78], "ai_3": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/2, kjeragShip 0/5, preciShip 0/2, sargonShip 0/4, siracusaShip 0/7, skillfulShip 0/5, soloShip 0/12",null,null,null,59] }, { "round": 10, "ai_0": [1,28,14,0,0,5,8,"f12b88a9",121,"arcaneShip 1/8, kazimierzShip 0/8, kjeragShip 1/22, preciShip 2/38, skillfulShip 1/10, suntShip 1/0, swiftShip 1/43",25,25,0,87], - "ai_1": [1,19,12,0,0,5,8,"1577d46b",151,"arcaneShip 0/2, deputShip 2/10, kazimierzShip 0/15, kjeragShip 1/47, preciShip 0/2, sargonShip 1/61, siracusaShip 0/6, skillfulShip 1/15, soloShip 0/2, steadShip 1/18, swiftShip 0/21",24,25,1,84], - "ai_2": [1,20,16,0,2,5,8,"c36cb210",149,"arcaneShip 1/14, deputShip 0/27, egirShip 0/8, indomShip 0/12, kazimierzShip 0/2, kjeragShip 1/24, lateranoShip 0/6, raidShip 0/6, soloShip 1/14, steadShip 2/53, suntShip 1/2, swiftShip 0/4, victoriaShip 1/42, visiShip 0/2, yanShip 0/10",25,25,0,94], + "ai_1": [1,20,15,0,0,5,8,"0230fafb",152,"arcaneShip 0/2, deputShip 2/10, kazimierzShip 0/15, kjeragShip 1/39, preciShip 0/2, sargonShip 1/70, siracusaShip 0/6, skillfulShip 1/15, soloShip 0/2, steadShip 1/18, swiftShip 0/21",23,25,2,85], + "ai_2": [1,20,13,0,2,5,8,"4592c36e",154,"arcaneShip 1/16, deputShip 0/29, egirShip 0/8, indomShip 1/29, kazimierzShip 0/2, kjeragShip 0/20, lateranoShip 0/6, raidShip 0/6, skillfulShip 0/2, soloShip 1/12, steadShip 1/49, suntShip 1/2, swiftShip 0/4, victoriaShip 1/46, yanShip 0/10",25,25,0,90], "ai_3": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/2, kjeragShip 0/5, preciShip 0/2, sargonShip 0/4, siracusaShip 0/7, skillfulShip 0/5, soloShip 0/12",null,null,null,59] }, { "round": 11, - "ai_0": [1,21,12,0,0,5,8,"68c202f4",127,"arcaneShip 2/14, kazimierzShip 0/8, kjeragShip 1/22, preciShip 2/43, skillfulShip 0/10, suntShip 1/0, swiftShip 1/48",17,24,7,100], - "ai_1": [1,15,12,0,2,5,8,"a9511e49",208,"arcaneShip 0/2, deputShip 2/14, kazimierzShip 0/15, kjeragShip 1/59, preciShip 0/2, sargonShip 1/83, siracusaShip 0/6, skillfulShip 1/19, soloShip 0/2, steadShip 0/18, swiftShip 1/33",20,24,4,95], - "ai_2": [1,14,14,0,0,5,8,"e34dbdff",166,"arcaneShip 1/16, deputShip 0/29, egirShip 0/8, indomShip 0/12, kazimierzShip 0/2, kjeragShip 1/28, lateranoShip 0/8, raidShip 0/6, soloShip 1/14, steadShip 2/58, suntShip 1/2, swiftShip 0/4, victoriaShip 1/48, visiShip 0/4, yanShip 0/10",18,24,6,106], + "ai_0": [1,25,12,0,0,5,8,"57c3bbc6",141,"arcaneShip 1/8, kazimierzShip 0/8, kjeragShip 1/32, preciShip 2/43, skillfulShip 1/10, suntShip 1/0, swiftShip 1/48",14,24,10,99], + "ai_1": [1,18,12,0,2,5,8,"ebc4eef2",209,"arcaneShip 0/2, deputShip 2/14, kazimierzShip 0/15, kjeragShip 1/51, preciShip 0/2, sargonShip 1/92, siracusaShip 0/6, skillfulShip 1/19, soloShip 0/2, steadShip 0/18, swiftShip 1/33",20,24,4,98], + "ai_2": [1,20,14,0,0,5,8,"8777b0c2",193,"arcaneShip 1/24, deputShip 0/29, egirShip 0/8, indomShip 1/44, kazimierzShip 0/2, kjeragShip 0/22, lateranoShip 0/6, raidShip 0/6, skillfulShip 1/4, soloShip 1/12, steadShip 1/55, suntShip 1/2, swiftShip 0/4, victoriaShip 1/52, yanShip 0/12",24,24,0,103], "ai_3": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/2, kjeragShip 0/5, preciShip 0/2, sargonShip 0/4, siracusaShip 0/7, skillfulShip 0/5, soloShip 0/12",null,null,null,59] }, { "round": 12, - "ai_0": [1,11,12,0,0,6,8,"c358ec16",138,"arcaneShip 2/14, kazimierzShip 0/8, kjeragShip 1/23, preciShip 2/48, skillfulShip 0/10, suntShip 1/0, swiftShip 1/53",6,47,41,111], - "ai_1": [1,5,14,0,0,6,8,"ed9f802c",273,"arcaneShip 0/2, deputShip 1/16, kazimierzShip 0/15, kjeragShip 1/74, preciShip 0/2, sargonShip 1/94, siracusaShip 0/6, skillfulShip 1/26, soloShip 0/2, steadShip 1/20, swiftShip 1/43",25,47,22,109], - "ai_2": [1,4,12,0,0,6,8,"d6c6d034",183,"arcaneShip 1/18, deputShip 0/31, egirShip 0/8, indomShip 0/12, kazimierzShip 0/2, kjeragShip 1/30, lateranoShip 0/10, raidShip 0/6, soloShip 1/16, steadShip 2/65, suntShip 1/2, swiftShip 0/4, victoriaShip 1/52, visiShip 0/6, yanShip 0/10",15,47,32,117], + "ai_0": [1,15,12,0,0,6,8,"db751bba",157,"arcaneShip 1/8, kazimierzShip 0/8, kjeragShip 1/38, preciShip 2/48, skillfulShip 1/10, suntShip 1/0, swiftShip 1/53",12,47,35,110], + "ai_1": [1,8,14,0,0,6,8,"2246afd5",264,"arcaneShip 0/4, deputShip 1/16, kazimierzShip 0/15, kjeragShip 1/61, preciShip 0/4, sargonShip 1/103, siracusaShip 0/6, skillfulShip 1/21, soloShip 0/2, steadShip 1/20, swiftShip 1/43",11,47,36,113], + "ai_2": [1,10,12,0,0,6,8,"fc2ff295",221,"arcaneShip 1/24, deputShip 0/31, egirShip 0/10, indomShip 1/56, kazimierzShip 0/2, kjeragShip 0/22, lateranoShip 0/6, raidShip 0/6, skillfulShip 1/6, soloShip 1/14, steadShip 1/61, suntShip 1/2, swiftShip 0/4, victoriaShip 1/58, yanShip 0/12",16,47,31,115], "ai_3": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/2, kjeragShip 0/5, preciShip 0/2, sargonShip 0/4, siracusaShip 0/7, skillfulShip 0/5, soloShip 0/12",null,null,null,59] }, { "round": 13, - "ai_0": [1,1,12,0,0,6,8,"0c518f2d",180,"arcaneShip 2/26, kazimierzShip 0/8, kjeragShip 1/27, preciShip 2/53, skillfulShip 1/16, suntShip 1/0, swiftShip 1/58",5,39,34,122], - "ai_1": [1,2,12,0,0,6,8,"74d1d862",328,"arcaneShip 0/2, deputShip 2/20, kazimierzShip 0/17, kjeragShip 1/95, preciShip 0/2, sargonShip 1/98, siracusaShip 0/6, skillfulShip 1/30, soloShip 0/2, steadShip 1/24, suntShip 1/4, swiftShip 1/57",36,39,3,121], - "ai_2": [0,0,12,0,0,6,0,"811c9dc5",0,"arcaneShip 0/20, deputShip 0/31, egirShip 0/8, indomShip 0/12, kazimierzShip 0/2, kjeragShip 0/36, lateranoShip 0/12, raidShip 0/6, soloShip 0/16, steadShip 0/75, suntShip 0/2, swiftShip 0/4, victoriaShip 0/56, visiShip 0/8, yanShip 0/10",19,39,20,129], + "ai_0": [1,5,12,0,0,6,8,"cd4ad4bf",218,"arcaneShip 1/8, kazimierzShip 0/8, kjeragShip 1/89, preciShip 2/53, skillfulShip 1/10, suntShip 1/0, swiftShip 1/58",28,39,11,120], + "ai_1": [0,0,12,0,0,6,0,"811c9dc5",0,"arcaneShip 0/4, deputShip 0/20, kazimierzShip 0/15, kjeragShip 0/82, preciShip 0/4, sargonShip 0/107, siracusaShip 0/6, skillfulShip 0/25, soloShip 0/2, steadShip 0/24, suntShip 0/4, swiftShip 0/55",27,39,12,125], + "ai_2": [0,0,12,0,0,6,0,"811c9dc5",0,"arcaneShip 0/34, deputShip 0/31, egirShip 0/10, indomShip 0/56, kazimierzShip 0/2, kjeragShip 0/28, lateranoShip 0/6, raidShip 0/6, skillfulShip 0/8, soloShip 0/14, steadShip 0/67, suntShip 0/2, swiftShip 0/4, victoriaShip 0/64, yanShip 0/14",23,39,16,127], "ai_3": [0,0,0,0,0,4,0,"811c9dc5",0,"arcaneShip 0/2, kjeragShip 0/5, preciShip 0/2, sargonShip 0/4, siracusaShip 0/7, skillfulShip 0/5, soloShip 0/12",null,null,null,59] } ], @@ -1151,26 +1151,26 @@ "eliminatedRound": null, "lp": 0, "bandId": "band_sarkazb", - "title": {"id":"comment_4","name":"精英云集","picId":"comment_icon_4","text":"晋升精锐次数最多"}, - "trophies": 3, - "reward": 340, - "stats": {"activatedLayers":202,"bossDamage":433732,"dmgDealt":4961668,"gold":135,"itemsEquipped":13,"kills":156,"leaks":113,"lpLost":44,"merges":4,"perfectRounds":6,"refreshes":25}, - "lineup": ["6_16_a@12,4","1_17_b@12,8[5_07_e_a+3_06_e_b]","4_13_a@11,4","3_11_a@11,8[3_04_e_b+1_02_e_b]","6_05_a@10,4","4_10_a@10,5","4_22_a@10,7[4_02_e_b+4_04_e_a]","1_19_b@10,8[1_05_e_a+2_04_e_a]"], - "bonds": ["arcaneShip 2/40","kazimierzShip 0/8","kjeragShip 1/27","preciShip 2/53","skillfulShip 1/24","suntShip 1/0","swiftShip 1/58"] - }, - "ai_1": { - "alive": true, - "victory": false, - "roundsPassed": 13, - "eliminatedRound": null, - "lp": 0, - "bandId": "band_kirara", "title": {"id":"comment_2","name":"不朽盟约","picId":"comment_icon_2","text":"激活的盟约层数总和最高"}, "trophies": 3, "reward": 340, - "stats": {"activatedLayers":361,"bossDamage":1944902,"dmgDealt":9217989,"gold":133,"itemsEquipped":15,"kills":223,"leaks":46,"lpLost":24,"merges":2,"perfectRounds":7,"refreshes":28}, - "lineup": ["3_13_a@12,8[6_02_e_a+3_08_e_b]","4_21_a@11,4","4_14_a@11,8","3_20_a@10,4[5_02_e_a+1_02_e_a]","2_08_b@10,7[3_05_e_b+4_04_e_a]","6_19_a@10,8[3_07_e_a+4_03_e_a]","1_02_b@9,4[3_03_e_a]","4_24_a@9,9"], - "bonds": ["arcaneShip 0/2","deputShip 2/24","kazimierzShip 0/17","kjeragShip 1/99","preciShip 0/2","sargonShip 1/102","siracusaShip 0/6","skillfulShip 1/34","soloShip 0/2","steadShip 1/28","suntShip 1/8","swiftShip 1/66"] + "stats": {"activatedLayers":228,"bossDamage":182496,"dmgDealt":5951691,"gold":132,"itemsEquipped":14,"kills":164,"leaks":87,"lpLost":40,"merges":3,"perfectRounds":6,"refreshes":27}, + "lineup": ["4_21_a@12,4","1_17_b@12,8[4_06_e_a+5_07_e_a]","4_14_a@11,4[4_04_e_a]","3_11_a@11,8[3_04_e_b+1_02_e_a]","4_02_a@10,4","4_22_a@10,7[4_02_e_a+4_10_e_a]","1_19_b@10,8[1_05_e_a+2_04_e_a]","4_13_a@9,8[3_06_e_b+3_04_e_a]"], + "bonds": ["arcaneShip 1/8","kazimierzShip 0/8","kjeragShip 1/89","preciShip 2/58","skillfulShip 1/10","suntShip 1/0","swiftShip 1/63"] + }, + "ai_1": { + "alive": false, + "victory": false, + "roundsPassed": 12, + "eliminatedRound": 13, + "lp": 0, + "bandId": "band_kirara", + "title": {"id":"comment_6","name":"挥金如土","picId":"comment_icon_6","text":"消耗资金最多"}, + "trophies": 3, + "reward": 298, + "stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":6090165,"gold":125,"itemsEquipped":13,"kills":206,"leaks":63,"lpLost":28,"merges":2,"perfectRounds":7,"refreshes":25}, + "lineup": [], + "bonds": ["arcaneShip 0/4","deputShip 0/20","kazimierzShip 0/15","kjeragShip 0/82","preciShip 0/4","sargonShip 0/107","siracusaShip 0/6","skillfulShip 0/25","soloShip 0/2","steadShip 0/24","suntShip 0/4","swiftShip 0/55"] }, "ai_2": { "alive": false, @@ -1179,12 +1179,12 @@ "eliminatedRound": 13, "lp": 0, "bandId": "band_bldsk", - "title": {"id":"comment_5","name":"万事俱备","picId":"comment_icon_5","text":"装备配发数量最多"}, + "title": {"id":"comment_4","name":"精英云集","picId":"comment_icon_4","text":"晋升精锐次数最多"}, "trophies": 3, "reward": 298, - "stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":5615159,"gold":129,"itemsEquipped":21,"kills":195,"leaks":73,"lpLost":34,"merges":4,"perfectRounds":5,"refreshes":18}, + "stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":6858444,"gold":127,"itemsEquipped":22,"kills":210,"leaks":62,"lpLost":28,"merges":3,"perfectRounds":6,"refreshes":14}, "lineup": [], - "bonds": ["arcaneShip 0/20","deputShip 0/31","egirShip 0/8","indomShip 0/12","kazimierzShip 0/2","kjeragShip 0/36","lateranoShip 0/12","raidShip 0/6","soloShip 0/16","steadShip 0/75","suntShip 0/2","swiftShip 0/4","victoriaShip 0/56","visiShip 0/8","yanShip 0/10"] + "bonds": ["arcaneShip 0/34","deputShip 0/31","egirShip 0/10","indomShip 0/56","kazimierzShip 0/2","kjeragShip 0/28","lateranoShip 0/6","raidShip 0/6","skillfulShip 0/8","soloShip 0/14","steadShip 0/67","suntShip 0/2","swiftShip 0/4","victoriaShip 0/64","yanShip 0/14"] }, "ai_3": { "alive": false, @@ -1193,7 +1193,7 @@ "eliminatedRound": 8, "lp": 0, "bandId": "band_cathy", - "title": {"id":"comment_6","name":"挥金如土","picId":"comment_icon_6","text":"消耗资金最多"}, + "title": {"id":"comment_5","name":"万事俱备","picId":"comment_icon_5","text":"装备配发数量最多"}, "trophies": 1, "reward": 149, "stats": {"activatedLayers":0,"bossDamage":0,"dmgDealt":692486,"gold":59,"itemsEquipped":6,"kills":55,"leaks":41,"lpLost":27,"merges":0,"perfectRounds":3,"refreshes":3}, @@ -1212,7 +1212,7 @@ "combat": "server", "boost": null, "setup": {"stageId":"act1autochess_m01","bossId":"boss_1","hiddenBossId":"boss_9","factions":["FLY","DOT","REFLECTION"]}, - "end": {"victory":true,"roundsPassed":14,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":27,"bossPoolLeft":0,"virtualMs":119900}, + "end": {"victory":true,"roundsPassed":14,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":37,"bossPoolLeft":0,"virtualMs":119900}, "rng": {"setup":25,"shop":482,"waves":0,"draft":34,"bots":18094,"meta":81}, "errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0}, "rounds": [ @@ -1254,7 +1254,7 @@ { "round": 8, "ai_0": [1,30,13,0,4,4,8,"dd94b4a8",45,"arcaneShip 0/2, preciShip 1/7, siracusaShip 1/26, soloShip 1/3, steadShip 1/9",24,24,0,69], - "ai_1": [1,28,12,0,0,4,8,"a16d247e",121,"arcaneShip 1/16, deputShip 1/8, kjeragShip 1/29, preciShip 1/35, soloShip 1/2, steadShip 1/19, suntShip 1/8, victoriaShip 1/4",22,23,1,62] + "ai_1": [1,28,12,0,0,4,8,"a16d247e",121,"arcaneShip 1/16, deputShip 1/8, kjeragShip 1/29, preciShip 1/35, soloShip 1/2, steadShip 1/19, suntShip 1/8, victoriaShip 1/4",23,23,0,62] }, { "round": 9, @@ -1274,12 +1274,12 @@ { "round": 12, "ai_0": [1,20,12,0,0,6,8,"6c0894ab",123,"arcaneShip 1/19, indomShip 0/8, preciShip 1/29, siracusaShip 1/67, soloShip 1/3, steadShip 0/9, suntShip 1/0, swiftShip 1/5, victoriaShip 0/8, visiShip 0/8",29,46,17,125], - "ai_1": [1,18,12,0,0,6,8,"eb25e112",207,"arcaneShip 1/34, deputShip 1/16, indomShip 0/8, kjeragShip 1/49, preciShip 1/53, soloShip 1/10, steadShip 2/29, suntShip 2/16, victoriaShip 0/12, visiShip 0/8",36,46,10,109] + "ai_1": [1,18,12,0,0,6,8,"3c8a5177",207,"arcaneShip 1/34, deputShip 1/16, indomShip 0/8, kjeragShip 1/49, preciShip 1/53, soloShip 1/10, steadShip 2/29, suntShip 2/16, victoriaShip 0/12, visiShip 0/8",36,46,10,109] }, { "round": 13, - "ai_0": [1,10,12,0,0,6,8,"542c547b",165,"arcaneShip 2/23, indomShip 0/8, lateranoShip 1/0, maniShip 1/0, preciShip 1/39, raidShip 1/10, siracusaShip 1/75, soloShip 1/3, steadShip 0/9, suntShip 1/0, swiftShip 1/15, victoriaShip 0/8, visiShip 0/8",20,39,19,138], - "ai_1": [1,17,12,0,0,6,8,"20ec6e25",221,"arcaneShip 1/36, deputShip 1/18, indomShip 0/8, kjeragShip 1/51, preciShip 1/55, soloShip 1/12, steadShip 2/31, suntShip 2/18, victoriaShip 0/12, visiShip 0/8",38,39,1,120] + "ai_0": [1,19,12,0,0,6,8,"542c547b",165,"arcaneShip 2/23, indomShip 0/8, lateranoShip 1/0, maniShip 1/0, preciShip 1/39, raidShip 1/10, siracusaShip 1/75, soloShip 1/3, steadShip 0/9, suntShip 1/0, swiftShip 1/15, victoriaShip 0/8, visiShip 0/8",20,39,19,138], + "ai_1": [1,18,12,0,0,6,8,"20ec6e25",221,"arcaneShip 1/36, deputShip 1/18, indomShip 0/8, kjeragShip 1/51, preciShip 1/55, soloShip 1/12, steadShip 2/31, suntShip 2/18, victoriaShip 0/12, visiShip 0/8",39,39,0,120] } ], "players": { @@ -1288,12 +1288,12 @@ "victory": true, "roundsPassed": 14, "eliminatedRound": null, - "lp": 10, + "lp": 19, "bandId": "band_doberm", "title": {"id":"comment_6","name":"挥金如土","picId":"comment_icon_6","text":"消耗资金最多"}, "trophies": 4, "reward": 400, - "stats": {"activatedLayers":195,"bossDamage":340203,"dmgDealt":3212670,"gold":149,"itemsEquipped":22,"kills":254,"leaks":43,"lpLost":20,"merges":3,"perfectRounds":9,"refreshes":25}, + "stats": {"activatedLayers":195,"bossDamage":340203,"dmgDealt":3208513,"gold":149,"itemsEquipped":22,"kills":253,"leaks":43,"lpLost":11,"merges":3,"perfectRounds":9,"refreshes":25}, "lineup": ["5_10_a@11,3[3_11_e_b+4_04_e_b]","6_11_a@11,6","1_01_b@11,7","1_17_a@10,3[1_01_e_a]","4_14_b@10,7[6_09_e_a+3_11_e_a]","4_16_a@10,8","4_02_a@9,8[6_01_e_a+3_03_e_b]","1_08_a@9,9[1_02_e_b+1_02_e_a]"], "bonds": ["arcaneShip 1/23","indomShip 0/8","lateranoShip 1/0","maniShip 1/0","preciShip 1/49","raidShip 1/20","siracusaShip 1/75","soloShip 1/3","steadShip 0/9","suntShip 1/0","swiftShip 1/25","victoriaShip 0/8","visiShip 0/8"] }, @@ -1302,12 +1302,12 @@ "victory": true, "roundsPassed": 14, "eliminatedRound": null, - "lp": 17, + "lp": 18, "bandId": "band_malkie", "title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"}, "trophies": 4, "reward": 400, - "stats": {"activatedLayers":243,"bossDamage":1009797,"dmgDealt":4621226,"gold":130,"itemsEquipped":29,"kills":263,"leaks":12,"lpLost":11,"merges":5,"perfectRounds":10,"refreshes":16}, + "stats": {"activatedLayers":243,"bossDamage":1009797,"dmgDealt":5234069,"gold":130,"itemsEquipped":29,"kills":283,"leaks":10,"lpLost":10,"merges":5,"perfectRounds":12,"refreshes":16}, "lineup": ["1_06_b@12,3[5_07_e_a+4_03_e_b]","1_02_b@12,4[5_02_e_a+4_11_e_b]","1_17_b@11,6[4_03_e_a+1_01_e_b]","3_11_b@11,7[3_01_e_a+3_02_e_a]","3_20_a@10,3[1_05_e_a+1_05_e_b]","1_10_b@10,8[4_02_e_a+6_11_e_a]","5_11_a@9,4[4_08_e_a+1_02_e_a]","5_12_a@9,9[4_10_e_a]"], "bonds": ["arcaneShip 1/40","deputShip 1/20","indomShip 0/8","kjeragShip 1/56","preciShip 1/57","soloShip 1/14","steadShip 2/36","suntShip 2/20","victoriaShip 0/12","visiShip 0/8"] } @@ -1518,8 +1518,8 @@ "combat": "client", "boost": null, "setup": {"stageId":"act1autochess_m01","bossId":"boss_5","hiddenBossId":"boss_10","factions":["DOT","INVISIBLE","REFLECTION"]}, - "end": {"victory":true,"roundsPassed":14,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":31,"bossPoolLeft":0,"virtualMs":116900}, - "rng": {"setup":25,"shop":403,"waves":0,"draft":34,"bots":18116,"meta":10}, + "end": {"victory":true,"roundsPassed":14,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":40,"bossPoolLeft":0,"virtualMs":116900}, + "rng": {"setup":25,"shop":403,"waves":0,"draft":34,"bots":18127,"meta":10}, "errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0}, "rounds": [ { @@ -1569,23 +1569,23 @@ }, { "round": 10, - "h_0": [1,28,12,0,0,5,8,"8437aa19",124,"arcaneShip 0/8, deputShip 1/6, emptyShip 1/6, kazimierzShip 0/4, preciShip 1/35, raidShip 1/26, skillfulShip 0/2, soloShip 1/6, steadShip 1/16, swiftShip 1/29, yanShip 0/1",31,31,0,87], + "h_0": [1,28,12,0,0,5,8,"8437aa19",128,"arcaneShip 0/8, deputShip 1/6, emptyShip 1/6, kazimierzShip 0/4, preciShip 1/35, raidShip 1/28, skillfulShip 0/2, soloShip 1/6, steadShip 1/18, swiftShip 1/29, yanShip 0/1",31,31,0,87], "ai_0": [1,23,12,0,0,5,8,"0147bc65",104,"arcaneShip 2/16, deputShip 0/8, kazimierzShip 0/8, lateranoShip 1/5, preciShip 1/19, raidShip 1/32, sargonShip 0/2, suntShip 1/8, swiftShip 1/24",31,31,0,87] }, { "round": 11, - "h_0": [1,28,12,0,0,5,8,"b5da5048",139,"arcaneShip 0/8, deputShip 0/6, emptyShip 1/6, kazimierzShip 0/4, preciShip 1/42, raidShip 1/31, skillfulShip 0/2, soloShip 1/6, steadShip 1/20, swiftShip 1/34, yanShip 0/1",25,25,0,98], + "h_0": [1,28,12,0,0,5,8,"b5da5048",149,"arcaneShip 0/8, deputShip 0/6, emptyShip 1/6, kazimierzShip 0/4, preciShip 1/42, raidShip 1/36, skillfulShip 0/2, soloShip 1/6, steadShip 1/25, swiftShip 1/34, yanShip 0/1",25,25,0,98], "ai_0": [1,23,12,0,0,5,8,"083c8c02",149,"arcaneShip 1/19, deputShip 0/8, kazimierzShip 0/8, lateranoShip 1/5, preciShip 2/24, raidShip 1/64, sargonShip 0/2, suntShip 1/8, swiftShip 1/29",25,25,0,99] }, { "round": 12, - "h_0": [1,28,12,0,0,5,8,"093d3c03",157,"arcaneShip 0/8, deputShip 0/6, egirShip 1/3, emptyShip 0/6, kazimierzShip 0/4, preciShip 1/49, raidShip 1/36, skillfulShip 0/2, soloShip 1/6, steadShip 1/24, suntShip 1/0, swiftShip 1/39, yanShip 0/1",23,31,8,109], - "ai_0": [1,23,12,0,0,6,8,"7258fcd5",191,"arcaneShip 1/21, deputShip 0/8, kazimierzShip 0/8, lateranoShip 1/11, preciShip 2/37, raidShip 1/80, sargonShip 0/2, suntShip 1/8, swiftShip 1/34",31,31,0,112] + "h_0": [1,28,12,0,0,5,8,"e54d1d0c",169,"arcaneShip 0/8, deputShip 0/6, egirShip 1/5, emptyShip 0/6, kazimierzShip 0/4, preciShip 1/49, raidShip 1/41, skillfulShip 0/2, soloShip 1/6, steadShip 1/29, suntShip 1/0, swiftShip 1/39, yanShip 0/1",21,31,10,109], + "ai_0": [1,23,12,0,0,6,8,"1cd60f15",191,"arcaneShip 1/21, deputShip 0/8, kazimierzShip 0/8, lateranoShip 1/11, preciShip 2/37, raidShip 1/80, sargonShip 0/2, suntShip 1/8, swiftShip 1/34",31,31,0,112] }, { "round": 13, - "h_0": [1,18,12,0,0,6,8,"ba279997",190,"arcaneShip 0/8, deputShip 0/6, egirShip 1/11, emptyShip 0/6, kazimierzShip 0/4, preciShip 1/54, raidShip 1/44, skillfulShip 0/2, soloShip 1/6, steadShip 1/31, suntShip 1/0, swiftShip 1/44, yanShip 0/1",21,57,36,120], - "ai_0": [1,13,12,0,0,6,8,"284baa2f",234,"arcaneShip 0/21, deputShip 0/8, kazimierzShip 0/8, lateranoShip 1/17, preciShip 2/48, raidShip 1/112, sargonShip 0/2, siracusaShip 0/6, soloShip 1/0, steadShip 1/4, suntShip 1/8, swiftShip 1/45",31,57,26,122] + "h_0": [1,18,12,0,0,6,8,"80188da8",196,"arcaneShip 0/8, deputShip 0/6, egirShip 1/11, emptyShip 0/6, kazimierzShip 0/4, preciShip 1/54, raidShip 1/47, skillfulShip 0/2, soloShip 1/6, steadShip 1/34, suntShip 1/0, swiftShip 1/44, yanShip 0/1",30,57,27,120], + "ai_0": [1,22,12,0,0,6,8,"d2a2d8aa",218,"arcaneShip 0/21, deputShip 0/8, kazimierzShip 0/8, lateranoShip 1/17, preciShip 2/48, raidShip 1/96, sargonShip 0/2, siracusaShip 0/6, soloShip 1/0, steadShip 1/4, suntShip 1/8, swiftShip 1/45",56,57,1,122] } ], "players": { @@ -1596,26 +1596,26 @@ "eliminatedRound": null, "lp": 18, "bandId": "band_amedic", - "title": {"id":"comment_3","name":"坚若磐石","picId":"comment_icon_3","text":"目标生命值损失最少"}, + "title": {"id":"comment_4","name":"精英云集","picId":"comment_icon_4","text":"晋升精锐次数最多"}, "trophies": 4, "reward": 400, - "stats": {"activatedLayers":172,"bossDamage":193091,"dmgDealt":2564165,"gold":131,"itemsEquipped":16,"kills":272,"leaks":44,"lpLost":10,"merges":4,"perfectRounds":11,"refreshes":13}, + "stats": {"activatedLayers":175,"bossDamage":191721,"dmgDealt":2653536,"gold":131,"itemsEquipped":16,"kills":280,"leaks":37,"lpLost":10,"merges":4,"perfectRounds":11,"refreshes":13}, "lineup": ["4_14_a@12,3[4_07_e_b+4_03_e_a]","3_10_b@11,3","6_04_a@11,4","3_09_a@11,8[3_08_e_a]","1_17_b@10,3[1_01_e_a+6_05_e_a]","5_05_a@10,4[3_04_e_a+4_02_e_a]","3_05_b@10,8[5_02_e_b+3_03_e_a]","2_17_a@9,4"], - "bonds": ["arcaneShip 1/8","deputShip 0/6","egirShip 1/11","emptyShip 0/6","kazimierzShip 0/8","preciShip 1/59","raidShip 0/44","skillfulShip 0/2","soloShip 1/6","steadShip 1/35","suntShip 1/0","swiftShip 1/53","yanShip 0/1"] + "bonds": ["arcaneShip 1/8","deputShip 0/6","egirShip 1/11","emptyShip 0/6","kazimierzShip 0/8","preciShip 1/59","raidShip 0/47","skillfulShip 0/2","soloShip 1/6","steadShip 1/38","suntShip 1/0","swiftShip 1/53","yanShip 0/1"] }, "ai_0": { "alive": true, "victory": true, "roundsPassed": 14, "eliminatedRound": null, - "lp": 13, + "lp": 22, "bandId": "band_chiave", "title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"}, "trophies": 4, "reward": 400, - "stats": {"activatedLayers":267,"bossDamage":586909,"dmgDealt":3838927,"gold":134,"itemsEquipped":19,"kills":276,"leaks":26,"lpLost":10,"merges":4,"perfectRounds":12,"refreshes":18}, + "stats": {"activatedLayers":251,"bossDamage":588279,"dmgDealt":4174649,"gold":134,"itemsEquipped":19,"kills":303,"leaks":1,"lpLost":1,"merges":4,"perfectRounds":12,"refreshes":18}, "lineup": ["4_10_a@12,3","4_01_a@12,8[6_02_e_a+2_01_e_a]","6_12_a@11,3[3_05_e_a+3_11_e_a]","4_14_a@11,8","1_01_b@10,3[1_05_e_b+3_01_e_b]","5_07_a@10,7[3_07_e_a+3_05_e_b]","1_18_b@10,8[4_11_e_a+4_05_e_a]","2_01_b@9,8[3_02_e_a+3_06_e_a]"], - "bonds": ["arcaneShip 1/27","deputShip 0/8","kazimierzShip 0/8","lateranoShip 1/17","preciShip 2/53","raidShip 1/112","sargonShip 0/2","siracusaShip 0/6","steadShip 0/4","suntShip 1/8","swiftShip 1/50"] + "bonds": ["arcaneShip 1/27","deputShip 0/8","kazimierzShip 0/8","lateranoShip 1/17","preciShip 2/53","raidShip 1/96","sargonShip 0/2","siracusaShip 0/6","steadShip 0/4","suntShip 1/8","swiftShip 1/50"] } }, "standIns": { @@ -1775,37 +1775,37 @@ }, { "round": 7, - "h_0": [1,27,10,0,2,4,8,"00ea2b4a",24,"kazimierzShip 0/8, kjeragShip 0/5, miraShip 1/5, preciShip 2/19, soloShip 1/0, swiftShip 0/8",28,28,0,49], + "h_0": [1,27,10,0,2,4,8,"00ea2b4a",25,"kazimierzShip 0/8, kjeragShip 0/5, miraShip 1/6, preciShip 2/19, soloShip 1/0, swiftShip 0/8",28,28,0,49], "ai_0": [1,45,10,0,0,4,8,"fda860c6",60,"deputShip 2/12, kazimierzShip 0/4, sargonShip 0/4, skillfulShip 1/10, soloShip 1/12, swiftShip 1/26",28,28,0,49] }, { "round": 8, - "h_0": [1,27,13,0,0,4,8,"acad3972",60,"kazimierzShip 0/8, kjeragShip 1/10, miraShip 1/8, preciShip 1/24, skillfulShip 1/5, swiftShip 1/13",19,19,0,63], + "h_0": [1,27,13,0,0,4,8,"acad3972",61,"kazimierzShip 0/8, kjeragShip 1/10, miraShip 1/9, preciShip 1/24, skillfulShip 1/5, swiftShip 1/13",19,19,0,63], "ai_0": [1,45,11,0,0,4,8,"15e7305f",98,"deputShip 2/16, kazimierzShip 0/4, sargonShip 0/4, siracusaShip 1/10, skillfulShip 1/16, soloShip 1/16, swiftShip 1/40",19,19,0,60] }, { "round": 9, - "h_0": [1,27,12,0,0,4,8,"e3eb5ec0",67,"kazimierzShip 0/8, kjeragShip 1/10, miraShip 0/8, preciShip 2/30, skillfulShip 1/7, soloShip 1/0, suntShip 1/0, swiftShip 1/20",19,19,0,76], + "h_0": [1,27,12,0,0,4,8,"e3eb5ec0",67,"kazimierzShip 0/8, kjeragShip 1/10, miraShip 0/9, preciShip 2/30, skillfulShip 1/7, soloShip 1/0, suntShip 1/0, swiftShip 1/20",19,19,0,76], "ai_0": [1,45,12,0,1,4,8,"7290040a",128,"deputShip 2/20, kazimierzShip 0/4, sargonShip 0/4, siracusaShip 1/14, skillfulShip 1/22, soloShip 1/20, suntShip 1/4, swiftShip 1/48",19,19,0,74] }, { "round": 10, - "h_0": [1,27,12,0,0,5,8,"63e7f103",90,"kazimierzShip 0/8, kjeragShip 1/11, miraShip 1/8, preciShip 2/35, skillfulShip 1/9, soloShip 1/0, suntShip 1/0, swiftShip 1/27",24,24,0,89], + "h_0": [1,27,12,0,0,5,8,"63e7f103",91,"kazimierzShip 0/8, kjeragShip 1/11, miraShip 1/9, preciShip 2/35, skillfulShip 1/9, soloShip 1/0, suntShip 1/0, swiftShip 1/27",24,24,0,89], "ai_0": [1,45,13,0,0,5,8,"435b20af",170,"deputShip 2/24, kazimierzShip 0/4, raidShip 1/12, sargonShip 0/4, siracusaShip 1/18, skillfulShip 1/28, soloShip 1/24, suntShip 1/8, swiftShip 1/56",22,24,2,86] }, { "round": 11, - "h_0": [1,24,12,0,0,5,8,"d027ae1c",170,"kazimierzShip 0/16, kjeragShip 1/43, miraShip 0/8, preciShip 2/45, skillfulShip 1/11, soloShip 1/0, suntShip 1/0, swiftShip 1/71",21,24,3,100], + "h_0": [1,24,12,0,0,5,8,"d027ae1c",170,"kazimierzShip 0/16, kjeragShip 1/43, miraShip 0/9, preciShip 2/45, skillfulShip 1/11, soloShip 1/0, suntShip 1/0, swiftShip 1/71",21,24,3,100], "ai_0": [1,41,12,0,0,5,8,"de415c2a",188,"deputShip 2/28, kazimierzShip 0/4, raidShip 0/12, sargonShip 0/4, siracusaShip 1/22, skillfulShip 1/34, soloShip 1/28, suntShip 1/12, swiftShip 1/64",20,24,4,98] }, { "round": 12, - "h_0": [1,23,12,0,0,6,8,"e434765b",226,"kazimierzShip 0/16, kjeragShip 1/59, miraShip 0/8, preciShip 2/55, skillfulShip 1/13, soloShip 1/0, suntShip 1/0, swiftShip 1/99",30,31,1,111], + "h_0": [1,23,12,0,0,6,8,"e434765b",226,"kazimierzShip 0/16, kjeragShip 1/59, miraShip 0/9, preciShip 2/55, skillfulShip 1/13, soloShip 1/0, suntShip 1/0, swiftShip 1/99",30,31,1,111], "ai_0": [1,31,12,0,0,6,8,"158fd843",218,"deputShip 2/32, kazimierzShip 0/4, raidShip 0/12, sargonShip 0/4, siracusaShip 1/26, skillfulShip 1/40, soloShip 1/32, suntShip 1/16, swiftShip 1/72",10,31,21,110] }, { "round": 13, - "h_0": [1,23,12,0,0,6,8,"42bc3ae3",308,"kazimierzShip 1/34, kjeragShip 1/80, miraShip 0/8, preciShip 2/65, skillfulShip 0/20, soloShip 1/0, suntShip 1/0, swiftShip 1/129",112,35,3,124], + "h_0": [1,23,12,0,0,6,8,"42bc3ae3",308,"kazimierzShip 1/34, kjeragShip 1/80, miraShip 0/9, preciShip 2/65, skillfulShip 0/20, soloShip 1/0, suntShip 1/0, swiftShip 1/129",112,35,3,124], "ai_0": [1,31,12,0,0,6,8,"638d3c38",262,"deputShip 2/36, emptyShip 1/4, kazimierzShip 0/8, raidShip 0/12, sargonShip 0/4, siracusaShip 1/72, skillfulShip 1/46, soloShip 0/32, suntShip 1/20, swiftShip 1/84",115,35,0,122] } ], @@ -1820,9 +1820,9 @@ "title": {"id":"comment_2","name":"不朽盟约","picId":"comment_icon_2","text":"激活的盟约层数总和最高"}, "trophies": 3, "reward": 320, - "stats": {"activatedLayers":341,"bossDamage":479336,"dmgDealt":3356097,"gold":136,"itemsEquipped":10,"kills":385,"leaks":22,"lpLost":4,"merges":4,"perfectRounds":8,"refreshes":18}, + "stats": {"activatedLayers":342,"bossDamage":479336,"dmgDealt":3356086,"gold":136,"itemsEquipped":10,"kills":385,"leaks":22,"lpLost":4,"merges":4,"perfectRounds":8,"refreshes":18}, "lineup": ["4_14_b@12,5","6_05_a@12,6","4_13_a@12,7[3_02_e_a]","3_11_a@11,8[5_02_e_a+5_03_e_a]","4_20_a@10,3","1_19_b@10,8[4_11_e_a]","6_19_a@9,4[4_07_e_b]","5_11_a@9,5"], - "bonds": ["kazimierzShip 1/34","kjeragShip 1/82","miraShip 1/11","preciShip 2/75","skillfulShip 0/20","soloShip 1/0","steadShip 0/2","suntShip 1/0","swiftShip 1/139","yanShip 0/6"] + "bonds": ["kazimierzShip 1/34","kjeragShip 1/82","miraShip 1/12","preciShip 2/75","skillfulShip 0/20","soloShip 1/0","steadShip 0/2","suntShip 1/0","swiftShip 1/139","yanShip 0/6"] }, "ai_0": { "alive": true, @@ -1868,7 +1868,7 @@ "combat": "client", "boost": null, "setup": {"stageId":"act2autochess_m03","bossId":"boss_4","hiddenBossId":"boss_9","factions":["FLY","TIMES","REFLECTION"]}, - "end": {"victory":true,"roundsPassed":14,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":33,"bossPoolLeft":0,"virtualMs":121400}, + "end": {"victory":true,"roundsPassed":14,"hiddenReached":false,"hiddenCleared":false,"reason":"victory","teamLp":34,"bossPoolLeft":0,"virtualMs":121400}, "rng": {"setup":25,"shop":690,"waves":0,"draft":40,"bots":19229,"meta":10}, "errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0}, "rounds": [ @@ -1927,7 +1927,7 @@ { "round": 13, "h_0": [1,28,12,0,0,6,8,"d867f422",180,"deputShip 1/26, indomShip 1/24, investShip 0/8, kazimierzShip 0/2, kjeragShip 0/8, preciShip 2/19, skillfulShip 1/20, soloShip 0/20, steadShip 0/76, swiftShip 1/66, victoriaShip 1/19, visiShip 1/6",35,43,8,121], - "ai_0": [1,6,18,0,0,6,8,"95334040",370,"deputShip 1/52, emptyShip 0/6, investShip 0/8, kazimierzShip 0/8, kjeragShip 1/37, miraShip 1/2, raidShip 1/21, siracusaShip 1/120, soloShip 0/24, suntShip 1/6, swiftShip 1/83, visiShip 1/49, yanShip 0/1",26,43,17,133] + "ai_0": [1,6,18,0,0,6,8,"4b1d99d4",370,"deputShip 1/52, emptyShip 0/6, investShip 0/8, kazimierzShip 0/8, kjeragShip 1/37, miraShip 1/2, raidShip 1/21, siracusaShip 1/120, soloShip 0/24, suntShip 1/6, swiftShip 1/83, visiShip 1/49, yanShip 0/1",21,43,22,133] } ], "players": { @@ -1936,12 +1936,12 @@ "victory": true, "roundsPassed": 14, "eliminatedRound": null, - "lp": 27, + "lp": 28, "bandId": "band_sarkazb", - "title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"}, + "title": {"id":"comment_3","name":"坚若磐石","picId":"comment_icon_3","text":"目标生命值损失最少"}, "trophies": 4, "reward": 400, - "stats": {"activatedLayers":226,"bossDamage":778218,"dmgDealt":4310945,"gold":132,"itemsEquipped":21,"kills":287,"leaks":22,"lpLost":17,"merges":1,"perfectRounds":9,"refreshes":42}, + "stats": {"activatedLayers":226,"bossDamage":706034,"dmgDealt":4237334,"gold":132,"itemsEquipped":21,"kills":287,"leaks":22,"lpLost":17,"merges":1,"perfectRounds":9,"refreshes":42}, "lineup": ["4_21_a@12,7","4_14_b@12,8[2_01_e_a+3_02_e_a]","1_06_a@11,6[3_11_e_a+2_01_e_b]","6_11_a@11,7","6_12_a@11,8[3_05_e_b+4_08_e_b]","6_05_a@10,5[3_06_e_b+4_07_e_a]","4_07_a@10,8[3_01_e_b+6_09_e_a]","5_06_a@9,9"], "bonds": ["deputShip 1/28","indomShip 1/29","investShip 0/8","kazimierzShip 0/2","kjeragShip 0/8","maniShip 1/2","preciShip 2/31","skillfulShip 1/22","soloShip 0/20","steadShip 0/76","swiftShip 1/78","victoriaShip 1/25","visiShip 1/11"] }, @@ -1952,10 +1952,10 @@ "eliminatedRound": null, "lp": 6, "bandId": "band_lmlee", - "title": {"id":"comment_2","name":"不朽盟约","picId":"comment_icon_2","text":"激活的盟约层数总和最高"}, + "title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"}, "trophies": 4, "reward": 400, - "stats": {"activatedLayers":404,"bossDamage":639282,"dmgDealt":3465108,"gold":145,"itemsEquipped":12,"kills":240,"leaks":49,"lpLost":21,"merges":3,"perfectRounds":7,"refreshes":29}, + "stats": {"activatedLayers":404,"bossDamage":711466,"dmgDealt":3498882,"gold":145,"itemsEquipped":12,"kills":236,"leaks":54,"lpLost":21,"merges":3,"perfectRounds":7,"refreshes":29}, "lineup": ["2_14_b@12,7","3_20_a@12,8","3_14_a@11,7","5_10_a@11,8","6_19_a@10,6[4_04_e_a]","4_04_a@10,7","3_18_b@10,8[3_04_e_b+5_02_e_a]","4_16_a@9,9[4_05_e_a+4_11_e_a]"], "bonds": ["deputShip 1/54","emptyShip 1/8","investShip 0/8","kazimierzShip 0/8","kjeragShip 1/39","miraShip 0/2","raidShip 1/28","siracusaShip 1/126","soloShip 0/24","suntShip 1/8","swiftShip 1/85","visiShip 1/56","yanShip 0/1"] } diff --git a/test/golden/roster.json b/test/golden/roster.json index 9dbcbe77..ceb3e93a 100644 --- a/test/golden/roster.json +++ b/test/golden/roster.json @@ -384,55 +384,57 @@ "time": 140, "ticks": 4200, "reason": "timeout", - "killed": 132, + "killed": 137, "total": 71, "unspawned": 0, "bossHpLeft": null, - "rngDraws": 63, + "rngDraws": 82, "errors": {"count":0,"kinds":[]}, - "players": {"p1":{"killed":132,"total":71,"perfect":false,"leaks":41,"leaksUncounted":1,"coins":4,"dmg":234357,"bossDmg":0,"heal":971,"deaths":11,"layerGains":{}}}, + "players": { + "p1": {"killed":137,"total":71,"perfect":false,"leaks":37,"leaksUncounted":1,"coins":6,"dmg":243212,"bossDmg":0,"heal":1027,"deaths":10,"layerGains":{"kjeragShip":1}} + }, "units": [ - ["p1",1,"op","chess_char_3_12_a",2,null,2567.4,1,194,4,3535,2567,394,14,1], - ["p1",2,"op","chess_char_3_16_a",1,null,2390.3,1,200,0,501,3361,577,1,1], - ["p1",3,"op","chess_char_3_18_a",2,null,1629.1,1,199,10,8958,3258,0,25,1], - ["p1",4,"op","chess_char_3_08_a",1,null,1519.4,1,4,18,32568,234,0,19,2], - ["p1",5,"op","chess_char_3_09_a",1,null,931.22,1,7,12,24494,462,0,63,2], - ["p1",6,"op","chess_char_3_10_a",1,null,0,0,10,11,12119,1815,0,22,2], - ["p1",7,"op","chess_char_3_11_a",1,null,1447.6,1,198,11,8446,1448,0,17,3], - ["p1",8,"op","chess_char_3_13_a",1,null,1170.4,1,188,9,8936,1170,0,22,9], - ["p1",9,"op","chess_char_3_14_a",1,null,0,0,5,22,20517,1376,0,47,2], - ["p1",10,"op","chess_char_3_17_a",1,null,0,0,8,9,50397,2471,0,69,4], - ["p1",11,"op","chess_char_3_19_a",2,null,900.9,1,148,18,37884,2265,0,95,2], - ["p1",12,"op","chess_char_3_20_a",1,null,1233.1,1,195,4,9204,1233,0,37,1], - ["p1",13,"token","token_10028_vigil_wolf",null,null,126.29,0,110,1,3993,1793,0,12,null], + ["p1",1,"op","chess_char_3_12_a",2,null,2567.4,1,198,4,4454,2567,481,16,1], + ["p1",2,"op","chess_char_3_16_a",1,null,2390.3,1,200,0,482,3236,546,3,1], + ["p1",3,"op","chess_char_3_18_a",2,null,1629.1,1,197,8,8448,3258,0,23,1], + ["p1",4,"op","chess_char_3_08_a",1,null,1636.4,1,4,17,22875,117,0,20,2], + ["p1",5,"op","chess_char_3_09_a",1,null,1016.22,1,7,17,20543,377,0,61,2], + ["p1",6,"op","chess_char_3_10_a",1,null,0,0,10,11,10077,1815,0,24,2], + ["p1",7,"op","chess_char_3_11_a",1,null,1447.6,1,199,13,9750,1448,0,20,3], + ["p1",8,"op","chess_char_3_13_a",1,null,1170.4,1,191,9,9558,1170,0,22,9], + ["p1",9,"op","chess_char_3_14_a",1,null,434.05,1,5,21,20594,1124,0,56,2], + ["p1",10,"op","chess_char_3_17_a",1,null,0,0,8,8,60289,2471,0,75,4], + ["p1",11,"op","chess_char_3_19_a",2,null,900.9,1,144,18,36468,2265,0,93,2], + ["p1",12,"op","chess_char_3_20_a",1,null,1233.1,1,196,3,17443,1233,0,37,1], + ["p1",13,"token","token_10028_vigil_wolf",null,null,405.92,1,145,8,22231,4118,0,48,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], - ["p1","~1","token","token_10028_vigil_wolf",null,null,405.92,1,149,3,12804,1971,0,31,null] + ["-","~2","device","trap_1105_accrate",null,null,100,1,2,0,0,0,0,0,null] ], "enemies": { "enemy_10029_vtshld": [1,0,0,0,0], "enemy_10073_mpcar": [1,1,0,0,2304], - "enemy_10127_rkmbst_2": [1,1,0,4772,31680], - "enemy_1045_hammer": [1,1,0,507,11520], - "enemy_1121_lifbos_2": [1,0,1,2242,9778], - "enemy_1172_dugago": [1,0,1,80,6208], - "enemy_1195_sfyin": [36,30,6,639,77041], - "enemy_1195_sfyin_2": [15,9,6,1280,42541], - "enemy_1196_msfyin": [60,52,8,0,108], - "enemy_1196_msfyin_2": [18,11,7,0,36], - "enemy_1197_sfshu": [9,8,1,539,23040], - "enemy_1198_msfshu": [24,17,7,0,56], - "enemy_1203_sfhu": [1,0,1,5613,4245], - "enemy_1252_lysytb_2": [1,0,1,1965,4970], - "enemy_1305_mhslim": [1,1,0,223,1382], - "enemy_1407_hummbd": [1,1,0,140,5184], - "enemy_1512_mcmstr": [1,0,1,7426,12093], - "enemy_2021_syfish": [1,0,1,0,2170] + "enemy_10127_rkmbst_2": [1,1,0,0,31680], + "enemy_1045_hammer": [1,1,0,1357,11520], + "enemy_1121_lifbos_2": [1,0,1,4949,12333], + "enemy_1172_dugago": [1,0,1,53,3229], + "enemy_1195_sfyin": [36,29,7,1047,74890], + "enemy_1195_sfyin_2": [15,10,5,1907,44904], + "enemy_1196_msfyin": [58,53,5,0,110], + "enemy_1196_msfyin_2": [20,14,6,0,51], + "enemy_1197_sfshu": [9,7,2,647,20650], + "enemy_1198_msfshu": [21,18,3,0,57], + "enemy_1203_sfhu": [1,1,0,4263,7488], + "enemy_1204_msfhu": [4,0,4,0,8], + "enemy_1252_lysytb_2": [1,0,1,2195,10044], + "enemy_1305_mhslim": [1,1,0,382,1382], + "enemy_1407_hummbd": [1,1,0,178,5184], + "enemy_1512_mcmstr": [1,0,1,7472,16434], + "enemy_2021_syfish": [1,0,1,24,944] }, - "hooks": [1,199,4200,599,599,926,931,363,144,186,30,29,0,18756,9,36,174,41,1,156,0,0,0], - "events": {"atk":745,"bounty":2,"deploy":23,"die":145,"dmg":919,"engage":14,"fx":147,"heal":1,"leak":41,"skill":59,"spawn":190,"status":42}, - "fx": {"aoe":2,"camouflage":1,"displace":25,"dp":2,"explode":22,"expose":1,"liberate":1,"phase":1,"pull":25,"revive":2,"sp":1,"strike":3,"summon":49,"volley":7,"wolfShadow":2,"wolfShadowLost":3}, - "snaps": "e84b5db6 9d40d50d 6409c429 2034ac7f 297068d0 3bed0634 f25a356f 97d8759d f98af162 a7eeb75e 408d18eb 9a2e0ddb 0dc77e62 856889bc" + "hooks": [1,199,4200,644,644,1020,1031,347,148,185,30,30,0,19658,10,42,175,37,1,158,1,0,0], + "events": {"atk":765,"bounty":3,"deploy":22,"die":148,"dmg":1019,"engage":13,"fx":184,"heal":3,"layer":1,"leak":37,"skill":60,"spawn":190,"status":54}, + "fx": {"aoe":2,"camouflage":1,"displace":25,"dp":3,"drone":40,"explode":18,"expose":1,"garrison":1,"liberate":1,"phase":1,"pull":25,"strike":3,"summon":48,"volley":7,"wolfShadow":3,"wolfShadowLost":5}, + "snaps": "e84b5db6 9d40d50d 3878a5dc d36b6850 ab92d57f 0ba92626 db3f7c37 d07cee65 d329ac7f ef5d89a6 d313b7e0 37a45546 d12f14cf 3e37d060" }, "roster-008": { "about": "pass 0 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", @@ -532,22 +534,22 @@ "total": 63, "unspawned": 0, "bossHpLeft": null, - "rngDraws": 131, + "rngDraws": 134, "errors": {"count":0,"kinds":[]}, "players": {"p1":{"killed":171,"total":63,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":12,"dmg":279620,"bossDmg":0,"heal":0,"deaths":1,"layerGains":{}}}, "units": [ ["p1",1,"op","chess_char_3_16_b",1,"uniequip_002_snakek",5899.3,1,3,0,0,0,0,0,0], ["p1",2,"op","chess_char_4_01_a",2,null,5020.11,1,6,0,0,0,0,0,0], - ["p1",3,"op","chess_char_3_18_b",2,"uniequip_002_vulpis",3844.06,1,8,1,4,0,0,2,1], + ["p1",3,"op","chess_char_3_18_b",2,"uniequip_002_vulpis",3844.06,1,8,1,3,0,0,2,1], ["p1",4,"op","chess_char_4_04_a",1,null,2831.68,1,12,8,25880,518,0,125,4], - ["p1",5,"op","chess_char_3_13_b",1,"uniequip_002_malist",2616.63,1,9,28,7594,0,0,66,32], - ["p1",6,"op","chess_char_3_14_b",1,"uniequip_002_slbell",3073.35,1,10,4,2466,0,0,30,3], - ["p1",7,"op","chess_char_3_17_b",1,"uniequip_002_shotst",4154.31,1,14,20,35570,1359,0,56,9], + ["p1",5,"op","chess_char_3_13_b",1,"uniequip_002_malist",2616.63,1,9,29,7168,0,0,65,31], + ["p1",6,"op","chess_char_3_14_b",1,"uniequip_002_slbell",3073.35,1,10,4,2466,0,0,29,3], + ["p1",7,"op","chess_char_3_17_b",1,"uniequip_002_shotst",4154.31,1,14,20,34161,1359,0,55,9], ["p1",8,"op","chess_char_3_19_b",2,"uniequip_002_vigil",3421.59,1,4,0,1,0,0,1,4], - ["p1",9,"op","chess_char_3_20_b",1,"uniequip_002_kjera",2759.35,1,7,0,2,0,0,1,1], + ["p1",9,"op","chess_char_3_20_b",1,"uniequip_002_kjera",2759.35,1,7,0,3,0,0,1,1], ["p1",10,"op","chess_char_3_21_b",2,"uniequip_002_archet",3025.77,1,11,81,136300,0,0,188,5], ["p1",11,"op","chess_char_4_02_a",2,null,2717.48,1,166,14,58983,2717,0,36,1], - ["p1",12,"op","chess_char_4_06_a",1,null,2371.14,1,13,15,11980,0,0,71,2], + ["p1",12,"op","chess_char_4_06_a",1,null,2371.14,1,13,14,13814,0,0,71,2], ["p1",13,"token","token_10028_vigil_wolf",null,null,1026,1,5,0,839,1920,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] @@ -572,10 +574,10 @@ "enemy_1513_dekght_2": [1,1,0,5803,43200], "enemy_2034_sythef": [1,1,0,0,8640] }, - "hooks": [1,187,4616,590,590,1083,1067,0,172,172,62,60,0,20683,79,5,171,0,1,174,0,0,0], - "events": {"atk":714,"bounty":6,"deploy":14,"die":172,"dmg":1067,"engage":11,"fx":163,"skill":122,"spawn":186,"status":202}, - "fx": {"camouflage":1,"crit":21,"displace":24,"dp":4,"explode":3,"phase":1,"ripple":8,"shadowWeave":26,"shield":2,"stealth":4,"summon":51,"telegraph":3,"volley":9,"wolfShadow":3,"wolfShadowLost":2,"zone":1}, - "snaps": "01350beb 4f981949 2a43b546 3d68ce51 18790043 6dd248ea 6618c5de 5b83238d ddb0a718 3f31cdcb 819adf23 5eadc00d 672cd300 0dbb81a4 84d48721 11f06591" + "hooks": [1,187,4616,587,587,1084,1068,0,172,172,61,59,0,20606,82,5,171,0,1,175,0,0,0], + "events": {"atk":711,"bounty":6,"deploy":14,"die":172,"dmg":1068,"engage":11,"fx":168,"skill":120,"spawn":186,"status":206}, + "fx": {"camouflage":1,"crit":24,"displace":24,"dp":4,"drone":2,"explode":3,"phase":1,"ripple":8,"shadowWeave":26,"shield":2,"stealth":4,"summon":51,"telegraph":3,"volley":9,"wolfShadow":3,"wolfShadowLost":2,"zone":1}, + "snaps": "01350beb 4f981949 2a43b546 3d68ce51 18790043 6dd248ea 6618c5de 5b83238d ddb0a718 3f31cdcb 1cf84a50 0ac9a037 ff08ab6c 2b33ab34 16e86795 84c754e5" }, "roster-010": { "about": "pass 0 band 4: chess_char_4_17_a chess_char_4_18_a chess_char_4_11_a chess_char_4_19_a chess_char_4_07_a chess_char_4_16_a chess_char_4_09_a chess_char_4_10_a chess_char_4_12_a chess_char_4_13_a chess_char_4_14_a chess_char_4_20_a token_10041_cathy_catsld token_10041_cathy_catsld", @@ -2196,60 +2198,60 @@ "time": 207.37, "ticks": 6221, "reason": "cleared", - "killed": 75, + "killed": 76, "total": 130, "unspawned": 0, "bossHpLeft": null, - "rngDraws": 172, + "rngDraws": 188, "errors": {"count":0,"kinds":[]}, "players": { "p1": { - "killed": 75, + "killed": 76, "total": 130, "perfect": false, - "leaks": 55, + "leaks": 54, "leaksUncounted": 0, "coins": 4, - "dmg": 1160465, + "dmg": 1189341, "bossDmg": 0, - "heal": 20941, + "heal": 20136, "deaths": 17, "layerGains": {"preciShip":8} } }, "units": [ - ["p1",1,"op","chess_char_6_03_b",0,"none",0,0,5,2,49206,5477,997,10,0], - ["p1",2,"op","chess_char_6_15_a",0,null,0,0,139,0,26545,6965,0,31,3], - ["p1",3,"op","chess_char_6_19_a",0,null,2132.82,1,157,0,11050,11412,0,24,2], - ["p1",4,"op","chess_char_6_17_a",0,null,0,0,134,2,10900,12844,0,41,0], + ["p1",1,"op","chess_char_6_03_b",0,"none",0,0,5,1,39056,5006,726,7,0], + ["p1",2,"op","chess_char_6_15_a",0,null,0,0,139,0,26555,6915,0,31,3], + ["p1",3,"op","chess_char_6_19_a",0,null,2230.28,1,157,0,15328,11166,0,28,3], + ["p1",4,"op","chess_char_6_17_a",0,null,0,0,134,2,10855,12803,0,40,0], ["p1",5,"op","chess_char_6_12_a",0,null,0,0,8,1,12206,2150,0,20,4], - ["p1",6,"op","chess_char_6_13_a",0,null,2043.36,1,12,1,39577,5895,925,66,4], - ["p1",7,"op","chess_char_6_14_a",0,null,1863.97,1,14,0,0,3566,10425,58,15], - ["p1",8,"op","chess_char_6_16_a",0,null,404.84,1,4,1,166510,895,0,109,4], - ["p1",9,"op","chess_char_6_18_a",0,null,0,0,107,2,60604,8712,0,83,2], - ["p1",10,"op","chess_char_6_20_a",0,null,653.14,1,146,0,0,3814,8594,36,0], - ["p1",11,"op","chess_char_6_01_b",0,"none",1603.8,1,13,33,255694,3538,0,77,5], - ["p1",12,"op","chess_char_6_02_b",0,"none",2296.4,1,15,33,528172,2220,0,0,17], + ["p1",6,"op","chess_char_6_13_a",0,null,2043.36,1,12,1,34080,5890,884,66,4], + ["p1",7,"op","chess_char_6_14_a",0,null,1863.97,1,14,0,0,3566,10519,59,15], + ["p1",8,"op","chess_char_6_16_a",0,null,404.84,1,4,5,157488,895,0,107,4], + ["p1",9,"op","chess_char_6_18_a",0,null,0,0,107,3,99946,8662,0,83,2], + ["p1",10,"op","chess_char_6_20_a",0,null,653.14,1,146,0,0,3631,8007,35,0], + ["p1",11,"op","chess_char_6_01_b",0,"none",1603.8,1,13,30,264646,3538,0,77,5], + ["p1",12,"op","chess_char_6_02_b",0,"none",2296.4,1,15,33,529180,2273,0,0,17], ["-","~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] ], "enemies": { - "enemy_1006_shield_3": [21,0,21,20265,336542], + "enemy_1006_shield_3": [21,0,21,19224,348443], "enemy_10083_hlbird": [1,1,0,0,2488], "enemy_1040_bombd": [1,1,0,2501,6636], - "enemy_1043_zomsbr": [66,63,3,548,286837], + "enemy_1043_zomsbr": [66,63,3,366,290732], "enemy_1161_tidmag": [1,1,0,3139,9953], "enemy_1202_msfzhi": [1,1,0,0,5], - "enemy_1273_stmgun_2": [1,0,1,9600,10936], - "enemy_1402_tgshd_2": [36,8,28,14955,457986], - "enemy_1415_mmkabi_2": [1,0,1,0,40107], - "enemy_2003_rockman": [1,0,1,904,8976] + "enemy_1273_stmgun_2": [1,0,1,9480,14091], + "enemy_1402_tgshd_2": [36,9,27,15049,467379], + "enemy_1415_mmkabi_2": [1,0,1,0,39454], + "enemy_2003_rockman": [1,0,1,892,10159] }, - "hooks": [1,157,6221,639,638,1382,1632,8342,92,147,56,54,59,23902,3684,26,130,55,1,92,2,4,0], - "events": {"atk":680,"bounty":2,"deploy":24,"die":92,"dmg":1425,"engage":9,"fx":650,"heal":524,"layer":2,"leak":55,"skill":110,"spawn":145,"status":871}, - "fx": {"airstrike":15,"aoe":3,"burst":4,"displace":2,"explode":16,"expose":466,"frostNova":17,"garrison":2,"healField":15,"link":1,"phase":1,"snow":37,"sunBurst":2,"talent":7,"telegraph":2,"wanted":60}, - "snaps": "352a6117 5197ba48 22ff25c2 16105f43 67bd4112 04c5a2b1 e4e63a95 9087d64d 41e697b3 8e3b24fc fa002205 4a75e62c a4551cf8 654d332a 8d6a840f 2e74744b bb1f92bb 7b473463 d11b7c5f e3c994e9 7f5f08b2" + "hooks": [1,157,6221,631,631,1442,1689,8140,93,147,57,55,59,23766,3660,26,130,54,1,93,2,3,0], + "events": {"atk":677,"bounty":2,"deploy":24,"die":93,"dmg":1482,"engage":9,"fx":659,"heal":517,"layer":2,"leak":54,"skill":112,"spawn":145,"status":881}, + "fx": {"airstrike":11,"aoe":3,"burst":3,"displace":2,"explode":16,"expose":480,"frostNova":17,"garrison":2,"healField":15,"link":1,"phase":1,"snow":37,"sunBurst":2,"talent":7,"telegraph":2,"wanted":60}, + "snaps": "352a6117 11d3bb1a dfeffae3 b7296cc6 1684ece3 f859c2a7 f4e90130 6b756d02 d56ccb68 ad6cb2eb 8093c7c9 788c6d05 100bd99d 1828c525 24645285 cc28fd34 78d3df1d 59f9c0ac 21669529 ad944f3f 00f62e15" }, "roster-037": { "about": "pass 1 band 7: chess_char_6_06_b chess_char_6_15_b chess_char_6_07_b chess_char_6_04_b chess_char_6_05_b chess_char_6_08_b chess_char_6_09_b chess_char_6_11_b chess_char_6_12_b chess_char_6_13_b chess_char_6_14_b chess_char_6_16_b token_10017_skadi2_dedant token_10030_mlyss_wtrman", @@ -2345,41 +2347,41 @@ "total": 157, "unspawned": 0, "bossHpLeft": null, - "rngDraws": 45, + "rngDraws": 38, "errors": {"count":0,"kinds":[]}, "players": { - "p1": {"killed":157,"total":157,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":8,"dmg":3467641,"bossDmg":0,"heal":73044,"deaths":2,"layerGains":{"raidShip":22}} + "p1": {"killed":157,"total":157,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":8,"dmg":3468742,"bossDmg":0,"heal":75788,"deaths":2,"layerGains":{"raidShip":22}} }, "units": [ - ["p1",1,"op","chess_char_5_08_b",1,"none",3052.5,1,2,19,393842,0,0,62,4], + ["p1",1,"op","chess_char_5_08_b",1,"none",3052.5,1,2,16,396088,0,0,61,4], ["p1",2,"op","chess_char_6_19_b",0,"uniequip_003_blkkgt",5230.39,1,4,0,0,0,0,0,0], ["p1",3,"op","chess_char_5_01_b",2,"none",2545.4,1,6,0,2613,0,0,2,0], - ["p1",4,"op","chess_char_5_05_b",1,"none",9477.62,1,7,9,113120,4230,480,20,1], - ["p1",5,"op","chess_char_5_06_b",1,"none",4121.7,1,8,107,2385886,24107,24107,110,8], - ["p1",6,"op","chess_char_6_17_b",0,"uniequip_003_nearl2",0,0,101,3,91899,9619,0,53,1], - ["p1",7,"op","chess_char_5_07_b",1,"none",3183.84,1,12,8,256736,45687,0,153,6], - ["p1",8,"op","chess_char_6_18_b",0,"none",1640.63,1,9,4,106163,0,0,149,1], - ["p1",9,"op","chess_char_6_20_b",0,"uniequip_003_agoat2",1628.75,1,10,0,0,0,45687,54,1], - ["p1",10,"op","chess_char_5_02_b",1,"uniequip_002_titi",1582.9,1,1,4,91738,0,2770,2,1], - ["p1",11,"op","chess_char_5_03_b",1,"none",1538.24,1,3,0,2310,162,0,2,1], - ["p1",12,"op","chess_char_5_10_b",1,"none",1518,1,5,2,23335,0,0,23,1] + ["p1",4,"op","chess_char_5_05_b",1,"none",9894.5,1,7,5,119878,1916,200,21,1], + ["p1",5,"op","chess_char_5_06_b",1,"none",2739.25,1,8,111,2304935,26335,24953,110,8], + ["p1",6,"op","chess_char_6_17_b",0,"uniequip_003_nearl2",0,0,104,2,81439,9619,0,48,2], + ["p1",7,"op","chess_char_5_07_b",1,"none",3183.84,1,12,4,256410,48757,0,153,7], + ["p1",8,"op","chess_char_6_18_b",0,"none",1640.63,1,9,14,187571,0,0,150,1], + ["p1",9,"op","chess_char_6_20_b",0,"uniequip_003_agoat2",1628.75,1,10,0,0,0,48757,56,1], + ["p1",10,"op","chess_char_5_02_b",1,"uniequip_002_titi",1582.9,1,1,4,94726,0,1878,2,1], + ["p1",11,"op","chess_char_5_03_b",1,"none",1619.2,1,3,0,2310,162,0,2,1], + ["p1",12,"op","chess_char_5_10_b",1,"none",1518,1,5,0,22772,0,0,24,1] ], "enemies": { - "enemy_1006_shield_3": [1,1,0,2931,143327], + "enemy_1006_shield_3": [1,1,0,1495,143327], "enemy_1021_bslime": [1,1,0,3065,8815], "enemy_1148_dssbr_2": [1,1,0,0,12899], "enemy_1198_msfshu_2": [1,1,0,0,6], - "enemy_1249_lysdb_2": [60,60,0,20261,1289945], - "enemy_1251_lysyta": [51,51,0,2355,502541], - "enemy_1270_nhstlk": [1,1,0,2036,42998], - "enemy_1329_cbshld": [39,39,0,49898,1397441], + "enemy_1249_lysdb_2": [60,60,0,20663,1289945], + "enemy_1251_lysyta": [51,51,0,2471,502541], + "enemy_1270_nhstlk": [1,1,0,1018,42998], + "enemy_1329_cbshld": [39,39,0,54817,1397441], "enemy_1389_winbab_2": [1,1,0,3097,25082], "enemy_2001_duckmi": [1,1,0,0,64497] }, - "hooks": [1,170,5944,764,762,3820,3763,578,159,159,25,20,40,15978,683,89,157,0,1,161,2,0,0], - "events": {"atk":1149,"bounty":4,"deploy":13,"die":159,"dmg":3763,"engage":10,"fx":97,"heal":485,"layer":2,"skill":45,"spawn":169,"status":182}, - "fx": {"aoe":16,"explode":1,"garrison":2,"garrisonGrant":4,"overload":4,"reborn":1,"shieldBreak":60,"sleepGuard":1,"sunBurst":3,"talent":3,"undying":2}, - "snaps": "2c013a42 e0a9d456 d93eb576 5f4d92f3 a5a0ebec 5214a5e1 27d57a43 91a4904c 9fca4890 d12b72df 7c44ce37 e62d1865 3d9a4fd9 350839a2 4e7c68e2 8dfe6cd9 9f96036b b28d664a 33c769dc 3d835553" + "hooks": [1,170,5944,769,768,3843,3786,581,159,159,27,21,40,15969,799,92,157,0,1,161,2,0,0], + "events": {"atk":1126,"bounty":4,"deploy":13,"die":159,"dmg":3786,"engage":10,"fx":96,"heal":505,"layer":2,"skill":48,"spawn":169,"status":167}, + "fx": {"aoe":16,"explode":1,"garrison":2,"garrisonGrant":4,"overload":4,"reborn":1,"shieldBreak":60,"sleepGuard":1,"sunBurst":2,"talent":3,"undying":2}, + "snaps": "9ab5c23c 2a5b65c5 0796d1a8 ad7e6d9d 75cedfd8 9848546b f7e72724 b88fcc71 1ff6c309 597743be 400aef19 82e8fb5f 026f17c9 b55df4cb a5230f2e ade7be1a ddb61150 833d6f90 e157e24a 73cac7a6" }, "roster-039": { "about": "pass 2 band 4: chess_char_3_12_a chess_char_3_12_b chess_char_3_18_a chess_char_3_18_b chess_char_3_04_a chess_char_3_05_a chess_char_3_04_b chess_char_3_05_b chess_char_3_01_a chess_char_3_19_a chess_char_3_21_a chess_char_3_01_b token_10028_vigil_wolf", diff --git a/test/sim/funnel-body.test.js b/test/sim/funnel-body.test.js index 074422e2..ec081448 100644 --- a/test/sim/funnel-body.test.js +++ b/test/sim/funnel-body.test.js @@ -4,6 +4,8 @@ import { test } from 'node:test'; import assert from 'node:assert/strict'; import { makeBattle, chessRec, enemyRec, checkInvariants } from '../helpers/battleHarness.js'; import { hitCount } from '../../server/sim/content/enemies/helpers.js'; +import { bodyInKeys } from '../../server/sim/body.js'; +import { DRONE_TAG } from '../../server/sim/content/kits/ops/chess_char_3_20-kjera.js'; const near = (a, b, label) => assert.ok(Math.abs(a - b) < 1e-6, `${label}: ${a} vs ${b}`); const ordinary = ['2_10', '3_13', '3_20', '4_03', '6_18'].flatMap((id) => ['a', 'b'].map((f) => ({ chessId: `chess_char_${id}_${f}` }))); @@ -79,15 +81,36 @@ test('unreleased attribute skills keep a body hit; released Kjera drones and Lol for (const v of volleys(h, u)) assert.equal(v.length, 2, `${id}: one pair per attack`); done(h); } - for (const id of ['chess_char_3_20_a', 'chess_char_3_20_b']) { + for (const id of ['chess_char_3_20_a', 'chess_char_3_20_b', 'chess_char_4_03_a', 'chess_char_4_03_b']) { const { h, u } = field({ chessId: id }); + h.run(2); + const before = mine(h, u).filter((c) => c.dmg.tags?.includes('funnel')); + assert.ok(before.length >= 1, `${id}: a pre-skill drone hit`); + const preScale = before.at(-1).amount / u.s.atk; u.skill.gainSp(999); assert.ok(h.runUntil(() => u.skill.active, 5)); - const start = mine(h, u).length; + const t0 = h.b.time; h.run(2); - const active = mine(h, u).slice(start); - assert.ok(active.length > 0, `${id}: skill hits`); - assert.ok(active.every((c) => c.dmg.isSkill && c.dmg.isAttack && !c.dmg.tags?.includes('funnel')), `${id}: no extra body`); + const full = u.s.atk * u.s.atkScaleMul; + const later = mine(h, u).filter((c) => c.t + 1e-9 >= t0 - h.b.dt); + const body = later.filter((c) => c.dmg.isAttack && !c.dmg.isSkill && !(c.dmg.tags || []).includes('funnel')); + const drones = later.filter((c) => (c.dmg.tags || []).includes(DRONE_TAG)); + assert.ok(body.length > 0, `${id}: the operator's own hit`); + assert.ok(drones.length >= 2, `${id}: both released drones`); + for (const c of body) { + near(c.amount, full, `${id} body is 100% ATK`); + assert.ok(!(c.dmg.tags || []).includes('addition')); + } + for (const c of drones) { + assert.ok(c.dmg.isSkill && !c.dmg.isAttack && c.type === 'arts', `${id}: drone skill hit`); + assert.ok(!(c.dmg.tags || []).includes('addition') && !(c.dmg.tags || []).includes('funnel')); + const r = c.amount / full; + assert.ok(r + 1e-6 >= u.profile.funnel.init && r <= u.profile.funnel.max + 1e-6, `${id} drone scale ${r}`); + } + const first = drones[0].amount / full; + if (id.startsWith('chess_char_4_03')) near(first, u.profile.funnel.init, `${id} restarts at the initial scale`); + else assert.ok(first > u.profile.funnel.init + 1e-6 && first + 1e-6 >= Math.min(u.profile.funnel.max, preScale + u.profile.funnel.delta) - 1e-6, + `${id} continues the pre-skill ramp (${first} after ${preScale})`); done(h); } }); @@ -128,18 +151,71 @@ test('Minimalist charged S2: two body hits and two drone additions share one tal } }); -test('released Kjera S2 locks retain their existing volley count; no body is added once per lock', () => { - for (const id of ['chess_char_3_20_a', 'chess_char_4_03_a']) { - for (const count of [1, 2]) { - const { h, u } = field({ chessId: id }); - if (count === 2) h.spawn('enemy_dummy', { pos: [11, 6] }); - u.skill.gainSp(999); - h.run(2); - const vs = volleys(h, u).filter((v) => v[0].dmg.isSkill); - assert.ok(vs.length > 0); - for (const v of vs) assert.equal(v.length, 2, `${id}: existing two released drones`); - done(h); +test('Whitw2 S1 on: the toggle keeps one body hit and both unreleased additions', () => { + for (const id of ['chess_char_6_18_a', 'chess_char_6_18_b']) { + const { h, u } = field({ chessId: id, skillIndex: 0 }); + assert.ok(u.skill.activate('test', { free: true })); + const t0 = h.b.time; + h.run(2); + const vs = volleys(h, u).filter((v) => v[0].t + 1e-9 >= t0); + assert.ok(vs.length >= 1, `${id}: attacks while S1 is on`); + for (const v of vs) { + const body = v.filter((c) => c.dmg.isAttack && !(c.dmg.tags || []).includes('addition')); + const drone = v.filter((c) => (c.dmg.tags || []).includes('funnel')); + assert.equal(body.length, 1, `${id}: the 100% body is not dropped`); + assert.equal(drone.length, 2, `${id}: both unreleased drones`); + near(body[0].amount, u.s.atk * u.s.atkScaleMul, `${id} body`); + for (const c of drone) { + assert.ok(!c.dmg.isAttack); + const r = c.amount / body[0].amount; + assert.ok(r + 1e-6 >= u.profile.funnel.init && r <= u.profile.funnel.max + 1e-6, `${id} ramp ${r}`); + } } + done(h); + } +}); + +test('Whitw2 S2 stays drone-only: no full-ATK body beside the ramp', () => { + for (const id of ['chess_char_6_18_a', 'chess_char_6_18_b']) { + const { h, u } = field({ chessId: id, skillIndex: 1 }); + u.skill.gainSp(999); + assert.ok(h.runUntil(() => u.skill.active, 8)); + const t0 = h.b.time; + h.run(2); + const full = u.s.atk * u.s.atkScaleMul; + const active = mine(h, u).filter((c) => c.t + 1e-9 >= t0 - h.b.dt && c.dmg.isSkill); + assert.ok(active.length > 0, `${id}: skill hits`); + assert.ok(active.every((c) => c.dmg.isAttack && !(c.dmg.tags || []).includes('funnel')), `${id}: ramp stays on the attack`); + assert.equal(active.filter((c) => Math.abs(c.amount - full) < 1e-4).length, 0, `${id}: no 100% body`); + done(h); + } +}); + +test('Kjera S2: a lock that leaves her range still takes drone hits, and the body does not follow it', () => { + const route = { + motion: 'FLY', start: [10, 6], end: [9, 2], + steps: [{ t: 'wait', s: 1.2 }, { t: 'move', p: [12, 6] }, { t: 'wait', s: 20 }, { t: 'move', p: [9, 2] }], + }; + for (const id of ['chess_char_3_20_a', 'chess_char_4_03_a']) { + const h = makeBattle({ + seed: 4, autoFinish: false, timeLimit: 40, captureNoisy: true, hooks: ['damaged', 'attack'], + defs: { enemies: { enemy_lock: enemyRec({ key: 'enemy_lock', hp: 1e8, speed: 1, motion: 'FLY' }) } }, + units: [{ uid: 1, row: 10, col: 4, chessId: id, carryState: { sp: 999 } }], + enemies: [{ key: 'enemy_lock', route }], + }); + h.step(); + const u = h.unit(1), e = h.enemies()[0]; + assert.ok(u.skill.active, `${id} opens on the carried SP`); + assert.ok(h.runUntil(() => e.alive && !bodyInKeys(e, u.rangeKeySet), 8), `${id}: the lock leaves range`); + h.run(1.5); + const t = h.b.time, attacks = u.stats.attacks; + h.run(3); + assert.ok(e.alive && u.skill.active && !bodyInKeys(e, u.rangeKeySet)); + const out = mine(h, u).filter((c) => c.target === e && c.t + 1e-9 >= t); + assert.ok(out.length > 0, `${id}: damage outside range`); + assert.ok(out.every((c) => (c.dmg.tags || []).includes(DRONE_TAG) && c.dmg.isSkill && !c.dmg.isAttack), `${id}: drone only`); + assert.equal(u.stats.attacks, attacks, `${id}: the body does not attack with nobody in range`); + done(h); } });