feedback5 WM: merge feedback4 at 13808e3 (W4A) — 高台 for every 「可以放置于远程位」 trait holder, the 5-阿戈尔 revive slots, the 联防 devour of whoever stands in front
Ported by hand into the split layout: -83fc408board.js placeClass: the player's loadout no longer counts, as in83fc408. feedback5's 补位 rule stays: a chess the player fields as its stand-in is placed by the stand-in's record (ps.fieldRecord). positionClass(rec) takes no module. -83fc408client piecePosition → public/js/ui/gameLogic/placement.js: meleeOnHighGround(rec) on the stand-in or chess record, no module. The gameLogic.js shim header and deployedModuleId's comment follow; deployedModuleId is kept, still exported and tested. -83fc408PlayerState._placementOf comment → server/match/player/placement.js. -83fc408tools/golden.mjs layout: positionClass without the module, on feedback5's stand-in body (recOf) and in diyLayout. - bonds/core.js (6ab9a06,8a2e0c7) applied cleanly; it equals 13808e3's plus feedback5's i18n toast. shared/highGround.js equals 13808e3's. - data/: only bonds.json (the 阿戈尔 spec text). node tools/build-data.mjs --offline on the merged tree rewrites all 15 files byte-identical. Golden regenerated: 16 scenarios moved, all by83fc408. Each fields 歌蕾蒂娅 (normal, or elite with HOK-X / no module), whom tools/golden.mjs now lays out beside the enemy path like a ranged operator instead of on the busiest melee tile: roster-010, roster-012, roster-029, roster-040, roster-041; bond-deputShip-high, bond-indomShip-low, bond-preciShip-low, bond-preciShip-high, bond-suntShip-low, bond-swiftShip-high; boss-boss_2-pair, boss-boss_4-pair, boss-boss_6-pair, hidden-boss_8-pair, hidden-boss_10-pair. This is the list in 83fc408's own message. With the 阿戈尔 commits reverted the digests are the same, so those two move nothing in this corpus. The standins, diy and matches families are unchanged: no stand-in or 自选 piece there is 歌蕾蒂娅, 崖心 or 见行者.
This commit is contained in:
commit
c5c52eed34
26 files changed
+1095
-871
No files matched your search
+1
-1
@@ -1 +1 @@
|
||||
{"yanShip":{"bondId":"yanShip","name":"炎","identifier":1,"isCore":true,"bondType":"SEASON","bondOrder":2,"powerIdList":["yan","sui","lungmen","lee","lgd"],"iconId":"icon_yanShip","activeCount":3,"thresholds":[3,6,9],"maxCount":null,"thresholdTemplate":"count_threshold_upward","countMode":"BOARD","countsHand":false,"countsGoldenOnly":false,"activeType":"BATTLE","isActiveInDeck":false,"noStack":false,"weight":10,"maxInactiveBondCount":-1,"layerMilestones":[],"desc":"【炎】干员攻击力提升(受层数影响)\n<在场6名不同【炎】干员>战斗开始时召唤可自主行动的“炎佑”,其攻击力生命值分别为开战时【炎】干员攻击力生命值总和的30%,“炎佑”同时攻击3个目标,可使用“祛恶之焰”,攻击时附带攻击力一定比例的灼燃损伤且周围敌人受到一定比例的元素脆弱\n<在场9名不同【炎】干员>改为召唤2只“炎佑”,攻击力提升至1.5倍,受到的伤害-90%","descRaw":"【炎】干员<@ba.vup>攻击力</>提升<@autochess.gray>(受层数影响)</>\n<在场<@autochess.dgreen>6</>名不同【炎】干员>战斗开始时召唤可自主行动的<@ba.vup>“炎佑”</>,其攻击力生命值分别为开战时【炎】干员攻击力生命值总和的30%,“炎佑”同时攻击3个目标,可使用<@ba.vup>“祛恶之焰”</>,攻击时附带攻击力一定比例的灼燃损伤且周围敌人受到一定比例的元素脆弱\n<在场<@autochess.dgreen>9</>名不同【炎】干员>改为召唤2只<@ba.vup>“炎佑”</>,攻击力提升至<@ba.vup>1.5</>倍,受到的伤害<@ba.vup>-90%</>","effectId":"bondeffect_yan","effectName":"炎","effectDesc":"【炎】干员攻击力+{0:0%}(受层数影响)\n<在场6名不同【炎】干员>战斗开始时收集【炎】干员部分属性召唤“炎佑”(其攻击力和生命值为【炎】干员攻击力和生命值总和的30%);“炎佑”同时攻击3个目标,攻击附带20%攻击力的灼燃损伤,周围敌人受到20%的元素脆弱,周期性使用“祛恶之焰”\n<在场9名不同【炎】干员>改为召唤2只“炎佑”;“炎佑”攻击力提升至1.5倍,受到的伤害-90%","effectDescRaw":"【炎】干员攻击力<@ba.vup>+{0:0%}</><@ba.acrem>(受层数影响)</>\n<在场<@ba.vup>6</>名不同【炎】干员>战斗开始时收集【炎】干员部分属性召唤“炎佑”(其攻击力和生命值为【炎】干员攻击力和生命值总和的30%);“炎佑”同时攻击3个目标,攻击附带20%<@ba.vup>攻击力</>的<@ba.vup>灼燃损伤</>,周围敌人受到20%的<@ba.vup>元素脆弱</>,周期性使用“祛恶之焰”\n<在场<@ba.vup>9</>名不同【炎】干员>改为召唤2只“炎佑”;“炎佑”攻击力提升至1.5倍,受到的伤害-90%","effectDescParams":[{"index":0,"format":"0%","base":"base_atk","perStack":"atk_per_stack"}],"bb":{"base_atk":0.23,"atk_per_stack":0.009,"power_bond_char_cnt":6,"ex_bond_char_cnt":9,"damage_resistance":0.9,"atk":1.5},"bbStr":{"key":"act1autochess_bond_eff_yan"},"buffs":[{"key":"env_gbuff_new","bb":{"base_atk":0.23,"atk_per_stack":0.009,"power_bond_char_cnt":6,"ex_bond_char_cnt":9,"damage_resistance":0.9,"atk":1.5},"bbStr":{"key":"act1autochess_bond_eff_yan"}}],"baseParams":["base_atk"],"perStackParams":["atk_per_stack"],"members":["chess_char_1_03_a","chess_char_2_04_a","chess_char_3_03_a","chess_char_3_04_a","chess_char_4_15_a","chess_char_4_17_a","chess_char_5_03_a","chess_char_5_12_a","chess_char_5_23_a","chess_char_6_03_a","chess_char_6_15_a"],"visibleMembers":["chess_char_1_03_a","chess_char_2_04_a","chess_char_3_03_a","chess_char_3_04_a","chess_char_4_17_a","chess_char_5_03_a","chess_char_5_12_a","chess_char_5_23_a","chess_char_6_03_a","chess_char_6_15_a"],"spec":{"tiers":[{"need":"3 distinct 炎 on board","effect":"炎 members (+调和 members) ATK x(1 + 0.23 + 0.009*L)."},{"need":"6 distinct","effect":"At battle start spawn 1 \"炎佑\" (enemy_9012_acloon template, allied flying ranged unit, not blockable, moves on its own). ATK = 0.30 x sum(ATK of 炎 operators on board at battle start), maxHP = 0.30 x sum(maxHP of those operators). Template: DEF 200, RES 0, BAT 2.5 s, ASPD 100, attack range radius 2.0 tiles, magic damage, hits up to 3 targets; every hit adds 灼燃损伤 (burn elemental damage) = 20% of its ATK and applies 元素脆弱 (elemental damage taken x1.2) to enemies within 0.8 tiles of the target. Skill \"祛恶之焰\": cooldown 15 s (first cast 15 s after spawn), channels a flame on one enemy in range dealing 60% ATK magic damage per second to it and to enemies within 1.0 tile, for up to 20 s."},{"need":"9 distinct","effect":"Spawn 2 炎佑 instead; each has ATK x1.5 and takes 90% less damage (damage_resistance 0.9)."}],"formulas":{"atkMultiplier":"1 + 0.23 + 0.009*L"},"caps":"none","layerGain":"Economy-driven: 惊蛰 获得时 +shop level (no activation needed); 小满 休整期结束 +1 per operator gained this rouLine truncated
|
||||
{"yanShip":{"bondId":"yanShip","name":"炎","identifier":1,"isCore":true,"bondType":"SEASON","bondOrder":2,"powerIdList":["yan","sui","lungmen","lee","lgd"],"iconId":"icon_yanShip","activeCount":3,"thresholds":[3,6,9],"maxCount":null,"thresholdTemplate":"count_threshold_upward","countMode":"BOARD","countsHand":false,"countsGoldenOnly":false,"activeType":"BATTLE","isActiveInDeck":false,"noStack":false,"weight":10,"maxInactiveBondCount":-1,"layerMilestones":[],"desc":"【炎】干员攻击力提升(受层数影响)\n<在场6名不同【炎】干员>战斗开始时召唤可自主行动的“炎佑”,其攻击力生命值分别为开战时【炎】干员攻击力生命值总和的30%,“炎佑”同时攻击3个目标,可使用“祛恶之焰”,攻击时附带攻击力一定比例的灼燃损伤且周围敌人受到一定比例的元素脆弱\n<在场9名不同【炎】干员>改为召唤2只“炎佑”,攻击力提升至1.5倍,受到的伤害-90%","descRaw":"【炎】干员<@ba.vup>攻击力</>提升<@autochess.gray>(受层数影响)</>\n<在场<@autochess.dgreen>6</>名不同【炎】干员>战斗开始时召唤可自主行动的<@ba.vup>“炎佑”</>,其攻击力生命值分别为开战时【炎】干员攻击力生命值总和的30%,“炎佑”同时攻击3个目标,可使用<@ba.vup>“祛恶之焰”</>,攻击时附带攻击力一定比例的灼燃损伤且周围敌人受到一定比例的元素脆弱\n<在场<@autochess.dgreen>9</>名不同【炎】干员>改为召唤2只<@ba.vup>“炎佑”</>,攻击力提升至<@ba.vup>1.5</>倍,受到的伤害<@ba.vup>-90%</>","effectId":"bondeffect_yan","effectName":"炎","effectDesc":"【炎】干员攻击力+{0:0%}(受层数影响)\n<在场6名不同【炎】干员>战斗开始时收集【炎】干员部分属性召唤“炎佑”(其攻击力和生命值为【炎】干员攻击力和生命值总和的30%);“炎佑”同时攻击3个目标,攻击附带20%攻击力的灼燃损伤,周围敌人受到20%的元素脆弱,周期性使用“祛恶之焰”\n<在场9名不同【炎】干员>改为召唤2只“炎佑”;“炎佑”攻击力提升至1.5倍,受到的伤害-90%","effectDescRaw":"【炎】干员攻击力<@ba.vup>+{0:0%}</><@ba.acrem>(受层数影响)</>\n<在场<@ba.vup>6</>名不同【炎】干员>战斗开始时收集【炎】干员部分属性召唤“炎佑”(其攻击力和生命值为【炎】干员攻击力和生命值总和的30%);“炎佑”同时攻击3个目标,攻击附带20%<@ba.vup>攻击力</>的<@ba.vup>灼燃损伤</>,周围敌人受到20%的<@ba.vup>元素脆弱</>,周期性使用“祛恶之焰”\n<在场<@ba.vup>9</>名不同【炎】干员>改为召唤2只“炎佑”;“炎佑”攻击力提升至1.5倍,受到的伤害-90%","effectDescParams":[{"index":0,"format":"0%","base":"base_atk","perStack":"atk_per_stack"}],"bb":{"base_atk":0.23,"atk_per_stack":0.009,"power_bond_char_cnt":6,"ex_bond_char_cnt":9,"damage_resistance":0.9,"atk":1.5},"bbStr":{"key":"act1autochess_bond_eff_yan"},"buffs":[{"key":"env_gbuff_new","bb":{"base_atk":0.23,"atk_per_stack":0.009,"power_bond_char_cnt":6,"ex_bond_char_cnt":9,"damage_resistance":0.9,"atk":1.5},"bbStr":{"key":"act1autochess_bond_eff_yan"}}],"baseParams":["base_atk"],"perStackParams":["atk_per_stack"],"members":["chess_char_1_03_a","chess_char_2_04_a","chess_char_3_03_a","chess_char_3_04_a","chess_char_4_15_a","chess_char_4_17_a","chess_char_5_03_a","chess_char_5_12_a","chess_char_5_23_a","chess_char_6_03_a","chess_char_6_15_a"],"visibleMembers":["chess_char_1_03_a","chess_char_2_04_a","chess_char_3_03_a","chess_char_3_04_a","chess_char_4_17_a","chess_char_5_03_a","chess_char_5_12_a","chess_char_5_23_a","chess_char_6_03_a","chess_char_6_15_a"],"spec":{"tiers":[{"need":"3 distinct 炎 on board","effect":"炎 members (+调和 members) ATK x(1 + 0.23 + 0.009*L)."},{"need":"6 distinct","effect":"At battle start spawn 1 \"炎佑\" (enemy_9012_acloon template, allied flying ranged unit, not blockable, moves on its own). ATK = 0.30 x sum(ATK of 炎 operators on board at battle start), maxHP = 0.30 x sum(maxHP of those operators). Template: DEF 200, RES 0, BAT 2.5 s, ASPD 100, attack range radius 2.0 tiles, magic damage, hits up to 3 targets; every hit adds 灼燃损伤 (burn elemental damage) = 20% of its ATK and applies 元素脆弱 (elemental damage taken x1.2) to enemies within 0.8 tiles of the target. Skill \"祛恶之焰\": cooldown 15 s (first cast 15 s after spawn), channels a flame on one enemy in range dealing 60% ATK magic damage per second to it and to enemies within 1.0 tile, for up to 20 s."},{"need":"9 distinct","effect":"Spawn 2 炎佑 instead; each has ATK x1.5 and takes 90% less damage (damage_resistance 0.9)."}],"formulas":{"atkMultiplier":"1 + 0.23 + 0.009*L"},"caps":"none","layerGain":"Economy-driven: 惊蛰 获得时 +shop level (no activation needed); 小满 休整期结束 +1 per operator gained this rouLine truncated
|
||||
+1
-1
@@ -154,7 +154,7 @@ Top level: `{ season, seasonName, modes, economy, lpCapPerRound, bossOvertimeAft
|
||||
| `name`, `appellation` | `"隐现"`, `"Insider"` | |
|
||||
| `rarity` | `5` | stars 1–6 |
|
||||
| `profession`, `subProfessionId`, `subProfessionName`, `position` | `"SNIPER"`, `"fastshot"`, `"速射手"`, `"RANGED"` | |
|
||||
| `placement` | | not stored. A MELEE chess may stand on a 高台 only when it is elite 歌蕾蒂娅 (`char_474_glady`, `isGolden`) carrying HOK-Y 淡金坠饰 (`uniequip_003_glady`), decided at place time from the loadout (`shared/highGround.js`, `board.js placeClass`). The trait 「可以放置于远程位」 is not read. Owner's decision 2026-10-04; §22.6's `placement: "all"` is gone. `position` stays MELEE for the battle |
|
||||
| `placement` | | not stored. A MELEE chess may also stand on a 高台 when its trait without a module (`traitBase`, else `trait`) reads 「可以放置于远程位」 — the 钩索师 / 推击手 branch trait: 歌蕾蒂娅, 崖心, 见行者, normal and elite; the module does not matter (every module of the three keeps the line). Read at place time (`shared/highGround.js meleeOnHighGround`, `board.js positionClass`); the owner's decision of 2026-10-05, following PRTS (it reverses the 2026-10-04 one: elite 歌蕾蒂娅 with HOK-Y only). `position` stays MELEE for the battle |
|
||||
| `nationId` | `"laterano"` | |
|
||||
| `bonds[]` | `["lateranoShip","swiftShip"]` | bondIds (→ `bonds.json`) |
|
||||
| `garrisonIds[]` | `["garrison_16_b"]` | 特质 (→ `garrisons.json`); first = displayed trait |
|
||||
|
||||
+2
-2
@@ -155,7 +155,7 @@ Ownership rule for parallel agents: **only edit files assigned to you**; if you
|
||||
- **Partner display** cols 11–18 of rows 9–12 (the unite field uses them).
|
||||
- **Boss field**: rows 1–5; left half cols 2–10, right half cols 10–18.
|
||||
- Enemy preview pen rows 14–18 × cols 7–13 (row 16 empty): during prep the next round's enemies idle there (upper-gate enemies rows 17–18, lower-gate rows 14–15, ≤ 50 models, spawn-time order) — research 08 §4 / 09 §2.
|
||||
- Tile semantics come from `data/stages.json` legend: height (LOW/HIGH), buildable (ALL/MELEE/RANGED/NONE — the **effective** deploy type: the 深水区 `tile_deepsea` refuses deployment, NONE with the level's `buildableType` ALL kept, PRTS 深水区 地形信息 "拒绝部署(待补充)"; an active 特制水上平台 makes its tile deployable in the prep deploy map only, §21.3), ground-passable, fly-only, special terrain (mire, smog, deepsea, infection). The fenced tiles (围墙 `tile_fence_bound` / 围栏 `tile_fence`, legend `b`: LOW, buildable ALL, passable to flyers only) take units, which attack normally from there but block no ground enemy (PRTS 地形机制, §21.23). Melee chess may stand only on LOW tiles with buildable ALL/MELEE — except elite 歌蕾蒂娅 carrying module HOK-Y 淡金坠饰 (`uniequip_003_glady`), who may use the ranged tiles too (owner's decision 2026-10-04; the branch trait 「可以放置于远程位」 is not read, §22.6 reversed); ranged chess on ALL/RANGED **and** on LOW ALL/MELEE tiles ("所有行动内远程干员可部署在近战位"). Tokens follow their own `position`; a summon marked `ownerRange` (狼群, 流形: "只能部署在召唤者攻击范围内") goes only on a tile of its owner's attack range — the loadout grid rotated by the owner's facing around its tile (`PlayerState.summonRange`, §21.3).
|
||||
- Tile semantics come from `data/stages.json` legend: height (LOW/HIGH), buildable (ALL/MELEE/RANGED/NONE — the **effective** deploy type: the 深水区 `tile_deepsea` refuses deployment, NONE with the level's `buildableType` ALL kept, PRTS 深水区 地形信息 "拒绝部署(待补充)"; an active 特制水上平台 makes its tile deployable in the prep deploy map only, §21.3), ground-passable, fly-only, special terrain (mire, smog, deepsea, infection). The fenced tiles (围墙 `tile_fence_bound` / 围栏 `tile_fence`, legend `b`: LOW, buildable ALL, passable to flyers only) take units, which attack normally from there but block no ground enemy (PRTS 地形机制, §21.23). Melee chess may stand only on LOW tiles with buildable ALL/MELEE — except a melee chess whose trait reads 「可以放置于远程位」 (the 钩索师 / 推击手 branch trait: 歌蕾蒂娅, 崖心, 见行者, normal and elite, with any module or none), which may use the ranged tiles too (`shared/highGround.js`; the owner's decision of 2026-10-05, following PRTS — it reverses the 2026-10-04 one that allowed only elite 歌蕾蒂娅 with HOK-Y; on a 高台 it attacks and blocks nothing); ranged chess on ALL/RANGED **and** on LOW ALL/MELEE tiles ("所有行动内远程干员可部署在近战位"). Tokens follow their own `position`; a summon marked `ownerRange` (狼群, 流形: "只能部署在召唤者攻击范围内") goes only on a tile of its owner's attack range — the loadout grid rotated by the owner's facing around its tile (`PlayerState.summonRange`, §21.3).
|
||||
- **Facing (corrected, see research 09 §1.2):** like standard Arknights, every board piece has a direction `dir ∈ UP|RIGHT|DOWN|LEFT` chosen with the 4-direction deploy wheel after dropping it on a tile (also re-orientable in place); default `RIGHT`; persists across rounds. Range grid entries are `[dRow, dCol]` relative to facing RIGHT and are rotated: RIGHT `(dr,dc)`, UP `(dc,−dr)`, LEFT `(−dr,−dc)`, DOWN `(−dc,dr)` (row 0 = bottom); `rangeExtend` applies along +dCol before rotating — to a running skill's range too, unless that skill ignores 攻击距离 (`targeting.noRangeExtend`, 信仰搅拌机 S3, §21.16). The right-side Final Assault player is mirrored col `c→20−c` with RIGHT↔LEFT (UP/DOWN unchanged).
|
||||
- **Range test:** an enemy is inside a grid range if the tile containing it (`round(y), round(x)`) is one of the range tiles; a huge enemy (data `hitArea`: 巨型单位, a 4.95 × 2.95 rectangle moved 1.0 up) if any tile its hit rectangle overlaps is one (PRTS 作战机制 "巨型BOSS单位的每一个占据的格子都可以让其本身通过格子判定"; `sim/body.js`, §19.4). Radius ranges (enemies, auras, AoE) use Euclidean distance in tiles — to a huge enemy's rectangle [ASSUMED] — except splash around a struck target, a 中点判定 on positions (PRTS 作战机制 "中点判定…案例:阻挡,酒神1天赋的1.3溅射半径"). A ranged enemy's normal attack takes an ally whose collider (radius 0.25, PRTS 作战机制 §碰撞体积 "我方干员碰撞体积基本均为以0.25格为半径的圆形") touches its range circle: centre distance ≤ `rangeRadius` + 0.25 (`constants.js ALLY_COLLIDER_RADIUS`, `ai.js enemyAttack`; §20.4).
|
||||
- **Fields at runtime:** a `Battle` receives a **field rect** (rows/cols subset) and the full stage grid. Normal battles use rows 9–12 × cols 0–10; unite uses rows 9–12 × cols 0–20 — on its own map, the escaped template's (stages.json `kind: 'unite'`, `unite.js uniteStageId`; GitHub #41), not the round's stage; boss uses rows 0–5 × cols 0–20 (solo boss uses the left half only). Pathfinding never leaves the rect.
|
||||
@@ -418,7 +418,7 @@ Per match: pick stage (weighted among the mode's `config.modes[m].stages`, weigh
|
||||
|
||||
### 6.6 AI players (bot.js)
|
||||
|
||||
Deterministic-ish heuristic player used for (a) AI teammates, (b) auto-play for disconnected humans (only auto-ready + auto-picks, not shopping, unless "AI 托管" is toggled), (c) tests. Strategy (§21.6): pick a band (weighted by starting LP; never one built around a bond the mode switches off — `gd.bandBondIds`, §21.26); each prep: take offers, sell dead bench weight, fill the board, complete affordable merges, level on the curve, then buy only merge progress / lineup upgrades worth more than the refreshes their price would buy (shop odds of completing held pairs), freeze for an unaffordable third copy (坎诺特 keeps 5 funds back); build around a committed focus core bond (a teammate's main bond on its strip counts against it; bonds the mode switches off never) + a second bond; value dealers by DPS vs the round's DEF / RES (an attack on every enemy in range counts double — 阵法术师 / 轰击术师), with the range the unit is deployed with; place by the exposure model + rehearsal on the server's deploy map (no 深水区; a tactician's 援军 within `PlayerState.summonRange`; a 钩索师 / 推击手 on the ground tiles, as a blocker — §22.6; `g.move` judges legality); items by effect (META §1.5: 突变细胞 on the least valuable normal single below 6阶, a cell left in temp gets a hand slot made for it, the operator its transformation gains is deployed by the next prep's lineup step like any owned unit — AI 托管 too; the buy loop's bench shed never sells a piece gained since the bot's last prep, §21.1); 机变 bounties by expected payout − expected LP loss over the offered cards; resolve temp — on a human seat under AI 托管 never by destroying an item while a bench operator can be sold for the slot —; ready. A bot's whole prep — shop decisions and layout planning (`botPrepBeginSteps`, 25–70 ms late in a 4-bot match), the layout rehearsal and `botPrepEndSteps` — runs in wall-clock slices of `botSliceMs` (8 ms) per scheduler callback on a real host (step generators that yield between whole actions, never with a transient board; the same actions in the same order, so decisions are unchanged; at once in virtual time).
|
||||
Deterministic-ish heuristic player used for (a) AI teammates, (b) auto-play for disconnected humans (only auto-ready + auto-picks, not shopping, unless "AI 托管" is toggled), (c) tests. Strategy (§21.6): pick a band (weighted by starting LP; never one built around a bond the mode switches off — `gd.bandBondIds`, §21.26); each prep: take offers, sell dead bench weight, fill the board, complete affordable merges, level on the curve, then buy only merge progress / lineup upgrades worth more than the refreshes their price would buy (shop odds of completing held pairs), freeze for an unaffordable third copy (坎诺特 keeps 5 funds back); build around a committed focus core bond (a teammate's main bond on its strip counts against it; bonds the mode switches off never) + a second bond; value dealers by DPS vs the round's DEF / RES (an attack on every enemy in range counts double — 阵法术师 / 轰击术师), with the range the unit is deployed with; place by the exposure model + rehearsal on the server's deploy map (no 深水区; a tactician's 援军 within `PlayerState.summonRange`; a melee chess whose trait reads 「可以放置于远程位」 (钩索师 / 推击手) on a 高台 whose range covers the enemy road, else on the ground, counted as a blocker in the lineup either way — §3; `g.move` judges legality); items by effect (META §1.5: 突变细胞 on the least valuable normal single below 6阶, a cell left in temp gets a hand slot made for it, the operator its transformation gains is deployed by the next prep's lineup step like any owned unit — AI 托管 too; the buy loop's bench shed never sells a piece gained since the bot's last prep, §21.1); 机变 bounties by expected payout − expected LP loss over the offered cards; resolve temp — on a human seat under AI 托管 never by destroying an item while a bench operator can be sold for the slot —; ready. A bot's whole prep — shop decisions and layout planning (`botPrepBeginSteps`, 25–70 ms late in a 4-bot match), the layout rehearsal and `botPrepEndSteps` — runs in wall-clock slices of `botSliceMs` (8 ms) per scheduler callback on a real host (step generators that yield between whole actions, never with a transient board; the same actions in the same order, so decisions are unchanged; at once in virtual time).
|
||||
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ server/match/
|
||||
(data/tuning.json, §3.1)
|
||||
pool.js SharedPool (copies per base chess, across players), per-match bans, copy-weighted rolls
|
||||
board.js placement legality from the stage legend on the deploy field (own board / boss half); a 高台
|
||||
also takes elite 歌蕾蒂娅 with HOK-Y (shared/highGround.js), slot helpers,
|
||||
also takes a melee chess whose trait reads 可以放置于远程位 (shared/highGround.js), slot helpers,
|
||||
reading order (boardOrder), a merge's elite tile in deployment order (mergeTile)
|
||||
bondsMeta.js bond counting modes, tiers, 调和 / 独行 / 助力 / 绝技, layers
|
||||
effectsMeta.js MetaRegistry + EffectDispatcher + the handler ctx (this document, §2)
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@
|
||||
|
||||
## 4. 摆阵与朝向
|
||||
|
||||
- 从整备区把干员拖到棋盘:近战位 / 远程位高亮为可放置格。**只有精锐歌蕾蒂娅、并且装备了模组 HOK-Y「淡金坠饰」,才能放到高台上**;崖心、见行者、没晋升的歌蕾蒂娅、换了别的模组或者不装备模组,都只能放在地面。站在高台上时照常攻击,但不阻挡敌人。**水里不能部署**:战场#08(涨潮控制)中间的那条水池(深水区)和官方一样拒绝部署,任何干员和召唤物都放不上去;突袭盟约的干员再部署、战术家的援军自动选战术点时也只会落在岸上。松手后出现**方向轮盘**,向上 / 右 / 下 / 左滑动,棋盘上会用橙色条纹预览旋转后的攻击范围,松手确认;松在中心或点「✕ 点击取消」取消。
|
||||
- 从整备区把干员拖到棋盘:近战位 / 远程位高亮为可放置格。**特性写着「可以放置于远程位」的近战干员(钩索师、推击手:歌蕾蒂娅、崖心、见行者)也能放到高台上**,普通和精锐都可以,装什么模组或者不装模组都一样;其他近战干员只能放在地面。站在高台上时照常攻击,但不阻挡敌人。**水里不能部署**:战场#08(涨潮控制)中间的那条水池(深水区)和官方一样拒绝部署,任何干员和召唤物都放不上去;突袭盟约的干员再部署、战术家的援军自动选战术点时也只会落在岸上。松手后出现**方向轮盘**,向上 / 右 / 下 / 左滑动,棋盘上会用橙色条纹预览旋转后的攻击范围,松手确认;松在中心或点「✕ 点击取消」取消。
|
||||
- 想只改朝向:把干员拖回它自己所在的格子再选方向。朝向会一直保留到下一回合。
|
||||
- **点选按地上的方格**:点哪个方格就选中站在那个方格上的单位,点空方格不选任何单位(点到后一格干员画出来的头部,算作点了后面那一格)。作战中友方同样按方格;敌人在格子之间走动,点它的身体或脚下附近(0.6 格内)即可,飞行敌人点它的身体。
|
||||
- 拖动时模型一直在指针 / 手指下(脚在指针下方约半格,鼠标和触屏一样),**指针所在的格子**就是落点并高亮;装备拖到哪个格子,就配发给那个格子上的干员;在商店栏上松手则放回原位。
|
||||
|
||||
@@ -2727,7 +2727,7 @@
|
||||
},
|
||||
{
|
||||
"need": "5 distinct",
|
||||
"effect": "The first 3 阿戈尔 members by position (the devour order: leftmost first, then topmost; fixed at battle start) each revive immediately on their own first knock-out, whatever the order of knock-outs (max_free_respawn_cnt 3)."
|
||||
"effect": "The first 3 阿戈尔 members to be knocked out, in knock-out order (the battle-start devour's food included; a member never knocked out takes none), each revive immediately on that first knock-out; a member takes at most one, and a save by its own kit / item / band revive is no knock-out (max_free_respawn_cnt 3; the owner's decision of 2026-10-05)."
|
||||
}
|
||||
],
|
||||
"algorithm": [
|
||||
@@ -2748,7 +2748,7 @@
|
||||
"howToPlay": "Put cheap/high-tier fodder in front of 阿戈尔 carries: they steal base ATK and block, gain layers, and (5) revive. Tier-6 fodder gives +6 layers per battle.",
|
||||
"assumed": [
|
||||
"5000 physical 流失 ignores DEF and shields",
|
||||
"marked allied units are the player's own operators (devour hits allies)"
|
||||
"marked allied units are operators of any player (devour hits allies): on a shared field a teammate's operator in front, standing or entering 联防 knocked out, is devoured too and the chain continues through a teammate's 阿戈尔 (the owner's decision of 2026-10-05: PRTS has no own-side limit)"
|
||||
]
|
||||
},
|
||||
"members": [
|
||||
|
||||
@@ -374,7 +374,7 @@ Members (11 chess, 10 in current shop pool; by tier in shop: {'1': 1, '2': 1, '3
|
||||
|
||||
- **[3 distinct]** 阿戈尔 members maxHP x(1 + 0.35 + 0.01*L).
|
||||
- **[3 distinct (battle start)]** Devour (吞噬): see algorithm.
|
||||
- **[5 distinct]** The first 3 阿戈尔 members by position — the devour order below (step 1), i.e. the deployment order, fixed at battle start — each revive immediately on their own first knock-out, whatever the order of knock-outs (max_free_respawn_cnt 3; PRTS 阿戈尔 备注 "从最先部署(更靠左和靠上的)的【阿戈尔】干员开始", players' videos; until 0.1.3 the remake gave them to the first 3 members knocked out). A devour knock-out of one of them spends its revive (it stays standing, step 4); any other member the devour knocks out stays down.
|
||||
- **[5 distinct]** The first 3 阿戈尔 members to be knocked out, in knock-out order, each revive immediately on that first knock-out (max_free_respawn_cnt 3; the owner's decision of 2026-10-05, following players' reports — GitHub #105, #140). The battle-start devour's knock-outs count, so the food usually takes them at t = 0 (it stands again, step 4) and survivors = uneaten members + 3. A member takes at most one, on its first knock-out of the battle, however many 阿戈尔 mark it (step 4 cancels its pending marks); a save by its own kit / item / band revive (斯卡蒂's DRE-Y, M3茧甲, 埃芒加德 [ASSUMED for the band]) is no knock-out and takes none. 0.1.3 gave them to the first 3 members by position, fixed at battle start (from PRTS's devour note "从最先部署(更靠左和靠上的)的【阿戈尔】干员开始" and players' videos), so uneaten front members held them.
|
||||
- Algorithm:
|
||||
1. Order: 阿戈尔 members sorted leftmost first, then topmost ("更靠左和靠上").
|
||||
2. Each 阿戈尔 in order marks the unit on the tile directly in front of it (its facing direction) and also the front-tile unit of every 阿戈尔 it has marked (chain). It never marks itself, a unit it already marked, or a unit that marked it.
|
||||
@@ -387,7 +387,7 @@ Members (11 chess, 10 in current shop pool; by tier in shop: {'1': 1, '2': 1, '3
|
||||
- How layers are gained: Devour (tier per devoured unit, every battle); 幽灵鲨 被击倒 +3; 归溟幽灵鲨 被击倒/替身切换 +5 阿戈尔 +5 不屈; 斯卡蒂 each 2 kills +1 阿戈尔/坚守/突袭; 海霓 first kill (enemy or ally) +3 阿戈尔/奥术; 机变 "斯卡蒂的盟誓" +8. Strategy 克莱门莎: an 阿戈尔 knocked out adds layers = its tier.
|
||||
- How it plays: Put cheap/high-tier fodder in front of 阿戈尔 carries: they steal base ATK and block, gain layers, and (5) revive. Tier-6 fodder gives +6 layers per battle.
|
||||
- 5000 physical 流失: less the target's DEF (PRTS 作战机制: a 物理/法术流失 "会受到目标当前防御力/法术抗性影响而相应衰减"; DEF-free [ASSUMED] until 0.1.1), no shields, dodge or damage multipliers (a 流失)
|
||||
- [ASSUMED] marked allied units are the player's own operators (devour hits allies)
|
||||
- Marked units are allied operators (devour hits allies), whoever owns them: on a shared field (联防, boss) a teammate's operator in front — standing, or one that entered 联防 knocked out — is devoured too, with the same base ATK / block gains, and the chain continues through a teammate's 阿戈尔 (the owner's decision of 2026-10-05; PRTS "依次吞噬身前一格干员" has no own-side limit; GitHub #140 comment 4). Its knock-out is its owner's (their revives). The remake's two 联防 helpers stand on board cols 3–9 and 11–17 with the road column 10 between them, so on the current maps no teammate's operator is ever in front.
|
||||
- Bond item (with 变形同构体 grants this bond): 阿戈尔重刃 `chess_item_3_07_e` (2 gold: 攻击力+40%,攻击速度-10)
|
||||
- Garrisons that explicitly add layers to this bond: `garrison_38`, `garrison_40`, `garrison_46`, `garrison_131` (see section 4; plus the generic ones)
|
||||
- Garrisons that scale with this bond's layers: `garrison_07`, `garrison_09`, `garrison_10`, `garrison_12`, `garrison_84`
|
||||
|
||||
@@ -1981,7 +1981,7 @@ Consequences for the current pool:
|
||||
- Tokens marked `DEFAULT` in `shopStateTokenDict` are these placeable pieces: 医疗探机, 诅咒娃娃, 狼群, 斯卡蒂的海嗣, 流形. `HIDDEN` tokens exist only in battle.
|
||||
- [ASSUMED] Summons do **not** use one of the 8 deploy slots, as in the base game. Keep this as a config flag.
|
||||
- **Battle start:** every board unit deploys for free, in order **从上到下>从左到右** (下半): down each column, the columns left to right (research 01 §4.3). In the boss round the order is mirrored for the right-side player. After that, knocked-out units redeploy automatically on their tile when the respawn timer is done and DP ≥ `cost` (DP starts at 10, +1/s, cap 99).
|
||||
- **Ranged units may stand on melee tiles** ("所有行动内远程干员可部署在近战位"). Melee units may **not** use ranged-only tiles (HIGH `h`) — except elite 歌蕾蒂娅 carrying HOK-Y 淡金坠饰 (`uniequip_003_glady`). The branch trait 「可以放置于远程位」 (钩索师 / 推击手; PRTS 新人入门 "可部署在高台和地面") is on every variant and is **not** read (owner's decision 2026-10-04, reversing the §22.6 reading of GitHub #32 item 4). 崖心 has only HOK-X; 见行者, a normal record, any other module and no module stay on the ground. Maps: see 05.
|
||||
- **Ranged units may stand on melee tiles** ("所有行动内远程干员可部署在近战位"). Melee units may **not** use ranged-only tiles (HIGH `h`) — except those whose trait reads 「可以放置于远程位」: the 钩索师 / 推击手 branch trait (歌蕾蒂娅, 崖心, 见行者, normal and elite; PRTS 歌蕾蒂娅 · 特性 and 新人入门 "可部署在高台和地面"), which every module of the three keeps, so any module or none. The owner's decision of 2026-10-05 follows PRTS (raised with the PRTS source in PR #69 by @sunstricken) and reverses the 2026-10-04 one (elite 歌蕾蒂娅 with HOK-Y only). A module's 部署效果 (教官 Y "可以额外部署在远程位") stays off in this mode (PRTS 卫戍协议/帮助 §战斗部署). Maps: see 05.
|
||||
|
||||
### C3. Pool membership per match
|
||||
The per-match ban removes every visible chess whose bonds are **all** in the disabled set. The rule is verified; see 01 Addendum A2. Elites of banned chess are also unobtainable. Hidden chess (17) stay out of the shop as §1.2 says.
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// light legal tiles while dragging; the server stays authoritative and may still refuse a move.
|
||||
//
|
||||
// Board = own normal field (GEO.FIELD rows 9–12, cols 2–10). Melee chess stand on `melee` deploy tiles
|
||||
// (LOW, buildable ALL/MELEE) — elite 歌蕾蒂娅 carrying HOK-Y (shared/highGround.js, the player's loadout) on any
|
||||
// deploy tile, the 高台 included (piecePosition 'ALL'); ranged chess on `melee ∪ rangedOnly` (stages.json → deployTiles.normal,
|
||||
// (LOW, buildable ALL/MELEE) — a melee chess whose trait reads 「可以放置于远程位」 (shared/highGround.js: 歌蕾蒂娅, 崖心,
|
||||
// 见行者, any module) on any deploy tile, the 高台 included (piecePosition 'ALL'); ranged chess on `melee ∪ rangedOnly` (stages.json → deployTiles.normal,
|
||||
// derived from the tile legend when missing — the legend's `buildable` is the effective type: 深水区 tile_deepsea
|
||||
// refuses deployment, PRTS 深水区 地形信息 "拒绝部署(待补充)", player report #3 after 0.1.0). Tokens follow their
|
||||
// own `position`; a summon whose text reads "只能部署在召唤者攻击范围内" (tokens.json `ownerRange`: 伺夜's 狼群,
|
||||
|
||||
@@ -6,7 +6,7 @@ import { meleeOnHighGround } from '../../../../shared/highGround.js';
|
||||
import { pieceDir, rangeTiles } from '../facing.js';
|
||||
import { isObj, tileKey } from './shared.js';
|
||||
import { boardTileOf, fieldTile } from './camera.js';
|
||||
import { deployedRecord, deployedModuleId, fieldsStandIn, standInOf } from './standIn.js';
|
||||
import { deployedRecord, fieldsStandIn, standInOf } from './standIn.js';
|
||||
|
||||
|
||||
// ---- placement (canPlace mirror) ------------------------------------------------------------------------
|
||||
@@ -213,9 +213,10 @@ export function placementContext({ priv, stage, editable, field = 'normal', getC
|
||||
}
|
||||
|
||||
/**
|
||||
* Deploy position ('MELEE'|'RANGED'|'ALL') of a chess/token piece, or null for items. Elite 歌蕾蒂娅 carrying HOK-Y
|
||||
* (the viewer's loadout, shared/highGround.js) is 'ALL': any deployable tile, the 高台 included
|
||||
* (server/match/board.js placeClass; owner's decision 2026-10-04). Every other MELEE chess is ground-only.
|
||||
* Deploy position ('MELEE'|'RANGED'|'ALL') of a chess/token piece, or null for items. A MELEE chess whose trait reads
|
||||
* 「可以放置于远程位」 (shared/highGround.js: 歌蕾蒂娅, 崖心, 见行者, normal and elite, any module) is 'ALL': any deployable
|
||||
* tile, the 高台 included (server/match/board.js positionClass; the owner's decision of 2026-10-05). Every other MELEE
|
||||
* chess is ground-only.
|
||||
*/
|
||||
export function piecePosition(ctx, piece) {
|
||||
if (!isObj(piece)) return null;
|
||||
@@ -223,8 +224,7 @@ export function piecePosition(ctx, piece) {
|
||||
const chess = ctx.getChess(piece.id);
|
||||
// 0.2.0 补位: a chess the player fields as its stand-in is placed by the stand-in's position (server placeClass)
|
||||
const rec = (fieldsStandIn(ctx.priv, chess) && standInOf(chess, ctx.backups)) || chess;
|
||||
const moduleId = deployedModuleId(chess, ctx.priv, ctx.getChess, ctx.backups);
|
||||
if (meleeOnHighGround(rec, moduleId)) return 'ALL';
|
||||
if (meleeOnHighGround(rec)) return 'ALL';
|
||||
return rec?.position === 'MELEE' ? 'MELEE' : 'RANGED';
|
||||
}
|
||||
// tokens: MELEE → ground only; RANGED / ALL → any deployable tile
|
||||
|
||||
@@ -90,8 +90,8 @@ export function deployedRecord(chess, priv, getChess, backups) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The module id a deployed piece carries (the placement rule of elite 歌蕾蒂娅's HOK-Y reads it): a stand-in's backup
|
||||
* module, else the player's loadout.
|
||||
* The module id a deployed piece carries: a stand-in's backup module, else the player's loadout. (The 高台 rule no
|
||||
* longer reads it: since the owner's decision of 2026-10-05 it is the trait, whatever the module — shared/highGround.js.)
|
||||
*/
|
||||
export function deployedModuleId(chess, priv, getChess, backups) {
|
||||
if (!isObj(chess)) return null;
|
||||
|
||||
+26
-27
@@ -4,8 +4,8 @@
|
||||
// stage legend (data/stages.json `tiles[glyph]`: height + buildable) and the stage devices:
|
||||
// 'melee' — LOW tile with buildable ALL/MELEE, or a 深水区 under an active 特制水上平台 (waterPlatform, "在水上建立可以
|
||||
// 部署任意单位的平台"): melee AND ranged chess may stand here ("所有行动内远程干员可部署在近战位").
|
||||
// 'ranged' — HIGH tile with buildable ALL/RANGED, or a tile under an active platform (射击台): ranged only (and elite
|
||||
// 歌蕾蒂娅 carrying HOK-Y, placeClass below).
|
||||
// 'ranged' — HIGH tile with buildable ALL/RANGED, or a tile under an active platform (射击台): ranged only (and the
|
||||
// melee chess whose trait reads 「可以放置于远程位」, positionClass below).
|
||||
// (absent) — not deployable (NONE, forbidden, road lanes, tiles under active crates/mounds, the 深水区 — the legend's
|
||||
// `buildable` is the effective type: tile_deepsea refuses deployment, PRTS 深水区 地形信息
|
||||
// "拒绝部署(待补充)", although its level buildableType is ALL; player report #3 after 0.1.0, 战场#08's
|
||||
@@ -23,10 +23,10 @@
|
||||
// (10–12, 8), which are '#' on the normal field. The result equals stages[id].deployTiles.bossLeft / bossRight
|
||||
// mapped to board coordinates (test/match/playtest5-deploy.test.js).
|
||||
//
|
||||
// Chess follow their `position` (MELEE ⇒ melee tiles, RANGED ⇒ any deployable), except elite 歌蕾蒂娅 carrying module
|
||||
// HOK-Y 淡金坠饰 (uniequip_003_glady: `placeClass` / shared/highGround.js ⇒ any deployable tile). The branch trait
|
||||
// 「可以放置于远程位」 is not read (owner's decision 2026-10-04, reversing DESIGN §22.6): 崖心, 见行者, a normal record,
|
||||
// any other module and no module are ground-only. The equipped module is the player's loadout at place time.
|
||||
// Chess follow their `position` (MELEE ⇒ melee tiles, RANGED ⇒ any deployable), except a MELEE chess whose trait reads
|
||||
// 「可以放置于远程位」 — the 钩索师 / 推击手 branch trait: 歌蕾蒂娅, 崖心, 见行者, normal and elite, any module or none
|
||||
// (shared/highGround.js ⇒ any deployable tile; the owner's decision of 2026-10-05, following PRTS). The loadout does
|
||||
// not change the class.
|
||||
// Tokens follow their own `position` (ALL ⇒ any deployable tile, MELEE ⇒ melee tiles, RANGED ⇒ any deployable).
|
||||
// A token whose text reads "只能部署在召唤者攻击范围内" (tokens.json `ownerRange`: the tacticians' 援军 — 伺夜's 狼群,
|
||||
// 缪尔赛思's 流形; PRTS 狼群 特性) also needs a tile of its owner's attack range: `ownerRangeKeys` = the owner's range
|
||||
@@ -135,41 +135,40 @@ export function buildDeployMap(stage, { deviceOverrides = {}, tileOverrides = {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Placement class of a chess / token record: 'melee' | 'ranged' | 'all'. Widened to 'all' only for elite 歌蕾蒂娅
|
||||
* carrying HOK-Y (`moduleId` = uniequip_003_glady, shared/highGround.js): she may stand on the ranged (高台) tiles.
|
||||
* Any other module, no module, and every other MELEE record stay 'melee'. `chess.json` has no `placement` field.
|
||||
* Placement class of a chess / token record: 'melee' | 'ranged' | 'all'. A MELEE chess whose trait reads
|
||||
* 「可以放置于远程位」 (shared/highGround.js: 歌蕾蒂娅, 崖心, 见行者, normal and elite) is widened to 'all': it may also
|
||||
* stand on the ranged (高台) tiles. Every other MELEE record stays 'melee'. `chess.json` has no `placement` field.
|
||||
* @param {object|null} rec
|
||||
* @param {string|null} [moduleId] equipped module; ignored for tokens and non-golden records
|
||||
*/
|
||||
export function positionClass(rec, moduleId = null) {
|
||||
return meleeOnHighGround(rec, moduleId) ? 'all' : basePositionClass(rec);
|
||||
export function positionClass(rec) {
|
||||
return meleeOnHighGround(rec) ? 'all' : basePositionClass(rec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Placement class of a record under a player's loadout (the module `ps.loadoutFor` resolves, defaults included).
|
||||
* Tokens and records without a chess id ignore the loadout. A chess the player fields as its stand-in (0.2.0 补位,
|
||||
* `ps.fieldRecord`) is placed by the stand-in's position — the body that is deployed (圣约送葬人's 预备干员-先锋 stands on
|
||||
* the ground, 塞雷娅's Touch anywhere) [ASSUMED: the official deploy check reads the fielded character].
|
||||
* @param {{ loadoutFor?: (rec: object) => { moduleId?: string|null }|null, fieldRecord?: (rec: object) => object }|null} ps
|
||||
* Placement class of a record on a player's board — the server's single entry point for pieces (g.move, swaps, merges,
|
||||
* the audit, the invariants, the bot). Since the owner's decision of 2026-10-05 the player's loadout no longer changes
|
||||
* it (any module, or none). A chess the player fields as its stand-in (0.2.0 补位, `ps.fieldRecord`) is placed by the
|
||||
* stand-in's position — the body that is deployed (圣约送葬人's 预备干员-先锋 stands on the ground, 塞雷娅's Touch
|
||||
* anywhere) [ASSUMED: the official deploy check reads the fielded character]; tokens and records without a chess id
|
||||
* are their own body.
|
||||
* @param {{ fieldRecord?: (rec: object) => object }|null} ps
|
||||
* @param {object|null} rec
|
||||
*/
|
||||
export function placeClass(ps, rec) {
|
||||
if (!rec || !rec.chessId || !ps || typeof ps.loadoutFor !== 'function') return positionClass(rec);
|
||||
let moduleId = null;
|
||||
let body = rec;
|
||||
if (!rec || !rec.chessId || !ps || typeof ps.fieldRecord !== 'function') return positionClass(rec);
|
||||
let body;
|
||||
try {
|
||||
const lo = ps.loadoutFor(rec);
|
||||
moduleId = lo && typeof lo.moduleId === 'string' ? lo.moduleId : null;
|
||||
if (typeof ps.fieldRecord === 'function') body = ps.fieldRecord(rec) || rec;
|
||||
body = ps.fieldRecord(rec) || rec;
|
||||
} catch {
|
||||
moduleId = null;
|
||||
body = rec;
|
||||
}
|
||||
return positionClass(body, moduleId);
|
||||
return positionClass(body);
|
||||
}
|
||||
|
||||
/**
|
||||
* The record's own position class ('melee' | 'ranged' | 'all'), without the placement widening — the class the battle
|
||||
* plays (a MELEE operator still blocks on a ground tile; on a 高台 it blocks nothing): the bots' blocker test and the
|
||||
* tiles they plan for it (bot.js).
|
||||
* plays (a MELEE operator still blocks on a ground tile; on a 高台 it blocks nothing): the bots' blocker test and their
|
||||
* 高台 preference for a widened melee chess (bot.js isBlocker / planLayoutSteps).
|
||||
*/
|
||||
export function basePositionClass(rec) {
|
||||
const p = rec && typeof rec.position === 'string' ? rec.position.toUpperCase() : 'ALL';
|
||||
|
||||
+7
-4
@@ -34,8 +34,10 @@
|
||||
// covering units against the round's DEF / RES, blocker hold time, flyers only for anti-air) is maximized
|
||||
// greedily — blockers first, then damage dealers by DPS, then healers — over every
|
||||
// (legal tile, direction) pair of the server's deploy map (no 深水区). A MELEE operator is planned on the ground
|
||||
// tiles, where it blocks — except elite 歌蕾蒂娅 carrying HOK-Y, who may also take a 高台 (placeClass; owner's
|
||||
// decision 2026-10-04). She stays a blocker in the lineup (basePositionClass). Each unit's range grid — the one it is
|
||||
// tiles, where it blocks — except one whose trait reads 「可以放置于远程位」 (歌蕾蒂娅, 崖心, 见行者, any module:
|
||||
// placeClass 'all', shared/highGround.js), which takes a 高台 whose range covers the enemy road, else the ground
|
||||
// (owner 2026-10-04 for the 高台 preference, 2026-10-05 for who may use one). It stays a blocker in the lineup
|
||||
// (basePositionClass). Each unit's range grid — the one it is
|
||||
// deployed with, rangeRec (loadoutRecord attackRangeGrid) — is rotated per direction (DESIGN §3; RIGHT is tried first
|
||||
// and kept on ties, so symmetric ranges and melee units whose front adds nothing stay facing the gates), so
|
||||
// ranged units turn toward the enemy path tiles they cover best and blockers toward the road; on 气流 tiles
|
||||
@@ -951,8 +953,9 @@ export function* planLayoutSteps(m, ps, pieces, params = LAYOUT_PARAMS, { occupi
|
||||
let bestV = -Infinity;
|
||||
// a "只能部署在召唤者攻击范围内" summon (伺夜's 狼群, 缪尔赛思's 流形): only the tiles of its owner's range
|
||||
const within = p.kind === 'token' && typeof ps.summonRange === 'function' ? ps.summonRange(p) : null;
|
||||
// ground tiles for a MELEE blocker. placeClass 'all' is only elite 歌蕾蒂娅 + HOK-Y: she may stand on a 高台,
|
||||
// and when one of those tiles covers the enemy road she is planned there (owner 2026-10-04: the bot uses the 高台).
|
||||
// ground tiles for a MELEE blocker. placeClass 'all' on a MELEE record is a chess whose trait reads 「可以放置于远程位」
|
||||
// (歌蕾蒂娅, 崖心, 见行者, any module): it may stand on a 高台, and when one of those tiles covers the enemy road it is
|
||||
// planned there even with the ground free (owner 2026-10-04: the bot uses the 高台; 2026-10-05: every such chess).
|
||||
const cls = p.kind === 'token' ? basePositionClass(r0) : placeClass(ps, m.gd.chess(p.id) || r0);
|
||||
const preferHigh = cls === 'all' && basePositionClass(r0) === 'melee';
|
||||
let bestHigh = null;
|
||||
|
||||
@@ -37,7 +37,8 @@ export class PlayerPlacement {
|
||||
|
||||
_placementOf(piece) {
|
||||
const rec = piece.kind === 'token' ? this.gd.token(piece.id) : this.gd.chess(piece.id);
|
||||
// elite 歌蕾蒂娅 + HOK-Y may use a 高台; the module is this player's loadout (owner's decision 2026-10-04)
|
||||
// a melee chess whose trait reads 「可以放置于远程位」 may use a 高台, whatever its module (shared/highGround.js); a
|
||||
// stand-in is placed by its own record (placeClass)
|
||||
return placeClass(this, rec);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
// 拉特兰 lateranoShip member ammo skills start with floor(ammo × (1 + base_ammo_percent + ammo_percent_per_stack·L));
|
||||
// 6: every ammo used by a member → all members ATK +atk_per_consume (≤ max_atk_for_consume)
|
||||
// 阿戈尔 egirShip members max HP +(base_max_hp + max_hp_per_stack·L) (直接乘算); battle start devour (see devour());
|
||||
// 5: the first max_free_respawn_cnt members by position (the devour's order, fixed at battle
|
||||
// start) each redeploy at once (free) on their first knock-out
|
||||
// 5: the first max_free_respawn_cnt members knocked out (in knock-out order, the devour's food
|
||||
// included) each redeploy at once (free) on that first knock-out
|
||||
// 叙拉古 siracusaShip every member deployment: ASPD +(base + per·L) for (base_duration + per·L) s; 6: 隐匿 for the same
|
||||
// time, and while hidden / end_duration s after, every 普通伤害 hit (siracusaRolls) procs (PRD,
|
||||
// nominal `prob`) base_damage + damage_per_stack·L true damage + fear `fear` s
|
||||
@@ -34,7 +34,7 @@
|
||||
// Two players in one field: everything is per player (own members, own deployments); the 谢拉格 wind and 炎佑 act on
|
||||
// every enemy of the field (debuffs on shared enemies help both, research 06 §8.6).
|
||||
// Hook priorities: 拉特兰 skillStart −10 (after kits' own ammo changes), 阿戈尔 death 11 (5-tier revive, before 不屈's
|
||||
// death 10), layerGain −100 (after 魔王-style modifiers).
|
||||
// death 10; every `fatal` saver runs before any death hook), layerGain −100 (after 魔王-style modifiers).
|
||||
|
||||
import * as S from '../support/index.js';
|
||||
import { mitigate } from '../../damage.js';
|
||||
@@ -334,15 +334,14 @@ function installLaterano(battle, pid, bb, members) {
|
||||
|
||||
// "更靠左和靠上": left first (on the player's own board: mirrored players count from the field's right), then top first —
|
||||
// row 0 is the BOTTOM row (DESIGN §3), so the top of the board is the highest row index. The order is a board position,
|
||||
// independent of the members' directions (only "身前" follows each member's `dir`). The devour marks in this order and the
|
||||
// 5-tier revive's beneficiaries are the first members in it (PRTS "从最先部署(更靠左和靠上的)的【阿戈尔】干员开始"; the
|
||||
// battle's initial deployment order, Battle.start).
|
||||
// independent of the members' directions (only "身前" follows each member's `dir`). The devour marks in this order (PRTS
|
||||
// "从最先部署(更靠左和靠上的)的【阿戈尔】干员开始"; the battle's initial deployment order, Battle.start).
|
||||
const boardCol = (u) => (u.player && u.player.mirror ? -u.tileC : u.tileC);
|
||||
const egirOrder = (a, b) => boardCol(a) - boardCol(b) || b.tileR - a.tileR || a.id - b.id;
|
||||
|
||||
/**
|
||||
* 联防: an operator forced out at the deployment (carry.down, Battle.start, before battleStart) still stands on its
|
||||
* deploy position. The devour and the 5-tier revive slots both count it there (PRTS 盟约记录 前3名 / 最先部署).
|
||||
* deploy position for the devour (PRTS 盟约记录 最先部署). The forced exit is not a knock-out, so it takes no 5-tier slot.
|
||||
*/
|
||||
function egirDownAtStart(battle, u) {
|
||||
return S.isOp(u) && !u.alive && u.removeReason === FORCED_EXIT && !!u.carry && u.carry.down === true
|
||||
@@ -365,11 +364,14 @@ function egirDownAtStart(battle, u) {
|
||||
* out and back in the same pass still gives its marks).
|
||||
* 联防: the operators down since the end of their own combat (forced out by Battle.start) mark, are marked and resolve
|
||||
* their marks like standing ones, but nothing resolves on them (below; per players' reports, owner's decision 2026-10-04).
|
||||
* Each devoured operator adds its tier to 阿戈尔 once (IN_BATTLE gain, disabled in 联防 / boss fields).
|
||||
* Whose operator stands in front does not matter (PRTS "依次吞噬身前一格干员", no own-side limit; the owner's decision of
|
||||
* 2026-10-05 after GitHub #140 comment 4): on a shared field (联防, boss) a teammate's operator — standing, or entering
|
||||
* 联防 down — is marked like an own one, gives the same base ATK / block count, and the chain goes on through it when it
|
||||
* is an 阿戈尔 (S.isMember: its own bonds). Its knock-out is its owner's (their bonds' revives, 不屈 …), credited to the
|
||||
* marker as usual. Each devoured operator adds its tier to 阿戈尔 once (IN_BATTLE gain, disabled in 联防 / boss fields).
|
||||
* Tokens / devices / empty tiles are never devoured.
|
||||
*/
|
||||
function devour(battle, pid, bb, members) {
|
||||
const memberSet = new Set(members);
|
||||
// 联防: an operator down at the end of its own combat (carryState.down — Battle.start forced it out right before
|
||||
// battleStart, FORCED_EXIT) takes part in the devour as if it stood on its tile, then stays out: it marks in its turn,
|
||||
// it is "the unit in front" of another (the chain goes on through it when it is a member), its base ATK / block count
|
||||
@@ -378,12 +380,14 @@ function devour(battle, pid, bb, members) {
|
||||
// report #3, GitHub #33 item 3), owner's decision 2026-10-04; until 0.1.2 the forced exit came first and the chain broke.
|
||||
const downAtStart = (u) => egirDownAtStart(battle, u);
|
||||
const order = members.filter((u) => S.onField(u) || downAtStart(u)).sort(egirOrder);
|
||||
// the operator in front, whoever owns it (until 0.1.3 only the player's own): a living one, else one lying there since
|
||||
// the 联防 start (carry.down, forced out) — a teammate's included
|
||||
const opAt = (u) => {
|
||||
const [r, c] = S.frontTile(u);
|
||||
const a = S.allyAt(battle, r, c, pid);
|
||||
const a = S.allyAt(battle, r, c);
|
||||
if (a) return S.isOp(a) && a.alive ? a : null;
|
||||
const d = battle.downOn(r, c);
|
||||
return d && d.ownerId === pid && downAtStart(d) ? d : null;
|
||||
return d && downAtStart(d) ? d : null;
|
||||
};
|
||||
const markedBy = new Map(); // marker → [targets]
|
||||
const marks = [];
|
||||
@@ -398,7 +402,8 @@ function devour(battle, pid, bb, members) {
|
||||
if ((markedBy.get(t) ?? []).includes(m)) continue;
|
||||
seen.add(t);
|
||||
mine.push(t);
|
||||
if (memberSet.has(t)) queue.push(t);
|
||||
// through a marked 阿戈尔 (for the player's own operators: exactly its members; a teammate's by its own bonds)
|
||||
if (S.isMember(battle, t, 'egirShip')) queue.push(t);
|
||||
}
|
||||
markedBy.set(m, mine);
|
||||
if (!mine.length) continue;
|
||||
@@ -437,37 +442,37 @@ function installEgir(battle, pid, bb, members) {
|
||||
};
|
||||
apply();
|
||||
onLayers(battle, pid, 'egirShip', apply);
|
||||
// 5: "前3名【阿戈尔】干员首次被击倒时立刻复活" — the 3 (bonds.json max_free_respawn_cnt) are the first 3 members BY POSITION,
|
||||
// in the devour's order above = the battle's deployment order (PRTS 盟约记录 阿戈尔 备注 "从最先部署(更靠左和靠上的)的
|
||||
// 【阿戈尔】干员开始"; players' videos: the revivers go by position, not by who is eaten or knocked out first). They are
|
||||
// fixed at battle start, before the devour; each revives once, on its own first knock-out ('killed'), whatever the order
|
||||
// of knock-outs, so a member the devour knocks out comes back only when it is one of them. Until 0.1.3 the first 3
|
||||
// members knocked out took the revives and the devour's food spent them at t = 0. A member entering 联防 down (forced
|
||||
// out before battleStart) keeps the slot its position earned: the forced exit is not a 击倒 (reason !== 'killed'), so
|
||||
// the charge waits until they are knocked out after standing back up. A 调和 member counts like any other.
|
||||
// [ASSUMED] a beneficiary 埃芒加德 / M3茧甲 save in place (items revivedInPlace, the stand-in for PRTS's 0-time redeploy)
|
||||
// has used its revive (PRTS 不屈 备注: a held 复活 is consumed even when another effect redeploys the unit at once).
|
||||
// PRTS: the knocked-out unit's next deployment has 0 redeploy time and 0 cost, i.e. it IS knocked out (被击倒 triggers,
|
||||
// 克莱门莎, 幽灵鲨 … fire) and redeploys at once where it lies (the engine's rest tile, Battle._layBody: the tile it was
|
||||
// knocked out on — a raid-relocated member comes back where it fell —, or its own home when it fell on another board
|
||||
// piece's home; PRTS 卫戍协议/帮助 §作战阶段 单位部署) with full HP, SP reset and `deploy` effects (卡西米尔 / 叙拉古).
|
||||
// Death priority 11: before 不屈 (10), whose redeploy "also consumes a 复活 charge" — with this order the charge is
|
||||
// always the one used, same outcome. The marks still pending on a revived member are cancelled (devour).
|
||||
// 5: "前3名【阿戈尔】干员首次被击倒时立刻复活" — the 3 (bonds.json max_free_respawn_cnt) slots go to the first 3 members
|
||||
// knocked out, in knock-out order: the owner's decision of 2026-10-05, following players' reports (GitHub #105, #140:
|
||||
// "没被吃的阿戈尔干员也会占用复活名额" — with 0.1.3's fixed holders by position the uneaten front members held the
|
||||
// slots, so whatever the food chain ate only 3 阿戈尔 stood). A knock-out by the battle-start devour counts like any
|
||||
// other, so the eaten food usually takes them at t = 0 and survivors = uneaten members + 3. A member takes at most one
|
||||
// slot, on its first knock-out ('killed') in the battle: its later knock-outs never take one, and a first knock-out
|
||||
// after the 3 are gone stays down. However many members mark it, its pending marks are cancelled once it is knocked
|
||||
// out (devour), so a multi-devoured member spends one slot at most. Its own saver acts first: every kit, item or band
|
||||
// revive that prevents or replaces the knock-out is a `fatal` hook (斯卡蒂's DRE-Y −50, kit savers 10 … −60, 坚固维式
|
||||
// 重锤 PRIO_REVIVE −100, M3茧甲 PRIO_RESPAWN −101, 埃芒加德 −110), so the unit is never knocked out and no slot is used —
|
||||
// the slot waits for its first real knock-out [ASSUMED for 埃芒加德, a band: as M3茧甲, the item revive the owner named].
|
||||
// An operator entering 联防 down (FORCED_EXIT) is not knocked out either; a 调和 member counts like any other. Each
|
||||
// battle (normal, 联防, boss) counts its own. PRTS: the knocked-out unit's next deployment has 0 redeploy time and 0
|
||||
// cost, i.e. it IS knocked out (被击倒 triggers, 克莱门莎, 幽灵鲨 … fire) and redeploys at once where it lies (the
|
||||
// engine's rest tile, Battle._layBody: the tile it was knocked out on — a raid-relocated member comes back where it
|
||||
// fell —, or its own home when it fell on another board piece's home; PRTS 卫戍协议/帮助 §作战阶段 单位部署) with full
|
||||
// HP, SP reset and `deploy` effects (卡西米尔 / 叙拉古). Death priority 11: before 不屈 (10), whose redeploy "also
|
||||
// consumes a 复活 charge" — with this order the slot is always the one used, same outcome. Until 0.1.3 the slots were
|
||||
// fixed at battle start for the first 3 members by position (§23.20); until 0.1.2 the first 3 knocked out took them
|
||||
// but a revived member's pending marks could knock it out again (GitHub #33, fixed in devour since).
|
||||
const max = reached(battle, pid, 'egirShip', bb.power_bond_char_cnt) ? Math.max(0, Math.floor(num(bb.max_free_respawn_cnt, 0))) : 0;
|
||||
const holders = new Map(); // beneficiary → its in-place revives (mem.revives) at battle start
|
||||
battle.on('battleStart', () => {
|
||||
for (const u of members.filter((x) => S.isOp(x) && (S.onField(x) || egirDownAtStart(battle, x))).sort(egirOrder).slice(0, max)) holders.set(u, u.mem.revives | 0);
|
||||
devour(battle, pid, bb, members);
|
||||
}, { once: true });
|
||||
battle.on('battleStart', () => devour(battle, pid, bb, members), { once: true });
|
||||
if (!(max > 0)) return;
|
||||
const used = new Set();
|
||||
const memberOps = new Set(members.filter(S.isOp));
|
||||
const knockedOut = new Set(); // members whose first knock-out of this battle has happened
|
||||
let revives = 0;
|
||||
battle.on('death', (c) => {
|
||||
const u = c.unit;
|
||||
if (c.reason !== 'killed' || !holders.has(u) || used.has(u)) return;
|
||||
used.add(u);
|
||||
if ((u.mem.revives | 0) !== holders.get(u)) return; // saved in place since the battle start: the revive is gone
|
||||
if (u.alive || u.removed) return;
|
||||
if (c.reason !== 'killed' || !memberOps.has(u) || knockedOut.has(u)) return;
|
||||
knockedOut.add(u);
|
||||
if (revives >= max || u.alive || u.removed) return;
|
||||
if (!battle.redeploy(u, { free: true })) return;
|
||||
revives++;
|
||||
S.fxOn(battle, 'revive', u, 'bond:egirShip', 'respawn', { n: revives });
|
||||
|
||||
+23
-12
@@ -1,21 +1,32 @@
|
||||
// shared/highGround.js — which MELEE chess may stand on a 高台 (a ranged deploy tile).
|
||||
//
|
||||
// Owner's decision 2026-10-04, reversing DESIGN §22.6. The branch trait 「可以放置于远程位」 is written on
|
||||
// every 钩索师 / 推击手 variant (歌蕾蒂娅, 崖心, 见行者, normal and elite) and is not trusted. Only elite
|
||||
// 歌蕾蒂娅 carrying module HOK-Y 淡金坠饰 may use a ranged tile. 崖心 (HOK-X only), 见行者, a normal
|
||||
// record, any other module, and no module are ground-only. The golden record is the elite (`isGolden`);
|
||||
// the same module test applies to it. A missing module id is ground-only.
|
||||
// The owner's decision of 2026-10-05, reversing the one of 2026-10-04 (elite 歌蕾蒂娅 with HOK-Y only): follow PRTS. A
|
||||
// MELEE chess whose trait reads 「可以放置于远程位」 may stand on a 高台 as well as on the ground. The line is the 钩索师 /
|
||||
// 推击手 branch trait (PRTS 歌蕾蒂娅 · 特性, raised with the PRTS source in PR #69 by @sunstricken; PRTS 新人入门: both
|
||||
// branches "可部署在高台和地面"): 歌蕾蒂娅, 崖心 and 见行者, normal and elite. It is the branch's own text, not a module
|
||||
// effect — every module of the three keeps it — so the loadout does not matter: any module, or none. The text read is
|
||||
// the record's trait without a module (`traitBase`, which an elite with modules carries; else `trait`). A module talent
|
||||
// such as the 教官's Y module ("可以额外部署在远程位") is a 部署效果, which 卫戍协议 switches off (PRTS 卫戍协议/帮助
|
||||
// §战斗部署), and is not read. The battle keeps position MELEE: on a 高台 the unit attacks and blocks nothing.
|
||||
|
||||
/** char_474_glady — 歌蕾蒂娅. */
|
||||
export const GLADIIA_CHAR_ID = 'char_474_glady';
|
||||
/** HOK-Y 淡金坠饰 (data/chess.json chess_char_4_12_b.modules, typeName HOK-Y). */
|
||||
export const GLADIIA_HOK_Y = 'uniequip_003_glady';
|
||||
/** The trait line that lets a MELEE chess stand on a ranged (高台) tile. */
|
||||
export const PLACE_ON_RANGED = '可以放置于远程位';
|
||||
|
||||
/**
|
||||
* The record's trait text without a module ('' when it has none).
|
||||
* @param {object|null} rec a chess record
|
||||
* @returns {string}
|
||||
*/
|
||||
export function baseTraitText(rec) {
|
||||
const t = rec ? rec.traitBase || rec.trait : null;
|
||||
return t && typeof t.desc === 'string' ? t.desc : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a MELEE chess record may also stand on a 高台: its trait reads 「可以放置于远程位」. Normal or elite, any module.
|
||||
* @param {object|null} rec a chess record (normal or golden)
|
||||
* @param {string|null|undefined} moduleId the equipped module (`resolveLoadout().moduleId`)
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function meleeOnHighGround(rec, moduleId) {
|
||||
return !!(rec && rec.isGolden === true && rec.charId === GLADIIA_CHAR_ID && moduleId === GLADIIA_HOK_Y);
|
||||
export function meleeOnHighGround(rec) {
|
||||
return !!rec && rec.position === 'MELEE' && baseTraitText(rec).includes(PLACE_ON_RANGED);
|
||||
}
|
||||
+132
-78
@@ -374,38 +374,39 @@ test('阿戈尔 devour order: left first, then top first (row 0 is the bottom: t
|
||||
checkInvariants(h.b);
|
||||
});
|
||||
|
||||
test('阿戈尔 5: the first 3 members by position (left column first, top first) revive at once on their first knock-out, whatever the order of knock-outs; the others never; a second knock-out is final', () => {
|
||||
test('阿戈尔 5: the 3 slots go to the first 3 members knocked out, wherever they stand; a later first knock-out stays down; a second knock-out is final; 3 members: none', () => {
|
||||
const list = [];
|
||||
for (let i = 0; i < 5; i++) list.push([`g${i}_a`, ['egirShip'], { skill: { spCost: 30, initSp: 5, duration: 10 } }]);
|
||||
// one per row pair so nobody devours anybody: col 3 rows 9–12 (g0 bottom … g3 top), g4 at (9,5). PRTS 盟约记录 阿戈尔
|
||||
// "前3名【阿戈尔】干员首次被击倒时立刻复活", the first 3 being the first deployed — "更靠左和靠上": g3, g2, g1
|
||||
// "前3名【阿戈尔】干员首次被击倒时立刻复活"; the owner's decision of 2026-10-05: the first 3 knocked out, in knock-out order
|
||||
const units = list.map(([id], i) => ({ chessId: id, row: 9 + (i % 4), col: 3 + 2 * Math.floor(i / 4) }));
|
||||
const h = makeBattle({ defs: defsOf(list), units, bonds: { egirShip: bondOn(5, 0, null, [3, 5]) }, hooks: ['death', 'deploy'] });
|
||||
h.step(1);
|
||||
const us = list.map(([id]) => h.unit(id));
|
||||
const kill = (u) => h.b.dealDamage(null, u, { amount: 1e9, type: 'true' });
|
||||
const redeploys = (u) => h.hooksOf('deploy').filter((c) => c.unit === u && !c.initial).length;
|
||||
// knocked out first, yet no beneficiary: g0 (bottom of the first column) and g4 (second column) stay down
|
||||
for (const u of [us[0], us[4]]) {
|
||||
kill(u);
|
||||
assert.ok(!u.alive, `${u.defId} is not among the first 3 by position: no revive`);
|
||||
assert.equal(redeploys(u), 0);
|
||||
}
|
||||
us[1].skill.gainSp(20, 'test');
|
||||
us[0].skill.gainSp(20, 'test');
|
||||
const tiles = us.map((u) => [u.tileR, u.tileC]);
|
||||
for (const i of [1, 3, 2]) {
|
||||
// g4 (second column) and g0 (bottom of the first column) first — the last two by position — then g2
|
||||
for (const i of [4, 0, 2]) {
|
||||
const u = us[i];
|
||||
const before = redeploys(u);
|
||||
kill(u);
|
||||
assert.ok(u.alive && u.deployed, `member ${i} back on the field`);
|
||||
close(u.hp, u.s.maxHp);
|
||||
assert.deepEqual([u.tileR, u.tileC], tiles[i], 'same tile');
|
||||
assert.ok(h.hooksOf('death').some((c) => c.unit === u && c.reason === 'killed'), 'it was knocked out (被击倒 triggers fire)');
|
||||
assert.equal(redeploys(u), before + 1, `member ${i} redeployed`);
|
||||
assert.equal(redeploys(u), 1, `member ${i} redeployed`);
|
||||
}
|
||||
assert.equal(us[1].skill.sp, 5, 'a redeploy restarts from the initial SP');
|
||||
kill(us[1]);
|
||||
assert.ok(!us[1].alive, 'second knock-out is final');
|
||||
assert.equal(us[0].skill.sp, 5, 'a redeploy restarts from the initial SP');
|
||||
// the 3 are gone: g3 (top-left, first by position) and g1 stay down on their first knock-out
|
||||
for (const i of [3, 1]) {
|
||||
kill(us[i]);
|
||||
assert.ok(!us[i].alive, `member ${i}: no slot left`);
|
||||
assert.equal(redeploys(us[i]), 0);
|
||||
}
|
||||
kill(us[4]);
|
||||
assert.ok(!us[4].alive, 'a second knock-out is final');
|
||||
assert.equal(h.eventsOf('fx').filter((x) => x[1] === 'revive').length, 3, 'three revives');
|
||||
checkInvariants(h.b);
|
||||
// a member moved off its board tile (突袭 / relocation) revives where it was knocked out; later redeploys go home
|
||||
const hm = makeBattle({ defs: defsOf(list), units, bonds: { egirShip: bondOn(5, 0, null, [3, 5]) }, hooks: [] });
|
||||
@@ -424,44 +425,126 @@ test('阿戈尔 5: the first 3 members by position (left column first, top first
|
||||
assert.ok(!h3.unit('g3_a').alive);
|
||||
});
|
||||
|
||||
test('阿戈尔 5 + the devour chain (GitHub #33): the devour knocks out the food, only the members among the first 3 by position come back; the others keep theirs for the fight (normal and 联防)', () => {
|
||||
// one row, all facing right: 浊心斯卡蒂 → 乌尔比安 → 幽灵鲨 → 海霓 → 深巡 → 隐现. PRTS 盟约记录 阿戈尔 备注 "标记按付与顺序触发
|
||||
// 【吞噬】效果,目标首次被击倒后解除自身被付与但还未触发的【吞噬】效果". The 3 revives belong to the first 3 by position
|
||||
// (浊心斯卡蒂, 乌尔比安, 幽灵鲨 — community reports 「阿戈尔盟约复活有bug,只能复活一个干员」); until 0.1.3 the first 3
|
||||
// knocked out took them, so the food (幽灵鲨, 海霓, 深巡) spent all 3 at t = 0 and nobody came back in the fight
|
||||
const ids = ['chess_char_6_04_a', 'chess_char_5_05_a', 'chess_char_2_07_a', 'chess_char_3_09_a', 'chess_char_1_04_a', 'chess_char_1_01_a'];
|
||||
test('阿戈尔 5 + the devour chain (GitHub #33, #105, #140): the eaten members take the 3 slots in knock-out order, uneaten ones keep none — survivors = uneaten + 3 (normal and 联防)', () => {
|
||||
// row 10, all facing right: 浊心斯卡蒂 → 幽灵鲨 → 海霓 → 深巡 → 歌蕾蒂娅 → 隐现; 乌尔比安 on row 12 faces an empty tile.
|
||||
// PRTS 盟约记录 阿戈尔 备注 "标记按付与顺序触发【吞噬】效果,目标首次被击倒后解除自身被付与但还未触发的【吞噬】效果". Until 0.1.3
|
||||
// the slots belonged to the first 3 by position (浊心斯卡蒂, 乌尔比安, 幽灵鲨: two uneaten members held them, so only 幽灵鲨
|
||||
// of the food came back — "没被吃的阿戈尔干员也会占用复活名额", "无论食物链怎么吃最终都只有三名阿戈尔人存活")
|
||||
const ids = ['chess_char_6_04_a', 'chess_char_2_07_a', 'chess_char_3_09_a', 'chess_char_1_04_a', 'chess_char_4_12_a', 'chess_char_1_01_a'];
|
||||
const ULPIA = 'chess_char_5_05_a';
|
||||
for (const kind of ['normal', 'unite']) {
|
||||
const h = makeBattle({
|
||||
kind, units: ids.map((chessId, i) => ({ chessId, row: 10, col: 2 + i })), bonds: { egirShip: bondOn(5, 0, null, [3, 5]) },
|
||||
hooks: ['damaged', 'death', 'deploy'], captureNoisy: true, autoFinish: false, timeLimit: 60,
|
||||
kind, units: [...ids.map((chessId, i) => ({ chessId, row: 10, col: 2 + i })), { chessId: ULPIA, row: 12, col: 3 }],
|
||||
bonds: { egirShip: bondOn(6, 0, null, [3, 5]) }, hooks: ['damaged', 'death', 'deploy'], captureNoisy: true, autoFinish: false, timeLimit: 60,
|
||||
});
|
||||
h.step(1);
|
||||
const [skadi, ulpia, ghost, hn, deep, fodder] = ids.map((id) => h.unit(id));
|
||||
// 浊心斯卡蒂 marks the whole row and resolves first; every later mark is on a unit already knocked out (乌尔比安's), or
|
||||
// comes from one (幽灵鲨's, 海霓's, 深巡's)
|
||||
const [skadi, ghost, hn, deep, glady, fodder] = ids.map((id) => h.unit(id));
|
||||
const ulpia = h.unit(ULPIA);
|
||||
// 浊心斯卡蒂 marks the whole row (through the members) and resolves first; every later mark is on a unit knocked out
|
||||
assert.deepEqual(tagged(h, 'bond:egir:devour').map((c) => [c.source.defId, c.target.defId]),
|
||||
[ulpia, ghost, hn, deep, fodder].map((t) => [skadi.defId, t.defId]), kind);
|
||||
[ghost, hn, deep, glady, fodder].map((t) => [skadi.defId, t.defId]), kind);
|
||||
const kos = (u) => h.hooksOf('death').filter((c) => c.unit === u && c.reason === 'killed').length;
|
||||
const revived = (u) => h.hooksOf('deploy').filter((c) => c.unit === u && !c.initial).length;
|
||||
for (const u of [ghost, hn, deep]) {
|
||||
assert.equal(h.hooksOf('death').filter((c) => c.unit === u && c.reason === 'killed').length, 1, `${kind}: ${u.defId} knocked out once`);
|
||||
}
|
||||
assert.equal(revived(ghost), 1, `${kind}: 幽灵鲨 (third by position) revived at once`);
|
||||
assert.equal(revived(hn) + revived(deep), 0, `${kind}: 海霓 and 深巡 (fourth, fifth) not revived`);
|
||||
for (const u of [ghost, hn, deep, glady]) assert.equal(kos(u), 1, `${kind}: ${u.defId} knocked out once`);
|
||||
for (const u of [ghost, hn, deep]) assert.equal(revived(u), 1, `${kind}: ${u.defId} (knocked out 1st–3rd) revived at once`);
|
||||
assert.equal(revived(glady), 0, `${kind}: 歌蕾蒂娅 (knocked out 4th) stays down`);
|
||||
assert.equal(kos(skadi) + kos(ulpia) + revived(skadi) + revived(ulpia), 0, `${kind}: the uneaten members take no slot`);
|
||||
h.run(3);
|
||||
for (const u of [skadi, ulpia, ghost]) assert.ok(u.alive && u.deployed && u.hp > 0, `${kind}: ${u.defId} standing`);
|
||||
for (const u of [hn, deep, fodder]) assert.ok(!u.alive, `${kind}: ${u.defId} down`);
|
||||
// 浊心斯卡蒂 and 乌尔比安 still hold theirs: their first knock-out in the fight is revived, 幽灵鲨's second is final
|
||||
for (const u of [skadi, ulpia]) {
|
||||
const members = [skadi, ghost, hn, deep, glady, ulpia];
|
||||
assert.deepEqual(members.filter((u) => u.alive).map((u) => u.defId), [skadi, ghost, hn, deep, ulpia].map((u) => u.defId),
|
||||
`${kind}: survivors = the 2 uneaten + 3`);
|
||||
assert.ok(!fodder.alive, `${kind}: the fodder (no member) is down`);
|
||||
// nothing is left for the fight: 浊心斯卡蒂's first knock-out and 幽灵鲨's second stay down
|
||||
for (const u of [skadi, ghost]) {
|
||||
h.b.dealDamage(null, u, { amount: 1e9, type: 'true' });
|
||||
assert.ok(u.alive && revived(u) === 1, `${kind}: ${u.defId} revived in the fight`);
|
||||
assert.ok(!u.alive, `${kind}: ${u.defId} stays down`);
|
||||
}
|
||||
h.b.dealDamage(null, ghost, { amount: 1e9, type: 'true' });
|
||||
assert.ok(!ghost.alive, `${kind}: 幽灵鲨 has no revive left`);
|
||||
checkInvariants(h.b);
|
||||
}
|
||||
});
|
||||
|
||||
test('阿戈尔 5 beneficiaries: fixed at battle start — a 联防 member entering down keeps the slot, a 调和 member is one, the mirrored boss side counts from its own left', () => {
|
||||
test('阿戈尔 5: a member devoured by several 阿戈尔 spends one slot at most — its pending marks are cancelled once it is knocked out', () => {
|
||||
// A (10,3) → B (10,4) → X (10,5) and C (11,5, facing DOWN) → X: three marks on X; D (12,8) faces an empty tile
|
||||
const list = [['A_a', ['egirShip']], ['B_a', ['egirShip']], ['X_a', ['egirShip']], ['C_a', ['egirShip']], ['D_a', ['egirShip']]];
|
||||
const defs = defsOf(list.map(([id, b]) => [id, b, { stats: { maxHp: 3000 } }]));
|
||||
const units = [
|
||||
{ chessId: 'A_a', row: 10, col: 3 }, { chessId: 'B_a', row: 10, col: 4 }, { chessId: 'X_a', row: 10, col: 5 },
|
||||
{ chessId: 'C_a', row: 11, col: 5, dir: 'DOWN' }, { chessId: 'D_a', row: 12, col: 8 },
|
||||
];
|
||||
const h = makeBattle({ defs, units, bonds: { egirShip: bondOn(5, 0, null, [3, 5]) }, hooks: ['damaged', 'death', 'deploy'], captureNoisy: true, autoFinish: false, timeLimit: 60 });
|
||||
h.step(1);
|
||||
const [a, b, x, c, d] = ['A_a', 'B_a', 'X_a', 'C_a', 'D_a'].map((id) => h.unit(id));
|
||||
const kos = (u) => h.hooksOf('death').filter((e) => e.unit === u && e.reason === 'killed').length;
|
||||
const revived = (u) => h.hooksOf('deploy').filter((e) => e.unit === u && !e.initial).length;
|
||||
// marked by A (through B), by B and by C; A's mark knocks it out, B's and C's are cancelled
|
||||
assert.deepEqual(tagged(h, 'bond:egir:devour').map((e) => [e.source.defId, e.target.defId]), [['A_a', 'B_a'], ['A_a', 'X_a']]);
|
||||
for (const u of [b, x]) assert.ok(u.alive && kos(u) === 1 && revived(u) === 1, `${u.defId}: one knock-out, one slot`);
|
||||
close(x.hp, x.s.maxHp, 1e-6, 'X at full HP: no second mark');
|
||||
// two slots used: D's first knock-out takes the third, C's stays down
|
||||
h.b.dealDamage(null, d, { amount: 1e9, type: 'true' });
|
||||
assert.ok(d.alive, 'D: the third slot');
|
||||
h.b.dealDamage(null, c, { amount: 1e9, type: 'true' });
|
||||
assert.ok(!c.alive, 'C: none left');
|
||||
assert.ok(a.alive && kos(a) === 0, 'A never knocked out');
|
||||
checkInvariants(h.b);
|
||||
// X with more HP survives A's and B's marks and falls to C's: still one knock-out, one slot
|
||||
const tough = defsOf(list.map(([id, bd]) => [id, bd, { stats: { maxHp: id === 'X_a' ? 8000 : 3000 } }]));
|
||||
const t = makeBattle({ defs: tough, units, bonds: { egirShip: bondOn(5, 0, null, [3, 5]) }, hooks: ['damaged', 'death', 'deploy'], captureNoisy: true, autoFinish: false, timeLimit: 60 });
|
||||
t.step(1);
|
||||
const tx = t.unit('X_a');
|
||||
assert.deepEqual(tagged(t, 'bond:egir:devour').map((e) => [e.source.defId, e.target.defId]), [['A_a', 'B_a'], ['A_a', 'X_a'], ['B_a', 'X_a'], ['C_a', 'X_a']]);
|
||||
assert.equal(t.hooksOf('death').filter((e) => e.unit === tx && e.reason === 'killed').length, 1, 'X knocked out once, by the third mark');
|
||||
assert.ok(tx.alive && t.eventsOf('fx').filter((e) => e[1] === 'revive').length === 2, 'B and X: two slots');
|
||||
checkInvariants(t.b);
|
||||
});
|
||||
|
||||
test('阿戈尔 5: an operator\'s own save uses no slot (斯卡蒂\'s DRE-Y, M3茧甲, 埃芒加德 [ASSUMED for the band]); the slot waits for its first real knock-out', () => {
|
||||
// 斯卡蒂 (elite, module DRE-Y by default) enters 联防 at half HP in front of 乌尔比安: his mark is lethal, DRE-Y saves her
|
||||
// (PRTS: once per deployment, full HP with max HP −60 %) — no knock-out, so no slot
|
||||
const SKADI = 'chess_char_3_05_b', ULPIA = 'chess_char_5_05_a', GHOST = 'chess_char_2_07_a', HN = 'chess_char_3_09_a', DEEP = 'chess_char_1_04_a';
|
||||
const h = makeBattle({
|
||||
kind: 'unite', autoFinish: false, timeLimit: 60, hooks: ['damaged', 'death', 'deploy'], captureNoisy: true,
|
||||
units: [
|
||||
{ chessId: ULPIA, row: 10, col: 3 }, { chessId: SKADI, row: 10, col: 4, dir: 'UP', carryState: { hpPct: 0.5 } },
|
||||
{ chessId: GHOST, row: 12, col: 3 }, { chessId: HN, row: 12, col: 5 }, { chessId: DEEP, row: 12, col: 7 },
|
||||
],
|
||||
bonds: { egirShip: bondOn(5, 0, null, [3, 5]) },
|
||||
});
|
||||
h.step(1);
|
||||
const sk = h.unit(SKADI);
|
||||
assert.deepEqual(tagged(h, 'bond:egir:devour').map((c) => [c.source.defId, c.target.defId]), [[ULPIA, SKADI]]);
|
||||
assert.ok(sk.alive && buffOf(sk, 'trait:skadi_tide'), 'saved by her module');
|
||||
assert.equal(h.hooksOf('death').filter((c) => c.unit === sk).length, 0, 'not knocked out');
|
||||
assert.equal(h.eventsOf('fx').filter((x) => x[1] === 'revive' && x[4] && x[4].n).length, 0, 'no 阿戈尔 revive');
|
||||
const kill = (id) => { const u = h.unit(id); h.b.dealDamage(null, u, { amount: 1e9, type: 'true' }); return u.alive; };
|
||||
// all 3 slots are still there: 幽灵鲨, 海霓 and then 斯卡蒂 (DRE-Y spent in this deployment) come back, 深巡 does not
|
||||
assert.deepEqual([GHOST, HN, SKADI, DEEP].map(kill), [true, true, true, false]);
|
||||
checkInvariants(h.b);
|
||||
|
||||
const list = [['g0_a', ['egirShip']], ['g1_a', ['egirShip']], ['g2_a', ['egirShip']], ['g3_a', ['egirShip']], ['g4_a', ['egirShip']]];
|
||||
const units = (it = {}) => list.map(([chessId], i) => ({ chessId, row: 9 + (i % 2) * 3, col: 3 + i, items: it[i] }));
|
||||
const killed = (b, id) => { const u = b.unit(id); b.b.dealDamage(null, u, { amount: 1e9, type: 'true' }); return u; };
|
||||
// M3茧甲 (an item 复活, in place): g0 is saved, the 3 slots go to g1, g2, g3; g4 stays down
|
||||
const hi = makeBattle({ defs: defsOf(list), autoFinish: false, timeLimit: 60, hooks: ['death', 'deploy'], units: units({ 0: ['chess_item_4_12_e_a'] }), bonds: { egirShip: bondOn(5, 0, null, [3, 5]) } });
|
||||
hi.step(1);
|
||||
const g0 = killed(hi, 'g0_a');
|
||||
assert.ok(g0.alive && hi.hooksOf('death').filter((c) => c.unit === g0).length === 0, 'item: saved in place (no knock-out)');
|
||||
assert.deepEqual(['g1_a', 'g2_a', 'g3_a', 'g4_a'].map((id) => killed(hi, id).alive), [true, true, true, false], 'item: three slots left after the save');
|
||||
checkInvariants(hi.b);
|
||||
// 埃芒加德 (命结之秘: the battle's first 3 knock-downs revive in place — its own count, unchanged): g0, g1, g2 saved by it;
|
||||
// the 阿戈尔 slots then go to g3, g4 and g0's first real knock-out; g1's real one finds none
|
||||
const hb = makeBattle({ defs: defsOf(list), autoFinish: false, timeLimit: 60, hooks: ['death', 'deploy'], units: units(), bandId: 'band_ermengard', bonds: { egirShip: bondOn(5, 0, null, [3, 5]) } });
|
||||
hb.step(1);
|
||||
for (const id of ['g0_a', 'g1_a', 'g2_a']) {
|
||||
const u = killed(hb, id);
|
||||
assert.ok(u.alive && hb.hooksOf('death').filter((c) => c.unit === u).length === 0, `band: ${id} saved in place`);
|
||||
}
|
||||
assert.deepEqual(hb.eventsOf('fx').filter((x) => x[1] === 'revive' && x[4] && x[4].left != null).map((x) => x[4].left), [2, 1, 0], '埃芒加德 spent its 3');
|
||||
assert.deepEqual(['g3_a', 'g4_a', 'g0_a', 'g1_a'].map((id) => killed(hb, id).alive), [true, true, true, false], 'band: the 阿戈尔 slots are untouched');
|
||||
checkInvariants(hb.b);
|
||||
});
|
||||
|
||||
test('阿戈尔 5 slots in 联防 and on the boss field: a member entering down takes none until it is knocked out after standing up; a 调和 member takes one; a mirrored player counts its own knock-outs', () => {
|
||||
const list = [['g0_a', ['egirShip']], ['g1_a', ['egirShip']], ['g2_a', ['egirShip']], ['g3_a', ['egirShip']], ['g4_a', ['egirShip']], ['mani_a', ['maniShip']]];
|
||||
// five members in five columns (one per column, nobody in front of anybody): g0 col 3 … g4 col 7
|
||||
const units = list.slice(0, 5).map(([chessId], i) => ({ chessId, row: 9 + (i % 2) * 3, col: 3 + i }));
|
||||
@@ -470,8 +553,8 @@ test('阿戈尔 5 beneficiaries: fixed at battle start — a 联防 member enter
|
||||
h.b.dealDamage(null, u, { amount: 1e9, type: 'true' });
|
||||
return u.alive;
|
||||
};
|
||||
// 联防: g0 entered down (forced out before battleStart). The slots stay the first 3 by position — g0, g1, g2.
|
||||
// The forced exit is not a 击倒, so g0's charge waits until they stand back up. g3 is not promoted into it.
|
||||
// 联防: g0 entered down (forced out before battleStart — not a 击倒, so no slot); g4 and g3 take two slots, g0's first
|
||||
// knock-out after it stands back up takes the third, g1 finds none
|
||||
const hu = makeBattle({
|
||||
kind: 'unite', defs: defsOf(list), autoFinish: false, timeLimit: 60, bonds: { egirShip: bondOn(5, 0, null, [3, 5]) },
|
||||
units: units.map((u, i) => (i === 0 ? { ...u, carryState: { down: true } } : u)),
|
||||
@@ -479,59 +562,30 @@ test('阿戈尔 5 beneficiaries: fixed at battle start — a 联防 member enter
|
||||
hu.step(1);
|
||||
const g0 = hu.unit('g0_a');
|
||||
assert.ok(!g0.alive, 'g0 forced out');
|
||||
assert.deepEqual(['g4_a', 'g3_a', 'g1_a', 'g2_a'].map((id) => revives(hu, id)), [false, false, true, true]);
|
||||
assert.deepEqual(['g4_a', 'g3_a'].map((id) => revives(hu, id)), [true, true]);
|
||||
assert.ok(hu.runUntil(() => g0.alive && g0.deployed, 25), 'g0 stands back up inside the redeploy time');
|
||||
assert.equal(revives(hu, 'g0_a'), true, 'g0 still held the first slot');
|
||||
hu.b.dealDamage(null, g0, { amount: 1e9, type: 'true' });
|
||||
assert.ok(!g0.alive, 'g0 has no second revive');
|
||||
assert.equal(revives(hu, 'g0_a'), true, 'g0: its first knock-out takes the third slot');
|
||||
assert.equal(revives(hu, 'g1_a'), false, 'g1: none left');
|
||||
checkInvariants(hu.b);
|
||||
// 调和 (an active 调和 member enjoys the core bonds) in the first column: one of the 3
|
||||
// 调和 (an active 调和 member enjoys the core bonds): knocked out first, it takes the first slot
|
||||
const hm = makeBattle({
|
||||
defs: defsOf(list), autoFinish: false, timeLimit: 60,
|
||||
units: [{ chessId: 'mani_a', row: 11, col: 2 }, ...units.slice(0, 4)],
|
||||
bonds: { egirShip: bondOn(5, 0, null, [3, 5]), maniShip: { count: 1, active: true, tier: 1, layers: 0 } },
|
||||
});
|
||||
hm.step(1);
|
||||
assert.deepEqual(['g2_a', 'mani_a', 'g0_a', 'g1_a'].map((id) => revives(hm, id)), [false, true, true, true]);
|
||||
// the right-hand boss player (mirrored): its board's left is the field's right — board cols 3, 4, 5 = field cols 17,
|
||||
// 16, 15 hold the revives (read in field columns from the left they would go to g4, g3, g2)
|
||||
assert.deepEqual(['mani_a', 'g3_a', 'g2_a', 'g0_a'].map((id) => revives(hm, id)), [true, true, true, false]);
|
||||
// the right-hand boss player (mirrored): the order of its own knock-outs, wherever they stand
|
||||
const hb = makeBattle({
|
||||
kind: 'boss', defs: defsOf(list), autoFinish: false, timeLimit: 60,
|
||||
players: [{ playerId: 'R1', side: 'R', colOffset: 8, units: units.map((u, i) => ({ ...u, uid: i + 1 })), bonds: { egirShip: bondOn(5, 0, null, [3, 5]) } }],
|
||||
});
|
||||
hb.step(1);
|
||||
assert.deepEqual(['g4_a', 'g3_a', 'g0_a', 'g1_a', 'g2_a'].map((id) => [hb.unit(id).tileC, revives(hb, id)]),
|
||||
[[13, false], [14, false], [17, true], [16, true], [15, true]]);
|
||||
[[13, true], [14, true], [17, true], [16, false], [15, false]]);
|
||||
checkInvariants(hb.b);
|
||||
});
|
||||
|
||||
test('阿戈尔 5: a beneficiary 埃芒加德 or M3茧甲 save in place has used its 阿戈尔 revive [ASSUMED]; the others keep theirs', () => {
|
||||
const list = [['g0_a', ['egirShip']], ['g1_a', ['egirShip']], ['g2_a', ['egirShip']], ['g3_a', ['egirShip']], ['g4_a', ['egirShip']]];
|
||||
const units = (it = {}) => list.map(([chessId], i) => ({ chessId, row: 9 + (i % 2) * 3, col: 3 + i, items: it[i] }));
|
||||
const kill = (h, id) => { const u = h.unit(id); h.b.dealDamage(null, u, { amount: 1e9, type: 'true' }); return u; };
|
||||
for (const how of ['band', 'item']) {
|
||||
const h = makeBattle({
|
||||
defs: defsOf(list), autoFinish: false, timeLimit: 60, hooks: ['death', 'deploy'],
|
||||
units: units(how === 'item' ? { 0: ['chess_item_4_12_e_a'] } : {}), ...(how === 'band' ? { bandId: 'band_ermengard' } : {}),
|
||||
bonds: { egirShip: bondOn(5, 0, null, [3, 5]) },
|
||||
});
|
||||
h.step(1);
|
||||
// g0, g1, g2 (columns 3–5) hold the 阿戈尔 revives; g0 is saved in place first
|
||||
const g0 = kill(h, 'g0_a');
|
||||
assert.ok(g0.alive && h.hooksOf('death').filter((c) => c.unit === g0).length === 0, `${how}: saved in place (no knock-out)`);
|
||||
// 埃芒加德 saves the battle's first 3 knock-downs: its other 2 go to g3 and g4 (no 阿戈尔 beneficiaries)
|
||||
if (how === 'band') for (const id of ['g3_a', 'g4_a']) assert.ok(kill(h, id).alive, 'band revive');
|
||||
kill(h, 'g0_a');
|
||||
assert.ok(!g0.alive, `${how}: its 阿戈尔 revive went with the save — its first knock-out is final`);
|
||||
assert.equal(h.hooksOf('deploy').filter((c) => c.unit === g0 && !c.initial).length, 0);
|
||||
for (const id of ['g1_a', 'g2_a']) {
|
||||
const u = kill(h, id);
|
||||
assert.ok(u.alive && h.hooksOf('deploy').filter((c) => c.unit === u && !c.initial).length === 1, `${how}: ${id} revived by 阿戈尔`);
|
||||
}
|
||||
checkInvariants(h.b);
|
||||
}
|
||||
});
|
||||
|
||||
test('阿戈尔 devour, a unit back during the pass: a marker revived by the 5-tier revive still gives its marks; a target revived in place (埃芒加德) or redeployed (不屈) takes none', () => {
|
||||
// g1 (10,3) → g2 (10,4, 3000 × 1.35 HP: knocked out by g1's mark, revived) → g3 (10,5) → fodder (10,6); g4 / g5 face empty tiles
|
||||
const list = [
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
// test/content/feedback4-egir-unite.test.js — 阿戈尔's battle-start devour in 联防 (GitHub #105, #140 comment 4; the
|
||||
// owner's decision of 2026-10-05). PRTS 盟约记录 阿戈尔: "战斗开始时【阿戈尔】干员依次吞噬身前一格干员" — no own-side limit:
|
||||
// the operator on the front tile is devoured whoever owns it, a teammate's living operator or a teammate's operator
|
||||
// that entered 联防 knocked out (carry.down, forced out right after the deployment), and the marker gains its base ATK
|
||||
// and block count exactly as in a solo battle. 联防 still adds no layers ("该阶段不能叠加层数"). The remake's two 联防
|
||||
// helpers stand on board cols 3–9 and 11–17 (colOffset 8) with the road column 10 between them, so these fields put the
|
||||
// teammate's operator on col 10 (a LOW tile the sim deploys on) to be in front. The last test runs the own-board case
|
||||
// through unite.js's carry: a chain whose food is down since the own combat gives 联防 the gains of the own combat.
|
||||
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { makeBattle, checkInvariants } from '../helpers/battleHarness.js';
|
||||
import { uniteBattleOpts } from '../../server/match/unite.js';
|
||||
import { makeMatch } from '../match/harness.js';
|
||||
import { FORCED_EXIT } from '../../server/sim/constants.js';
|
||||
|
||||
const close = (a, b, eps = 1e-6, msg = '') => assert.ok(Math.abs(a - b) <= eps, `${msg} expected ${b}, got ${a}`);
|
||||
const bondOn = (count, layers = 0) => ({ count, active: count >= 3, tier: count >= 5 ? 2 : count >= 3 ? 1 : 0, layers });
|
||||
const buffOf = (u, key) => u.buffs.find((b) => b.key === key) ?? null;
|
||||
const devours = (h) => h.hooksOf('damaged').filter((c) => c.dmg && c.dmg.tags && c.dmg.tags.includes('bond:egir:devour'));
|
||||
|
||||
const ULPIA = 'chess_char_5_05_a', GHOST = 'chess_char_2_07_a', GLADY = 'chess_char_4_12_a', DEEP = 'chess_char_1_04_a';
|
||||
const HN = 'chess_char_3_09_a', MIZUKI = 'chess_char_4_09_a', FODDER = 'chess_char_1_01_a';
|
||||
|
||||
/** p1's 3 阿戈尔: 乌尔比安 on (10,9) facing right — its front tile is field (10,10) — and two facing empty tiles. */
|
||||
const p1Units = () => [
|
||||
{ uid: 1, kind: 'chess', chessId: ULPIA, row: 10, col: 9, dir: 'RIGHT' },
|
||||
{ uid: 2, kind: 'chess', chessId: GLADY, row: 12, col: 3, dir: 'RIGHT' },
|
||||
{ uid: 3, kind: 'chess', chessId: DEEP, row: 12, col: 5, dir: 'RIGHT' },
|
||||
];
|
||||
const player = (playerId, seat, colOffset, units, bonds) => ({ playerId, seat, side: 'L', colOffset, units, bonds, bandId: null, playerEffects: [] });
|
||||
|
||||
/**
|
||||
* A battle where `front` (chess ids, left to right) stands on field (10,10), (10,11) …: owned by p1 itself (`owner`
|
||||
* 'own', board cols 10, 11 …) or by the teammate p2 (`owner` 'mate', colOffset 8: board cols 2, 3 …).
|
||||
*/
|
||||
function field({ kind = 'unite', owner = 'own', front = [FODDER], extra = {}, p2Bonds = {}, p2Units = [] } = {}) {
|
||||
const lane = front.map((chessId, i) => ({ uid: 100 + i, kind: 'chess', chessId, row: 10, dir: 'RIGHT', ...(extra[i] || {}) }));
|
||||
const players = owner === 'own'
|
||||
? [player('p1', 0, 0, [...p1Units(), ...lane.map((u, i) => ({ ...u, col: 10 + i }))], { egirShip: bondOn(3, 10) })]
|
||||
: [player('p1', 0, 0, p1Units(), { egirShip: bondOn(3, 10) }),
|
||||
player('p2', 1, 8, [...lane.map((u, i) => ({ ...u, col: 2 + i })), ...p2Units], p2Bonds)];
|
||||
const h = makeBattle({ kind, players, autoFinish: false, timeLimit: 60, hooks: ['damaged', 'death', 'deploy', 'kill', 'layerGain'], captureNoisy: true });
|
||||
h.step();
|
||||
return h;
|
||||
}
|
||||
|
||||
test('联防: an 阿戈尔 devours a teammate\'s living operator in front — the same base ATK and block count as an own one, the 物理流失 lands, no layers', () => {
|
||||
const solo = field({ kind: 'normal' });
|
||||
const own = field();
|
||||
const mate = field({ owner: 'mate' });
|
||||
const ref = buffOf(solo.unit(1), 'bond:egir:devour');
|
||||
const fodderBase = solo.unit(100).base;
|
||||
assert.ok(ref, 'solo: 乌尔比安 devours the operator in front');
|
||||
close(ref.mods.atkFlat, fodderBase.atk, 1e-9, 'its base ATK');
|
||||
assert.equal(ref.mods.blockCnt, fodderBase.blockCnt, 'its block count');
|
||||
for (const [tag, h] of [['own', own], ['teammate\'s', mate]]) {
|
||||
const ulpia = h.unit(1), t = h.unit(100);
|
||||
assert.deepEqual(buffOf(ulpia, 'bond:egir:devour')?.mods, ref.mods, `${tag}: the solo gains`);
|
||||
close(ulpia.s.atk, own.unit(1).s.atk, 1e-6, `${tag}: 乌尔比安's ATK`);
|
||||
assert.equal(ulpia.s.blockCnt, solo.unit(1).s.blockCnt, `${tag}: the block count`);
|
||||
const d = devours(h);
|
||||
assert.deepEqual(d.map((c) => [c.source.uid, c.target.uid]), [[1, 100]], `${tag}: one mark`);
|
||||
close(d[0].amount, devours(solo)[0].amount, 1e-6, `${tag}: the same 物理流失`);
|
||||
assert.ok(!t.alive && h.hooksOf('kill').some((c) => c.victim === t && c.killer === ulpia), `${tag}: knocked out, credited to 乌尔比安`);
|
||||
assert.equal(h.b.getPlayer('p1').bonds.egirShip.layers, 10, `${tag}: 联防 adds no layers`);
|
||||
assert.equal(h.hooksOf('layerGain').length, 0, `${tag}: no layer gain at all`);
|
||||
checkInvariants(h.b);
|
||||
}
|
||||
assert.equal(solo.b.getPlayer('p1').bonds.egirShip.layers, 10 + 1, 'solo: the devoured tier as layers');
|
||||
assert.equal(mate.unit(100).ownerId, 'p2');
|
||||
});
|
||||
|
||||
test('联防: a teammate\'s operator that entered 联防 down is devoured as if it stood — the same gains, nothing lands on it, it stays forced out', () => {
|
||||
const up = field({ owner: 'mate' });
|
||||
const down = field({ owner: 'mate', extra: { 0: { carryState: { down: true } } } });
|
||||
const ownDown = field({ extra: { 0: { carryState: { down: true } } } });
|
||||
const t = down.unit(100);
|
||||
assert.ok(!t.alive && t.removeReason === FORCED_EXIT && down.b.isDown(t), 'the teammate\'s operator lies on (10,10), forced out');
|
||||
for (const [tag, h] of [['teammate\'s', down], ['own', ownDown]]) {
|
||||
assert.deepEqual(buffOf(h.unit(1), 'bond:egir:devour')?.mods, buffOf(up.unit(1), 'bond:egir:devour').mods, `${tag} down: the gains of the standing one`);
|
||||
assert.equal(devours(h).length, 0, `${tag} down: no 物理流失 on it`);
|
||||
assert.equal(h.hooksOf('death').filter((c) => c.unit === h.unit(100) && c.reason === 'killed').length, 0, `${tag} down: no knock-out`);
|
||||
assert.equal(h.b.getPlayer('p1').bonds.egirShip.layers, 10, `${tag} down: no layers`);
|
||||
checkInvariants(h.b);
|
||||
}
|
||||
});
|
||||
|
||||
test('联防: the chain goes on through a teammate\'s 阿戈尔 — the gains equal the same chain of own operators; its knock-out spends its owner\'s 5-tier slot', () => {
|
||||
const own = field({ front: [GHOST, FODDER] });
|
||||
// p2 holds 5 阿戈尔 (5-tier active): 幽灵鲨 in front of 乌尔比安, four more on its board facing empty tiles
|
||||
const p2Units = [HN, MIZUKI, GLADY, DEEP].map((chessId, i) => ({ uid: 200 + i, kind: 'chess', chessId, row: 12, col: 3 + 2 * i, dir: 'RIGHT' }));
|
||||
const mate = field({ owner: 'mate', front: [GHOST, FODDER], p2Units, p2Bonds: { egirShip: bondOn(5) } });
|
||||
const ref = buffOf(own.unit(1), 'bond:egir:devour');
|
||||
close(ref.mods.atkFlat, own.unit(100).base.atk + own.unit(101).base.atk, 1e-9, 'own chain: 幽灵鲨 and, through her, the fodder');
|
||||
assert.deepEqual(buffOf(mate.unit(1), 'bond:egir:devour')?.mods, ref.mods, 'the teammate\'s chain gives the same');
|
||||
assert.deepEqual(devours(mate).map((c) => [c.source.uid, c.target.uid]), devours(own).map((c) => [c.source.uid, c.target.uid]));
|
||||
const ghost = mate.unit(100);
|
||||
assert.equal(mate.hooksOf('death').filter((c) => c.unit === ghost && c.reason === 'killed').length, 1, '幽灵鲨 knocked out by p1\'s mark');
|
||||
assert.ok(ghost.alive && mate.hooksOf('deploy').some((c) => c.unit === ghost && !c.initial), 'p2\'s 5-tier revives her at once');
|
||||
assert.ok(!own.unit(100).alive, 'p1 has no 5-tier: its own 幽灵鲨 stays down');
|
||||
assert.equal(mate.b.getPlayer('p1').bonds.egirShip.layers, 10, 'no layers');
|
||||
checkInvariants(mate.b);
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
// the own board through unite.js: a chain whose food is down since the own combat
|
||||
|
||||
let gdCache = null;
|
||||
const gd = () => (gdCache ??= makeMatch({ mode: 'coop', humans: 3, seed: 1, fake: true }).start().m.gd);
|
||||
|
||||
test('联防 through unite.js: food knocked out by the own combat\'s devour enters down, and 乌尔比安 gets exactly the own combat\'s base ATK and block count', () => {
|
||||
// 乌尔比安 → 幽灵鲨 → 歌蕾蒂娅 → fodder on row 10 (3 阿戈尔: no revive), 30 s own combat
|
||||
const ids = [ULPIA, GHOST, GLADY, FODDER];
|
||||
const units = ids.map((chessId, i) => ({ uid: i + 1, kind: 'chess', chessId, row: 10, col: 3 + i, dir: 'RIGHT', items: [] }));
|
||||
const bonds = { egirShip: bondOn(3, 10) };
|
||||
const own = makeBattle({ players: [player('p1', 0, 0, units, bonds)], autoFinish: false, timeLimit: 30 });
|
||||
own.runToEnd(60);
|
||||
const gain = buffOf(own.unit(1), 'bond:egir:devour').mods;
|
||||
const unitsEnd = own.result().perPlayer.p1.unitsEnd;
|
||||
assert.deepEqual(unitsEnd.filter((u) => !u.alive).map((u) => u.uid).sort(), [2, 3, 4], 'the food is down at the end');
|
||||
// the helper's 联防 input as unite.js builds it from that result
|
||||
const ps = {
|
||||
playerId: 'p1', seat: 0,
|
||||
board: new Map(units.map((u) => [`${u.row},${u.col}`, { uid: u.uid, kind: 'chess' }])),
|
||||
battleInput: ({ side, colOffset, carry }) => ({
|
||||
...player('p1', 0, colOffset, units.map((u) => ({ ...u, ...(carry.has(u.uid) ? { carryState: carry.get(u.uid) } : {}) })), bonds), side,
|
||||
}),
|
||||
};
|
||||
const m = { gd: gd(), round: 3, lastResults: new Map([['p1', { unitsEnd }]]), dispatch() {} };
|
||||
const { players } = uniteBattleOpts(m, { helpers: [ps], leaked: [] }, 60);
|
||||
assert.deepEqual(players[0].units.filter((u) => u.carryState?.down).map((u) => u.uid), [2, 3, 4]);
|
||||
const u = makeBattle({ kind: 'unite', players, autoFinish: false, timeLimit: 60 });
|
||||
u.step();
|
||||
const ulpia = u.unit(1);
|
||||
assert.deepEqual(buffOf(ulpia, 'bond:egir:devour')?.mods, gain, 'the own combat\'s gains');
|
||||
close(gain.atkFlat, [2, 3, 4].reduce((s, uid) => s + u.unit(uid).base.atk, 0), 1e-9, '幽灵鲨 + 歌蕾蒂娅 + fodder base ATK');
|
||||
assert.equal(gain.blockCnt, [2, 3, 4].reduce((s, uid) => s + u.unit(uid).base.blockCnt, 0));
|
||||
for (const uid of [2, 3, 4]) assert.ok(!u.unit(uid).alive && u.unit(uid).removeReason === FORCED_EXIT, `${uid} forced out`);
|
||||
assert.equal(u.b.getPlayer('p1').bonds.egirShip.layers, 10, 'no layers in 联防');
|
||||
checkInvariants(u.b);
|
||||
});
|
||||
+104
-104
@@ -122,7 +122,7 @@
|
||||
"snaps": "b677776a 05df3ce3 3f4ea1ef 7c86ba28 c343548f 5e5789b8"
|
||||
},
|
||||
"bond-deputShip-high": {
|
||||
"about": "助力 high: tier 2 layers 999; chess_char_4_11_b chess_char_4_12_b chess_char_1_06_b chess_char_1_13_b chess_char_2_14_b chess_char_1_06_a chess_char_1_13_a chess_char_4_10_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"about": "助力 high: tier 2 layers 999; chess_char_4_11_b chess_char_1_06_b chess_char_1_13_b chess_char_2_14_b chess_char_1_06_a chess_char_1_13_a chess_char_4_10_b chess_char_4_12_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"fast": true,
|
||||
"kind": "normal",
|
||||
"stageId": "act2autochess_m03",
|
||||
@@ -130,8 +130,8 @@
|
||||
"round": 10,
|
||||
"seed": 1208009840,
|
||||
"waveId": "act1autochess_h03",
|
||||
"time": 101.97,
|
||||
"ticks": 3059,
|
||||
"time": 98.27,
|
||||
"ticks": 2948,
|
||||
"reason": "cleared",
|
||||
"killed": 8,
|
||||
"total": 8,
|
||||
@@ -139,27 +139,27 @@
|
||||
"bossHpLeft": null,
|
||||
"rngDraws": 1,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {"p1":{"killed":8,"total":8,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":129773,"bossDmg":0,"heal":7536,"deaths":0,"layerGains":{}}},
|
||||
"players": {"p1":{"killed":8,"total":8,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":129773,"bossDmg":0,"heal":7124,"deaths":0,"layerGains":{}}},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_4_11_b",1,"uniequip_002_cathy",2644,1,5,0,0,0,0,0,0],
|
||||
["p1",2,"op","chess_char_4_12_b",2,"uniequip_002_glady",2232,1,6,0,14088,0,0,8,1],
|
||||
["p1",3,"op","chess_char_1_06_b",1,"uniequip_002_vendla",1051.4,1,7,4,47025,6060,5773,45,3],
|
||||
["p1",4,"op","chess_char_1_13_b",1,"uniequip_002_podego",815.5,1,9,1,36853,0,0,38,5],
|
||||
["p1",5,"op","chess_char_2_14_b",1,"uniequip_002_flower",1544,1,10,0,0,160,506,22,2],
|
||||
["p1",6,"op","chess_char_1_06_a",1,null,1137,1,11,1,21655,1572,1226,40,1],
|
||||
["p1",7,"op","chess_char_1_13_a",1,null,913,1,4,0,870,0,0,1,1],
|
||||
["p1",8,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1664,1,8,1,9282,95,31,7,2],
|
||||
["p1",2,"op","chess_char_1_06_b",1,"uniequip_002_vendla",1002.81,1,7,2,42201,5880,5545,41,3],
|
||||
["p1",3,"op","chess_char_1_13_b",1,"uniequip_002_podego",815.5,1,9,1,34934,0,0,35,5],
|
||||
["p1",4,"op","chess_char_2_14_b",1,"uniequip_002_flower",1544,1,10,0,0,0,399,19,1],
|
||||
["p1",5,"op","chess_char_1_06_a",1,null,1137,1,11,1,21655,1548,1148,40,1],
|
||||
["p1",6,"op","chess_char_1_13_a",1,null,913,1,4,0,0,0,0,0,0],
|
||||
["p1",7,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1664,1,8,1,12717,64,0,9,2],
|
||||
["p1",8,"op","chess_char_4_12_b",2,"uniequip_002_glady",2232,1,6,2,18266,31,31,10,1],
|
||||
["p1",9,"token","token_10041_cathy_catsld",null,null,100,1,12,0,0,0,0,0,null],
|
||||
["p1",10,"token","token_10041_cathy_catsld",null,null,100,1,13,0,0,0,0,0,null],
|
||||
["-","~1","device","trap_1105_accrate",null,null,100,1,1,0,0,0,0,0,null],
|
||||
["-","~2","device","trap_1105_accrate",null,null,100,1,2,0,0,0,0,0,null],
|
||||
["-","~3","device","trap_1105_accrate",null,null,100,1,3,0,0,0,0,0,null]
|
||||
],
|
||||
"enemies": {"enemy_1005_yokai_2":[4,4,0,96,5357],"enemy_1005_yokai_3":[2,2,0,1022,69120],"enemy_9009_acfort":[2,2,0,709,55296]},
|
||||
"hooks": [1,21,3059,230,230,369,369,2366,8,8,15,12,0,11504,115,0,8,0,1,7,0,0,0],
|
||||
"events": {"atk":230,"deploy":10,"die":8,"dmg":369,"fx":37,"heal":78,"skill":27,"spawn":21,"status":84},
|
||||
"fx": {"beam":2,"counter":16,"pull":1,"slippery":2,"taunt":4,"tornado":1,"tornadoPulse":5,"zone":6},
|
||||
"snaps": "f7c1fb30 eb023e29 d1fffc22 c886d0aa 5bf78694 5f3df034 3d54c073 581471d0 d97ecde2 8c045b67 57772151"
|
||||
"enemies": {"enemy_1005_yokai_2":[4,4,0,96,5357],"enemy_1005_yokai_3":[2,2,0,862,69120],"enemy_9009_acfort":[2,2,0,685,55296]},
|
||||
"hooks": [1,21,2948,217,217,357,357,2132,8,8,13,11,0,11234,107,0,8,0,1,7,0,0,0],
|
||||
"events": {"atk":217,"deploy":10,"die":8,"dmg":357,"fx":36,"heal":74,"skill":24,"spawn":21,"status":80},
|
||||
"fx": {"beam":2,"counter":16,"pull":1,"slippery":2,"taunt":4,"tornado":1,"tornadoPulse":5,"zone":5},
|
||||
"snaps": "f66ffc26 e4eea262 37ff890d e451ff33 28b10f94 47d55e15 7cf8b2aa 7d1d7e17 11c2118a 7599f2fd"
|
||||
},
|
||||
"bond-egirShip-low": {
|
||||
"about": "阿戈尔 low: tier 1 layers 1; chess_char_1_04_a chess_char_3_16_a chess_char_2_07_a chess_char_3_18_a chess_char_3_05_a chess_char_3_14_a chess_char_3_17_a chess_char_3_19_a token_10028_vigil_wolf",
|
||||
@@ -321,7 +321,7 @@
|
||||
"snaps": "48d2a0bc 7a5c72a3 37963453 9c6110e3 fcf46ff8 04b08d2c c03bf731 3792e3d9 e4639ebf decf37ce a41ea7f2 bd40f194 8e5c993d 300fcece"
|
||||
},
|
||||
"bond-indomShip-low": {
|
||||
"about": "不屈 low: tier 1 layers 1; chess_char_1_20_a chess_char_4_11_a chess_char_4_12_a chess_char_2_12_a chess_char_4_09_a chess_char_4_10_a chess_char_4_13_a chess_char_4_14_a token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"about": "不屈 low: tier 1 layers 1; chess_char_1_20_a chess_char_4_11_a chess_char_2_12_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 token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"fast": false,
|
||||
"kind": "normal",
|
||||
"stageId": "act1autochess_m03",
|
||||
@@ -329,38 +329,38 @@
|
||||
"round": 5,
|
||||
"seed": 1441167629,
|
||||
"waveId": "act1autochess_05",
|
||||
"time": 95.97,
|
||||
"ticks": 2879,
|
||||
"time": 67.97,
|
||||
"ticks": 2039,
|
||||
"reason": "cleared",
|
||||
"killed": 17,
|
||||
"killed": 18,
|
||||
"total": 18,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": null,
|
||||
"rngDraws": 20,
|
||||
"rngDraws": 14,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":17,"total":18,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":86976,"bossDmg":0,"heal":1523,"deaths":5,"layerGains":{"indomShip":2}}
|
||||
"p1": {"killed":18,"total":18,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":86976,"bossDmg":0,"heal":1661,"deaths":3,"layerGains":{"indomShip":2}}
|
||||
},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_1_20_a",1,null,1627.2,1,4,0,640,571,0,38,0],
|
||||
["p1",2,"op","chess_char_4_11_a",1,null,0,0,5,0,68,2585,0,3,1],
|
||||
["p1",3,"op","chess_char_4_12_a",2,null,0,0,7,0,11547,3277,1523,33,2],
|
||||
["p1",4,"op","chess_char_2_12_a",1,null,1107,1,34,0,881,1107,0,13,2],
|
||||
["p1",5,"op","chess_char_4_09_a",1,null,2044.67,1,10,8,40549,93,0,15,2],
|
||||
["p1",6,"op","chess_char_4_10_a",1,null,1029.36,1,6,7,17689,259,0,17,1],
|
||||
["p1",7,"op","chess_char_4_13_a",1,null,0,0,9,2,10229,1587,0,21,4],
|
||||
["p1",8,"op","chess_char_4_14_a",1,null,1276,1,35,0,5373,1276,0,8,1],
|
||||
["p1",1,"op","chess_char_1_20_a",1,null,577.4,1,5,0,421,1621,0,26,0],
|
||||
["p1",2,"op","chess_char_4_11_a",1,null,0,0,6,0,0,3002,0,0,1],
|
||||
["p1",3,"op","chess_char_2_12_a",1,null,1107,1,34,1,393,1107,0,10,2],
|
||||
["p1",4,"op","chess_char_4_09_a",1,null,1978.85,1,9,9,39308,159,0,13,1],
|
||||
["p1",5,"op","chess_char_4_10_a",1,null,1288,1,7,4,22387,0,0,17,1],
|
||||
["p1",6,"op","chess_char_4_12_a",2,null,989.98,1,10,0,0,2425,1661,0,0],
|
||||
["p1",7,"op","chess_char_4_13_a",1,null,0,0,11,0,6895,1587,0,13,2],
|
||||
["p1",8,"op","chess_char_4_14_a",1,null,1276,1,4,4,17572,0,0,12,5],
|
||||
["p1",9,"token","token_10041_cathy_catsld",null,null,100,1,12,0,0,0,0,0,null],
|
||||
["p1",10,"token","token_10041_cathy_catsld",null,null,100,1,13,0,0,0,0,0,null],
|
||||
["-","~1","device","trap_1105_accrate",null,null,100,1,1,0,0,0,0,0,null],
|
||||
["-","~2","device","trap_1105_accrate",null,null,100,1,2,0,0,0,0,0,null],
|
||||
["-","~3","device","trap_1105_accrate",null,null,100,1,3,0,0,0,0,0,null]
|
||||
],
|
||||
"enemies": {"enemy_1158_divman":[15,15,0,2849,57024],"enemy_1160_hvyslr":[2,1,1,5740,23040],"enemy_1161_tidmag":[1,1,0,2166,6912]},
|
||||
"hooks": [1,33,2879,214,214,306,308,1042,22,23,13,13,0,8131,210,8,18,1,1,22,1,0,9],
|
||||
"events": {"atk":257,"deploy":12,"die":22,"dmg":308,"fx":48,"layer":1,"leak":1,"skill":26,"spawn":31,"status":99},
|
||||
"fx": {"dilemma":2,"displace":7,"dodge":9,"explosion":1,"frostNova":4,"garrison":1,"levitate":7,"overclock":1,"pull":1,"shield":2,"slippery":1,"splash":2,"tornado":2,"tornadoPulse":8},
|
||||
"snaps": "8db24db5 bd49abba e851f738 07d3cf13 3b2ba3a7 f0b55220 093a961a 3f9a349d b6a73354 da1b7817"
|
||||
"enemies": {"enemy_1158_divman":[15,15,0,2119,57024],"enemy_1160_hvyslr":[2,2,0,5090,23040],"enemy_1161_tidmag":[1,1,0,2691,6912]},
|
||||
"hooks": [1,32,2039,172,172,261,269,1137,21,21,12,12,0,5972,102,9,18,0,1,21,1,1,3],
|
||||
"events": {"atk":222,"deploy":11,"die":21,"dmg":269,"fx":26,"layer":1,"skill":24,"spawn":31,"status":80},
|
||||
"fx": {"burst":1,"dilemma":1,"dodge":3,"explosion":5,"frostNova":2,"garrison":1,"levitate":7,"overclock":1,"shield":2,"slippery":1,"splash":2},
|
||||
"snaps": "910f43b9 691d4675 7aa329ef 265d3e05 a0f84586 b0546a70 a29372ef"
|
||||
},
|
||||
"bond-indomShip-high": {
|
||||
"about": "不屈 high: tier 2 layers 999; chess_char_1_20_b chess_char_3_16_b chess_char_4_23_b chess_char_5_01_b chess_char_2_12_b chess_char_4_24_b chess_char_4_25_b chess_char_4_26_b",
|
||||
@@ -876,7 +876,7 @@
|
||||
"snaps": "ae3e9ee4 e795ca48 af286313 5aa3428e 6e5316b8 959e25b3 4a8f8f76 e74c3a44 496ccf66 d9ba6888 55757f23 aa695997 2dac6dad 8ad5fbdb 83692eb8 8299c089"
|
||||
},
|
||||
"bond-preciShip-low": {
|
||||
"about": "精准 low: tier 1 layers 1; chess_char_4_11_a chess_char_4_12_a chess_char_4_04_a chess_char_4_07_a chess_char_4_09_a chess_char_1_09_a chess_char_1_17_a chess_char_4_10_a token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"about": "精准 low: tier 1 layers 1; chess_char_4_11_a chess_char_4_04_a chess_char_4_07_a chess_char_4_09_a chess_char_1_09_a chess_char_1_17_a chess_char_4_10_a chess_char_4_12_a token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"fast": false,
|
||||
"kind": "normal",
|
||||
"stageId": "act1autochess_m01",
|
||||
@@ -884,39 +884,39 @@
|
||||
"round": 5,
|
||||
"seed": 2452926770,
|
||||
"waveId": "act1autochess_05",
|
||||
"time": 53.4,
|
||||
"ticks": 1602,
|
||||
"time": 54,
|
||||
"ticks": 1620,
|
||||
"reason": "cleared",
|
||||
"killed": 21,
|
||||
"total": 21,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": null,
|
||||
"rngDraws": 24,
|
||||
"rngDraws": 21,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {"p1":{"killed":21,"total":21,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":73125,"bossDmg":0,"heal":0,"deaths":1,"layerGains":{"visiShip":4}}},
|
||||
"players": {"p1":{"killed":21,"total":21,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":73125,"bossDmg":0,"heal":0,"deaths":0,"layerGains":{"visiShip":4}}},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_4_11_a",1,null,2144,1,6,0,0,0,0,0,0],
|
||||
["p1",2,"op","chess_char_4_12_a",2,null,1754,1,7,2,10949,0,0,16,1],
|
||||
["p1",3,"op","chess_char_4_04_a",1,null,1760,1,8,7,14485,0,0,40,2],
|
||||
["p1",4,"op","chess_char_4_07_a",1,null,0,0,10,2,9734,1738,0,24,6],
|
||||
["p1",5,"op","chess_char_4_09_a",1,null,2137.6,1,11,8,26928,0,0,15,2],
|
||||
["p1",6,"op","chess_char_1_09_a",1,null,1770,1,4,0,0,0,0,0,0],
|
||||
["p1",7,"op","chess_char_1_17_a",1,null,1139,1,5,0,0,0,0,0,0],
|
||||
["p1",8,"op","chess_char_4_10_a",1,null,1288,1,9,2,11029,0,0,12,1],
|
||||
["p1",9,"token","token_10041_cathy_catsld",null,null,100,1,13,0,0,0,0,0,null],
|
||||
["p1",10,"token","token_10041_cathy_catsld",null,null,100,1,12,0,0,0,0,0,null],
|
||||
["p1",2,"op","chess_char_4_04_a",1,null,1760,1,7,4,7013,0,0,26,2],
|
||||
["p1",3,"op","chess_char_4_07_a",1,null,840,1,8,2,6582,898,0,21,4],
|
||||
["p1",4,"op","chess_char_4_09_a",1,null,2137.6,1,10,10,32312,0,0,17,2],
|
||||
["p1",5,"op","chess_char_1_09_a",1,null,1770,1,4,0,0,0,0,0,0],
|
||||
["p1",6,"op","chess_char_1_17_a",1,null,1139,1,5,0,0,0,0,0,0],
|
||||
["p1",7,"op","chess_char_4_10_a",1,null,1288,1,9,2,9397,0,0,11,1],
|
||||
["p1",8,"op","chess_char_4_12_a",2,null,1754,1,11,3,17821,0,0,19,1],
|
||||
["p1",9,"token","token_10041_cathy_catsld",null,null,100,1,12,0,0,0,0,0,null],
|
||||
["p1",10,"token","token_10041_cathy_catsld",null,null,100,1,13,0,0,0,0,0,null],
|
||||
["-","~1","device","trap_1105_accrate",null,null,100,1,1,0,0,0,0,0,null],
|
||||
["-","~2","device","trap_1105_accrate",null,null,100,1,2,0,0,0,0,0,null],
|
||||
["-","~3","device","trap_1105_accrate",null,null,100,1,3,0,0,0,0,0,null]
|
||||
],
|
||||
"enemies": {"enemy_1249_lysdb_2":[5,5,0,0,27000],"enemy_1251_lysyta":[15,15,0,24,37125],"enemy_1328_cbjedi":[1,1,0,1714,9000]},
|
||||
"hooks": [1,34,1602,113,113,162,157,0,22,22,12,9,0,6783,35,3,21,0,1,22,2,0,0],
|
||||
"events": {"atk":133,"deploy":10,"die":22,"dmg":157,"fx":65,"layer":2,"skill":21,"spawn":34,"status":48},
|
||||
"fx": {"charge":6,"dilemma":2,"displace":10,"garrison":2,"levitate":11,"pull":1,"shadowWeave":16,"shieldBreak":5,"slippery":1,"splash":3,"stealth":2,"tornado":1,"tornadoPulse":5},
|
||||
"snaps": "e57ceca7 ff94bb6d b8280d4d 705592d2 6381d0d2 8d1a1548"
|
||||
"enemies": {"enemy_1249_lysdb_2":[5,5,0,0,27000],"enemy_1251_lysyta":[15,15,0,0,37125],"enemy_1328_cbjedi":[1,1,0,898,9000]},
|
||||
"hooks": [1,34,1620,96,96,157,152,0,21,21,10,7,0,6646,33,1,21,0,1,21,2,0,0],
|
||||
"events": {"atk":119,"deploy":10,"die":21,"dmg":152,"fx":61,"layer":2,"skill":17,"spawn":34,"status":46},
|
||||
"fx": {"charge":4,"dilemma":2,"displace":14,"garrison":2,"levitate":11,"pull":1,"shadowWeave":11,"shieldBreak":5,"slippery":1,"splash":2,"stealth":2,"tornado":1,"tornadoPulse":5},
|
||||
"snaps": "c27c0600 1d169021 02c1eb1d 8ea4ebf1 57022adf 39e3da22"
|
||||
},
|
||||
"bond-preciShip-high": {
|
||||
"about": "精准 high: tier 2 layers 999; chess_char_4_11_b chess_char_4_12_b chess_char_4_09_b chess_char_1_09_b chess_char_1_17_b chess_char_2_01_b chess_char_4_10_b chess_char_4_13_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"about": "精准 high: tier 2 layers 999; chess_char_4_11_b chess_char_4_09_b chess_char_1_09_b chess_char_1_17_b chess_char_2_01_b chess_char_4_10_b chess_char_4_12_b chess_char_4_13_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"fast": true,
|
||||
"kind": "normal",
|
||||
"stageId": "act1autochess_m04",
|
||||
@@ -931,29 +931,29 @@
|
||||
"total": 24,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": null,
|
||||
"rngDraws": 19,
|
||||
"rngDraws": 21,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {"p1":{"killed":24,"total":24,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":144083,"bossDmg":0,"heal":0,"deaths":2,"layerGains":{}}},
|
||||
"players": {"p1":{"killed":24,"total":24,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":144293,"bossDmg":0,"heal":1227,"deaths":2,"layerGains":{}}},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_4_11_b",1,"uniequip_002_cathy",1261.53,1,8,0,0,2143,0,0,1],
|
||||
["p1",2,"op","chess_char_4_12_b",2,"uniequip_002_glady",2232,1,6,0,0,0,0,0,0],
|
||||
["p1",3,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",3992.8,1,9,0,17552,0,0,7,1],
|
||||
["p1",4,"op","chess_char_1_09_b",1,"uniequip_002_caper",3876.25,1,4,10,33806,0,0,13,1],
|
||||
["p1",5,"op","chess_char_1_17_b",1,"uniequip_002_indigo",1356,1,5,0,0,0,0,5,1],
|
||||
["p1",6,"op","chess_char_2_01_b",1,"uniequip_002_excu",0,0,11,6,38016,2146,0,6,1],
|
||||
["p1",7,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1664,1,7,5,52591,0,0,7,1],
|
||||
["p1",8,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",0,0,10,3,2118,1989,0,0,3],
|
||||
["p1",1,"op","chess_char_4_11_b",1,"uniequip_002_cathy",1459,1,8,0,0,1837,0,0,1],
|
||||
["p1",2,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",3992.8,1,6,0,0,0,0,0,0],
|
||||
["p1",3,"op","chess_char_1_09_b",1,"uniequip_002_caper",3876.25,1,4,12,50704,0,0,12,1],
|
||||
["p1",4,"op","chess_char_1_17_b",1,"uniequip_002_indigo",1356,1,5,0,0,0,0,8,1],
|
||||
["p1",5,"op","chess_char_2_01_b",1,"uniequip_002_excu",0,0,11,6,38016,2146,0,6,1],
|
||||
["p1",6,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1664,1,7,5,53097,0,0,7,1],
|
||||
["p1",7,"op","chess_char_4_12_b",2,"uniequip_002_glady",2232,1,9,0,948,1227,1227,2,1],
|
||||
["p1",8,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",0,0,10,1,1527,1989,0,0,1],
|
||||
["p1",9,"token","token_10041_cathy_catsld",null,null,100,1,12,0,0,0,0,0,null],
|
||||
["p1",10,"token","token_10041_cathy_catsld",null,null,100,1,13,0,0,0,0,0,null],
|
||||
["-","~1","device","trap_1105_accrate",null,null,100,1,1,0,0,0,0,0,null],
|
||||
["-","~2","device","trap_1105_accrate",null,null,100,1,2,0,0,0,0,0,null],
|
||||
["-","~3","device","trap_1105_accrate",null,null,100,1,3,0,0,0,0,0,null]
|
||||
],
|
||||
"enemies": {"enemy_1019_jshoot_2":[7,7,0,4441,21773],"enemy_1299_ymkilr_2":[3,3,0,1837,38016],"enemy_1422_lrsldr_2":[14,14,0,0,88704]},
|
||||
"hooks": [1,37,2071,84,84,151,151,0,26,26,9,8,0,4304,189,10,24,0,1,26,0,0,0],
|
||||
"events": {"atk":85,"deploy":10,"die":26,"dmg":151,"fx":17,"skill":17,"spawn":37,"status":13},
|
||||
"fx": {"crit":2,"dilemma":1,"frostNova":3,"levitate":7,"overclock":1,"slippery":1,"strike":2},
|
||||
"snaps": "88ecbc01 8a1ee02f cd042d3b 73363111 6ff4e2d8 de909066 a4a9c65d"
|
||||
"enemies": {"enemy_1019_jshoot_2":[7,7,0,3373,21773],"enemy_1299_ymkilr_2":[3,3,0,1837,38016],"enemy_1422_lrsldr_2":[14,14,0,0,88704]},
|
||||
"hooks": [1,37,2071,84,84,166,166,663,26,26,7,6,0,4290,103,10,24,0,1,26,0,0,0],
|
||||
"events": {"atk":84,"deploy":10,"die":26,"dmg":166,"fx":21,"skill":13,"spawn":37,"status":10},
|
||||
"fx": {"crit":2,"frostNova":1,"levitate":7,"overclock":1,"pull":1,"slippery":1,"strike":2,"tornado":1,"tornadoPulse":5},
|
||||
"snaps": "1c35197a b5a550c2 449f2d84 3e5d7032 3c466668 15903287 c2362cab"
|
||||
},
|
||||
"bond-raidShip-low": {
|
||||
"about": "突袭 low: tier 1 layers 1; chess_char_4_17_a chess_char_4_18_a chess_char_2_09_a chess_char_4_19_a chess_char_1_18_a chess_char_4_13_a chess_char_4_14_a chess_char_4_20_a",
|
||||
@@ -1440,7 +1440,7 @@
|
||||
"snaps": "b3fec5d9 59ebb356 6d90ccd4 672b65be b58aec4b 60fa7afc 4d71ceab 1048946f 06425012 99d5d7f3 b20b2b93"
|
||||
},
|
||||
"bond-suntShip-low": {
|
||||
"about": "绝技 low: tier 1 layers 1; chess_char_1_02_b chess_char_4_17_a chess_char_4_18_a chess_char_4_12_a chess_char_4_16_a chess_char_1_01_b chess_char_4_13_a chess_char_4_14_a",
|
||||
"about": "绝技 low: tier 1 layers 1; chess_char_1_02_b chess_char_4_17_a chess_char_4_18_a chess_char_4_16_a chess_char_1_01_b chess_char_4_12_a chess_char_4_13_a chess_char_4_14_a",
|
||||
"fast": false,
|
||||
"kind": "normal",
|
||||
"stageId": "act2autochess_m03",
|
||||
@@ -1455,27 +1455,27 @@
|
||||
"total": 21,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": null,
|
||||
"rngDraws": 8,
|
||||
"rngDraws": 19,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {"p1":{"killed":21,"total":21,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":92198,"bossDmg":0,"heal":396,"deaths":2,"layerGains":{}}},
|
||||
"players": {"p1":{"killed":21,"total":21,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":93600,"bossDmg":0,"heal":468,"deaths":1,"layerGains":{}}},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_1_02_b",1,"uniequip_002_yak",3154,1,4,0,0,0,0,0,0],
|
||||
["p1",2,"op","chess_char_4_17_a",1,null,2818.99,1,5,2,1418,30,0,4,0],
|
||||
["p1",3,"op","chess_char_4_18_a",1,null,4587.2,1,8,3,8181,0,0,9,1],
|
||||
["p1",4,"op","chess_char_4_12_a",2,null,0,0,10,5,17855,2150,396,17,1],
|
||||
["p1",5,"op","chess_char_4_16_a",2,null,1246,1,33,0,6418,1246,0,26,2],
|
||||
["p1",6,"op","chess_char_1_01_b",1,"uniequip_002_inside",1421,1,6,7,23924,0,0,32,1],
|
||||
["p1",7,"op","chess_char_4_13_a",1,null,1587,1,7,2,6599,0,0,18,5],
|
||||
["p1",8,"op","chess_char_4_14_a",1,null,1276,1,9,2,27804,0,0,14,4],
|
||||
["p1",2,"op","chess_char_4_17_a",1,null,2698.96,1,5,4,8462,150,0,18,0],
|
||||
["p1",3,"op","chess_char_4_18_a",1,null,4587.2,1,8,7,16386,15,15,17,2],
|
||||
["p1",4,"op","chess_char_4_16_a",2,null,0,0,10,3,13468,1699,453,25,2],
|
||||
["p1",5,"op","chess_char_1_01_b",1,"uniequip_002_inside",1421,1,6,6,26692,0,0,42,2],
|
||||
["p1",6,"op","chess_char_4_12_a",2,null,1754,1,7,0,0,0,0,0,0],
|
||||
["p1",7,"op","chess_char_4_13_a",1,null,1587,1,9,1,11465,0,0,28,6],
|
||||
["p1",8,"op","chess_char_4_14_a",1,null,1276,1,11,0,17127,0,0,14,3],
|
||||
["-","~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_1249_lysdb_2":[5,5,0,1739,34560],"enemy_1251_lysyta":[15,15,0,121,47520],"enemy_1328_cbjedi":[1,1,0,1566,11520]},
|
||||
"hooks": [1,33,1604,143,143,216,211,276,23,23,14,13,14,6222,470,20,21,0,1,23,0,0,0],
|
||||
"events": {"atk":143,"deploy":9,"die":23,"dmg":208,"fx":57,"skill":29,"spawn":32,"status":42},
|
||||
"fx": {"displace":26,"explosion":4,"frostNova":5,"pull":1,"rockslide":1,"shieldBreak":8,"sp":2,"swordStorm":2,"thorns":2,"tornado":1,"tornadoPulse":5},
|
||||
"snaps": "d4d5e757 8604a676 5217be11 0c4d8f95 9d7986ea ac98758f"
|
||||
"enemies": {"enemy_1249_lysdb_2":[5,5,0,453,34560],"enemy_1251_lysyta":[15,15,0,229,47520],"enemy_1328_cbjedi":[1,1,0,1182,11520]},
|
||||
"hooks": [1,32,1604,172,172,234,225,9,23,22,15,14,20,5887,502,14,21,0,1,23,0,0,0],
|
||||
"events": {"atk":172,"deploy":8,"die":22,"dmg":219,"fx":50,"heal":2,"skill":31,"spawn":32,"status":98},
|
||||
"fx": {"block":4,"explosion":3,"frostNova":6,"rockslide":2,"shieldBreak":11,"swordRain":12,"swordStorm":2,"thorns":10},
|
||||
"snaps": "241cb7e7 200c57ef 07026ad0 06c49f0b 308a5472 31b270f1"
|
||||
},
|
||||
"bond-suntShip-high": {
|
||||
"about": "绝技 high: tier 2 layers 999; chess_char_1_02_b chess_char_1_04_b chess_char_4_19_a chess_char_1_01_b chess_char_1_03_b chess_char_1_06_b chess_char_4_20_a chess_char_4_21_a",
|
||||
@@ -1548,7 +1548,7 @@
|
||||
"snaps": "5fab4324 4504ae6f ce2c7b3f 273640e9 88622454"
|
||||
},
|
||||
"bond-swiftShip-high": {
|
||||
"about": "迅捷 high: tier 1 layers 999; chess_char_4_11_b chess_char_4_12_b chess_char_1_19_b chess_char_4_07_b chess_char_4_09_b chess_char_1_01_b chess_char_4_06_b chess_char_4_10_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"about": "迅捷 high: tier 1 layers 999; chess_char_4_11_b chess_char_1_19_b chess_char_4_07_b chess_char_4_09_b chess_char_1_01_b chess_char_4_06_b chess_char_4_10_b chess_char_4_12_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"fast": true,
|
||||
"kind": "normal",
|
||||
"stageId": "act2autochess_m01",
|
||||
@@ -1556,33 +1556,33 @@
|
||||
"round": 10,
|
||||
"seed": 1175070139,
|
||||
"waveId": "act1autochess_h03",
|
||||
"time": 102.8,
|
||||
"ticks": 3084,
|
||||
"time": 108.37,
|
||||
"ticks": 3251,
|
||||
"reason": "cleared",
|
||||
"killed": 24,
|
||||
"killed": 23,
|
||||
"total": 24,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": null,
|
||||
"rngDraws": 222,
|
||||
"rngDraws": 271,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {"p1":{"killed":24,"total":24,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":235584,"bossDmg":0,"heal":815,"deaths":1,"layerGains":{}}},
|
||||
"players": {"p1":{"killed":23,"total":24,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":219573,"bossDmg":0,"heal":742,"deaths":4,"layerGains":{}}},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_4_11_b",1,"uniequip_002_cathy",2644,1,4,0,0,0,0,0,0],
|
||||
["p1",2,"op","chess_char_4_12_b",2,"uniequip_002_glady",1351.48,1,6,3,26379,1695,815,30,4],
|
||||
["p1",3,"op","chess_char_1_19_b",1,"uniequip_002_wildmn",0,0,7,1,13581,1971,0,41,3],
|
||||
["p1",4,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",2383,1,5,0,0,0,0,0,0],
|
||||
["p1",5,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",2777.6,1,8,7,94293,0,0,37,5],
|
||||
["p1",6,"op","chess_char_1_01_b",1,"uniequip_002_inside",1421,1,1,2,15429,0,0,67,4],
|
||||
["p1",7,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,2,9,50453,0,0,102,3],
|
||||
["p1",8,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1664,1,3,2,35449,0,0,21,2],
|
||||
["p1",1,"op","chess_char_4_11_b",1,"uniequip_002_cathy",0,0,4,0,0,4098,0,0,1],
|
||||
["p1",2,"op","chess_char_1_19_b",1,"uniequip_002_wildmn",0,0,6,1,4054,1971,0,20,1],
|
||||
["p1",3,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",0,0,7,0,1332,2383,0,10,10],
|
||||
["p1",4,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",2777.6,1,5,5,65655,0,0,24,3],
|
||||
["p1",5,"op","chess_char_1_01_b",1,"uniequip_002_inside",1421,1,1,2,17948,0,0,76,5],
|
||||
["p1",6,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,2,10,67651,0,0,110,3],
|
||||
["p1",7,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1664,1,3,2,36325,0,0,22,2],
|
||||
["p1",8,"op","chess_char_4_12_b",2,"uniequip_002_glady",0,0,8,3,26608,2974,742,16,2],
|
||||
["p1",9,"token","token_10041_cathy_catsld",null,null,100,1,9,0,0,0,0,0,null],
|
||||
["p1",10,"token","token_10041_cathy_catsld",null,null,100,1,10,0,0,0,0,0,null]
|
||||
],
|
||||
"enemies": {"enemy_1010_demon":[7,7,0,0,60480],"enemy_1422_lrsldr_2":[14,14,0,0,88704],"enemy_1425_lrcmra_2":[3,3,0,3666,86400]},
|
||||
"hooks": [1,34,3084,303,303,546,546,438,25,25,21,18,67,4354,126,3,24,0,1,25,0,0,0],
|
||||
"events": {"atk":351,"deploy":10,"die":25,"dmg":546,"fx":142,"skill":39,"spawn":34,"status":201},
|
||||
"fx": {"crit":45,"dilemma":5,"displace":17,"garrisonGrant":1,"levitate":20,"pull":4,"quadShot":2,"slippery":2,"sp":17,"splash":5,"tornado":4,"tornadoPulse":20},
|
||||
"snaps": "9b63f336 925188d7 6ea278e3 95d08962 b1f0ec9e 54a4f92e 6a3a048f ec134a87 227825d7 a8d37494 90671c04"
|
||||
"enemies": {"enemy_1010_demon":[7,7,0,1205,60480],"enemy_1422_lrsldr_2":[14,14,0,74,88704],"enemy_1425_lrcmra_2":[3,2,1,10147,70389]},
|
||||
"hooks": [1,34,3251,301,301,557,557,400,27,28,27,25,76,3567,117,10,24,1,1,27,0,0,0],
|
||||
"events": {"atk":349,"deploy":10,"die":27,"dmg":557,"fx":146,"leak":1,"skill":52,"spawn":34,"status":196},
|
||||
"fx": {"charge":10,"crit":53,"dilemma":3,"displace":16,"garrisonGrant":1,"levitate":21,"overclock":1,"pull":1,"quadShot":2,"slippery":2,"sp":23,"splash":7,"tornado":1,"tornadoPulse":5},
|
||||
"snaps": "52481b26 a970d314 2696635b 9c15cc8e 501817d0 a8faf661 7e05b7cf ffceee93 c505d863 f99ccd20 1c4895d8"
|
||||
},
|
||||
"bond-victoriaShip-low": {
|
||||
"about": "维多利亚 low: tier 1 layers 1; chess_char_3_06_a chess_char_3_02_a chess_char_3_03_a chess_char_3_04_a chess_char_3_05_a chess_char_1_06_a chess_char_2_05_a chess_char_2_10_a",
|
||||
|
||||
+308
-241
@@ -126,7 +126,7 @@
|
||||
"snaps": "dc0d56b5 5ea2fc96 22a7c614 a844181b da3c3f7d 949d5dbc f7646a53 01f0d227 f3885c32 030b669b 1fb58b64 44930d09 d25240d2 f8eafa88 14aa67a5 9dfef3d2 753642cc"
|
||||
},
|
||||
"boss-boss_2-pair": {
|
||||
"about": "假想敌:铳 pair pool 3000000: chess_char_5_19_b chess_char_4_01_b chess_char_5_14_b chess_char_5_17_b chess_char_5_15_b chess_char_5_20_b chess_char_5_21_b chess_char_5_22_b chess_char_5_23_b chess_char_4_02_b | chess_char_4_11_b chess_char_4_12_b chess_char_4_04_b chess_char_4_07_b chess_char_4_16_b chess_char_4_09_b chess_char_4_06_b chess_char_4_10_b chess_char_4_13_b chess_char_4_14_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"about": "假想敌:铳 pair pool 3000000: chess_char_5_19_b chess_char_4_01_b chess_char_5_14_b chess_char_5_17_b chess_char_5_15_b chess_char_5_20_b chess_char_5_21_b chess_char_5_22_b chess_char_5_23_b chess_char_4_02_b | chess_char_4_11_b chess_char_4_04_b chess_char_4_07_b chess_char_4_16_b chess_char_4_09_b chess_char_4_06_b chess_char_4_10_b chess_char_4_12_b chess_char_4_13_b chess_char_4_14_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"fast": false,
|
||||
"kind": "boss",
|
||||
"stageId": "act2autochess_m04",
|
||||
@@ -137,45 +137,78 @@
|
||||
"time": 200,
|
||||
"ticks": 6000,
|
||||
"reason": "forced",
|
||||
"killed": 7,
|
||||
"killed": 8,
|
||||
"total": 8,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": 2356149,
|
||||
"rngDraws": 412,
|
||||
"bossHpLeft": 2350858,
|
||||
"rngDraws": 752,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":7,"total":8,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":606132,"bossDmg":324770,"heal":21014,"deaths":1,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":816500,"bossDmg":315268,"heal":3306,"deaths":2,"layerGains":{}}
|
||||
"p1": {"killed":8,"total":8,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":687741,"bossDmg":360696,"heal":26057,"deaths":0,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":822679,"bossDmg":285212,"heal":6813,"deaths":2,"layerGains":{}}
|
||||
},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",3907,1,9,1,202994,1042,0,71,3],
|
||||
["p1",2,"op","chess_char_4_01_b",2,"uniequip_002_rmixer",5482.35,1,11,0,8474,11961,300,48,1],
|
||||
["p1",3,"op","chess_char_5_14_b",1,"none",1994,1,7,0,34133,2238,179,55,19],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",2738,1,13,0,11086,0,0,80,1],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",1170,1,1,0,109255,0,2041,49,10],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",2418.5,1,3,0,81091,0,0,53,5],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",2769.3,1,17,1,25904,2295,811,48,2],
|
||||
["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",1611,1,41,0,91104,1611,0,25,12],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",1610,1,5,0,0,0,17670,23,3],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",1695,1,15,0,42090,1393,13,34,2],
|
||||
["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",1697.41,1,45,0,0,4941,348,0,1],
|
||||
["p2",12,"op","chess_char_4_12_b",2,"uniequip_002_glady",2232,1,12,0,32476,0,0,45,3],
|
||||
["p2",13,"op","chess_char_4_04_b",1,"uniequip_002_ines",3545.85,1,46,1,271164,879,451,280,8],
|
||||
["p2",14,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",0,0,14,0,2411,2646,263,13,6],
|
||||
["p2",15,"op","chess_char_4_16_b",2,"uniequip_002_texas2",2671.35,1,47,0,77003,4837,555,181,8],
|
||||
["p2",16,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",1851.91,1,16,0,85508,1270,344,75,5],
|
||||
["p2",17,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,2,0,1366,0,0,13,1],
|
||||
["p2",18,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1664,1,4,1,100869,0,0,70,3],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,18,0,112248,1346,1346,167,46],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1626,1,20,3,133456,0,0,65,16],
|
||||
["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",3907,1,9,0,181915,1042,0,71,3],
|
||||
["p1",2,"op","chess_char_4_01_b",2,"uniequip_002_rmixer",3537,1,11,0,24014,19274,205,73,1],
|
||||
["p1",3,"op","chess_char_5_14_b",1,"none",1994,1,7,0,32112,1028,124,26,17],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",2738,1,13,0,5410,0,0,33,1],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",1170,1,1,0,109631,0,7204,57,10],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",2418.5,1,3,0,87026,0,0,44,4],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",2769.3,1,17,0,19587,0,0,38,1],
|
||||
["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",1611,1,19,3,195138,1308,1308,70,23],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",1610,1,5,0,0,0,17167,27,3],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",1695,1,15,0,32909,1393,49,35,3],
|
||||
["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",2644,1,48,0,35,3833,460,1,2],
|
||||
["p2",12,"op","chess_char_4_04_b",1,"uniequip_002_ines",3545.85,1,44,1,254443,511,511,218,8],
|
||||
["p2",13,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",2144.97,1,8,0,2891,1249,1011,21,7],
|
||||
["p2",14,"op","chess_char_4_16_b",2,"uniequip_002_texas2",2671.35,1,47,2,117728,5484,1501,158,12],
|
||||
["p2",15,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",2777.6,1,10,0,57785,0,0,54,3],
|
||||
["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,2,1,201569,0,0,183,3],
|
||||
["p2",17,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1664,1,4,0,0,0,0,0,0],
|
||||
["p2",18,"op","chess_char_4_12_b",2,"uniequip_002_glady",2232,1,18,0,49124,3331,3331,46,4],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,41,1,58765,1989,0,93,25],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1626,1,6,0,80338,0,0,49,15],
|
||||
["p2",21,"token","token_10041_cathy_catsld",null,null,100,1,21,0,0,0,0,0,null],
|
||||
["p2",22,"token","token_10041_cathy_catsld",null,null,100,1,22,0,0,0,0,0,null]
|
||||
],
|
||||
"enemies": {"enemy_1005_yokai_2":[6,6,0,3949,62190],"enemy_1430_lrrook":[2,1,1,0,720539],"enemy_9017_achunt":[2,0,0,32509,643851]},
|
||||
"hooks": [1,45,6000,1397,1409,2577,2608,3285,10,22,155,149,20,41642,1572,0,10,1,1,11,0,11,2],
|
||||
"events": {"atk":1453,"deploy":35,"die":21,"dmg":2604,"fx":554,"heal":57,"leak":1,"skill":304,"spawn":32,"status":586},
|
||||
"fx": {"aoe":35,"appear":2,"blink":11,"burst":11,"catShield":1,"charge":6,"counter":20,"crit":19,"dilemma":5,"disappear":2,"dodge":2,"explosion":16,"frostNova":46,"iceSpike":40,"overclock":1,"pull":3,"ripple":19,"sentry":4,"sermon":1,"shadowWeave":8,"shield":5,"slippery":3,"soul":3,"sp":10,"stealth":8,"swordRain":63,"swordStorm":8,"tornado":3,"tornadoPulse":15,"weightless":5,"zone":179},
|
||||
"snaps": "bded3f8f 3be8bd3e 953a4177 0b7ebd10 0f36b9fa 98a31839 7097940b ccf68cd9 9f1e238b dbe2e9a7 c44e08ee 2e00e3ad e7215027 389a6d2f e881db8e e3b3ba28 ac1c13c3 18a7c70a 66ee300b 08fe4144"
|
||||
"enemies": {"enemy_1005_yokai_2":[6,6,0,2907,62190],"enemy_1430_lrrook":[2,2,0,0,802449],"enemy_9017_achunt":[2,0,0,37534,649142]},
|
||||
"hooks": [1,46,6000,1326,1334,3080,3125,4772,12,22,145,142,30,41390,1023,0,10,0,1,12,0,12,1],
|
||||
"events": {"atk":1360,"deploy":36,"die":22,"dmg":3119,"fx":674,"heal":100,"skill":287,"spawn":32,"status":493},
|
||||
"fx": {
|
||||
"aoe": 43,
|
||||
"appear": 2,
|
||||
"blink": 12,
|
||||
"burst": 12,
|
||||
"catShield": 1,
|
||||
"charge": 7,
|
||||
"counter": 30,
|
||||
"crit": 100,
|
||||
"dilemma": 3,
|
||||
"disappear": 2,
|
||||
"dodge": 1,
|
||||
"explosion": 15,
|
||||
"frostNova": 25,
|
||||
"garrisonGrant": 1,
|
||||
"iceSpike": 33,
|
||||
"overclock": 2,
|
||||
"pull": 4,
|
||||
"quadShot": 2,
|
||||
"ripple": 13,
|
||||
"sentry": 3,
|
||||
"sermon": 1,
|
||||
"shadowWeave": 8,
|
||||
"shield": 7,
|
||||
"soul": 5,
|
||||
"sp": 9,
|
||||
"stealth": 8,
|
||||
"swordRain": 106,
|
||||
"swordStorm": 12,
|
||||
"tornado": 4,
|
||||
"tornadoPulse": 20,
|
||||
"weightless": 4,
|
||||
"zone": 179
|
||||
},
|
||||
"snaps": "3cd698b1 c4c10bef daadee84 5c3c1c12 96ba3e74 96f0d391 80d19d1f 30a2db6e 6243ea15 3f0082c4 c13bd213 98f0e36a 2c94c94c 4baf1af3 acdcb24d c81946fb e1f31d51 fcc2b87d bf80310a 917c2427"
|
||||
},
|
||||
"boss-boss_2-solo": {
|
||||
"about": "假想敌:铳 solo pool 750000: chess_char_4_17_b chess_char_4_18_b chess_char_4_23_b chess_char_4_19_b chess_char_4_22_b chess_char_4_20_b chess_char_4_21_b chess_char_4_24_b chess_char_4_25_b chess_char_4_26_b",
|
||||
@@ -335,7 +368,7 @@
|
||||
"snaps": "165e5292 c4adc9b7 d9efbe56 b04b7078 02908f60 4fd4ad05 065d2593 63d56b7a a53e0b0e e1fd3f2a b6534bb2 cac54dd4 80457fc1 f44190f2 fba20cd8 4fb50167 41e708fa"
|
||||
},
|
||||
"boss-boss_4-pair": {
|
||||
"about": "盐风主教昆图斯 pair pool 4200000: chess_char_5_19_b chess_char_4_01_b chess_char_5_14_b chess_char_5_17_b chess_char_5_15_b chess_char_5_20_b chess_char_5_21_b chess_char_5_22_b chess_char_5_23_b chess_char_4_02_b | chess_char_4_11_b chess_char_4_12_b chess_char_4_04_b chess_char_4_07_b chess_char_4_16_b chess_char_4_09_b chess_char_4_06_b chess_char_4_10_b chess_char_4_13_b chess_char_4_14_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"about": "盐风主教昆图斯 pair pool 4200000: chess_char_5_19_b chess_char_4_01_b chess_char_5_14_b chess_char_5_17_b chess_char_5_15_b chess_char_5_20_b chess_char_5_21_b chess_char_5_22_b chess_char_5_23_b chess_char_4_02_b | chess_char_4_11_b chess_char_4_04_b chess_char_4_07_b chess_char_4_16_b chess_char_4_09_b chess_char_4_06_b chess_char_4_10_b chess_char_4_12_b chess_char_4_13_b chess_char_4_14_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"fast": false,
|
||||
"kind": "boss",
|
||||
"stageId": "act2autochess_m02",
|
||||
@@ -349,78 +382,78 @@
|
||||
"killed": 10,
|
||||
"total": 14,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": 2825291,
|
||||
"rngDraws": 471,
|
||||
"bossHpLeft": 3202998,
|
||||
"rngDraws": 670,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":10,"total":14,"perfect":false,"leaks":4,"leaksUncounted":0,"coins":0,"dmg":1339007,"bossDmg":473761,"heal":54412,"deaths":13,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":1103445,"bossDmg":900948,"heal":4247,"deaths":11,"layerGains":{}}
|
||||
"p1": {"killed":10,"total":14,"perfect":false,"leaks":2,"leaksUncounted":0,"coins":0,"dmg":929216,"bossDmg":303862,"heal":30593,"deaths":19,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":false,"leaks":2,"leaksUncounted":0,"coins":0,"dmg":1007145,"bossDmg":693141,"heal":3732,"deaths":15,"layerGains":{}}
|
||||
},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",0,0,47,2,138926,8083,269,21,2],
|
||||
["p1",2,"op","chess_char_4_01_b",2,"uniequip_002_rmixer",1875.61,1,50,0,16890,9787,775,13,2],
|
||||
["p1",3,"op","chess_char_5_14_b",1,"none",1445.61,1,54,0,49842,12274,1523,26,10],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",0,0,52,0,39707,13906,2210,35,2],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",850.6,1,55,2,367176,3392,13317,106,17],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",908.73,1,56,2,130196,11108,599,39,4],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",1250.45,1,19,0,164370,4283,221,209,6],
|
||||
["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",1202.87,1,57,2,279814,2473,454,58,20],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",1113.15,1,7,0,0,4854,34778,69,4],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",1316.45,1,15,0,152086,4283,265,71,3],
|
||||
["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",0,0,46,0,0,6742,0,0,1],
|
||||
["p2",12,"op","chess_char_4_12_b",2,"uniequip_002_glady",0,0,45,0,29962,5888,1424,11,2],
|
||||
["p2",13,"op","chess_char_4_04_b",1,"uniequip_002_ines",3468.16,1,26,0,443585,2606,119,325,9],
|
||||
["p2",14,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",0,0,44,0,17702,5178,97,19,7],
|
||||
["p2",15,"op","chess_char_4_16_b",2,"uniequip_002_texas2",2322.38,1,27,0,157329,6484,329,208,2],
|
||||
["p2",16,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",0,0,51,1,159918,7145,375,53,5],
|
||||
["p2",17,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",0,0,53,1,12062,3470,348,16,1],
|
||||
["p2",18,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1736.19,1,12,0,74688,4283,467,68,4],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,20,0,132635,5655,655,186,49],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1247.45,1,58,0,75565,2437,433,30,10],
|
||||
["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",0,0,53,2,117363,8141,327,18,1],
|
||||
["p1",2,"op","chess_char_4_01_b",2,"uniequip_002_rmixer",0,0,51,0,17733,11157,815,15,2],
|
||||
["p1",3,"op","chess_char_5_14_b",1,"none",0,0,62,0,55117,10500,760,8,10],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",752.57,1,54,0,9532,18845,873,11,1],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",804.59,1,67,1,323528,4299,3100,82,14],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",270.47,1,58,1,85423,10413,575,38,4],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",0,0,19,0,97856,2109,24,118,3],
|
||||
["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",0,0,3,3,121166,1980,369,42,14],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",0,0,55,0,0,4347,23631,39,3],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",1265.2,1,61,2,101498,2701,120,49,3],
|
||||
["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",0,0,47,0,0,6984,241,0,1],
|
||||
["p2",12,"op","chess_char_4_04_b",1,"uniequip_002_ines",1587.75,1,49,1,187019,4777,120,200,7],
|
||||
["p2",13,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",1820.42,1,64,0,23276,5661,228,32,7],
|
||||
["p2",14,"op","chess_char_4_16_b",2,"uniequip_002_texas2",1220.73,1,63,0,110018,6776,140,176,5],
|
||||
["p2",15,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",1413.53,1,56,0,242751,5255,264,54,5],
|
||||
["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",0,0,57,0,179403,3739,617,159,3],
|
||||
["p2",17,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1983,1,65,0,0,3629,120,0,0],
|
||||
["p2",18,"op","chess_char_4_12_b",2,"uniequip_002_glady",2100.38,1,60,0,64416,3658,1000,74,4],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1680.9,1,59,0,54090,2834,537,54,16],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1194.87,1,66,0,146172,2521,464,69,14],
|
||||
["p2",21,"token","token_10041_cathy_catsld",null,null,100,1,21,0,0,0,0,0,null],
|
||||
["p2",22,"token","token_10041_cathy_catsld",null,null,100,1,22,0,0,0,0,0,null]
|
||||
],
|
||||
"enemies": {"enemy_1010_demon":[4,4,0,9842,200612],"enemy_1438_dspred":[10,6,4,20511,867131],"enemy_1521_dslily":[1,0,0,86181,1374709]},
|
||||
"hooks": [1,56,6000,1451,1565,3107,3244,6682,34,40,160,157,13,41191,1906,17,15,4,1,36,0,37,4],
|
||||
"events": {"atk":1663,"deploy":41,"die":36,"dmg":3234,"fx":807,"heal":272,"leak":4,"skill":317,"spawn":37,"status":905},
|
||||
"enemies": {"enemy_1010_demon":[4,4,0,3991,200612],"enemy_1438_dspred":[10,6,4,14373,738747],"enemy_1521_dslily":[1,0,0,94162,997002]},
|
||||
"hooks": [1,65,6000,1201,1270,2930,3054,5119,44,50,117,115,15,31431,1146,14,15,4,1,46,0,30,4],
|
||||
"events": {"atk":1435,"deploy":50,"die":46,"dmg":3045,"fx":727,"heal":166,"leak":4,"skill":232,"spawn":37,"status":796},
|
||||
"fx": {
|
||||
"aoe": 42,
|
||||
"appear": 11,
|
||||
"aoe": 28,
|
||||
"appear": 8,
|
||||
"blink": 2,
|
||||
"burst": 37,
|
||||
"burst": 30,
|
||||
"charge": 7,
|
||||
"counter": 13,
|
||||
"crit": 7,
|
||||
"counter": 15,
|
||||
"crit": 74,
|
||||
"dilemma": 5,
|
||||
"disappear": 11,
|
||||
"displace": 24,
|
||||
"disappear": 8,
|
||||
"displace": 28,
|
||||
"dodge": 4,
|
||||
"explosion": 10,
|
||||
"frostNova": 49,
|
||||
"explosion": 14,
|
||||
"frostNova": 16,
|
||||
"grow": 1,
|
||||
"iceSpike": 163,
|
||||
"iceSpike": 88,
|
||||
"overclock": 1,
|
||||
"pull": 2,
|
||||
"ripple": 22,
|
||||
"pull": 4,
|
||||
"quadShot": 3,
|
||||
"ripple": 17,
|
||||
"rockfall": 18,
|
||||
"sentry": 1,
|
||||
"sentry": 2,
|
||||
"sermon": 2,
|
||||
"shadowWeave": 1,
|
||||
"shadowWeave": 5,
|
||||
"shield": 5,
|
||||
"slippery": 4,
|
||||
"soul": 9,
|
||||
"soul": 5,
|
||||
"sp": 11,
|
||||
"stealth": 9,
|
||||
"swordRain": 8,
|
||||
"swordStorm": 2,
|
||||
"stealth": 7,
|
||||
"swordRain": 27,
|
||||
"swordStorm": 5,
|
||||
"tentacle": 6,
|
||||
"tide": 5,
|
||||
"tornado": 2,
|
||||
"tornadoPulse": 10,
|
||||
"tornado": 4,
|
||||
"tornadoPulse": 20,
|
||||
"weightless": 4,
|
||||
"zone": 299
|
||||
"zone": 248
|
||||
},
|
||||
"snaps": "d5d054b2 cb90423b fee6602b ae24e1c0 e3c68927 26da52e2 6b690f9e cc8b62da 7602985f 437d670e 7b48851f 42782701 8c223b0c d5735dbe d7c8a039 0958be10 ecae9db7 bda3f543 442eb94c 6e3370b7"
|
||||
"snaps": "d5cfa048 05581e84 c8799f99 16719fc9 baac34eb 215b818c 39438feb 8ce78fdb 57634639 a6449f74 25f63a7a e196b737 ddc7d8ac 4a1bf12f 4c54ac5b 953c2875 7a3caa77 6805c13f 133ed228 6d33c7b6"
|
||||
},
|
||||
"boss-boss_4-solo": {
|
||||
"about": "盐风主教昆图斯 solo pool 1050000: chess_char_4_17_b chess_char_4_18_b chess_char_4_23_b chess_char_4_19_b chess_char_4_22_b chess_char_4_20_b chess_char_4_21_b chess_char_4_24_b chess_char_4_25_b chess_char_4_26_b",
|
||||
@@ -606,7 +639,7 @@
|
||||
"snaps": "1b2c287a 675f6516 fe7fec9f 7befc28b 5055ef2d f5a1b7d4 597e1735 157dd534 488e94fe b43c89ae cc11a2ec b2d6ae70 81dc7d36"
|
||||
},
|
||||
"boss-boss_6-pair": {
|
||||
"about": "阿利斯泰尔,帝国余晖 pair pool 3980000: chess_char_5_19_b chess_char_4_01_b chess_char_5_14_b chess_char_5_17_b chess_char_5_15_b chess_char_5_20_b chess_char_5_21_b chess_char_5_22_b chess_char_5_23_b chess_char_4_02_b | chess_char_4_11_b chess_char_4_12_b chess_char_4_04_b chess_char_4_07_b chess_char_4_16_b chess_char_4_09_b chess_char_4_06_b chess_char_4_10_b chess_char_4_13_b chess_char_4_14_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"about": "阿利斯泰尔,帝国余晖 pair pool 3980000: chess_char_5_19_b chess_char_4_01_b chess_char_5_14_b chess_char_5_17_b chess_char_5_15_b chess_char_5_20_b chess_char_5_21_b chess_char_5_22_b chess_char_5_23_b chess_char_4_02_b | chess_char_4_11_b chess_char_4_04_b chess_char_4_07_b chess_char_4_16_b chess_char_4_09_b chess_char_4_06_b chess_char_4_10_b chess_char_4_12_b chess_char_4_13_b chess_char_4_14_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"fast": false,
|
||||
"kind": "boss",
|
||||
"stageId": "act1autochess_m07",
|
||||
@@ -620,49 +653,84 @@
|
||||
"killed": 4,
|
||||
"total": 6,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": 2726484,
|
||||
"rngDraws": 136,
|
||||
"bossHpLeft": 2704841,
|
||||
"rngDraws": 598,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":4,"total":6,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":956228,"bossDmg":516630,"heal":5866,"deaths":6,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":875767,"bossDmg":736886,"heal":1349,"deaths":13,"layerGains":{}}
|
||||
"p1": {"killed":4,"total":6,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":1067324,"bossDmg":606787,"heal":7410,"deaths":3,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":1192744,"bossDmg":668371,"heal":775,"deaths":8,"layerGains":{}}
|
||||
},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",3907,1,3,2,128856,0,0,35,2],
|
||||
["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",3907,1,3,1,137921,0,0,31,2],
|
||||
["p1",2,"op","chess_char_4_01_b",2,"uniequip_002_rmixer",3537,1,1,0,0,0,0,0,0],
|
||||
["p1",3,"op","chess_char_5_14_b",1,"none",1994,1,5,0,51547,0,0,0,15],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",4654.6,1,11,0,15412,4549,4549,16,1],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",1170,1,7,2,335436,0,1317,71,12],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",1382,1,13,0,204001,0,0,75,6],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",0,0,40,0,19031,3258,0,21,1],
|
||||
["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",0,0,41,0,146978,3222,0,50,16],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",0,0,42,0,1934,3220,0,0,0],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",1695,1,9,0,53033,0,0,40,2],
|
||||
["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",2644,1,38,0,0,12227,333,0,1],
|
||||
["p2",12,"op","chess_char_4_12_b",2,"uniequip_002_glady",2232,1,2,0,0,0,0,0,0],
|
||||
["p2",13,"op","chess_char_4_04_b",1,"uniequip_002_ines",0,0,46,0,137499,9146,872,177,6],
|
||||
["p2",14,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",2383,1,10,0,0,0,0,0,0],
|
||||
["p2",15,"op","chess_char_4_16_b",2,"uniequip_002_texas2",527.19,1,53,0,50030,8463,144,167,5],
|
||||
["p2",16,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",0,0,49,0,170880,5555,0,71,4],
|
||||
["p2",17,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,8,0,0,0,0,0,0],
|
||||
["p2",18,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1664,1,12,0,310308,0,0,107,4],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",0,0,50,0,126161,3978,0,113,29],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",0,0,51,0,80890,4878,0,27,5],
|
||||
["p2",21,"token","token_10041_cathy_catsld",null,null,100,1,22,0,0,0,0,0,null],
|
||||
["p2",22,"token","token_10041_cathy_catsld",null,null,100,1,21,0,0,0,0,0,null]
|
||||
["p1",3,"op","chess_char_5_14_b",1,"none",1994,1,5,1,42476,0,0,0,14],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",4654.6,1,11,1,25797,1781,1781,17,1],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",1170,1,7,1,310098,0,3003,72,14],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",1382,1,13,0,209427,0,0,73,6],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",1629,1,47,0,31874,1629,0,38,2],
|
||||
["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",1611,1,48,0,251573,1611,0,86,24],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",1610,1,44,0,1934,3190,2627,3,1],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",1695,1,9,0,56225,0,0,43,2],
|
||||
["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",2644,1,42,0,0,12187,268,0,1],
|
||||
["p2",12,"op","chess_char_4_04_b",1,"uniequip_002_ines",2016.1,1,50,0,132143,10153,457,228,6],
|
||||
["p2",13,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",2383,1,6,0,0,0,0,0,0],
|
||||
["p2",14,"op","chess_char_4_16_b",2,"uniequip_002_texas2",1619,1,45,0,42786,8389,49,192,4],
|
||||
["p2",15,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",2777.6,1,14,0,242636,0,0,117,6],
|
||||
["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,8,0,487364,0,0,140,2],
|
||||
["p2",17,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1664,1,12,0,0,0,0,0,0],
|
||||
["p2",18,"op","chess_char_4_12_b",2,"uniequip_002_glady",2232,1,16,0,67574,0,0,168,6],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,46,0,134081,1989,0,125,31],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1626,1,49,0,86161,3252,0,33,6],
|
||||
["p2",21,"token","token_10041_cathy_catsld",null,null,100,1,21,0,0,0,0,0,null],
|
||||
["p2",22,"token","token_10041_cathy_catsld",null,null,100,1,22,0,0,0,0,0,null]
|
||||
],
|
||||
"enemies": {
|
||||
"enemy_10028_vtswd": [4,4,0,0,0],
|
||||
"enemy_10029_vtshld": [2,2,0,0,0],
|
||||
"enemy_10030_vtwand": [2,2,0,0,0],
|
||||
"enemy_10085_hllevi_2": [2,0,2,0,377867],
|
||||
"enemy_1010_demon": [4,4,0,16776,200612],
|
||||
"enemy_9032_aclionk": [1,0,0,41719,1253516]
|
||||
"enemy_10030_vtwand": [1,1,0,0,0],
|
||||
"enemy_10085_hllevi_2": [2,0,2,0,784297],
|
||||
"enemy_1010_demon": [4,4,0,13968,200612],
|
||||
"enemy_9032_aclionk": [1,0,0,30213,1275159]
|
||||
},
|
||||
"hooks": [1,51,6000,985,992,1563,1663,1575,31,35,109,105,0,31092,1258,4,15,2,1,27,0,8,1],
|
||||
"events": {"atk":1079,"deploy":36,"die":33,"dmg":1647,"fx":475,"heal":8,"leak":2,"skill":214,"spawn":37,"status":770},
|
||||
"fx": {"aoe":39,"appear":4,"blink":2,"burst":8,"crit":1,"dilemma":4,"disappear":4,"displace":14,"dodge":1,"equip":10,"explosion":5,"frostNova":29,"garrisonGrant":1,"iceSpike":17,"overclock":1,"revive":2,"ripple":20,"sentry":3,"shadowWeave":3,"shield":1,"slippery":4,"soul":2,"sp":17,"stealth":6,"sword":2,"swordRain":20,"swordStorm":5,"telegraph":14,"vest":2,"weightless":6,"zone":228},
|
||||
"snaps": "67c68c34 87636137 f5a31952 ab1da9a5 b1b9fa49 914f12bb 25261c33 394b5256 240747e9 0a21097a 58de0dfb f7f72619 6d5001dd e6829d8b 7761d7f9 3e5f6259 689b106e 52d8928a ac7284a0 448e2f14"
|
||||
"hooks": [1,49,6000,1361,1380,2376,2393,818,22,26,128,124,0,39025,1440,4,14,2,1,18,0,4,1],
|
||||
"events": {"atk":1441,"deploy":35,"die":24,"dmg":2375,"fx":660,"heal":25,"leak":2,"skill":252,"spawn":36,"status":926},
|
||||
"fx": {
|
||||
"aoe": 46,
|
||||
"appear": 4,
|
||||
"blink": 2,
|
||||
"burst": 4,
|
||||
"crit": 88,
|
||||
"dilemma": 6,
|
||||
"disappear": 4,
|
||||
"displace": 19,
|
||||
"dodge": 1,
|
||||
"equip": 8,
|
||||
"explosion": 6,
|
||||
"frostNova": 31,
|
||||
"garrisonGrant": 1,
|
||||
"iceSpike": 34,
|
||||
"overclock": 1,
|
||||
"pull": 6,
|
||||
"quadShot": 2,
|
||||
"revive": 2,
|
||||
"ripple": 18,
|
||||
"sentry": 3,
|
||||
"shadowWeave": 3,
|
||||
"shield": 1,
|
||||
"soul": 4,
|
||||
"sp": 14,
|
||||
"stealth": 6,
|
||||
"sword": 3,
|
||||
"swordRain": 15,
|
||||
"swordStorm": 4,
|
||||
"telegraph": 14,
|
||||
"tornado": 6,
|
||||
"tornadoPulse": 30,
|
||||
"vest": 2,
|
||||
"weightless": 6,
|
||||
"zone": 266
|
||||
},
|
||||
"snaps": "71ea5c09 c637fdb1 ef8eff23 dafd1b16 870d3a92 c8bef56e ef385349 8b0f67e6 f4ecdaae c2e41218 843a4c25 28a91424 99e64585 bf703aff 37e6b10f a0d2f168 c9b4c589 01338b90 c29679c2 2b5a6bd0"
|
||||
},
|
||||
"boss-boss_6-solo": {
|
||||
"about": "阿利斯泰尔,帝国余晖 solo pool 995000: chess_char_4_17_b chess_char_4_18_b chess_char_4_23_b chess_char_4_19_b chess_char_4_22_b chess_char_4_20_b chess_char_4_21_b chess_char_4_24_b chess_char_4_25_b chess_char_4_26_b",
|
||||
@@ -826,7 +894,7 @@
|
||||
"snaps": "fb57a457 3421e2b8 dbddb577 aef7b23c d91bd1fa 3b8774f3 e60348ab e4ca3c93 a3da29b6 ff5e9594 61b7b3b6 fe058645 c5dfd928 9f980ca6 e767bfd0 564e23cc be96a5c2 f867fc1e fa98a005 402593b3"
|
||||
},
|
||||
"hidden-boss_8-pair": {
|
||||
"about": "假想敌:胄 pair pool 7200000: chess_char_5_19_b chess_char_4_01_b chess_char_5_14_b chess_char_5_17_b chess_char_5_15_b chess_char_5_20_b chess_char_5_21_b chess_char_5_22_b chess_char_5_23_b chess_char_4_02_b | chess_char_4_11_b chess_char_4_12_b chess_char_4_04_b chess_char_4_07_b chess_char_4_16_b chess_char_4_09_b chess_char_4_06_b chess_char_4_10_b chess_char_4_13_b chess_char_4_14_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"about": "假想敌:胄 pair pool 7200000: chess_char_5_19_b chess_char_4_01_b chess_char_5_14_b chess_char_5_17_b chess_char_5_15_b chess_char_5_20_b chess_char_5_21_b chess_char_5_22_b chess_char_5_23_b chess_char_4_02_b | chess_char_4_11_b chess_char_4_04_b chess_char_4_07_b chess_char_4_16_b chess_char_4_09_b chess_char_4_06_b chess_char_4_10_b chess_char_4_12_b chess_char_4_13_b chess_char_4_14_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"fast": false,
|
||||
"kind": "hidden",
|
||||
"stageId": "act1autochess_m05",
|
||||
@@ -837,95 +905,94 @@
|
||||
"time": 200,
|
||||
"ticks": 6000,
|
||||
"reason": "forced",
|
||||
"killed": 13,
|
||||
"killed": 14,
|
||||
"total": 18,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": 6018290,
|
||||
"rngDraws": 684,
|
||||
"bossHpLeft": 6093249,
|
||||
"rngDraws": 678,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":13,"total":18,"perfect":false,"leaks":2,"leaksUncounted":0,"coins":0,"dmg":1938099,"bossDmg":992806,"heal":51019,"deaths":17,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":false,"leaks":2,"leaksUncounted":0,"coins":0,"dmg":381327,"bossDmg":188904,"heal":6914,"deaths":26,"layerGains":{}}
|
||||
"p1": {"killed":14,"total":18,"perfect":false,"leaks":2,"leaksUncounted":0,"coins":0,"dmg":1631955,"bossDmg":556895,"heal":40979,"deaths":16,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":712904,"bossDmg":548802,"heal":7371,"deaths":22,"layerGains":{}}
|
||||
},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",7814,1,87,2,88478,21913,689,42,3],
|
||||
["p1",2,"op","chess_char_4_01_b",2,"uniequip_002_rmixer",2847.9,1,76,0,6045,15126,739,25,2],
|
||||
["p1",3,"op","chess_char_5_14_b",1,"none",3988,1,88,0,42463,15591,4140,40,8],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",2260.62,1,86,0,31022,24337,1819,21,2],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",1214.62,1,81,5,960839,4155,16322,100,13],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",0,0,79,3,428143,14006,338,38,4],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",0,0,1,1,144400,4077,819,12,2],
|
||||
["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",0,0,64,1,24893,6619,175,14,2],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",0,0,71,0,0,12336,25861,23,2],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",0,0,77,1,211816,10287,117,11,2],
|
||||
["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",0,0,74,0,0,7013,271,0,1],
|
||||
["p2",12,"op","chess_char_4_12_b",2,"uniequip_002_glady",0,0,70,0,16804,5349,885,6,1],
|
||||
["p2",13,"op","chess_char_4_04_b",1,"uniequip_002_ines",0,0,82,1,15203,15182,83,71,4],
|
||||
["p2",14,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",0,0,63,0,8814,10282,1941,3,2],
|
||||
["p2",15,"op","chess_char_4_16_b",2,"uniequip_002_texas2",0,0,84,1,91608,19229,327,30,10],
|
||||
["p2",16,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",0,0,62,2,85162,9516,232,23,2],
|
||||
["p2",17,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,89,0,18343,1561,0,158,3],
|
||||
["p2",18,"op","chess_char_4_10_b",1,"uniequip_002_aroma",0,0,18,0,110240,6337,343,59,2],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",0,0,73,0,30032,6533,2555,36,13],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",0,0,61,0,5121,3529,277,3,1],
|
||||
["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",0,0,3,6,303727,22484,384,33,2],
|
||||
["p1",2,"op","chess_char_4_01_b",2,"uniequip_002_rmixer",0,0,7,0,9900,9238,344,9,1],
|
||||
["p1",3,"op","chess_char_5_14_b",1,"none",3988,1,81,2,60038,14145,3817,35,10],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",0,0,78,0,29874,23536,239,30,3],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",1277.62,1,73,1,527300,3402,17766,98,9],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",0,0,71,1,87427,11850,264,21,2],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",3258,1,80,0,3102,3731,473,4,1],
|
||||
["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",3222,1,82,2,346270,3566,344,38,16],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",3220,1,88,0,4066,8508,17348,15,2],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",3390,1,77,2,260251,6780,0,23,2],
|
||||
["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",360.32,1,72,0,0,6510,0,0,2],
|
||||
["p2",12,"op","chess_char_4_04_b",1,"uniequip_002_ines",2149,1,83,2,12140,16725,87,82,5],
|
||||
["p2",13,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",0,0,64,0,14723,13084,4743,15,6],
|
||||
["p2",14,"op","chess_char_4_16_b",2,"uniequip_002_texas2",1540.38,1,85,1,79696,16385,45,26,10],
|
||||
["p2",15,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",0,0,61,0,90500,10324,259,37,3],
|
||||
["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,91,2,309879,1561,0,146,2],
|
||||
["p2",17,"op","chess_char_4_10_b",1,"uniequip_002_aroma",878.05,1,87,0,68641,5875,409,72,3],
|
||||
["p2",18,"op","chess_char_4_12_b",2,"uniequip_002_glady",2232,1,76,0,46791,3707,1475,38,2],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",0,0,65,0,20579,4017,39,35,10],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",0,0,66,1,69955,3567,315,25,5],
|
||||
["p2",21,"token","token_10041_cathy_catsld",null,null,100,1,21,0,0,0,0,0,null],
|
||||
["p2",22,"token","token_10041_cathy_catsld",null,null,100,1,22,0,0,0,0,0,null]
|
||||
],
|
||||
"enemies": {
|
||||
"enemy_10027_vtsk": [6,1,4,144022,770521],
|
||||
"enemy_10027_vtsk": [6,2,2,121147,924905],
|
||||
"enemy_1005_yokai": [4,4,0,0,1600],
|
||||
"enemy_1229_darmy_2": [8,8,0,1944,294231],
|
||||
"enemy_9013_acstmk_2": [1,0,0,47998,1181710],
|
||||
"enemy_9014_acstma": [5,4,0,6191,10472],
|
||||
"enemy_9015_acstmb": [3,2,0,12821,83514],
|
||||
"enemy_9016_acstmr": [8,7,0,0,49]
|
||||
"enemy_1229_darmy_2": [8,8,0,4691,294231],
|
||||
"enemy_9013_acstmk_2": [1,0,0,43305,1106751],
|
||||
"enemy_9014_acstma": [5,4,0,7224,30080],
|
||||
"enemy_9015_acstmb": [3,2,0,12628,13124],
|
||||
"enemy_9016_acstmr": [8,7,0,0,54]
|
||||
},
|
||||
"hooks": [1,88,6000,818,818,2739,2842,6739,70,75,79,76,7,20346,731,14,35,4,1,70,0,0,5],
|
||||
"events": {"atk":955,"deploy":53,"die":71,"dmg":2841,"fx":634,"heal":146,"leak":4,"skill":155,"spawn":57,"status":683},
|
||||
"hooks": [1,89,6000,891,892,2797,3003,4207,66,69,96,92,9,23645,681,20,35,2,1,69,0,9,3],
|
||||
"events": {"atk":1042,"deploy":54,"die":67,"dmg":2998,"fx":569,"heal":157,"leak":2,"skill":188,"spawn":57,"status":603},
|
||||
"fx": {
|
||||
"aoe": 18,
|
||||
"appear": 10,
|
||||
"beam": 46,
|
||||
"blink": 15,
|
||||
"charge": 9,
|
||||
"counter": 7,
|
||||
"crit": 85,
|
||||
"dilemma": 2,
|
||||
"disappear": 10,
|
||||
"displace": 1,
|
||||
"dodge": 5,
|
||||
"explode": 7,
|
||||
"explosion": 1,
|
||||
"frostNova": 13,
|
||||
"iceSpike": 12,
|
||||
"levitate": 4,
|
||||
"overclock": 1,
|
||||
"palsy": 5,
|
||||
"phase": 1,
|
||||
"pull": 1,
|
||||
"aoe": 34,
|
||||
"appear": 7,
|
||||
"beam": 45,
|
||||
"blink": 14,
|
||||
"burst": 9,
|
||||
"charge": 12,
|
||||
"counter": 9,
|
||||
"crit": 83,
|
||||
"dilemma": 3,
|
||||
"disappear": 7,
|
||||
"dodge": 3,
|
||||
"explode": 3,
|
||||
"explosion": 5,
|
||||
"frostNova": 10,
|
||||
"iceSpike": 4,
|
||||
"overclock": 2,
|
||||
"palsy": 2,
|
||||
"phase": 4,
|
||||
"pull": 2,
|
||||
"quadShot": 2,
|
||||
"revive": 2,
|
||||
"ripple": 1,
|
||||
"sentry": 5,
|
||||
"sermon": 2,
|
||||
"ripple": 9,
|
||||
"sentry": 4,
|
||||
"sermon": 1,
|
||||
"shadowWeave": 10,
|
||||
"shell": 8,
|
||||
"shield": 5,
|
||||
"slippery": 2,
|
||||
"sp": 5,
|
||||
"spGain": 4,
|
||||
"splash": 1,
|
||||
"stealth": 4,
|
||||
"shield": 6,
|
||||
"slippery": 3,
|
||||
"soul": 9,
|
||||
"sp": 6,
|
||||
"spGain": 5,
|
||||
"stealth": 5,
|
||||
"summon": 4,
|
||||
"swordRain": 70,
|
||||
"swordRain": 57,
|
||||
"swordStorm": 10,
|
||||
"telegraph": 6,
|
||||
"tornado": 1,
|
||||
"tornadoPulse": 5,
|
||||
"weightless": 4,
|
||||
"zone": 230
|
||||
"tornado": 2,
|
||||
"tornadoPulse": 10,
|
||||
"weightless": 2,
|
||||
"zone": 150
|
||||
},
|
||||
"snaps": "264b53d3 3ee7ee43 f3f2921c 6864a65d 84ad689b c6b276f5 bd8cd5a4 4b9cc96b 46aef8e5 b338b3d6 37a849e7 3c63cb44 b806b557 ef133aaa d4ea6b4c dadce104 8a17da59 ff167e0f 33de0e99 8bedfdbc"
|
||||
"snaps": "3795cfd4 7f3862ea 8a202402 eeabbd1c cee0f0ab 5eafb35e f8a05875 1ed26b9a c9fdd9f1 e83ff1eb 77018d16 9bc0b42e 220cb648 f306f10d e8c3af47 3520d118 79f41539 410fee0c 3d280f53 466b98d1"
|
||||
},
|
||||
"hidden-boss_8-solo": {
|
||||
"about": "假想敌:胄 solo pool 1800000: chess_char_4_17_b chess_char_4_18_b chess_char_4_23_b chess_char_4_19_b chess_char_4_22_b chess_char_4_20_b chess_char_4_21_b chess_char_4_24_b chess_char_4_25_b chess_char_4_26_b",
|
||||
@@ -1141,7 +1208,7 @@
|
||||
"snaps": "3c1045a0 9d7d77a9 a1302e26 19ce8f60 d773ac92 c1604114 ce3ff643 dc9c2381 ee91c31a 0e7f8e4d 9af2b87d fb2021c1 ee17f723 6cc85d21 ddbddcf1 fef4d0f5"
|
||||
},
|
||||
"hidden-boss_10-pair": {
|
||||
"about": "假想敌:管 pair pool 7600000: chess_char_5_19_b chess_char_4_01_b chess_char_5_14_b chess_char_5_17_b chess_char_5_15_b chess_char_5_20_b chess_char_5_21_b chess_char_5_22_b chess_char_5_23_b chess_char_4_02_b | chess_char_4_11_b chess_char_4_12_b chess_char_4_04_b chess_char_4_07_b chess_char_4_16_b chess_char_4_09_b chess_char_4_06_b chess_char_4_10_b chess_char_4_13_b chess_char_4_14_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"about": "假想敌:管 pair pool 7600000: chess_char_5_19_b chess_char_4_01_b chess_char_5_14_b chess_char_5_17_b chess_char_5_15_b chess_char_5_20_b chess_char_5_21_b chess_char_5_22_b chess_char_5_23_b chess_char_4_02_b | chess_char_4_11_b chess_char_4_04_b chess_char_4_07_b chess_char_4_16_b chess_char_4_09_b chess_char_4_06_b chess_char_4_10_b chess_char_4_12_b chess_char_4_13_b chess_char_4_14_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"fast": false,
|
||||
"kind": "hidden",
|
||||
"stageId": "act1autochess_m03",
|
||||
@@ -1155,85 +1222,85 @@
|
||||
"killed": 12,
|
||||
"total": 12,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": 6523847,
|
||||
"rngDraws": 459,
|
||||
"bossHpLeft": 6814341,
|
||||
"rngDraws": 1008,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":12,"total":12,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":438996,"bossDmg":268088,"heal":10923,"deaths":1,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":971661,"bossDmg":808065,"heal":4457,"deaths":6,"layerGains":{}}
|
||||
"p1": {"killed":12,"total":12,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":382222,"bossDmg":214972,"heal":8209,"deaths":1,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":737941,"bossDmg":570688,"heal":8845,"deaths":5,"layerGains":{}}
|
||||
},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",3907,1,5,0,0,0,0,0,0],
|
||||
["p1",2,"op","chess_char_4_01_b",2,"uniequip_002_rmixer",3537,1,9,0,0,0,0,0,0],
|
||||
["p1",3,"op","chess_char_5_14_b",1,"none",3489.5,1,15,0,0,0,0,0,0],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",2738,1,17,2,16622,6178,2600,38,1],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",1989,1,11,3,198811,0,5122,22,6],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",1382,1,19,1,62074,3102,3,55,5],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",1629,1,49,0,112453,2673,99,214,6],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",2738,1,17,1,19443,5825,2138,42,1],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",1989,1,11,3,158666,0,4974,24,5],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",1382,1,19,2,60570,981,0,64,6],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",1629,1,48,0,98183,3032,116,230,6],
|
||||
["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",1611,1,3,0,0,0,0,0,0],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",1610,1,7,0,0,0,3100,4,2],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",1695,1,13,0,49035,0,0,30,3],
|
||||
["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",2644,1,48,0,0,4098,0,0,1],
|
||||
["p2",12,"op","chess_char_4_12_b",2,"uniequip_002_glady",2232,1,46,0,7998,2420,188,13,1],
|
||||
["p2",13,"op","chess_char_4_04_b",1,"uniequip_002_ines",3545.85,1,30,0,316123,0,0,249,8],
|
||||
["p2",14,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",0,0,47,0,1824,6222,1217,4,2],
|
||||
["p2",15,"op","chess_char_4_16_b",2,"uniequip_002_texas2",1619,1,38,0,30117,2204,585,341,2],
|
||||
["p2",16,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",2233.4,1,20,9,346666,2569,1426,122,6],
|
||||
["p2",17,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,10,1,10469,40,40,13,2],
|
||||
["p2",18,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1664,1,18,0,99350,416,416,111,4],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,22,0,111844,585,585,200,49],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1626,1,4,0,47272,0,0,17,5],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",1610,1,7,0,0,0,981,1,1],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",1695,1,13,0,45360,0,0,30,3],
|
||||
["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",2644,1,6,0,0,0,0,0,0],
|
||||
["p2",12,"op","chess_char_4_04_b",1,"uniequip_002_ines",2149,1,51,0,114057,6080,385,174,6],
|
||||
["p2",13,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",213.43,1,52,0,3840,7314,855,1,1],
|
||||
["p2",14,"op","chess_char_4_16_b",2,"uniequip_002_texas2",2671.35,1,31,0,108979,0,0,249,2],
|
||||
["p2",15,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",1233.93,1,18,6,202897,2261,717,84,5],
|
||||
["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,12,2,160082,0,0,271,4],
|
||||
["p2",17,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1249.33,1,20,0,9408,1072,657,7,2],
|
||||
["p2",18,"op","chess_char_4_12_b",2,"uniequip_002_glady",1282.27,1,22,0,50178,7180,6230,122,5],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,4,1,30506,0,0,37,12],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1626,1,8,1,57995,0,0,26,6],
|
||||
["p2",21,"token","token_10041_cathy_catsld",null,null,100,1,23,0,0,0,0,0,null],
|
||||
["p2",22,"token","token_10041_cathy_catsld",null,null,100,1,24,0,0,0,0,0,null],
|
||||
["-","~1","device","trap_1105_accrate",null,null,100,1,1,0,0,0,0,0,null],
|
||||
["-","~2","device","trap_1105_accrate",null,null,100,1,2,0,0,0,0,0,null]
|
||||
],
|
||||
"enemies": {
|
||||
"enemy_1402_tgshd_2": [2,2,0,7907,173864],
|
||||
"enemy_9010_acpupp": [2,2,0,5741,160520],
|
||||
"enemy_9021_acduml_2": [1,0,0,0,1076153],
|
||||
"enemy_9022_acdumm": [1,0,0,193,0],
|
||||
"enemy_9023_acdums": [12,12,0,10463,120]
|
||||
"enemy_1402_tgshd_2": [2,2,0,5170,173864],
|
||||
"enemy_9010_acpupp": [2,2,0,5184,160520],
|
||||
"enemy_9021_acduml_2": [1,0,0,343,785659],
|
||||
"enemy_9022_acdumm": [1,0,0,453,0],
|
||||
"enemy_9023_acdums": [12,12,0,16949,120]
|
||||
},
|
||||
"hooks": [1,49,6000,1271,1399,2370,2478,4004,23,24,103,99,0,33138,1829,9,18,0,1,25,0,4,0],
|
||||
"events": {"atk":1376,"deploy":29,"die":24,"dmg":2444,"fx":892,"heal":72,"skill":202,"spawn":42,"status":665},
|
||||
"hooks": [1,50,6000,1176,1325,2523,2675,5575,22,24,65,60,0,30221,1487,5,18,0,1,24,0,5,0],
|
||||
"events": {"atk":1269,"deploy":30,"die":24,"dmg":2664,"fx":984,"heal":48,"skill":125,"spawn":42,"status":569},
|
||||
"fx": {
|
||||
"appear": 2,
|
||||
"beam": 13,
|
||||
"blink": 1,
|
||||
"burst": 4,
|
||||
"charge": 2,
|
||||
"crit": 11,
|
||||
"dilemma": 6,
|
||||
"disappear": 2,
|
||||
"displace": 4,
|
||||
"beam": 12,
|
||||
"blink": 2,
|
||||
"burst": 5,
|
||||
"charge": 1,
|
||||
"crit": 130,
|
||||
"dilemma": 5,
|
||||
"ember": 2,
|
||||
"explode": 178,
|
||||
"explosion": 5,
|
||||
"expose": 200,
|
||||
"frostNova": 49,
|
||||
"iceSpike": 176,
|
||||
"overclock": 1,
|
||||
"explode": 191,
|
||||
"explosion": 6,
|
||||
"expose": 181,
|
||||
"frostNova": 12,
|
||||
"garrisonGrant": 1,
|
||||
"iceSpike": 195,
|
||||
"levitate": 4,
|
||||
"phase": 33,
|
||||
"pull": 1,
|
||||
"pull": 4,
|
||||
"quadShot": 4,
|
||||
"ripple": 30,
|
||||
"sentry": 1,
|
||||
"shadowWeave": 1,
|
||||
"sentry": 3,
|
||||
"shadowWeave": 5,
|
||||
"shield": 1,
|
||||
"shieldBreak": 2,
|
||||
"slippery": 4,
|
||||
"sp": 3,
|
||||
"stealth": 8,
|
||||
"shieldBreak": 1,
|
||||
"slippery": 2,
|
||||
"sp": 1,
|
||||
"splash": 2,
|
||||
"stealth": 6,
|
||||
"summon": 8,
|
||||
"swordRain": 15,
|
||||
"swordRain": 7,
|
||||
"swordStorm": 2,
|
||||
"telegraph": 2,
|
||||
"tornado": 1,
|
||||
"tornadoPulse": 5,
|
||||
"weightless": 5,
|
||||
"zone": 114
|
||||
"tornado": 5,
|
||||
"tornadoPulse": 20,
|
||||
"weightless": 6,
|
||||
"zone": 95
|
||||
},
|
||||
"snaps": "25ef01ee 4abf4c16 b375ed07 8d3c80f2 d3cb4ab8 7558361c 01ebe8a3 81c99dce dccd0467 18020580 509655e7 f0474cd0 7634409f 417bf8f0 c74c69b7 6b815153 874d16ed 19d663e0 b751da53 2e4691bb"
|
||||
"snaps": "2d13cea7 f06b6ad4 1d7dfd15 e852f80b 0b756fcb 070248ab 0b86ce84 646bfdc9 b14a05d3 e9cf92b6 d36049ba a96f982d 8e26903b 1c8b3d68 986a0718 a884edff 84fc9d78 132274c4 2cbd5800 af396c48"
|
||||
},
|
||||
"hidden-boss_10-solo": {
|
||||
"about": "假想敌:管 solo pool 1900000: chess_char_4_17_b chess_char_4_18_b chess_char_4_23_b chess_char_4_19_b chess_char_4_22_b chess_char_4_20_b chess_char_4_21_b chess_char_4_24_b chess_char_4_25_b chess_char_4_26_b",
|
||||
|
||||
+163
-197
@@ -591,7 +591,7 @@
|
||||
"snaps": "666c3952 b094f1ea 38685430 9f090539 ee670c94 1074c7a5 93293922 a5617f28 5b7f9793 3c0a7490 14387936 dcb74c1a a58e1beb 82ecbe91 64e48fa5 85eef6b4"
|
||||
},
|
||||
"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_12_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_13_a chess_char_4_14_a chess_char_4_20_a token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"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",
|
||||
"fast": true,
|
||||
"kind": "normal",
|
||||
"stageId": "act2autochess_m03",
|
||||
@@ -602,56 +602,56 @@
|
||||
"time": 170,
|
||||
"ticks": 5100,
|
||||
"reason": "timeout",
|
||||
"killed": 40,
|
||||
"killed": 35,
|
||||
"total": 102,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": null,
|
||||
"rngDraws": 114,
|
||||
"rngDraws": 64,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":40,"total":102,"perfect":false,"leaks":62,"leaksUncounted":0,"coins":4,"dmg":469309,"bossDmg":0,"heal":4633,"deaths":21,"layerGains":{"preciShip":8}}
|
||||
"p1": {"killed":35,"total":102,"perfect":false,"leaks":67,"leaksUncounted":0,"coins":4,"dmg":368790,"bossDmg":0,"heal":1892,"deaths":22,"layerGains":{"preciShip":12}}
|
||||
},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_4_17_a",1,null,0,0,4,0,947,2849,0,7,0],
|
||||
["p1",2,"op","chess_char_4_18_a",1,null,0,0,5,1,8608,3319,452,4,4],
|
||||
["p1",3,"op","chess_char_4_11_a",1,null,2144,1,125,0,0,3002,0,0,1],
|
||||
["p1",4,"op","chess_char_4_12_a",2,null,0,0,102,5,70347,5044,1536,37,2],
|
||||
["p1",5,"op","chess_char_4_19_a",2,null,0,0,82,0,6224,3120,0,9,1],
|
||||
["p1",6,"op","chess_char_4_07_a",1,null,0,0,112,0,423,3476,0,2,1],
|
||||
["p1",7,"op","chess_char_4_16_a",2,null,1,1,129,5,100862,8873,2644,33,9],
|
||||
["p1",8,"op","chess_char_4_09_a",1,null,0,0,15,0,16650,1336,0,14,2],
|
||||
["p1",9,"op","chess_char_4_10_a",1,null,0,0,6,0,40704,2190,0,17,1],
|
||||
["p1",10,"op","chess_char_4_13_a",1,null,0,0,111,1,30141,3174,0,43,5],
|
||||
["p1",11,"op","chess_char_4_14_a",1,null,0,0,104,14,173742,2552,0,33,2],
|
||||
["p1",12,"op","chess_char_4_20_a",2,null,0,0,93,4,20658,2434,0,10,1],
|
||||
["p1",13,"token","token_10041_cathy_catsld",null,null,100,1,16,0,0,0,0,0,null],
|
||||
["p1",14,"token","token_10041_cathy_catsld",null,null,100,1,17,0,0,0,0,0,null],
|
||||
["p1",1,"op","chess_char_4_17_a",1,null,0,0,5,0,1673,2849,0,10,0],
|
||||
["p1",2,"op","chess_char_4_18_a",1,null,0,0,6,0,1211,4202,1335,2,2],
|
||||
["p1",3,"op","chess_char_4_11_a",1,null,0,0,10,0,2906,2813,0,6,1],
|
||||
["p1",4,"op","chess_char_4_19_a",2,null,0,0,97,1,14708,3120,0,23,1],
|
||||
["p1",5,"op","chess_char_4_07_a",1,null,1738,1,132,0,1309,3476,0,1,1],
|
||||
["p1",6,"op","chess_char_4_16_a",2,null,0,0,128,0,76151,6230,0,27,5],
|
||||
["p1",7,"op","chess_char_4_09_a",1,null,0,0,11,1,18583,1336,0,12,1],
|
||||
["p1",8,"op","chess_char_4_10_a",1,null,0,0,108,1,26881,4894,0,19,1],
|
||||
["p1",9,"op","chess_char_4_12_a",2,null,0,0,119,0,30032,4065,557,22,1],
|
||||
["p1",10,"op","chess_char_4_13_a",1,null,0,0,99,2,28369,3174,0,49,4],
|
||||
["p1",11,"op","chess_char_4_14_a",1,null,0,0,94,12,133618,2552,0,25,2],
|
||||
["p1",12,"op","chess_char_4_20_a",2,null,0,0,4,3,33349,1217,0,13,1],
|
||||
["p1",13,"token","token_10041_cathy_catsld",null,null,100,1,17,0,0,0,0,0,null],
|
||||
["p1",14,"token","token_10041_cathy_catsld",null,null,100,1,16,0,0,0,0,0,null],
|
||||
["-","~1","device","trap_1105_accrate",null,null,100,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_10034_cnvsax": [1,1,0,4495,42998],
|
||||
"enemy_1005_yokai": [24,16,8,0,60158],
|
||||
"enemy_1005_yokai_2": [27,11,14,5256,113643],
|
||||
"enemy_1005_yokai_3": [6,0,5,11587,126060],
|
||||
"enemy_10034_cnvsax": [1,1,0,681,42998],
|
||||
"enemy_1005_yokai": [24,12,12,0,56519],
|
||||
"enemy_1005_yokai_2": [27,5,17,5019,75583],
|
||||
"enemy_1005_yokai_3": [6,0,6,16842,91811],
|
||||
"enemy_10083_hlbird": [1,1,0,0,6450],
|
||||
"enemy_10144_xdelk_2": [1,0,1,2904,32957],
|
||||
"enemy_1050_lslime": [1,0,1,11734,13748],
|
||||
"enemy_1158_divman": [1,1,0,130,14189],
|
||||
"enemy_1174_duholy_2": [1,0,1,801,15691],
|
||||
"enemy_1204_msfhu_2": [1,0,1,0,3],
|
||||
"enemy_1267_nhpbr_2": [1,0,1,61,3079],
|
||||
"enemy_1269_nhfly": [33,10,23,3841,20722],
|
||||
"enemy_1321_wdarft": [1,0,1,0,0],
|
||||
"enemy_1422_lrsldr_2": [1,0,1,0,19051],
|
||||
"enemy_1516_jakill": [1,0,1,559,559],
|
||||
"enemy_10144_xdelk_2": [1,0,1,3226,29892],
|
||||
"enemy_1050_lslime": [1,0,1,11038,23577],
|
||||
"enemy_1158_divman": [1,1,0,140,14189],
|
||||
"enemy_1174_duholy_2": [1,0,1,1192,3341],
|
||||
"enemy_1204_msfhu_2": [1,0,1,0,4],
|
||||
"enemy_1267_nhpbr_2": [1,0,1,61,1368],
|
||||
"enemy_1269_nhfly": [33,15,18,1358,19707],
|
||||
"enemy_1321_wdarft": [1,0,1,0,2047],
|
||||
"enemy_1422_lrsldr_2": [1,0,1,290,1118],
|
||||
"enemy_1516_jakill": [1,0,1,81,186],
|
||||
"enemy_2034_sythef_2": [1,0,1,0,0]
|
||||
},
|
||||
"hooks": [1,130,5100,428,428,1138,1119,1063,65,120,29,30,0,8699,498,10,102,59,1,200,2,0,36],
|
||||
"events": {"atk":499,"bounty":2,"deploy":25,"die":61,"dmg":1106,"fx":217,"heal":8,"layer":2,"leak":59,"skill":60,"spawn":119,"status":299},
|
||||
"fx": {"beam":22,"block":3,"catShield":2,"charge":1,"dilemma":2,"dodge":36,"explode":10,"explosion":2,"featherArrow":1,"flame":1,"frostNova":5,"garrison":2,"garrisonGrant":1,"overclock":1,"phase":2,"pull":1,"riposte":6,"rockslide":4,"shieldBreak":4,"slippery":1,"summon":11,"swordRain":65,"swordStorm":9,"telegraph":2,"thorns":5,"tornado":2,"tornadoPulse":9,"undying":7},
|
||||
"snaps": "a11f2665 9baaf19a a258b427 863efa4f 43f80da4 c6c6f65e 7aab7b2c 09e96778 49e81712 765f2fc7 05846969 695663e8 a03aa97d 7282e471 60f7d2fd 7acacb36 d0ea0f47"
|
||||
"hooks": [1,130,5100,419,419,1068,1050,388,57,119,20,21,0,7357,426,12,102,62,1,207,3,0,10],
|
||||
"events": {"atk":485,"bounty":2,"deploy":25,"die":57,"dmg":958,"fx":147,"heal":4,"layer":3,"leak":62,"skill":42,"spawn":119,"status":274},
|
||||
"fx": {"block":8,"catShield":1,"charge":1,"dilemma":1,"dodge":10,"explode":18,"explosion":2,"featherArrow":1,"flame":1,"frostNova":4,"garrison":3,"garrisonGrant":1,"overclock":1,"pull":1,"riposte":2,"rockslide":2,"shieldBreak":5,"slippery":1,"summon":11,"swordRain":48,"swordStorm":5,"telegraph":1,"thorns":6,"tornado":1,"tornadoPulse":5,"undying":7},
|
||||
"snaps": "57fe2e2f 05cb1dd6 05449e83 01d92a19 0c015524 660c9ef2 e1049717 fa7b12b0 10282468 a6f30d20 85d4d2ac b372d741 f5d4046d 46ea6a3e 85cf9d81 bf132acf 0b714eed"
|
||||
},
|
||||
"roster-011": {
|
||||
"about": "pass 0 band 5: chess_char_4_23_a chess_char_4_01_b chess_char_4_22_a chess_char_4_04_b chess_char_4_07_b chess_char_4_09_b chess_char_4_21_a chess_char_4_24_a chess_char_4_25_a chess_char_4_26_a chess_char_4_02_b chess_char_4_06_b",
|
||||
@@ -714,7 +714,7 @@
|
||||
"snaps": "8355ba8e b483fc98 ddfdaa13 5fc4a7e3 87630e6b bb7676b5 602f1b6c deddef4d b644bbab d7cd7b43 7a00491d 0d4cf0e9 d59a8e71 047d45f8 dbb2b808 377bf9f1 21d2cfb1 b58b930c 1a1a80bc"
|
||||
},
|
||||
"roster-012": {
|
||||
"about": "pass 0 band 5: chess_char_4_17_b chess_char_4_18_b chess_char_4_11_b chess_char_4_12_b chess_char_4_19_b chess_char_4_22_b chess_char_4_16_b chess_char_4_10_b chess_char_4_13_b chess_char_4_14_b chess_char_4_20_b chess_char_4_21_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"about": "pass 0 band 5: chess_char_4_17_b chess_char_4_18_b chess_char_4_11_b chess_char_4_19_b chess_char_4_22_b chess_char_4_16_b chess_char_4_10_b chess_char_4_12_b chess_char_4_13_b chess_char_4_14_b chess_char_4_20_b chess_char_4_21_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"fast": true,
|
||||
"kind": "normal",
|
||||
"stageId": "act1autochess_m01",
|
||||
@@ -722,93 +722,59 @@
|
||||
"round": 10,
|
||||
"seed": 1517795683,
|
||||
"waveId": "act1autochess_h03",
|
||||
"time": 168.8,
|
||||
"ticks": 5064,
|
||||
"time": 161.47,
|
||||
"ticks": 4844,
|
||||
"reason": "cleared",
|
||||
"killed": 98,
|
||||
"total": 98,
|
||||
"killed": 97,
|
||||
"total": 99,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": null,
|
||||
"rngDraws": 269,
|
||||
"rngDraws": 126,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":98,"total":98,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":12,"dmg":1014531,"bossDmg":0,"heal":28275,"deaths":11,"layerGains":{"preciShip":16}}
|
||||
"p1": {"killed":97,"total":99,"perfect":false,"leaks":2,"leaksUncounted":0,"coins":10,"dmg":969109,"bossDmg":0,"heal":21585,"deaths":5,"layerGains":{"preciShip":8}}
|
||||
},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_4_17_b",1,"uniequip_002_hsguma",0,0,7,1,684,3513,0,18,0],
|
||||
["p1",2,"op","chess_char_4_18_b",1,"uniequip_002_mudrok",5849.95,1,10,15,197322,12343,12089,47,26],
|
||||
["p1",3,"op","chess_char_4_11_b",1,"uniequip_002_cathy",0,0,104,0,1866,7466,0,2,2],
|
||||
["p1",4,"op","chess_char_4_12_b",2,"uniequip_002_glady",0,0,97,15,71683,6330,1866,26,3],
|
||||
["p1",5,"op","chess_char_4_19_b",2,"uniequip_002_flamtl",0,0,81,7,46030,4236,0,32,2],
|
||||
["p1",6,"op","chess_char_4_22_b",2,"uniequip_002_svrash",0,0,8,6,79400,11299,0,54,2],
|
||||
["p1",7,"op","chess_char_4_16_b",2,"uniequip_002_texas2",1619,1,9,0,4991,2637,0,46,1],
|
||||
["p1",8,"op","chess_char_4_10_b",1,"uniequip_002_aroma",319.84,1,4,37,302772,1344,0,45,4],
|
||||
["p1",9,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,5,0,28650,2013,0,56,22],
|
||||
["p1",10,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",276,1,105,15,217355,4648,0,29,14],
|
||||
["p1",11,"op","chess_char_4_20_b",2,"uniequip_002_fartth",0,0,91,2,63780,2838,0,24,2],
|
||||
["p1",12,"op","chess_char_4_21_b",1,"uniequip_002_plosis",1584,1,6,0,0,728,14319,41,2],
|
||||
["p1",13,"token","token_10041_cathy_catsld",null,null,100,1,16,0,0,0,0,0,null],
|
||||
["p1",14,"token","token_10041_cathy_catsld",null,null,100,1,17,0,0,0,0,0,null],
|
||||
["p1",1,"op","chess_char_4_17_b",1,"uniequip_002_hsguma",2598.06,1,7,0,2985,915,0,12,0],
|
||||
["p1",2,"op","chess_char_4_18_b",1,"uniequip_002_mudrok",6104,1,9,4,64155,880,880,34,4],
|
||||
["p1",3,"op","chess_char_4_11_b",1,"uniequip_002_cathy",4098.2,1,116,1,562,4096,0,2,2],
|
||||
["p1",4,"op","chess_char_4_19_b",2,"uniequip_002_flamtl",0,0,89,1,22210,4236,0,23,2],
|
||||
["p1",5,"op","chess_char_4_22_b",2,"uniequip_002_svrash",2169,1,120,7,103124,5538,0,27,3],
|
||||
["p1",6,"op","chess_char_4_16_b",2,"uniequip_002_texas2",865.4,1,8,0,3976,4769,0,30,1],
|
||||
["p1",7,"op","chess_char_4_10_b",1,"uniequip_002_aroma",145.6,1,4,0,0,1518,0,0,0],
|
||||
["p1",8,"op","chess_char_4_12_b",2,"uniequip_002_glady",2232,1,5,2,14460,1114,1114,17,2],
|
||||
["p1",9,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,11,21,186998,2091,0,92,38],
|
||||
["p1",10,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1576,1,13,43,472756,7856,0,56,23],
|
||||
["p1",11,"op","chess_char_4_20_b",2,"uniequip_002_fartth",700.8,1,6,18,97883,718,0,36,6],
|
||||
["p1",12,"op","chess_char_4_21_b",1,"uniequip_002_plosis",1534,1,14,0,0,9743,19590,97,2],
|
||||
["p1",13,"token","token_10041_cathy_catsld",null,null,100,1,17,0,0,0,0,0,null],
|
||||
["p1",14,"token","token_10041_cathy_catsld",null,null,100,1,16,0,0,0,0,0,null],
|
||||
["-","~1","device","trap_1105_accrate",null,null,100,0,1,0,0,0,0,0,null],
|
||||
["-","~2","device","trap_1105_accrate",null,null,100,0,2,0,0,0,0,0,null],
|
||||
["-","~3","device","trap_1105_accrate",null,null,100,0,3,0,0,0,0,0,null]
|
||||
],
|
||||
"enemies": {
|
||||
"enemy_10042_prtrop": [1,1,0,432,6912],
|
||||
"enemy_10042_prtrop": [1,1,0,0,6912],
|
||||
"enemy_10085_hllevi_2": [1,1,0,0,92160],
|
||||
"enemy_10159_mntrjn": [1,1,0,0,32256],
|
||||
"enemy_1062_rager_2": [1,1,0,2729,34560],
|
||||
"enemy_1160_hvyslr_2": [1,1,0,273,16128],
|
||||
"enemy_1183_mlasrt": [1,1,0,2290,7488],
|
||||
"enemy_1207_sfji_2": [1,1,0,2759,16128],
|
||||
"enemy_1208_msfji_2": [2,2,0,0,60],
|
||||
"enemy_1267_nhpbr": [45,45,0,7161,233280],
|
||||
"enemy_1267_nhpbr_2": [24,24,0,6347,152064],
|
||||
"enemy_1062_rager_2": [1,1,0,0,34560],
|
||||
"enemy_1160_hvyslr_2": [1,1,0,0,16128],
|
||||
"enemy_1183_mlasrt": [1,1,0,1482,7488],
|
||||
"enemy_1207_sfji_2": [1,1,0,1504,16128],
|
||||
"enemy_1208_msfji_2": [3,2,1,0,84],
|
||||
"enemy_1267_nhpbr": [45,45,0,11316,233280],
|
||||
"enemy_1267_nhpbr_2": [24,24,0,8146,152064],
|
||||
"enemy_1270_nhstlk": [1,1,0,0,13824],
|
||||
"enemy_1270_nhstlk_2": [15,15,0,11782,276480],
|
||||
"enemy_1270_nhstlk_2": [15,15,0,7672,276480],
|
||||
"enemy_1325_cbgpro_2": [1,1,0,0,5299],
|
||||
"enemy_1425_lrcmra_2": [1,1,0,1498,28800],
|
||||
"enemy_1525_blkswb": [1,1,0,19723,64512],
|
||||
"enemy_2050_smsha": [1,1,0,4403,46080]
|
||||
"enemy_1425_lrcmra_2": [1,1,0,980,28800],
|
||||
"enemy_1525_blkswb": [1,0,1,9347,23316],
|
||||
"enemy_2050_smsha": [1,1,0,3030,46080]
|
||||
},
|
||||
"hooks": [1,120,5064,549,549,1427,1629,1096,109,112,80,80,0,15333,1661,61,98,0,1,118,2,1,15],
|
||||
"events": {"atk":812,"bounty":6,"deploy":19,"die":112,"dmg":1612,"fx":394,"heal":78,"layer":2,"skill":161,"spawn":115,"status":508},
|
||||
"fx": {
|
||||
"beam": 4,
|
||||
"blink": 1,
|
||||
"block": 3,
|
||||
"burst": 1,
|
||||
"displace": 35,
|
||||
"dodge": 15,
|
||||
"explode": 7,
|
||||
"explosion": 14,
|
||||
"featherArrow": 2,
|
||||
"flame": 2,
|
||||
"frostNova": 22,
|
||||
"garrison": 2,
|
||||
"garrisonGrant": 1,
|
||||
"healField": 2,
|
||||
"levitate": 78,
|
||||
"overclock": 2,
|
||||
"palsy": 3,
|
||||
"pull": 2,
|
||||
"revive": 2,
|
||||
"riposte": 10,
|
||||
"rockslide": 26,
|
||||
"shieldBreak": 17,
|
||||
"slash": 23,
|
||||
"slippery": 4,
|
||||
"splash": 25,
|
||||
"summon": 1,
|
||||
"swordStorm": 1,
|
||||
"telegraph": 2,
|
||||
"thorns": 3,
|
||||
"tornado": 3,
|
||||
"tornadoPulse": 10,
|
||||
"truesilver": 2,
|
||||
"zone": 69
|
||||
},
|
||||
"snaps": "c0395dfa 57f0c65b dd894131 ed91373b 34231a57 1b35b13e fe159d38 ca7769d5 2fa91817 9d9936db fe9fdd5a ba850298 b65e03a5 3a2fd6e9 a6cd2062 be05fd78 23784858"
|
||||
"hooks": [1,120,4844,461,461,1342,1344,815,102,107,83,80,0,15613,1768,15,99,2,1,112,1,0,1],
|
||||
"events": {"atk":605,"bounty":5,"deploy":18,"die":105,"dmg":1336,"fx":233,"heal":207,"layer":1,"leak":2,"skill":165,"spawn":116,"status":877},
|
||||
"fx": {"beam":6,"blink":2,"displace":15,"dodge":1,"explode":4,"explosion":23,"featherArrow":6,"flame":2,"frostNova":38,"garrison":1,"garrisonGrant":1,"healField":2,"overclock":2,"pull":2,"revive":3,"riposte":1,"rockslide":4,"shieldBreak":8,"slash":23,"summon":1,"swordStorm":1,"telegraph":3,"tornado":2,"tornadoPulse":10,"truesilver":3,"zone":69},
|
||||
"snaps": "a9c24b01 070a342d a4b58bdf 051cb577 59867a3f 61db8ba1 87293c19 3a21d440 1c33208d ee986ec5 cab0042a 1a4eb997 f60c3ff7 f078add6 9b09092c ae0c42e1 0666df4a"
|
||||
},
|
||||
"roster-013": {
|
||||
"about": "pass 0 band 5: chess_char_4_23_b chess_char_5_08_a chess_char_5_01_a chess_char_5_05_a chess_char_5_06_a chess_char_5_07_a chess_char_4_24_b chess_char_4_25_b chess_char_4_26_b chess_char_5_02_a chess_char_5_03_a chess_char_5_10_a",
|
||||
@@ -1808,7 +1774,7 @@
|
||||
"snaps": "7c092213 7eeed0b1 ac8f2ed3 3858c149 5c4c9042 6e0b6dfc ecb20138 7bcdcc30 87e0ab2d d6d96690 40c393bf c32baa7d e3c84877 885dfe2b 0445be42 4f286152 de0ce50d"
|
||||
},
|
||||
"roster-029": {
|
||||
"about": "pass 1 band 4: chess_char_4_17_a chess_char_4_18_a chess_char_4_11_a chess_char_4_12_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_13_a chess_char_4_14_a chess_char_4_20_a token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
"about": "pass 1 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",
|
||||
"fast": false,
|
||||
"kind": "normal",
|
||||
"stageId": "act1autochess_m07",
|
||||
@@ -1816,52 +1782,52 @@
|
||||
"round": 8,
|
||||
"seed": 3016944661,
|
||||
"waveId": "act1autochess_h01",
|
||||
"time": 158.8,
|
||||
"ticks": 4764,
|
||||
"time": 154.7,
|
||||
"ticks": 4641,
|
||||
"reason": "cleared",
|
||||
"killed": 78,
|
||||
"killed": 76,
|
||||
"total": 85,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": null,
|
||||
"rngDraws": 99,
|
||||
"rngDraws": 83,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":78,"total":85,"perfect":false,"leaks":7,"leaksUncounted":0,"coins":4,"dmg":318167,"bossDmg":0,"heal":3327,"deaths":10,"layerGains":{"preciShip":4}}
|
||||
"p1": {"killed":76,"total":85,"perfect":false,"leaks":9,"leaksUncounted":0,"coins":4,"dmg":309220,"bossDmg":0,"heal":3524,"deaths":6,"layerGains":{"preciShip":4}}
|
||||
},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_4_17_a",0,null,1139.6,1,110,2,20509,2880,0,64,2],
|
||||
["p1",2,"op","chess_char_4_18_a",0,null,2867,1,6,7,22524,4394,2929,55,2],
|
||||
["p1",3,"op","chess_char_4_11_a",0,null,2144,1,106,2,3579,3145,0,11,0],
|
||||
["p1",4,"op","chess_char_4_12_a",0,null,1754,1,104,3,8643,2902,398,27,9],
|
||||
["p1",5,"op","chess_char_4_19_a",0,null,1560,1,105,4,8607,3442,0,39,4],
|
||||
["p1",6,"op","chess_char_4_07_a",0,null,1738,1,89,2,13301,2526,0,35,2],
|
||||
["p1",7,"op","chess_char_4_16_a",0,null,257.6,1,63,20,55897,11230,0,97,5],
|
||||
["p1",8,"op","chess_char_4_09_a",0,null,386,1,3,7,25390,1000,0,12,9],
|
||||
["p1",9,"op","chess_char_4_10_a",0,null,0,0,5,0,0,1338,0,0,0],
|
||||
["p1",10,"op","chess_char_4_13_a",0,null,0,0,7,8,30420,2137,0,64,19],
|
||||
["p1",11,"op","chess_char_4_14_a",0,null,1096,1,107,8,39405,5906,0,16,1],
|
||||
["p1",12,"op","chess_char_4_20_a",0,null,1217,1,11,15,89892,500,0,55,2],
|
||||
["p1",13,"token","token_10041_cathy_catsld",null,null,100,1,16,0,0,0,0,0,null],
|
||||
["p1",14,"token","token_10041_cathy_catsld",null,null,100,1,15,0,0,0,0,0,null],
|
||||
["p1",1,"op","chess_char_4_17_a",0,null,1139.6,1,101,0,13558,2008,0,47,2],
|
||||
["p1",2,"op","chess_char_4_18_a",0,null,2580,1,5,2,5324,3725,2225,30,1],
|
||||
["p1",3,"op","chess_char_4_11_a",0,null,2144,1,105,0,1383,3073,0,15,0],
|
||||
["p1",4,"op","chess_char_4_19_a",0,null,1560,1,94,1,353,1860,0,12,4],
|
||||
["p1",5,"op","chess_char_4_07_a",0,null,331.2,1,11,5,8888,2907,0,33,2],
|
||||
["p1",6,"op","chess_char_4_16_a",0,null,601.6,1,63,12,37012,9546,0,66,5],
|
||||
["p1",7,"op","chess_char_4_09_a",0,null,1326,1,14,17,84925,520,0,36,17],
|
||||
["p1",8,"op","chess_char_4_10_a",0,null,338,1,4,0,0,1500,0,0,0],
|
||||
["p1",9,"op","chess_char_4_12_a",0,null,1754,1,6,0,0,1899,1299,0,0],
|
||||
["p1",10,"op","chess_char_4_13_a",0,null,1587,1,8,3,14535,500,0,40,13],
|
||||
["p1",11,"op","chess_char_4_14_a",0,null,0,0,10,16,48517,7376,0,26,2],
|
||||
["p1",12,"op","chess_char_4_20_a",0,null,223,1,12,20,94726,1094,0,56,2],
|
||||
["p1",13,"token","token_10041_cathy_catsld",null,null,100,1,15,0,0,0,0,0,null],
|
||||
["p1",14,"token","token_10041_cathy_catsld",null,null,100,1,16,0,0,0,0,0,null],
|
||||
["-","~1","device","trap_1105_accrate",null,null,100,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_10081_mpplai": [1,1,0,0,2000],
|
||||
"enemy_1026_aghost": [1,1,0,0,3040],
|
||||
"enemy_1148_dssbr": [45,44,1,2857,99163],
|
||||
"enemy_1148_dssbr_2": [27,27,0,434,77760],
|
||||
"enemy_1160_hvyslr_2": [1,0,1,3783,2416],
|
||||
"enemy_1200_msfjin_2": [1,0,1,0,29],
|
||||
"enemy_1272_nhtank_2": [1,1,0,12240,12000],
|
||||
"enemy_1407_hummbd": [1,1,0,48,3600],
|
||||
"enemy_1439_dslntf": [6,3,3,7340,112566],
|
||||
"enemy_2002_bearmi_2": [1,0,1,2252,5593]
|
||||
"enemy_1148_dssbr": [45,43,2,146,99626],
|
||||
"enemy_1148_dssbr_2": [27,26,1,150,76514],
|
||||
"enemy_1160_hvyslr_2": [1,0,1,6789,9376],
|
||||
"enemy_1200_msfjin_2": [1,1,0,0,35],
|
||||
"enemy_1272_nhtank_2": [1,0,1,8756,2813],
|
||||
"enemy_1407_hummbd": [1,1,0,20,3600],
|
||||
"enemy_1439_dslntf": [6,2,4,4696,103415],
|
||||
"enemy_2002_bearmi_2": [1,1,0,1311,8800]
|
||||
},
|
||||
"hooks": [1,109,4764,670,670,1086,1879,759,88,95,55,54,0,22092,730,68,85,7,1,88,1,10,8],
|
||||
"events": {"atk":685,"bounty":2,"deploy":22,"die":88,"dmg":1865,"fx":73,"heal":477,"layer":1,"leak":7,"skill":112,"spawn":101,"status":236},
|
||||
"fx": {"block":10,"burst":10,"displace":3,"dodge":8,"dp":4,"explode":1,"expose":2,"garrison":1,"garrisonGrant":1,"phase":1,"riposte":8,"shieldBreak":14,"swordRain":5,"zone":5},
|
||||
"snaps": "5ee1d302 1c02fbcd cbb518f8 fc90ae00 98195e0a 21da2468 b9aa38e0 db0862b7 a4015752 c3d0537c 5e0bdc1d b3dd31dc 595b167d 137aa308 f30e8d89 932e6025"
|
||||
"hooks": [1,106,4641,470,470,920,1638,1314,82,91,48,48,0,22203,805,35,85,9,1,82,1,4,1],
|
||||
"events": {"atk":508,"bounty":2,"deploy":19,"die":82,"dmg":1628,"fx":45,"heal":418,"layer":1,"leak":9,"skill":99,"spawn":101,"status":149},
|
||||
"fx": {"block":11,"burst":4,"dodge":1,"dp":4,"explode":1,"expose":1,"garrison":1,"garrisonGrant":1,"phase":1,"riposte":1,"shieldBreak":10,"swordRain":5,"zone":4},
|
||||
"snaps": "d1a66fbb 1e4c3412 cfa655f4 33ae5aea be858e5a e390032f a14b2f14 f815866a e4173185 0a72a5c9 f546a0e1 e7e58926 f223a279 820a4de9 842392b8 3e71a88c"
|
||||
},
|
||||
"roster-030": {
|
||||
"about": "pass 1 band 5: chess_char_4_23_a chess_char_4_01_b chess_char_4_22_a chess_char_4_04_b chess_char_4_07_b chess_char_4_09_b chess_char_4_21_a chess_char_4_24_a chess_char_4_25_a chess_char_4_26_a chess_char_4_02_b chess_char_4_06_b",
|
||||
@@ -2465,7 +2431,7 @@
|
||||
"snaps": "abe7527f 54d37f93 efbcd554 1b821656 ac9c33a5 269cae9f 3f080e3a ac1ef736 a3e7f2b4 6db02653 6f34cc83 4cb3d2a7 22ba9134 7bd4222a 99114c8f cc0a8a71 3af49395"
|
||||
},
|
||||
"roster-040": {
|
||||
"about": "pass 2 band 4: chess_char_4_01_a chess_char_4_17_a chess_char_4_18_a chess_char_4_12_a chess_char_4_04_a chess_char_4_07_a chess_char_4_16_a chess_char_4_09_a chess_char_3_19_b chess_char_3_21_b chess_char_4_02_a chess_char_4_13_a token_10028_vigil_wolf",
|
||||
"about": "pass 2 band 4: chess_char_4_01_a chess_char_4_17_a chess_char_4_18_a chess_char_4_04_a chess_char_4_07_a chess_char_4_16_a chess_char_4_09_a chess_char_3_19_b chess_char_3_21_b chess_char_4_02_a chess_char_4_12_a chess_char_4_13_a token_10028_vigil_wolf",
|
||||
"fast": false,
|
||||
"kind": "normal",
|
||||
"stageId": "act1autochess_m07",
|
||||
@@ -2476,50 +2442,50 @@
|
||||
"time": 170,
|
||||
"ticks": 5100,
|
||||
"reason": "timeout",
|
||||
"killed": 25,
|
||||
"killed": 26,
|
||||
"total": 65,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": null,
|
||||
"rngDraws": 226,
|
||||
"rngDraws": 264,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {"p1":{"killed":25,"total":65,"perfect":false,"leaks":40,"leaksUncounted":0,"coins":2,"dmg":405931,"bossDmg":0,"heal":339,"deaths":25,"layerGains":{}}},
|
||||
"players": {"p1":{"killed":26,"total":65,"perfect":false,"leaks":39,"leaksUncounted":0,"coins":2,"dmg":522251,"bossDmg":0,"heal":2607,"deaths":24,"layerGains":{}}},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_4_01_a",1,null,0,0,4,0,3410,2638,0,29,1],
|
||||
["p1",2,"op","chess_char_4_17_a",2,null,0,0,7,0,14528,2849,0,10,1],
|
||||
["p1",3,"op","chess_char_4_18_a",2,null,0,0,9,0,12723,2867,0,11,1],
|
||||
["p1",4,"op","chess_char_4_12_a",1,null,0,0,87,1,22077,3847,339,27,1],
|
||||
["p1",5,"op","chess_char_4_04_a",2,null,1623.38,1,96,2,14512,7177,0,15,5],
|
||||
["p1",6,"op","chess_char_4_07_a",2,null,0,0,77,0,9369,7998,0,23,1],
|
||||
["p1",7,"op","chess_char_4_16_a",1,null,0,0,94,2,56048,7476,0,11,7],
|
||||
["p1",8,"op","chess_char_4_09_a",2,null,0,0,3,0,0,1336,0,0,0],
|
||||
["p1",9,"op","chess_char_3_19_b",1,"none",0,0,5,5,51724,1648,0,66,1],
|
||||
["p1",10,"op","chess_char_3_21_b",1,"uniequip_004_archet",0,0,95,10,148810,3180,0,81,9],
|
||||
["p1",11,"op","chess_char_4_02_a",1,null,0,0,84,1,20900,2856,0,8,1],
|
||||
["p1",12,"op","chess_char_4_13_a",2,null,0,0,79,4,51831,3174,0,54,1],
|
||||
["p1",13,"token","token_10028_vigil_wolf",null,null,0,0,6,0,0,2567,0,0,null],
|
||||
["p1",1,"op","chess_char_4_01_a",1,null,0,0,3,0,1766,2638,0,26,1],
|
||||
["p1",2,"op","chess_char_4_17_a",2,null,0,0,6,0,16458,2849,0,8,1],
|
||||
["p1",3,"op","chess_char_4_18_a",2,null,0,0,8,0,11377,3440,573,16,1],
|
||||
["p1",4,"op","chess_char_4_04_a",2,null,0,0,87,1,21332,7040,0,15,4],
|
||||
["p1",5,"op","chess_char_4_07_a",2,null,0,0,83,0,7036,8298,0,12,1],
|
||||
["p1",6,"op","chess_char_4_16_a",1,null,598.66,1,95,1,59960,9220,1097,22,8],
|
||||
["p1",7,"op","chess_char_4_09_a",2,null,0,0,15,0,17346,1336,0,20,1],
|
||||
["p1",8,"op","chess_char_3_19_b",1,"none",0,0,4,6,63118,1648,0,74,1],
|
||||
["p1",9,"op","chess_char_3_21_b",1,"uniequip_004_archet",0,0,93,6,200251,3180,0,95,10],
|
||||
["p1",10,"op","chess_char_4_02_a",1,null,0,0,86,7,49901,2856,0,18,1],
|
||||
["p1",11,"op","chess_char_4_12_a",1,null,1336.37,1,96,3,39488,3109,937,36,1],
|
||||
["p1",12,"op","chess_char_4_13_a",2,null,0,0,74,2,34218,3174,0,56,1],
|
||||
["p1",13,"token","token_10028_vigil_wolf",null,null,0,0,5,0,0,3541,0,0,null],
|
||||
["-","~1","device","trap_1105_accrate",null,null,100,1,1,0,0,0,0,0,null],
|
||||
["-","~2","device","trap_1105_accrate",null,null,100,1,2,0,0,0,0,0,null]
|
||||
],
|
||||
"enemies": {
|
||||
"enemy_1005_yokai": [24,11,13,0,47446],
|
||||
"enemy_1005_yokai_2": [27,10,15,7994,80198],
|
||||
"enemy_1005_yokai_3": [6,1,5,18348,169071],
|
||||
"enemy_10065_ftzlc": [1,1,0,461,16339],
|
||||
"enemy_10162_mnctpt": [1,0,1,8402,20600],
|
||||
"enemy_1119_vofsd": [1,0,1,91,45544],
|
||||
"enemy_1005_yokai": [24,12,12,0,53015],
|
||||
"enemy_1005_yokai_2": [27,10,12,9713,80177],
|
||||
"enemy_1005_yokai_3": [6,1,5,17224,260867],
|
||||
"enemy_10065_ftzlc": [1,1,0,0,16339],
|
||||
"enemy_10162_mnctpt": [1,0,1,6850,54659],
|
||||
"enemy_1119_vofsd": [1,0,1,443,29483],
|
||||
"enemy_1196_msfyin_2": [1,1,0,0,3],
|
||||
"enemy_1254_lypa_2": [1,0,1,8720,22211],
|
||||
"enemy_1367_dseed": [1,0,1,0,1701],
|
||||
"enemy_1517_xi": [1,0,1,5597,2809],
|
||||
"enemy_1254_lypa_2": [1,0,1,9320,21814],
|
||||
"enemy_1367_dseed": [1,0,1,0,1730],
|
||||
"enemy_1517_xi": [1,0,1,8379,4156],
|
||||
"enemy_9016_acstmr": [1,1,0,0,8]
|
||||
},
|
||||
"hooks": [1,95,5100,540,540,822,868,503,52,90,29,28,16,7806,316,21,65,38,1,62,0,1,0],
|
||||
"events": {"atk":613,"bounty":1,"deploy":28,"die":52,"dmg":862,"fx":94,"leak":38,"skill":57,"spawn":80,"status":159},
|
||||
"fx": {"beam":5,"block":3,"buff":2,"burst":1,"coldWind":1,"displace":15,"dp":1,"iceSpike":1,"liberate":1,"overclock":1,"overload":1,"palsy":3,"revive":3,"rockfall":1,"sentry":6,"shadowWeave":11,"shield":7,"shieldBreak":6,"stone":1,"swordStorm":7,"telegraph":2,"volley":9,"wake":1,"wolfShadow":1,"wolfShadowLost":3,"zone":1},
|
||||
"snaps": "3eace5b8 61afe6da d60244f3 faf22b5a 4881cb88 a672b7d1 5494d9f4 f46efc11 dbe6624d 0c5503e3 15f7a0aa 6dfaa49b e212841f ac453bb9 08d4fce3 ddc0d417 bce1ca77"
|
||||
"hooks": [1,95,5100,623,623,982,1032,890,52,86,31,31,15,8307,265,14,65,34,1,63,0,2,4],
|
||||
"events": {"atk":711,"bounty":1,"deploy":28,"die":52,"dmg":1021,"fx":92,"heal":2,"leak":34,"skill":62,"spawn":80,"status":161},
|
||||
"fx": {"beam":4,"block":6,"buff":2,"burst":2,"coldWind":1,"dodge":4,"dp":1,"explode":1,"liberate":1,"overclock":1,"overload":1,"palsy":2,"revive":3,"ripple":1,"rockfall":1,"sentry":6,"shadowWeave":11,"shield":7,"shieldBreak":7,"stone":1,"swordStorm":8,"telegraph":3,"volley":10,"wake":1,"wolfShadow":2,"wolfShadowLost":4,"zone":1},
|
||||
"snaps": "b82d753d c1224ffa 2d897565 74a8e929 046afe0b 75038b5d 5f2916e2 8335adba f033f2bd 01cd1644 28e6e00b 23057f96 cb63f907 cd02b5d1 70389501 b9dc0523 663a48bf"
|
||||
},
|
||||
"roster-041": {
|
||||
"about": "pass 2 band 5: chess_char_4_23_a chess_char_4_01_b chess_char_4_19_a chess_char_4_22_a chess_char_4_12_b chess_char_4_04_b chess_char_4_07_b chess_char_4_09_b chess_char_4_20_a chess_char_4_24_a chess_char_4_25_a chess_char_4_02_b",
|
||||
"about": "pass 2 band 5: chess_char_4_23_a chess_char_4_01_b chess_char_4_19_a chess_char_4_22_a chess_char_4_04_b chess_char_4_07_b chess_char_4_09_b chess_char_4_20_a chess_char_4_24_a chess_char_4_25_a chess_char_4_02_b chess_char_4_12_b",
|
||||
"fast": false,
|
||||
"kind": "normal",
|
||||
"stageId": "act2autochess_m01",
|
||||
@@ -2530,46 +2496,46 @@
|
||||
"time": 190,
|
||||
"ticks": 5700,
|
||||
"reason": "timeout",
|
||||
"killed": 40,
|
||||
"killed": 46,
|
||||
"total": 47,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": null,
|
||||
"rngDraws": 81,
|
||||
"rngDraws": 46,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":40,"total":47,"perfect":false,"leaks":7,"leaksUncounted":0,"coins":8,"dmg":505596,"bossDmg":0,"heal":35729,"deaths":6,"layerGains":{"visiShip":8}}
|
||||
"p1": {"killed":46,"total":47,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":8,"dmg":576429,"bossDmg":0,"heal":10491,"deaths":7,"layerGains":{"visiShip":5}}
|
||||
},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_4_23_a",1,null,0,0,59,0,14296,4358,0,37,1],
|
||||
["p1",2,"op","chess_char_4_01_b",1,"none",2261.07,1,9,1,12965,2729,0,125,2],
|
||||
["p1",3,"op","chess_char_4_19_a",1,null,1246.08,1,65,0,1103,4894,0,25,2],
|
||||
["p1",4,"op","chess_char_4_22_a",1,null,2022,1,7,0,2567,2035,1345,66,1],
|
||||
["p1",5,"op","chess_char_4_12_b",1,"none",4562.3,1,11,1,35031,22559,14453,82,5],
|
||||
["p1",6,"op","chess_char_4_04_b",2,"uniequip_002_ines",2149,1,14,7,116578,7728,1513,130,1],
|
||||
["p1",7,"op","chess_char_4_07_b",2,"none",0,0,52,2,32885,4466,0,49,2],
|
||||
["p1",8,"op","chess_char_4_09_b",2,"uniequip_004_mizuki",1756,1,1,1,12149,527,311,5,1],
|
||||
["p1",9,"op","chess_char_4_20_a",1,null,1217,1,2,3,31008,0,0,78,3],
|
||||
["p1",10,"op","chess_char_4_24_a",2,null,1726,1,3,17,187142,0,0,41,4],
|
||||
["p1",11,"op","chess_char_4_25_a",1,null,1221,1,4,5,29495,0,0,0,3],
|
||||
["p1",12,"op","chess_char_4_02_b",1,"none",2966.25,1,5,3,30378,1420,673,11,2],
|
||||
["p1","~1","token","char_613_acmedc",null,null,1314,1,13,0,0,0,17433,42,2]
|
||||
["p1",1,"op","chess_char_4_23_a",1,null,0,0,62,2,13372,4358,0,67,2],
|
||||
["p1",2,"op","chess_char_4_01_b",1,"none",3062.64,1,9,1,7452,1928,0,117,2],
|
||||
["p1",3,"op","chess_char_4_19_a",1,null,673,1,66,0,1168,4007,0,20,2],
|
||||
["p1",4,"op","chess_char_4_22_a",1,null,2022,1,7,0,1295,2450,456,37,1],
|
||||
["p1",5,"op","chess_char_4_04_b",2,"uniequip_002_ines",0,0,64,7,57793,11293,0,69,3],
|
||||
["p1",6,"op","chess_char_4_07_b",2,"none",2233,1,8,1,9741,1604,328,9,1],
|
||||
["p1",7,"op","chess_char_4_09_b",2,"uniequip_004_mizuki",965.8,1,12,24,336232,2382,0,52,2],
|
||||
["p1",8,"op","chess_char_4_20_a",1,null,1217,1,2,1,22138,0,0,83,3],
|
||||
["p1",9,"op","chess_char_4_24_a",2,null,1726,1,3,8,66392,0,0,34,5],
|
||||
["p1",10,"op","chess_char_4_25_a",1,null,1221,1,4,2,15585,0,0,0,3],
|
||||
["p1",11,"op","chess_char_4_02_b",1,"none",2966.25,1,1,0,20830,0,0,4,1],
|
||||
["p1",12,"op","chess_char_4_12_b",1,"none",4562.3,1,5,0,24432,0,0,70,4],
|
||||
["p1","~1","token","char_613_acmedc",null,null,1314,1,13,0,0,0,9707,25,1]
|
||||
],
|
||||
"enemies": {
|
||||
"enemy_1001_bigbo": [1,1,0,2149,17600],
|
||||
"enemy_1001_bigbo": [1,1,0,2752,17600],
|
||||
"enemy_10097_crshd": [1,1,0,0,8000],
|
||||
"enemy_1045_hammer": [1,1,0,307,8000],
|
||||
"enemy_1045_hammer_2": [6,5,0,18440,80250],
|
||||
"enemy_1061_zomshd": [33,27,1,25211,362935],
|
||||
"enemy_1045_hammer": [1,1,0,0,8000],
|
||||
"enemy_1045_hammer_2": [6,5,0,18232,93466],
|
||||
"enemy_1061_zomshd": [33,33,0,4255,415749],
|
||||
"enemy_1166_dusbr": [1,1,0,0,2400],
|
||||
"enemy_1204_msfhu_2": [1,1,0,0,6],
|
||||
"enemy_1288_duskls_2": [1,1,0,162,4805],
|
||||
"enemy_1427_lrnazg": [1,1,0,1121,12000],
|
||||
"enemy_2010_csdcr": [1,1,0,2800,9600]
|
||||
"enemy_1288_duskls_2": [1,1,0,0,9608],
|
||||
"enemy_1427_lrnazg": [1,1,0,1031,12000],
|
||||
"enemy_2010_csdcr": [1,1,0,960,9600]
|
||||
},
|
||||
"hooks": [1,65,5700,1112,1112,1391,1406,26919,46,48,29,23,74,26284,88,62,47,1,1,47,2,0,5],
|
||||
"events": {"atk":1300,"bounty":4,"deploy":18,"die":47,"dmg":1362,"fx":173,"heal":54,"layer":2,"leak":1,"skill":52,"spawn":60,"status":296},
|
||||
"fx": {"aoe":2,"beam":1,"buff":2,"devour":4,"displace":9,"dodge":5,"ember":1,"garrison":2,"garrisonGrant":1,"link":3,"mote":98,"overload":3,"reweave":3,"riposte":1,"ripple":1,"sentry":2,"shadowWeave":25,"shield":1,"snow":1,"summon":1,"wake":5,"zone":2},
|
||||
"snaps": "af06579c 3fd6674e fd823b49 3720d672 741d61e5 50c92e6f 03053fa6 2b115dd6 cee39675 eb727d90 c7a11465 7ba12c0d 15b1683c 0cb8d4c1 f3758ac4 4e5bee43 b1945ebf 6735e46d eb8d8138"
|
||||
"hooks": [1,66,5700,768,768,1222,1218,23194,53,54,30,25,70,28131,99,60,47,0,1,55,1,0,13],
|
||||
"events": {"atk":1079,"bounty":4,"deploy":19,"die":54,"dmg":1143,"fx":189,"heal":31,"layer":1,"skill":55,"spawn":60,"status":338},
|
||||
"fx": {"aoe":2,"beam":3,"buff":1,"devour":5,"displace":35,"dodge":13,"ember":2,"garrison":1,"garrisonGrant":1,"link":3,"mote":75,"overload":4,"revive":1,"reweave":3,"riposte":3,"ripple":2,"sentry":5,"shadowWeave":20,"shield":3,"snow":1,"summon":1,"wake":4,"zone":1},
|
||||
"snaps": "10b0fc57 1879e30f a24d840f f56b69d5 fe01ffb5 2b00a1f2 bccbdb42 61be28b4 65fb3286 2994327f 0e37070a c71c8c1a 60bbb02c 25591720 152ece36 27f67e48 ea1cc871 ea955985 f28f1cc0"
|
||||
},
|
||||
"roster-042": {
|
||||
"about": "pass 2 band 5: chess_char_4_17_b chess_char_4_18_b chess_char_4_23_b chess_char_4_19_b chess_char_4_22_b chess_char_5_01_a chess_char_4_16_b chess_char_4_13_b chess_char_4_20_b chess_char_4_24_b chess_char_4_25_b chess_char_5_02_a",
|
||||
|
||||
+13
-14
@@ -55,27 +55,26 @@ test('glyph rules: melee only on LOW buildable ALL/MELEE; ranged also on HIGH/RA
|
||||
assert.ok(canPlace(buildDeployMap(null), 'melee', 10, 5));
|
||||
});
|
||||
|
||||
test('positionClass: melee stays ground-only; only elite 歌蕾蒂娅 + HOK-Y is widened (owner 2026-10-04)', () => {
|
||||
test('positionClass: a MELEE chess whose trait reads 「可以放置于远程位」 is widened, normal or elite, whatever the module (owner 2026-10-05)', () => {
|
||||
assert.equal(positionClass({ position: 'MELEE' }), 'melee');
|
||||
assert.equal(positionClass({ position: 'MELEE', placement: 'all' }), 'melee', 'the old placement field is ignored');
|
||||
assert.equal(basePositionClass({ position: 'MELEE', isGolden: true, charId: 'char_474_glady' }), 'melee');
|
||||
assert.equal(positionClass({ position: 'MELEE', trait: { desc: '技能可以使敌人产生位移\n可以放置于远程位' } }), 'all', 'the trait line');
|
||||
assert.equal(positionClass({ position: 'MELEE', trait: { desc: '可以额外部署在远程位' } }), 'melee', 'another wording is not the line');
|
||||
assert.equal(positionClass({ position: 'RANGED', trait: { desc: '可以放置于远程位' } }), 'ranged', 'a ranged record keeps its class');
|
||||
assert.equal(basePositionClass({ position: 'MELEE', trait: { desc: '可以放置于远程位' } }), 'melee', 'the battle class stays melee');
|
||||
assert.equal(positionClass({ position: 'RANGED' }), 'ranged');
|
||||
assert.equal(positionClass({ position: 'ALL' }), 'all');
|
||||
assert.equal(positionClass(null), 'all');
|
||||
const HOK_Y = 'uniequip_003_glady';
|
||||
const gladE = DATA.chess.chess_char_4_12_b;
|
||||
const map = buildDeployMap(DATA.stages.act2autochess_m01);
|
||||
assert.ok(!canPlace(map, positionClass(DATA.chess.chess_char_4_12_a, HOK_Y), 10, 4), 'normal 歌蕾蒂娅, even with the id, not');
|
||||
assert.ok(!canPlace(map, positionClass(gladE), 10, 4), 'elite with no module id (default is not passed) not');
|
||||
assert.ok(!canPlace(map, positionClass(gladE, 'uniequip_002_glady'), 10, 4), 'HOK-X not');
|
||||
assert.ok(!canPlace(map, positionClass(gladE, 'none'), 10, 4), 'no module not');
|
||||
assert.ok(canPlace(map, positionClass(gladE, HOK_Y), 10, 4), 'elite + HOK-Y on the 高台');
|
||||
assert.ok(canPlace(map, positionClass(gladE, HOK_Y), 9, 3), 'and still on the ground');
|
||||
assert.ok(!canPlace(map, positionClass(DATA.chess.chess_char_2_03_b, HOK_Y), 10, 4), '崖心 not');
|
||||
assert.ok(!canPlace(map, positionClass(DATA.chess.chess_char_3_07_b, HOK_Y), 10, 4), '见行者 not');
|
||||
// the six trait holders: 歌蕾蒂娅 / 崖心 (钩索师) and 见行者 (推击手), normal and elite
|
||||
for (const id of ['chess_char_4_12_a', 'chess_char_4_12_b', 'chess_char_2_03_a', 'chess_char_2_03_b', 'chess_char_3_07_a', 'chess_char_3_07_b']) {
|
||||
assert.equal(positionClass(DATA.chess[id]), 'all', id);
|
||||
assert.ok(canPlace(map, positionClass(DATA.chess[id]), 10, 4), `${id} on the 高台`);
|
||||
assert.ok(canPlace(map, positionClass(DATA.chess[id]), 9, 3), `${id} still on the ground`);
|
||||
assert.equal(basePositionClass(DATA.chess[id]), 'melee', `${id} blocks like a melee unit`);
|
||||
assert.equal(DATA.chess[id].placement, undefined);
|
||||
}
|
||||
assert.ok(!canPlace(map, positionClass(DATA.chess.chess_char_1_02_a), 10, 4), '角峰 (重装) not');
|
||||
assert.equal(DATA.chess.chess_char_4_12_a.placement, undefined);
|
||||
assert.equal(gladE.placement, undefined);
|
||||
});
|
||||
|
||||
test('g.move: legality per chess position, BAD_TILE outside, deploy cap 8, swaps allowed at cap', () => {
|
||||
|
||||
@@ -11,13 +11,15 @@
|
||||
// nowhere to go); moving the owner sends it back anyway (PRTS 卫戍协议/帮助 "移动干员时,其所属召唤物全部退场并重置
|
||||
// 至手牌区") — with no room it leaves the board until the next round start.
|
||||
// The sim side (突袭 landing tile, tactical point) is test/sim/feedback1-water.test.js.
|
||||
// Owner's decision 2026-10-04 reverses DESIGN §22.6: the trait 「可以放置于远程位」 is not trusted. Only elite
|
||||
// 歌蕾蒂娅 carrying HOK-Y 淡金坠饰 (uniequip_003_glady) may stand on a 高台. The battle keeps position MELEE
|
||||
// (on a 高台 she attacks but blocks nothing). A bot may plan that one loadout on a 高台; everyone else stays on the ground.
|
||||
// 高台: the owner's decision of 2026-10-05 (reversing the one of 2026-10-04, elite 歌蕾蒂娅 with HOK-Y only) follows
|
||||
// PRTS — every MELEE chess whose trait reads 「可以放置于远程位」 (the 钩索师 / 推击手 branch trait: 歌蕾蒂娅, 崖心, 见行者,
|
||||
// normal and elite) may stand on a 高台, with any module or none; raised with the PRTS source in PR #69 by
|
||||
// @sunstricken. The battle keeps position MELEE (on a 高台 they attack but block nothing). The bots plan them on a 高台
|
||||
// that covers the enemy road; every other melee unit stays on the ground.
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { buildDeployMap, canPlace as boardCanPlace, legalTiles, positionClass, placeClass, tileKey, ownerRangeKeys } from '../../server/match/board.js';
|
||||
import { GLADIIA_HOK_Y } from '../../shared/highGround.js';
|
||||
import { PLACE_ON_RANGED, meleeOnHighGround } from '../../shared/highGround.js';
|
||||
import { ERR } from '../../shared/constants.js';
|
||||
import { DATA, makeMatch, give, giveItem, checkInvariants, chessOfTier } from './harness.js';
|
||||
import { botPrep, planLayout, fieldModel } from '../../server/match/bot.js';
|
||||
@@ -305,75 +307,67 @@ test('#9 bots place 狼群 / 流形 only inside their owner\'s range', () => {
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
// 高台: only elite 歌蕾蒂娅 + HOK-Y (owner's decision 2026-10-04)
|
||||
// 高台: every melee chess whose trait reads 「可以放置于远程位」, any module (the owner's decision of 2026-10-05)
|
||||
|
||||
const HIGH_STAGE = 'act2autochess_m01';
|
||||
const HIGH = ['10,4', '11,4', '12,4']; // 战场#01(下半)'s ranged-only (高台) tiles
|
||||
const GLAD_N = 'chess_char_4_12_a';
|
||||
const GLAD_E = 'chess_char_4_12_b'; // the golden record
|
||||
const CLIFF_N = 'chess_char_2_03_a';
|
||||
const CLIFF_E = 'chess_char_2_03_b';
|
||||
const FORCER_N = 'chess_char_3_07_a';
|
||||
const FORCER_E = 'chess_char_3_07_b';
|
||||
const HOLDERS = [GLAD_N, GLAD_E, CLIFF_N, CLIFF_E, FORCER_N, FORCER_E];
|
||||
const HOK_X = 'uniequip_002_glady';
|
||||
const HOK_Y = 'uniequip_003_glady';
|
||||
const TANK = (c) => c.profession === 'TANK' && c.position === 'MELEE';
|
||||
const rc = (k) => k.split(',').map(Number);
|
||||
const toHand = (m, ps, p) => move(m, p.uid, { area: 'hand', idx: ps.hand.findIndex((x) => x == null) });
|
||||
const equip = (ps, module) => {
|
||||
assert.equal(ps.setLoadout({ [GLAD_N]: { module } }), true, module);
|
||||
};
|
||||
/**
|
||||
* The loadouts each holder is tried with: its default (null), no module, and every module it has. 崖心 and 见行者 are
|
||||
* hidden this season (never in the pool): a player cannot set their loadout (shared/protocol.js checkLoadout), so they
|
||||
* are tried with their defaults (elite: HOK-X / PUS-X).
|
||||
*/
|
||||
const loadoutsOf = (id) => (DATA.chess[DATA.chess[id].baseId].isHidden ? [null]
|
||||
: [null, 'none', ...(DATA.chess[DATA.chess[id].baseId].goldenId ? DATA.chess[DATA.chess[DATA.chess[id].baseId].goldenId].modules : []).map((x) => x.uniEquipId)]);
|
||||
|
||||
test('高台 data: no chess stores placement; HOK-Y is 淡金坠饰 on the elite 歌蕾蒂娅 only', () => {
|
||||
test('高台 data: no chess stores placement; 「可以放置于远程位」 is the trait of exactly the six 钩索师 / 推击手 records, and every module keeps it', () => {
|
||||
assert.equal(Object.values(DATA.chess).some((c) => c.placement !== undefined), false);
|
||||
for (const t of Object.values(DATA.tokens)) assert.equal(t.placement, undefined, t.tokenId);
|
||||
const e = DATA.chess[GLAD_E];
|
||||
const y = e.modules.find((m) => m.uniEquipId === GLADIIA_HOK_Y);
|
||||
assert.equal(e.charId, 'char_474_glady');
|
||||
assert.equal(e.isGolden, true);
|
||||
assert.equal(y.typeName, 'HOK-Y');
|
||||
assert.equal(y.name, '淡金坠饰');
|
||||
assert.equal(e.modules.find((m) => m.isDefault).uniEquipId, HOK_X, 'the default module is HOK-X, ground-only');
|
||||
assert.equal(DATA.chess[GLAD_N].isGolden, false);
|
||||
assert.ok(!DATA.chess[CLIFF_E].modules.some((m) => m.uniEquipId === GLADIIA_HOK_Y), '崖心 has no HOK-Y');
|
||||
assert.equal(DATA.chess[GLAD_N].position, 'MELEE');
|
||||
assert.equal(e.position, 'MELEE');
|
||||
const widened = Object.values(DATA.chess).filter((c) => meleeOnHighGround(c)).map((c) => c.chessId).sort();
|
||||
assert.deepEqual(widened, HOLDERS.slice().sort());
|
||||
for (const id of HOLDERS) {
|
||||
const c = DATA.chess[id];
|
||||
assert.equal(c.position, 'MELEE', id);
|
||||
assert.ok(['钩索师', '推击手'].includes(c.subProfessionName), id);
|
||||
for (const x of c.modules || []) assert.ok(x.traitOverride.desc.includes(PLACE_ON_RANGED), `${id} ${x.typeName} keeps the line`);
|
||||
}
|
||||
// the module text never adds the line to anybody else (教官 Y "可以额外部署在远程位" is a talent, not the trait)
|
||||
for (const c of Object.values(DATA.chess)) {
|
||||
if (HOLDERS.includes(c.chessId)) continue;
|
||||
for (const x of c.modules || []) assert.ok(!(x.traitOverride?.desc || '').includes(PLACE_ON_RANGED), `${c.chessId} ${x.typeName}`);
|
||||
}
|
||||
assert.equal(DATA.chess[GLAD_E].modules.find((x) => x.uniEquipId === HOK_Y).typeName, 'HOK-Y');
|
||||
});
|
||||
|
||||
test('高台 table: (operator, module, tile) → allowed only for elite 歌蕾蒂娅 + HOK-Y on a 高台; ranged unchanged', () => {
|
||||
test('高台 table: every trait holder, normal and elite, with its default, no module or any module, may take each 高台; a 重装 is refused; ranged unchanged', () => {
|
||||
const { m, ps } = prep(HIGH_STAGE);
|
||||
assert.deepEqual([...ps.deployMap()].filter(([, cls]) => cls === 'ranged').map(([k]) => k).sort(), HIGH);
|
||||
// rows: chess id, module set on the 歌蕾蒂娅 loadout (null = leave the default), expect 高台
|
||||
const rows = [
|
||||
[GLAD_E, GLADIIA_HOK_Y, true],
|
||||
[GLAD_E, HOK_X, false],
|
||||
[GLAD_E, 'none', false],
|
||||
[GLAD_N, GLADIIA_HOK_Y, false],
|
||||
[GLAD_N, null, false],
|
||||
[CLIFF_E, GLADIIA_HOK_Y, false],
|
||||
[FORCER_N, null, false],
|
||||
[FORCER_E, null, false],
|
||||
];
|
||||
const owned = new Map();
|
||||
for (const [id, module, allowHigh] of rows) {
|
||||
if (module) equip(ps, module);
|
||||
else ps.setLoadout({});
|
||||
let p = owned.get(id);
|
||||
if (!p) { p = give(m, ps, id); owned.set(id, p); }
|
||||
else if (ps.find(p.uid)?.area === 'board') assert.deepEqual(toHand(m, ps, p), { ok: true });
|
||||
for (const k of HIGH) {
|
||||
const [r, c] = rc(k);
|
||||
const res = move(m, p.uid, board(r, c), 'DOWN');
|
||||
if (allowHigh) {
|
||||
assert.deepEqual(res, { ok: true }, `${id} ${module} → ${k}`);
|
||||
for (const id of HOLDERS) {
|
||||
const p = give(m, ps, id);
|
||||
for (const module of loadoutsOf(id)) {
|
||||
assert.equal(ps.setLoadout(module ? { [DATA.chess[id].baseId]: { module } } : {}), true, `${id} ${module}`);
|
||||
for (const k of HIGH) {
|
||||
const [r, c] = rc(k);
|
||||
assert.deepEqual(move(m, p.uid, board(r, c), 'DOWN'), { ok: true }, `${id} ${module || 'default'} → ${k}`);
|
||||
assert.equal(ps.board.get(k), p);
|
||||
checkInvariants(m);
|
||||
assert.deepEqual(toHand(m, ps, p), { ok: true });
|
||||
} else {
|
||||
assert.equal(res.error, ERR.BAD_TILE, `${id} ${module || 'default'} → ${k}`);
|
||||
}
|
||||
assert.deepEqual(move(m, p.uid, board(9, 3)), { ok: true }, `${id}: the ground stays legal`);
|
||||
assert.equal(placeClass(ps, DATA.chess[id]), 'all', id);
|
||||
assert.deepEqual(toHand(m, ps, p), { ok: true });
|
||||
}
|
||||
assert.deepEqual(move(m, p.uid, board(9, 3)), { ok: true }, `${id}: the ground stays legal`);
|
||||
assert.equal(placeClass(ps, DATA.chess[id]) === 'all', allowHigh, id);
|
||||
assert.deepEqual(toHand(m, ps, p), { ok: true });
|
||||
ps.setLoadout({});
|
||||
}
|
||||
const tank = give(m, ps, chessOfTier(1, TANK).find((x) => m.pool.has(x)));
|
||||
@@ -390,43 +384,41 @@ test('高台 table: (operator, module, tile) → allowed only for elite 歌蕾
|
||||
m.dispose();
|
||||
});
|
||||
|
||||
test('高台 client: drag highlights follow the loadout; a 重装 keeps "近战单位只能部署在地面"', () => {
|
||||
test('高台 client: drag highlights = the server for every trait holder under any module; a 重装 keeps "近战单位只能部署在地面"', () => {
|
||||
const { m, ps } = prep(HIGH_STAGE);
|
||||
equip(ps, GLADIIA_HOK_Y);
|
||||
const glad = give(m, ps, GLAD_E);
|
||||
const normal = give(m, ps, GLAD_N);
|
||||
const cliff = give(m, ps, CLIFF_E);
|
||||
const holders = HOLDERS.map((id) => give(m, ps, id));
|
||||
const tank = give(m, ps, chessOfTier(1, TANK).find((x) => m.pool.has(x)));
|
||||
const ranged = give(m, ps, chessOfTier(1, RANGED).find((x) => m.pool.has(x)));
|
||||
const ctx = clientCtx(m, ps);
|
||||
const map = ps.deployMap();
|
||||
for (const p of [glad, normal, cliff, tank, ranged]) {
|
||||
const lit = boardTargets(ctx, p.uid).legal.map(([r, c]) => tileKey(r, c)).sort();
|
||||
assert.deepEqual(lit, legalTiles(map, placeClass(ps, DATA.chess[p.id])).map(([r, c]) => tileKey(r, c)).sort(), `${p.id}: highlights = the server`);
|
||||
}
|
||||
for (const k of HIGH) {
|
||||
const [r, c] = rc(k);
|
||||
assert.equal(clientCanPlace(ctx, glad.uid, board(r, c)).ok, true, k);
|
||||
for (const p of [normal, cliff, tank]) {
|
||||
const res = clientCanPlace(ctx, p.uid, board(r, c));
|
||||
assert.equal(res.ok, false, p.id);
|
||||
for (const loadout of [{}, { [GLAD_N]: { module: HOK_Y } }, { [GLAD_N]: { module: HOK_X } }, { [GLAD_N]: { module: 'none' } }]) {
|
||||
assert.equal(ps.setLoadout(loadout), true);
|
||||
const ctx = clientCtx(m, ps);
|
||||
for (const p of [...holders, tank, ranged]) {
|
||||
const lit = boardTargets(ctx, p.uid).legal.map(([r, c]) => tileKey(r, c)).sort();
|
||||
assert.deepEqual(lit, legalTiles(map, placeClass(ps, DATA.chess[p.id])).map(([r, c]) => tileKey(r, c)).sort(), `${p.id}: highlights = the server`);
|
||||
}
|
||||
for (const k of HIGH) {
|
||||
const [r, c] = rc(k);
|
||||
for (const p of holders) assert.equal(clientCanPlace(ctx, p.uid, board(r, c)).ok, true, `${p.id} → ${k}`);
|
||||
const res = clientCanPlace(ctx, tank.uid, board(r, c));
|
||||
assert.equal(res.ok, false);
|
||||
assert.equal(res.reason, '近战单位只能部署在地面');
|
||||
assert.equal(clientCanPlace(ctx, ranged.uid, board(r, c)).ok, true);
|
||||
}
|
||||
assert.equal(clientCanPlace(ctx, ranged.uid, board(r, c)).ok, true);
|
||||
}
|
||||
m.dispose();
|
||||
});
|
||||
|
||||
test('高台 swaps: elite 歌蕾蒂娅 + HOK-Y trades with a ranged operator, not with a 重装', () => {
|
||||
test('高台 swaps: 歌蕾蒂娅 (normal, no module) trades with a ranged operator, not with a 重装', () => {
|
||||
const { m, ps } = prep(HIGH_STAGE);
|
||||
equip(ps, GLADIIA_HOK_Y);
|
||||
const glad = give(m, ps, GLAD_E);
|
||||
const glad = give(m, ps, GLAD_N);
|
||||
const tank = give(m, ps, chessOfTier(1, TANK).find((x) => m.pool.has(x)));
|
||||
const ranged = give(m, ps, chessOfTier(1, RANGED).find((x) => m.pool.has(x)));
|
||||
assert.deepEqual(move(m, glad.uid, board(10, 4), 'DOWN'), { ok: true });
|
||||
assert.deepEqual(move(m, tank.uid, board(9, 3)), { ok: true });
|
||||
assert.deepEqual(move(m, ranged.uid, board(11, 4)), { ok: true });
|
||||
let ctx = clientCtx(m, ps);
|
||||
// swapping 歌蕾蒂娅 (高台) with the 重装 (ground) would put the 重装 on the 高台
|
||||
assert.equal(clientCanPlace(ctx, glad.uid, board(9, 3)).ok, false);
|
||||
assert.equal(move(m, glad.uid, board(9, 3)).error, ERR.BAD_TILE);
|
||||
assert.equal(clientCanPlace(ctx, tank.uid, board(10, 4)).ok, false);
|
||||
@@ -444,16 +436,14 @@ test('高台 swaps: elite 歌蕾蒂娅 + HOK-Y trades with a ranged operator, no
|
||||
m.dispose();
|
||||
});
|
||||
|
||||
test('高台 battle input: elite 歌蕾蒂娅 + HOK-Y is fielded on (10,4) and blocks nothing there; on the ground she blocks', () => {
|
||||
test('高台 battle input: 歌蕾蒂娅 is fielded on (10,4) and blocks nothing there; on the ground she blocks', () => {
|
||||
const { m, ps } = prep(HIGH_STAGE);
|
||||
equip(ps, GLADIIA_HOK_Y);
|
||||
const glad = give(m, ps, GLAD_E);
|
||||
const glad = give(m, ps, GLAD_N);
|
||||
assert.deepEqual(move(m, glad.uid, board(10, 4), 'DOWN'), { ok: true });
|
||||
const u0 = ps.battleInput().units.find((u) => u.uid === glad.uid);
|
||||
assert.deepEqual([u0.row, u0.col, u0.dir, u0.moduleId], [10, 4, 'DOWN', GLADIIA_HOK_Y]);
|
||||
assert.deepEqual([u0.row, u0.col, u0.dir], [10, 4, 'DOWN']);
|
||||
m.dispose();
|
||||
// position stays MELEE either way: the normal record (the same body the 0.1.2 measurement used) attacks the lane
|
||||
// from the 高台 and blocks nothing there. HOK-Y's own range is not what this asserts.
|
||||
// position stays MELEE either way: she attacks the lane from the 高台 and blocks nothing there
|
||||
for (const [r, c, dir, high] of [[10, 4, 'DOWN', true], [9, 5, 'RIGHT', false]]) {
|
||||
const h = makeBattle({
|
||||
stageId: HIGH_STAGE, seed: 3, timeLimit: 60, autoFinish: false,
|
||||
@@ -473,42 +463,36 @@ test('高台 battle input: elite 歌蕾蒂娅 + HOK-Y is fielded on (10,4) and b
|
||||
}
|
||||
});
|
||||
|
||||
test('高台 bots: elite 歌蕾蒂娅 + HOK-Y takes a 高台 that covers the road while the ground is still free', () => {
|
||||
test('高台 bots: every trait holder, normal and elite, takes a 高台 that covers the road while the ground is still free; a plain melee stays on the road', () => {
|
||||
const { m, ps } = prep(HIGH_STAGE, 11);
|
||||
equip(ps, GLADIIA_HOK_Y);
|
||||
const elite = give(m, ps, GLAD_E);
|
||||
const k = planLayout(m, ps, [elite]).get(elite.uid);
|
||||
assert.equal(ps.deployMap().get(k), 'ranged', `planned on a 高台 with the road open (${k})`);
|
||||
const [r, c] = rc(k);
|
||||
assert.deepEqual(move(m, elite.uid, board(r, c)), { ok: true });
|
||||
m.dispose();
|
||||
});
|
||||
|
||||
test('高台 bots: everyone else stays on the road; elite 歌蕾蒂娅 + HOK-Y may take a 高台 when the ground is full', () => {
|
||||
const { m, ps } = prep(HIGH_STAGE, 11);
|
||||
const pieces = ['chess_char_4_02_a', GLAD_N, FORCER_N, 'chess_char_2_03_a'].map((id) => give(m, ps, id));
|
||||
const plan = planLayout(m, ps, pieces);
|
||||
const map = ps.deployMap();
|
||||
const road = fieldModel(m, ps).ground;
|
||||
for (const p of pieces.slice(1)) {
|
||||
const k = plan.get(p.uid);
|
||||
assert.equal(map.get(k), 'melee', `${p.id} on a ground tile (${k})`);
|
||||
assert.ok(road.has(k), `${p.id} on an enemy road tile (${k})`);
|
||||
assert.equal(move(m, p.uid, board(10, 4)).error, ERR.BAD_TILE, `${p.id} deploy refused`);
|
||||
for (const id of HOLDERS) {
|
||||
const p = give(m, ps, id);
|
||||
for (const module of loadoutsOf(id)) {
|
||||
assert.equal(ps.setLoadout(module ? { [DATA.chess[id].baseId]: { module } } : {}), true);
|
||||
const plan = planLayout(m, ps, [p]);
|
||||
const k = plan.get(p.uid);
|
||||
assert.equal(map.get(k), 'ranged', `${id} ${module || 'default'}: planned on a 高台 with the road open (${k})`);
|
||||
const [r, c] = rc(k);
|
||||
const cover = ownerRangeKeys(DATA.chess[id].rangeGrid, r, c, plan.dirOf(p.uid));
|
||||
assert.ok([...cover].some((t) => road.has(t)), `${id}: its range from ${k} covers the road`);
|
||||
assert.deepEqual(move(m, p.uid, board(r, c), plan.dirOf(p.uid)), { ok: true });
|
||||
assert.deepEqual(toHand(m, ps, p), { ok: true });
|
||||
}
|
||||
}
|
||||
const elite = give(m, ps, GLAD_E);
|
||||
equip(ps, GLADIIA_HOK_Y);
|
||||
const melee = [...map].filter(([, cls]) => cls === 'melee').map(([k]) => k);
|
||||
const highPlan = planLayout(m, ps, [elite], undefined, { occupied: new Set(melee) });
|
||||
const hk = highPlan.get(elite.uid);
|
||||
assert.equal(map.get(hk), 'ranged', `HOK-Y planned on a 高台 (${hk})`);
|
||||
const [hr, hc] = rc(hk);
|
||||
assert.deepEqual(move(m, elite.uid, board(hr, hc)), { ok: true });
|
||||
ps.setLoadout({});
|
||||
// a plain melee operator (a 重装) stays on an enemy road tile, and a 高台 is no fallback for it once the ground is full
|
||||
const tank = give(m, ps, chessOfTier(1, TANK).find((x) => m.pool.has(x)));
|
||||
const k = planLayout(m, ps, [tank]).get(tank.uid);
|
||||
assert.equal(map.get(k), 'melee', `the 重装 on a ground tile (${k})`);
|
||||
assert.ok(road.has(k), `the 重装 on an enemy road tile (${k})`);
|
||||
assert.equal(move(m, tank.uid, board(10, 4)).error, ERR.BAD_TILE, 'the 重装 deploy refused');
|
||||
const melee = new Set([...map].filter(([, cls]) => cls === 'melee').map(([key]) => key));
|
||||
assert.equal(planLayout(m, ps, [tank], undefined, { occupied: melee }).get(tank.uid), undefined, 'no ground left: no plan');
|
||||
const glad = give(m, ps, GLAD_E);
|
||||
const hk = planLayout(m, ps, [glad], undefined, { occupied: melee }).get(glad.uid);
|
||||
assert.equal(map.get(hk), 'ranged', `elite 歌蕾蒂娅 still gets a 高台 (${hk})`);
|
||||
checkInvariants(m);
|
||||
assert.deepEqual(toHand(m, ps, elite), { ok: true });
|
||||
equip(ps, 'none');
|
||||
const refused = planLayout(m, ps, [elite], undefined, { occupied: new Set(melee) });
|
||||
assert.equal(refused.get(elite.uid), undefined, 'no module: a 高台 is not a fallback');
|
||||
assert.equal(move(m, elite.uid, board(10, 4)).error, ERR.BAD_TILE);
|
||||
m.dispose();
|
||||
});
|
||||
+13
-20
@@ -245,28 +245,21 @@ describe('placement mirror (canPlace)', () => {
|
||||
assert.equal(canPlace(ctx, m.uid, null).ok, false);
|
||||
assert.equal(canPlace(ctx, m.uid, { area: 'temp', idx: 0 }).ok, false, 'no temp target');
|
||||
});
|
||||
test('only elite 歌蕾蒂娅 carrying HOK-Y lights the 高台; 崖心, 见行者, a normal record and other modules stay on the ground', () => {
|
||||
const HOK_Y = 'uniequip_003_glady';
|
||||
const gladE = piece('chess_char_4_12_b');
|
||||
const gladN = piece('chess_char_4_12_a');
|
||||
const cliff = piece('chess_char_2_03_b');
|
||||
const forcer = piece('chess_char_3_07_b');
|
||||
test('every trait holder (歌蕾蒂娅, 崖心, 见行者, normal and elite) lights the 高台 whatever the module; a plain melee stays on the ground', () => {
|
||||
const holders = ['chess_char_4_12_a', 'chess_char_4_12_b', 'chess_char_2_03_a', 'chess_char_2_03_b', 'chess_char_3_07_a', 'chess_char_3_07_b'].map((id) => piece(id));
|
||||
const m = piece(MELEE);
|
||||
const loadout = { chess_char_4_12_a: { module: HOK_Y } };
|
||||
const ctx = ctxFor(privWith({ hand: [gladE, gladN, cliff, forcer, m], loadout }));
|
||||
for (const [row, col] of [[10, 4], [11, 4], [12, 4], [9, 3]]) assert.equal(canPlace(ctx, gladE.uid, { area: 'board', row, col }).ok, true, `elite HOK-Y on ${row},${col}`);
|
||||
const lit = boardTargets(ctx, gladE.uid).legal.map(([a, b]) => tileKey(a, b));
|
||||
assert.equal(lit.length, STAGE.deployTiles.normal.melee.length + STAGE.deployTiles.normal.rangedOnly.length, 'every deploy tile lit');
|
||||
for (const p of [gladN, cliff, forcer, m]) {
|
||||
assert.deepEqual(canPlace(ctx, p.uid, { area: 'board', row: 10, col: 4 }), { ok: false, code: 'BAD_TILE', reason: '近战单位只能部署在地面' }, p.id);
|
||||
assert.equal(canPlace(ctx, p.uid, { area: 'board', row: 9, col: 3 }).ok, true, `${p.id} on the ground`);
|
||||
const every = STAGE.deployTiles.normal.melee.length + STAGE.deployTiles.normal.rangedOnly.length;
|
||||
// the module does not matter: the default, HOK-Y, HOK-X and none on 歌蕾蒂娅; 崖心's HOK-X; none on 见行者
|
||||
for (const loadout of [null, { chess_char_4_12_a: { module: 'uniequip_003_glady' } }, { chess_char_4_12_a: { module: 'uniequip_002_glady' } },
|
||||
{ chess_char_4_12_a: { module: 'none' }, chess_char_2_03_a: { module: 'none' }, chess_char_3_07_a: { module: 'none' } }]) {
|
||||
const ctx = ctxFor(privWith({ hand: [...holders, m], loadout }));
|
||||
for (const p of holders) {
|
||||
for (const [row, col] of [[10, 4], [11, 4], [12, 4], [9, 3]]) assert.equal(canPlace(ctx, p.uid, { area: 'board', row, col }).ok, true, `${p.id} on ${row},${col} (${JSON.stringify(loadout)})`);
|
||||
assert.equal(boardTargets(ctx, p.uid).legal.length, every, `${p.id}: every deploy tile lit`);
|
||||
}
|
||||
assert.deepEqual(canPlace(ctx, m.uid, { area: 'board', row: 10, col: 4 }), { ok: false, code: 'BAD_TILE', reason: '近战单位只能部署在地面' }, '角峰');
|
||||
assert.equal(canPlace(ctx, m.uid, { area: 'board', row: 9, col: 3 }).ok, true, '角峰 on the ground');
|
||||
}
|
||||
const none = ctxFor(privWith({ hand: [gladE], loadout: { chess_char_4_12_a: { module: 'none' } } }));
|
||||
assert.equal(canPlace(none, gladE.uid, { area: 'board', row: 10, col: 4 }).ok, false, 'no module');
|
||||
const xmod = ctxFor(privWith({ hand: [gladE], loadout: { chess_char_4_12_a: { module: 'uniequip_002_glady' } } }));
|
||||
assert.equal(canPlace(xmod, gladE.uid, { area: 'board', row: 10, col: 4 }).ok, false, 'HOK-X');
|
||||
const bare = ctxFor(privWith({ hand: [gladE] }));
|
||||
assert.equal(canPlace(bare, gladE.uid, { area: 'board', row: 10, col: 4 }).ok, false, 'default module is HOK-X');
|
||||
});
|
||||
test('not editable ⇒ nothing is legal', () => {
|
||||
const m = piece(MELEE);
|
||||
|
||||
@@ -879,9 +879,9 @@ function buildChess(ctx) {
|
||||
rec.subProfessionName = uniequip.subProfDict?.[char.subProfessionId]?.subProfessionName || null;
|
||||
rec.position = char.position;
|
||||
rec.nationId = char.nationId || null;
|
||||
// 高台 is not a data flag. The trait line 「可以放置于远程位」 is on every 钩索师 / 推击手 variant and is not
|
||||
// trusted: only elite 歌蕾蒂娅 carrying HOK-Y may stand there, decided at place time (shared/highGround.js,
|
||||
// owner's decision 2026-10-04, reversing DESIGN §22.6).
|
||||
// 高台 is not a data flag: a MELEE chess whose trait (no module: `traitBase` / `trait`) reads 「可以放置于远程位」
|
||||
// — the 钩索师 / 推击手 branch trait — may stand there, read at place time (shared/highGround.js; the owner's
|
||||
// decision of 2026-10-05, following PRTS).
|
||||
|
||||
// Module (only active on golden chess: equipLevel > 0).
|
||||
const modId = shop.defaultUniEquipId || null;
|
||||
@@ -3576,7 +3576,7 @@ function validateAll(f) {
|
||||
// DESIGN §16 loadout choices
|
||||
if (!Array.isArray(c.skills) || c.skills.filter((s) => s.isDefault).length !== 1 || c.skills.find((s) => s.isDefault)?.skillId !== c.skill?.skillId) err(`chess ${c.chessId}: skills[] without exactly one default = skill`);
|
||||
if (c.modules && (c.modules.filter((m) => m.isDefault).length !== (c.module?.active ? 1 : 0) || !c.statsBase || !c.traitBase || !c.talentsBase)) err(`chess ${c.chessId}: inconsistent module choices`);
|
||||
// 高台 legality is loadout-aware (shared/highGround.js), never a field on the record
|
||||
// 高台 legality is read from the trait text at place time (shared/highGround.js), never a field on the record
|
||||
if (c.placement !== undefined) err(`chess ${c.chessId}: placement is not a data field`);
|
||||
}
|
||||
// the deliberate trigger deviations (DESIGN §21.29, §22.10) still override an official TAKE_DAMAGE row, on the normal
|
||||
|
||||
+3
-3
@@ -337,12 +337,12 @@ function layout(gd, stageId, wanted, { field = 'normal', colOffset = 0, max = 12
|
||||
};
|
||||
// a 补位 unit (`standIn`) is laid out by its stand-in's body (position, block count); every other by its chess record
|
||||
const recOf = (w) => (w.standIn ? gd.standIn(w.chessId) || data.chess[w.chessId] : data.chess[w.chessId]);
|
||||
const isMelee = (w) => positionClass(recOf(w), w.moduleId) === 'melee';
|
||||
const isMelee = (w) => positionClass(recOf(w)) === 'melee';
|
||||
const order = wanted.slice().sort((a, b) => (isMelee(b) - isMelee(a)) || (isMelee(a) ? (recOf(b).stats.blockCnt || 0) - (recOf(a).stats.blockCnt || 0) : 0));
|
||||
let uid = uid0;
|
||||
for (const w of order) {
|
||||
const rec = recOf(w);
|
||||
const free = units.length < max ? tiles(positionClass(rec, w.moduleId)) : [];
|
||||
const free = units.length < max ? tiles(positionClass(rec)) : [];
|
||||
if (!free.length) { rest.push(w); continue; }
|
||||
const [r, c] = free[0];
|
||||
used.add(tileKey(r, c));
|
||||
@@ -882,7 +882,7 @@ function diyLayout(stageId, wanted) {
|
||||
const rank = (r, c) => { const d = dist(r, c); return d === 0 ? 1.5 : d; };
|
||||
return out.sort((a, b) => rank(a[0], a[1]) - rank(b[0], b[1]));
|
||||
};
|
||||
const cls = (w) => positionClass(w.rec, w.diy.uniEquipId ?? null);
|
||||
const cls = (w) => positionClass(w.rec);
|
||||
const order = wanted.slice().sort((a, b) => ((cls(b) === 'melee') - (cls(a) === 'melee')) || (cls(a) === 'melee' ? (b.rec.stats.blockCnt || 0) - (a.rec.stats.blockCnt || 0) : 0));
|
||||
const units = [];
|
||||
let uid = 1;
|
||||
|
||||
Reference in new issue
Block a user