feedback5: merge W5V — the owner's decisions of 2026-10-06: 望's placed 棋子 take and return her stock (her skills cycle all battle), skill triggers through summon ranges (麦哲伦 S1, 令 S3, 电弧 S2 / S3; summoner.js summonTriggerArea), a melee 突袭 member prefers a tile where it can block (GitHub #148); from the sources: 泥岩 S3 闭锁 releases and stops blocking (PRTS 异常效果 不可阻挡), 忍冬 / 深靛 / 阿 pinned as they are, the 自选 kits' 庇护 copies use holdProtect; DESIGN §24.2's #148 note points to §25; golden: roster-040, boss-boss_2 / 3 / 4 / 6 / 7-pair, hidden-boss_10-pair moved (W5V's own; the sleep-port moves kept)
This commit is contained in:
commit
73b810ec45
27 files changed
+746
-334
No files matched your search
+1
-1
@@ -2221,7 +2221,7 @@ Reports after the 0.1.3 release. Each was checked against the official data and
|
||||
- [ASSUMED] (kept from §23.35): the sim's automatic tile searches (突袭 landing, summon / device tiles, `grid.canStand`
|
||||
without `ranged`) still treat every MELEE unit as ground-only; a prep placement on a 高台 is the tile the battle
|
||||
deploys and redeploys on.
|
||||
- Note on GitHub #148 (「突袭近战干员部署在高台」, a battle screenshot on the 深水区 map): not changed here. The rule
|
||||
- Note on GitHub #148 (「突袭近战干员部署在高台」, a battle screenshot on the 深水区 map): not changed here (0.2.0: a melee 突袭 member prefers a landing tile where it can block — the owner's decision of 2026-10-06, §25). The rule
|
||||
above admits no 突袭 operator on a 高台, and the 突袭 landing search is meant to be ground-only (the [ASSUMED] above);
|
||||
a melee 突袭 member standing on a 高台 after its jump needs its own reproduction.
|
||||
- **Integrator**: §23.35 (title and **Now**) describes the 2026-10-04 rule; it needs a pointer here ("withdrawn in
|
||||
|
||||
+8
-3
@@ -121,7 +121,8 @@ its loadout's `skillIndex` / `moduleId` and no equipment (the copies' items went
|
||||
Token pieces: `{ kind:'token', tokenId, ownerUid, row, col, dir? }` — the manually deployable summons the player placed
|
||||
(data `placeable`, PRTS 卫戍协议/帮助 §战斗部署; user playtest #6). A piece marks the tile its summon deploys on: a talent
|
||||
summon the owner holds from the start (狼群, 海嗣, 流形, 凯瑟琳's 爬行号·防护单元 — facing the operator it shields) deploys
|
||||
with the board; a skill's summon (赫默 S2 医疗探机, 巫恋 S2 诅咒娃娃, "获得一个…") deploys once at the battle start, free
|
||||
with the board (望's 棋子 too, each one occupying her stock while it stands and going back into it as it leaves — the
|
||||
owner's decision of 2026-10-06, kits/ops/op-wang.js); a skill's summon (赫默 S2 医疗探机, 巫恋 S2 诅咒娃娃, "获得一个…") deploys once at the battle start, free
|
||||
and regardless of the holding (PRTS §作战阶段 "所有手动部署的召唤物,无视所属干员的持有状态…作战开始时立即部署一次"), then
|
||||
waits on its tile and takes the field there each time the skill gives one (stock ≤ 1, after the token's redeploy time
|
||||
once it left, free; never while its owner is off the field [ASSUMED] — a stocked one deploys as soon as the owner is
|
||||
@@ -853,8 +854,12 @@ or guard with a per-unit flag while dealing it. When the guard trips, the logged
|
||||
(`unit.baseRangeKeys`: its own grid + its permanent rangeExtend — "攻击范围扩大" modules/talents as persist never-expiring
|
||||
`rangeExtend` buffs; no skill range, no temporary extend, no extra keys) or blocked by the melee unit — or, checked
|
||||
**every tick**, an enemy (flyers included) inside a content trigger range (`unit.skill.addTriggerRange(fn)`,
|
||||
`fn(battle, unit)` → list of ally units (their current range) or tile-key arrays; returns an unregister fn; not for
|
||||
heal skills: 海嗣 "攻击范围视为自身攻击范围的延伸", 流形); `SKILL_RANGE` — "不通过普通攻击/治疗触发技能,仅在技能范围内存在敌人(无视其不可选中)时释放技能": any
|
||||
`fn(battle, unit)` → list of ally units (their current range), tile-key arrays or `{ keys, profile }` (tile keys with
|
||||
the enemy profile the effect selects by — `canHitFly` false: ground enemies only); returns an unregister fn; not for
|
||||
heal skills: 海嗣 "攻击范围视为自身攻击范围的延伸", 流形, 谬因 S2's beam, and the areas a skill acts through around its
|
||||
owner's standing summons — 麦哲伦 S1 (her drones' ranges), 令 S3 (each summon's x-5, ground), 电弧 S2 (赛柯's range,
|
||||
ground) / S3 (桑特拉's range): the owner's larger-range rule of 2026-10-06, kits/shared/summoner.js
|
||||
`summonTriggerArea`); `SKILL_RANGE` — "不通过普通攻击/治疗触发技能,仅在技能范围内存在敌人(无视其不可选中)时释放技能": any
|
||||
living enemy (stealthed, untargetable, flying included) on `trigger.customRangeGrid` (= the skill's rangeGrid), every
|
||||
tick, no attack needed; `trigger.allies` (+ `hpAtMost`, default 1) — set by a kit, or by the data for an ally row (黍 S3's
|
||||
official `TRY_SEARCH_ALLY_SKILL`, "技能范围内存在可治疗的我方单位时释放技能": tools/build-data.mjs `TRIGGER_ALLY_RULES`,
|
||||
|
||||
@@ -36,7 +36,9 @@
|
||||
// next to the most advanced ground enemy it can reach: on a free tile its position may be deployed
|
||||
// on from which its range covers that enemy (GitHub issue #51 [ASSUMED]: the first of the 8 most
|
||||
// advanced that has such a tile; none → it stays and the next poll looks again, never a jump that
|
||||
// hits nothing); grid.canStand: never the 深水区 (player report #3 after 0.1.0, members dropped
|
||||
// hits nothing) — for a melee member that blocks, a tile where its block applies first (ground
|
||||
// units pass it, an enemy path runs through it: not a 围墙 — the owner's decision of 2026-10-06,
|
||||
// GitHub #148); grid.canStand: never the 深水区 (player report #3 after 0.1.0, members dropped
|
||||
// into 战场#08's pool after an enemy wading in it); Battle.isReservedTile: never a tile a knocked-out
|
||||
// operator lies on (player report F5, members landed on a fallen teammate). A real redeployment
|
||||
// (retreat + free redeploy on the landing tile, full HP, `deploy` fires — 部署时 traits such as
|
||||
@@ -268,25 +270,35 @@ function raidReach(u) {
|
||||
* Landing tile [row, col] of a jump to enemy `e`, or null: a tile from which the member's range (`reach`, raidReach)
|
||||
* covers the enemy's body (a huge enemy: any tile it occupies — body.js), within RAID_SEARCH tiles (Chebyshev) of the
|
||||
* enemy, inside the field rect, that the member's position may be deployed on (grid.canStand: never the 深水区 —
|
||||
* player report #3 after 0.1.0) and that is free (Battle.isReservedTile: no living unit, no knocked-out operator's
|
||||
* body — player report F5 —, no waiting piece's tile). The nearest first (Chebyshev, then 0.01·Manhattan); last
|
||||
* tie-break the offset in the member's facing-RIGHT frame (sim/dir.js localOrder; for a RIGHT-facing unit the plain
|
||||
* tile-key order), so the landing tile turns with its direction. Only the tiles a range offset leads back to from a
|
||||
* body tile are looked at, so a search that finds nothing stays cheap.
|
||||
* player report #3 after 0.1.0 —, and for a melee member low ground only, never a 高台: GitHub #148) and that is free
|
||||
* (Battle.isReservedTile: no living unit, no knocked-out operator's body — player report F5 —, no waiting piece's tile).
|
||||
* A melee member that blocks takes a tile where its block applies first — ground units pass it (not a 围墙 / 围栏 tile,
|
||||
* where a unit blocks no ground enemy: Battle._blockerFor) and an enemy ground path runs through it
|
||||
* (Battle.groundPathTiles) or its enemy stands on it — over one where it would block nothing (the owner's decision of
|
||||
* 2026-10-06 after GitHub
|
||||
* #148: a member landed on a 围墙 tile, drawn raised, while a road tile covered its enemy too [ASSUMED: the official
|
||||
* landing picks among the legal tiles at random]); then the nearest (Chebyshev, then 0.01·Manhattan); last tie-break
|
||||
* the offset in the member's facing-RIGHT frame (sim/dir.js localOrder; for a RIGHT-facing unit the plain tile-key
|
||||
* order), so the landing tile turns with its direction. Only the tiles a range offset leads back to from a body tile
|
||||
* are looked at, so a search that finds nothing stays cheap.
|
||||
*/
|
||||
function raidTile(battle, u, e, reach) {
|
||||
const er = Math.round(e.y), ec = Math.round(e.x);
|
||||
const ranged = u.def?.position === 'RANGED';
|
||||
let best = null, bd = Infinity, bo = null;
|
||||
for (const k of bodyKeys(e)) {
|
||||
const body = bodyKeys(e);
|
||||
const path = !ranged && u.s.blockCnt > 0 ? battle.groundPathTiles() : null;
|
||||
let best = null, bp = 2, bd = Infinity, bo = null;
|
||||
for (const k of body) {
|
||||
const br = Math.floor(k / COLS), bc = k - br * COLS;
|
||||
for (let i = 0; i < reach.length; i += 2) {
|
||||
const r = br - reach[i], c = bc - reach[i + 1], dr = r - er, dc = c - ec;
|
||||
if (Math.abs(dr) > RAID_SEARCH || Math.abs(dc) > RAID_SEARCH) continue;
|
||||
if (!battle.grid.inRect(r, c) || !battle.grid.canStand(r, c, { ranged }) || battle.isReservedTile(r, c)) continue;
|
||||
const t = r * COLS + c;
|
||||
const p = path && battle.grid.tile(r, c).pass === 'ALL' && (path.has(t) || body.includes(t)) ? 0 : 1; // its block applies
|
||||
const d = Math.max(Math.abs(dr), Math.abs(dc)) + 0.01 * (Math.abs(dr) + Math.abs(dc));
|
||||
const o = localOrder(dr, dc, u.dir);
|
||||
if (d < bd - 1e-9 || (Math.abs(d - bd) <= 1e-9 && localBefore(o, bo))) { best = [r, c]; bd = d; bo = o; }
|
||||
if (p < bp || (p === bp && (d < bd - 1e-9 || (Math.abs(d - bd) <= 1e-9 && localBefore(o, bo))))) { best = [r, c]; bp = p; bd = d; bo = o; }
|
||||
}
|
||||
}
|
||||
return best;
|
||||
|
||||
@@ -11,7 +11,8 @@ export default {
|
||||
// 柔光缚目: attacks bind the target `duration` s with `prob`; bound enemies are never chosen as targets.
|
||||
// Alternate S1 灯塔守卫者: for `duration` s the skill range (4-1), attack interval ×(1 + base_attack_time) (PRTS:
|
||||
// "大幅度缩短(-80%)" ⇒ ×0.2 — a flat −0.8 s on 3 s would be less than S2's "略微缩短 ×0.7"), every attack hits for
|
||||
// attack@atk_scale × ATK arts. Elite module MSC-X (store 4) is the mystic profile of the module trait (TUNE.mystic);
|
||||
// attack@atk_scale × ATK arts — its stored energies too (PRTS S1 备注 "该技能的"每次攻击的攻击倍率"会实时应用在特性积攒的"攻击
|
||||
// 能量"抛射物上"; the client's ChargeAttackS1 reads the same atk_scale), not the branch's general 100 %. Elite module MSC-X (store 4) is the mystic profile of the module trait (TUNE.mystic);
|
||||
// the store itself is the shared 秘术师 profile (professions.js installMystic: at the attack check, PRTS 分支特性信息).
|
||||
chess_char_1_17_a: (bb, chess, def) => {
|
||||
const t = talentBb(chess, 0);
|
||||
|
||||
@@ -20,7 +20,9 @@ export default {
|
||||
// regen; 精锐 module SOL-X: ATK/DEF + while blocking
|
||||
// S1 小施惩戒 (charges): next attack + extra_damage_ratio × ATK arts and +cost DP; S2 坠刃拷问 (charges, the data rule
|
||||
// SKILL_RANGE: fires once an enemy is inside its own range 3-12, charges 3 s apart): +cost DP, ≤ max_target enemies of that range take atk_scale arts and
|
||||
// 停顿 — the ones already 停顿 are also stunned. (SOL-Y "首次部署时部署费用-4": the initial deployment is free.)
|
||||
// 停顿 — the ones already 停顿 are also stunned; its targets come from the 3-12 only (PRTS S2 备注 "可对空;无法选中被自身
|
||||
// 阻挡而没有位于技能范围内的敌人" — an S2 note, not S3's: S3 隐狐之艺 has none, its client selector is the standard
|
||||
// 「同时攻击阻挡的所有敌人」 one). (SOL-Y "首次部署时部署费用-4": the initial deployment is free.)
|
||||
chess_char_3_18_a: (bb, chess, def) => {
|
||||
const d = defOf(chess, def);
|
||||
const t0 = talentBb(d, 0), t1 = talentBb(d, 1);
|
||||
|
||||
@@ -8,10 +8,12 @@ import {
|
||||
|
||||
export default withDefaults({
|
||||
// ===== 泥岩 (unyield) S2 岩崩锤 — next attack: heal 4 %, 190 % phys to all ground enemies around, 30 % stun; talents
|
||||
// S1 防御力强化·γ型 (TAKE_DAMAGE); S3 秽壤的血脉 (10 s dormant — cannot act, takes no damage, keeps blocking —
|
||||
// with enemies around −60 % speed; then ground enemies around stunned 3 s/3.5 s and for the rest of the skill
|
||||
// BAT −0.3 s, ATK/DEF up, attacks every blocked enemy); module UNY-Y (沃土的愿景): ATK/DEF +8 % with no ally
|
||||
// on the 8 tiles around
|
||||
// S1 防御力强化·γ型 (TAKE_DAMAGE); S3 秽壤的血脉 (10 s dormant — PRTS 备注 "实际将会进入闭锁状态": 闭锁 = 强制缴械 +
|
||||
// 无敌 + 不可阻挡 (PRTS 异常效果: SHELTERING; 不可阻挡 BLOCK_FREE "无法阻挡/被阻挡,自动解除阻挡") — she makes no attack,
|
||||
// takes no damage and blocks nobody: the enemies she held walk on (flag noBlock — "keeps blocking" until 0.2.0
|
||||
// WV); the 备注's 眩晕 / 冻结 / 沉默 反制 are not modelled — with enemies around −60 % speed; then ground
|
||||
// enemies around stunned 3 s/3.5 s and for the rest of the skill BAT −0.3 s, ATK/DEF up, attacks every blocked
|
||||
// enemy); module UNY-Y (沃土的愿景): ATK/DEF +8 % with no ally on the 8 tiles around
|
||||
chess_char_4_18_a: (bb, chess, def) => {
|
||||
const t0 = tbb(def, 0), t1 = tbb(def, 1);
|
||||
const tb = def.traitBb || {};
|
||||
@@ -25,7 +27,8 @@ export default withDefaults({
|
||||
attack: { hitAllBlocked: true },
|
||||
onStart({ battle, unit }) {
|
||||
unit.mem.mudS3 = { awake: false, t: 0 };
|
||||
battle.addBuff(unit, { key: 'mudrok:dormant', duration: sleep + 1, flags: { invulnerable: true, disarm: true }, visible: true });
|
||||
// 闭锁: 强制缴械 + 无敌 + 不可阻挡 (her blocked enemies are released: ai.js lets go of a noBlock blocker)
|
||||
battle.addBuff(unit, { key: 'mudrok:dormant', duration: sleep + 1, flags: { invulnerable: true, disarm: true, noBlock: true }, visible: true });
|
||||
battle.fx('stone', { x: unit.x, y: unit.y, id: unit.id });
|
||||
},
|
||||
onTick({ battle, unit, dt }) {
|
||||
|
||||
@@ -43,7 +43,9 @@
|
||||
// +attack_speed (S3) for the skill's duration (per 阿 on the target: independentCharacterSource). [ASSUMED] the volley
|
||||
// lands at once (its 0.42 s of shots and flight are not modelled); with no ally in his range the cast does nothing (the
|
||||
// client's sequence stops when its attack finds no target) — his skill still runs and spends its SP: the data's DEFAULT
|
||||
// trigger needs an enemy, not an ally (reported as an open question).
|
||||
// trigger needs an enemy, not an ally — settled by the sources in 0.2.0 WV: no skillTriggerDataList row names 阿 or 怪杰
|
||||
// (the basic strategy), the skill prefabs cast with no target and keep the SP spent (skchr_haak_2 / _3 `_allowNoTarget`
|
||||
// 1, `_checkHasTargetBeforeDoCast` 0, `_recoverSpIfNoTarget` 0) and PRTS 阿 has no note on it.
|
||||
|
||||
import { num, talentBb, moduleBb, moduleOn, skillRec, statBuff, toggleBuff, up } from '../shared/tier1.js';
|
||||
import { toLocal } from '../../../dir.js';
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
// invulnerable / untargetable one) and while it stays levitated takes atk_scale × her ATK arts damage per second (the
|
||||
// first after 0.5 s, then every `interval` s; 持续伤害, not dodgeable; 无来源 at her last ATK once she left).
|
||||
|
||||
import { num, up, traitBb, talentBb, skillRec, batMod, giveSp } from '../shared/tier1.js';
|
||||
import { num, up, traitBb, talentBb, skillRec, batMod, giveSp, protectMods } from '../shared/tier1.js';
|
||||
import { absoluteRangeKeys } from '../../../targeting.js';
|
||||
import { COLS } from '../../../constants.js';
|
||||
|
||||
@@ -58,7 +58,6 @@ const S3 = 'skchr_haruka_3';
|
||||
export const BUBBLE = 'haruka:bubble';
|
||||
/** The S3 levitation damage (haruka_s_3_debuff). */
|
||||
export const FLOAT_DOT = 'haruka:float';
|
||||
const protectMods = (v) => ({ physTakenMul: 1 - v, artsTakenMul: 1 - v });
|
||||
/** 浮光泡影: the break delay when the talent carries no `interval`. */
|
||||
const BREAK_DELAY = 0.5;
|
||||
/** S3's levitation damage: the first tick (haruka_s_3_debuff firstTriggerInterval). */
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
// - S3 披荆斩棘 (MANUAL, hurt SP; data DEFAULT, rawRule TAKE_DAMAGE): at once barrier +hp_ratio × max HP (topping T1's,
|
||||
// capped), then `duration` s ATK +atk, attack interval +base_attack_time s (a flat +0.9 on 1.6 s), taunt +taunt_level.
|
||||
|
||||
import { num, traitBb, talentBb, skillRec, toggleBuff, batMod, up, enemiesInGrid } from '../shared/tier1.js';
|
||||
import { num, traitBb, talentBb, skillRec, toggleBuff, batMod, up, enemiesInGrid, holdProtect, PROTECT } from '../shared/tier1.js';
|
||||
import { isHpLoss } from '../../../damage.js';
|
||||
|
||||
const S1 = 'skchr_judge_1';
|
||||
@@ -60,9 +60,6 @@ const X4 = Object.freeze([[1, -1], [1, 0], [1, 1], [0, -1], [0, 0], [0, 1], [-1,
|
||||
/** judge_s_2[aoe]: firstTriggerInterval 0.9 s, then triggerInterval 1 s. */
|
||||
const S2_FIRST = 0.9;
|
||||
const S2_EVERY = 1;
|
||||
/** 庇护 (ba.protect): one "同名效果取最高" effect per unit, whoever grants it (battle.applyStrongest). */
|
||||
const PROTECT = 'protect';
|
||||
const protectMods = (v) => ({ physTakenMul: 1 - v, artsTakenMul: 1 - v });
|
||||
|
||||
const bbOf = (chess, id) => skillRec(chess, id)?.bb ?? {};
|
||||
const tagged = (d, tag) => !!(d && Array.isArray(d.tags) && d.tags.includes(tag));
|
||||
@@ -79,7 +76,7 @@ export default {
|
||||
/** S2's 庇护 (damage_resistance[inf] for the skill's time). */
|
||||
const protect = (battle, unit, skill) => {
|
||||
const dr = num(b2.damage_resistance);
|
||||
if (dr > 0) battle.applyStrongest(unit, PROTECT, { duration: Math.max(0.05, skill.timeLeft), value: dr, mods: protectMods, source: unit });
|
||||
holdProtect(battle, unit, dr, Math.max(0.05, skill.timeLeft), unit); // 庇护: the shared effect (同名效果取最高)
|
||||
};
|
||||
/** judge_t_1's shield_scale: 1, + S2's shield_scale while S2 runs. */
|
||||
const shieldScale = (unit) => 1 + (unit.skill?.active && unit.skill.id === S2 ? num(b2.shield_scale) : 0);
|
||||
|
||||
@@ -42,7 +42,9 @@
|
||||
// The 备注's cast with no target cannot happen here: the data's DEFAULT casts it on an attack.
|
||||
// - S3 宁作吾 (MANUAL, data DEFAULT, 30 s): she and her summons ATK +atk, DEF +def; every `interval` (0.5) s from the moment
|
||||
// it covers a summon, every ground enemy on that summon's x-5 takes atk_scale × 令's ATK arts (溅射: not dodgeable, her
|
||||
// damage — PRTS); +cnt held when it ends (not when she leaves). Passive: the 弦惊 merge — at a 弦惊's deployment, another
|
||||
// damage — PRTS); +cnt held when it ends (not when she leaves). Its cast: the data's DEFAULT, and — the owner's
|
||||
// larger-range rule of 2026-10-06 (its pulses act on each summon's x-5) — also a ground enemy on a standing summon's x-5
|
||||
// (shared/summoner.js summonTriggerArea, checked every tick). Passive: the 弦惊 merge — at a 弦惊's deployment, another
|
||||
// basic 弦惊 of hers on its range ⇒ that one turns 高级形态 and the new one is absorbed (withdrawn); else, the new one
|
||||
// standing on the range of one or more basic ones ⇒ it turns 高级形态 and the latest deployed of them is absorbed. 高级形态
|
||||
// (until it leaves the field): its skill's 2.max_hp / 2.atk / 2.def (直接乘算), RES ×(1 + 2.magic_resistance), attack
|
||||
@@ -53,7 +55,7 @@
|
||||
// stats). Its attributes are in the stats.
|
||||
|
||||
import { num, talentBb, traitBb, moduleOn, skillRec, batMod, giveSp, up } from '../shared/tier1.js';
|
||||
import { summonDeck, holdBuff, tokenStat } from '../shared/summoner.js';
|
||||
import { summonDeck, holdBuff, tokenStat, summonTriggerArea } from '../shared/summoner.js';
|
||||
import { absoluteRangeKeys } from '../../../targeting.js';
|
||||
import { acquireTargets } from '../../../ai.js';
|
||||
import { COLS, PROJECTILE_SPEEDS } from '../../../constants.js';
|
||||
@@ -72,6 +74,8 @@ export const RECYCLE_DELAY = 1.2;
|
||||
const X5 = Object.freeze([[1, 0], [0, -1], [0, 0], [0, 1], [-1, 0]]);
|
||||
const TAG_S2 = 'ling:s2';
|
||||
const TAG_S3 = 'ling:s3';
|
||||
/** S3's pulses: ground enemies only ("不可对空"). */
|
||||
const GROUND = Object.freeze({ canHitFly: false });
|
||||
|
||||
const bbOf = (chess, id) => skillRec(chess, id)?.bb ?? {};
|
||||
const skillOn = (u, id) => !!(u && u.skill && u.skill.active && u.skill.id === id);
|
||||
@@ -127,7 +131,7 @@ function soulKit(t, owner, opts) {
|
||||
if (battle.time + 1e-9 < s.mem.lingAoeAt) return;
|
||||
s.mem.lingAoeAt += iv;
|
||||
const keys = absoluteRangeKeys(X5, s.tileR, s.tileC, s.dir, 0);
|
||||
for (const e of battle.enemiesInKeys(keys, s, { canHitFly: false })) {
|
||||
for (const e of battle.enemiesInKeys(keys, s, GROUND)) {
|
||||
if (!e.alive) continue;
|
||||
battle.dealDamage(owner, e, { amount: owner.s.atk * num(opts.b3.atk_scale), type: 'arts', isSkill: true, isSplash: true, canDodge: false, tags: ['skill', TAG_S3] });
|
||||
}
|
||||
@@ -241,6 +245,10 @@ export default {
|
||||
} },
|
||||
// 随付笺咏醉屠苏 lives in the deck's onLeave above
|
||||
],
|
||||
install(battle, unit) {
|
||||
// S3's cast: a ground enemy on a standing summon's x-5 too (the owner's larger-range rule, 2026-10-06)
|
||||
summonTriggerArea(battle, unit, S3, (t) => ({ keys: absoluteRangeKeys(X5, t.tileR, t.tileC, t.dir, 0), profile: GROUND }));
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -38,7 +38,9 @@
|
||||
// - S1 高效制冷模块 (MANUAL, data DEFAULT, 15 s): passive (while S1 is picked and not running) every attack@interval (3) s from
|
||||
// her deployment / the skill's end, every enemy (air units too) on her attack range and on each of her standing drones'
|
||||
// ranges (龙腾.F: x-4) takes 停顿 attack@sluggish s; while it runs, every 3 s from the cast, 束缚 attack@frozen_duration s
|
||||
// instead. It acts while she is stunned or silenced (the buff is neither — isStunnable / isSilenceable 0).
|
||||
// instead. It acts while she is stunned or silenced (the buff is neither — isStunnable / isSilenceable 0). Its cast:
|
||||
// the data's DEFAULT, and — the owner's larger-range rule of 2026-10-06 (its 束缚 acts through the drones' ranges) —
|
||||
// also an enemy (air units too) on a standing drone's range (shared/summoner.js summonTriggerArea, checked every tick).
|
||||
// - S2 激光开采模块 (MANUAL, data DEFAULT, 15 s): she and her drones ASPD +attack_speed; a 龙腾.L strikes every enemy on its tile
|
||||
// (群体) while it runs. S3 武装打击模块 (MANUAL, data DEFAULT, 15 s): she and her drones ATK +atk; 龙腾.A's blast radius
|
||||
// BLAST_S3 (1.25). Passive parts ("无人机可以部署在近战位 / 远程位"): placement — the piece's position, nothing in battle.
|
||||
@@ -51,10 +53,12 @@
|
||||
// drones' lower costs (the module variant); stage 2+ T1 "最多同时部署4个", stage 3 "属性更强的" (the module variant's stats).
|
||||
|
||||
import { num, talentBb, traitBb, moduleOn, skillRec, up } from '../shared/tier1.js';
|
||||
import { summonDeck, holdBuff, tokenStat } from '../shared/summoner.js';
|
||||
import { summonDeck, holdBuff, tokenStat, summonTriggerArea } from '../shared/summoner.js';
|
||||
import { absoluteRangeKeys } from '../../../targeting.js';
|
||||
import { COLS } from '../../../constants.js';
|
||||
|
||||
/** S1's selection on her range and her drones' (air units too). */
|
||||
const ANY = Object.freeze({ canHitFly: true });
|
||||
const S1 = 'skchr_mgllan_1';
|
||||
const S2 = 'skchr_mgllan_2';
|
||||
const S3 = 'skchr_mgllan_3';
|
||||
@@ -171,6 +175,8 @@ export default {
|
||||
install(battle, unit) {
|
||||
// S1 高效制冷模块: every attack@interval s, 停顿 (passive) / 束缚 (running) on her range and her drones' ranges
|
||||
if (picked !== S1) return;
|
||||
// its cast: an enemy on a standing drone's range too (the owner's larger-range rule, 2026-10-06)
|
||||
summonTriggerArea(battle, unit, S1, (d) => ({ keys: d.rangeKeys, profile: ANY }));
|
||||
const iv = num(b1['attack@interval'], 3);
|
||||
if (!(iv > 0)) return;
|
||||
const restart = (c) => { if (c.unit === unit) unit.mem.mgllanPulseAt = battle.time + iv; };
|
||||
@@ -186,7 +192,7 @@ export default {
|
||||
if (!(duration > 0)) return;
|
||||
const done = new Set();
|
||||
for (const src of [unit, ...(unit.mem.summonDeck?.standing() ?? [])]) {
|
||||
for (const e of battle.enemiesInKeys(src.rangeKeys, src, { canHitFly: true })) {
|
||||
for (const e of battle.enemiesInKeys(src.rangeKeys, src, ANY)) {
|
||||
if (done.has(e)) continue;
|
||||
done.add(e);
|
||||
battle.applyStatus(e, key, { duration, source: src });
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
// [ASSUMED] (beyond op-ironmn.js's): the 监工专员 loses its 1 HP per pulse with or without an operator in range (dec_blood is a
|
||||
// passive buff of the ability); the combined range one step deep; the 小工程师's 1 s heal / SP timer runs from its deployment.
|
||||
|
||||
import { num, talentBb, traitBb, skillRec, up, giveSp } from '../shared/tier1.js';
|
||||
import { num, talentBb, traitBb, skillRec, up, giveSp, holdProtect } from '../shared/tier1.js';
|
||||
import { absoluteRangeKeys } from '../../../targeting.js';
|
||||
import { COLS } from '../../../constants.js';
|
||||
import { frontOf } from '../../../dir.js';
|
||||
@@ -86,9 +86,6 @@ export const NSTBLD = 'token_10061_nasti_nstbld';
|
||||
const DEVICES = new Set([NSTDEF, NSTCHR, NSTBLD]);
|
||||
/** A device's 1-1 when its def carries none. */
|
||||
const FRONT1 = Object.freeze([[0, 0], [0, 1]]);
|
||||
/** 庇护 (ba.protect): one "同名效果取最高" effect per unit, whoever grants it (battle.applyStrongest; op-judge.js, op-zumama.js). */
|
||||
const PROTECT = 'protect';
|
||||
const protectMods = (v) => ({ physTakenMul: 1 - v, artsTakenMul: 1 - v });
|
||||
/** 注意安全's 庇护 refresh: a little longer than the check period, so it never lapses while it holds. */
|
||||
const T2_PERIOD = 0.25;
|
||||
const PROTECT_HOLD = T2_PERIOD + 0.05;
|
||||
@@ -402,13 +399,13 @@ export default {
|
||||
if (!up(unit)) { triggered = false; timers.clear(); return; }
|
||||
if (!triggered) triggered = battle.enemies.some((e) => e.alive && !e.hidden && RANGED_WAYS.has(String(e.def?.applyWay ?? '').toUpperCase()));
|
||||
if (!triggered) {
|
||||
if (resBase > 0) battle.applyStrongest(unit, PROTECT, { duration: PROTECT_HOLD, value: resBase, mods: protectMods, source: unit });
|
||||
holdProtect(battle, unit, resBase, PROTECT_HOLD, unit); // 庇护: the shared effect (同名效果取最高)
|
||||
return;
|
||||
}
|
||||
const who = [unit, ...battle.allyUnits.filter((a) => a !== unit && up(a) && !a.hidden && a.kind === 'op' && RANGED_POS.has(String(a.def?.position ?? '').toUpperCase()))];
|
||||
for (const a of [...timers.keys()]) if (!who.includes(a)) timers.delete(a);
|
||||
for (const a of who) {
|
||||
if (resPlus > 0) battle.applyStrongest(a, PROTECT, { duration: PROTECT_HOLD, value: resPlus, mods: protectMods, source: unit });
|
||||
holdProtect(battle, a, resPlus, PROTECT_HOLD, unit);
|
||||
if (!(spEvery > 0)) continue;
|
||||
if (!timers.has(a)) { timers.set(a, battle.time + spEvery); continue; }
|
||||
if (battle.time + 1e-9 < timers.get(a)) continue;
|
||||
|
||||
@@ -43,10 +43,14 @@
|
||||
// - S2 环形鳞地 (MANUAL, data DEFAULT, 25 s): +cnt held; she and her summons ATK +atk (base_attack_time 0: no change); 赛柯's
|
||||
// attacks fire BULLET_OFFSETS (three bullets: its centre, 0.2 tile left-up and right-down — fixed, PRTS) that fly its token
|
||||
// skill's attack@projectile_life_time s (0.6 at rank 4, 0.8 at rank 7: "子弹飞行距离+1"); its 3-2 range is unchanged at ranks
|
||||
// 4 / 7 (PRTS). Passive "会持续向前方发射子弹": 赛柯's data.
|
||||
// 4 / 7 (PRTS). Passive "会持续向前方发射子弹": 赛柯's data. Its cast: the data's DEFAULT, and — the owner's larger-range
|
||||
// rule of 2026-10-06 (it acts through 赛柯's shots) — also a ground enemy on a standing summon's range (its 3-2: the
|
||||
// bullets reach no air unit; shared/summoner.js summonTriggerArea, checked every tick).
|
||||
// - S3 手牵手 (MANUAL, data DEFAULT, 30 s): +cnt held; she and her summons ATK +atk; before each damage of her attacks and of
|
||||
// any damage of her summons on an enemy: 停顿 `sluggish` s and 法术脆弱 (artsFragile damage_scale − 1, "同名效果取最高") for
|
||||
// weak[magic][limit] s (a dodged hit still carries them [ASSUMED]). Passive "召唤物可部署在远程位…协同攻击": 桑特拉 (above).
|
||||
// Its cast: the data's DEFAULT, and — the owner's larger-range rule of 2026-10-06 (it acts through her summons' damage)
|
||||
// — also an enemy (air units too: S3 备注 "召唤物可对空") on a standing summon's range (summonTriggerArea).
|
||||
// - Modules SO-A 电弧特勤证章 / SO-B 新起点: their trait and talent parts act "在【岁的界园志异】中" only (the client gates them to
|
||||
// the 集成战略 theme rogue_yan / validInGameTag roguelike): N/A here — the module talents the composed record carries
|
||||
// (SO-A's hidden respawn_time / prob / sp, SO-B's attack@max_target and x-5 recall) are ignored; their attributes are in the
|
||||
@@ -54,7 +58,7 @@
|
||||
// its tests.
|
||||
|
||||
import { num, talentBb, skillRec, up } from '../shared/tier1.js';
|
||||
import { summonDeck, holdBuff, tokenStat } from '../shared/summoner.js';
|
||||
import { summonDeck, holdBuff, tokenStat, summonTriggerArea } from '../shared/summoner.js';
|
||||
import { acquireTargets } from '../../../ai.js';
|
||||
import { aggregateMods } from '../../../buffs.js';
|
||||
import { dirVec } from '../../../dir.js';
|
||||
@@ -79,6 +83,9 @@ const BULLET_OFFSETS = Object.freeze([[0, 0], [-0.2, 0.2], [0.2, -0.2]]);
|
||||
const LINK_SPEED = 50;
|
||||
const SHIELD_TYPES = Object.freeze(['phys', 'arts', 'true']);
|
||||
const KEY_BARRIER = 'radian:s1:barrier';
|
||||
/** The summons' areas a skill casts on (summonTriggerArea): 赛柯's bullets hit ground enemies only, S3's summons air too. */
|
||||
const GROUND = Object.freeze({ canHitFly: false });
|
||||
const ANY = Object.freeze({ canHitFly: true });
|
||||
const TAG_BULLET = 'radian:bullet';
|
||||
const TAG_LINK = 'radian:link';
|
||||
|
||||
@@ -268,6 +275,9 @@ export default {
|
||||
// 加油~ lives in the deck's install above (its 鼓舞 at each deployment and every second)
|
||||
],
|
||||
install(battle, unit) {
|
||||
// S2 / S3's cast: an enemy on a standing summon's range too (the owner's larger-range rule, 2026-10-06)
|
||||
summonTriggerArea(battle, unit, S2, (t) => ({ keys: t.rangeKeys, profile: GROUND }));
|
||||
summonTriggerArea(battle, unit, S3, (t) => ({ keys: t.rangeKeys, profile: ANY }));
|
||||
// S3 手牵手: before each damage of her attacks / of her summons' damage on an enemy, 停顿 + 法术脆弱
|
||||
if (picked !== S3) return;
|
||||
const slug = num(b3.sluggish), dur = num(b3['weak[magic][limit]']), frag = num(b3.damage_scale, 1) - 1;
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
// 单位时释放技能"), which tools/build-data.mjs (TRIGGER_ALLY_RULES) writes as the engine's SKILL_RANGE + `allies` on the
|
||||
// skill range x-2 (an injured, healable allied unit there, herself included; 古米 S1's option).
|
||||
|
||||
import { num, traitBb, skillRec, batMod, up, giveSp } from '../shared/tier1.js';
|
||||
import { num, traitBb, skillRec, batMod, up, giveSp, holdProtect } from '../shared/tier1.js';
|
||||
import { COLS } from '../../../constants.js';
|
||||
import { effectiveProfile, acquireTargets, performAttack } from '../../../ai.js';
|
||||
|
||||
@@ -80,9 +80,6 @@ const PROF_NEEDED = 3;
|
||||
const SUI_NEEDED = 4;
|
||||
/** 【岁】: character_table groupId 'sui' (data/backups.json diy.operators powers carry it for the 自选 picks). */
|
||||
const SUI = new Set(['char_2014_nian', 'char_2015_dusk', 'char_2023_ling', 'char_2024_chyue', 'char_2025_shu', 'char_2026_yu', 'char_2027_wang']);
|
||||
/** 庇护 (ba.protect): one "同名效果取最高" effect per unit, whoever grants it (battle.applyStrongest). */
|
||||
const PROTECT = 'protect';
|
||||
const protectMods = (v) => ({ physTakenMul: 1 - v, artsTakenMul: 1 - v });
|
||||
const FARM = 'talent:shu:farm';
|
||||
const HARVEST = 'skill:shu:harvest';
|
||||
|
||||
@@ -122,7 +119,7 @@ export default {
|
||||
if (hp > 0 && !(cur && cur.source !== unit && (cur.data?.v ?? 0) > hp && cur.timeLeft > 0.05)) {
|
||||
battle.addBuff(a, { key: FARM, duration: FARM_HOLD, mods: { hpRegen: hp }, source: unit, data: { v: hp }, tags: ['talent'] });
|
||||
}
|
||||
if (dr > 0) battle.applyStrongest(a, PROTECT, { duration: FARM_HOLD, value: dr, mods: protectMods, source: unit });
|
||||
holdProtect(battle, a, dr, FARM_HOLD, unit); // 庇护: the shared effect (同名效果取最高)
|
||||
}
|
||||
};
|
||||
/** Sow the tiles of `grid` around (r, c) — only tiles that can be deployed on or walked. Returns the new ones. */
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
// held like the hammer's (PRIO_UNDYING_HELD −99).
|
||||
// Statuses: none applied to enemies. Damage: arts normal attacks only.
|
||||
|
||||
import { num, up, traitBb, moduleBb, talentBb, skillRec, once } from '../shared/tier1.js';
|
||||
import { num, up, traitBb, moduleBb, talentBb, skillRec, once, holdProtect } from '../shared/tier1.js';
|
||||
import { releaseSkillSummon } from '../../tokens.js';
|
||||
import { holdsUndying, PRIO_UNDYING_HELD, PRIO_REVIVE, PRIO_RESPAWN } from '../../items/battle.js';
|
||||
import { absoluteRangeKeys } from '../../../targeting.js';
|
||||
@@ -69,9 +69,6 @@ const S1 = 'skchr_slent2_1';
|
||||
const S2 = 'skchr_slent2_2';
|
||||
const S3 = 'skchr_slent2_3';
|
||||
export const LAMP = 'token_10029_slent2_protrb';
|
||||
/** 庇护 (ba.protect, the client's damage_resistance[inf]): one "同名效果取最高" effect per unit (battle.applyStrongest). */
|
||||
export const PROTECT = 'protect';
|
||||
const protectMods = (v) => ({ physTakenMul: 1 - v, artsTakenMul: 1 - v });
|
||||
/** The client's trigger period of slent2_t_1 / slent2_t_2 (talent abilities, triggerInterval 0.1). */
|
||||
export const TALENT_IV = 0.1;
|
||||
/** Lifetime of a refreshed effect: a little longer than the refresh period, so it never lapses while it holds. */
|
||||
@@ -136,7 +133,7 @@ function lampKit(t, owner, t1) {
|
||||
const keys = new Set(absoluteRangeKeys(grid, lamp.tileR, lamp.tileC, lamp.dir, 0));
|
||||
for (const a of alliesOn(battle, lamp, keys)) {
|
||||
const v = shelterOf(tb, a, scale);
|
||||
if (v > 0) battle.applyStrongest(a, PROTECT, { duration: HOLD, value: v, mods: protectMods, source: lamp });
|
||||
holdProtect(battle, a, v, HOLD, lamp); // 庇护 (the client's damage_resistance[inf]): the shared effect
|
||||
}
|
||||
}, { owner: lamp, immediate: true });
|
||||
},
|
||||
@@ -194,7 +191,7 @@ export default {
|
||||
const now = new Set(allies);
|
||||
for (const a of allies) {
|
||||
const v = shelterOf(t1, a, scale);
|
||||
if (v > 0) battle.applyStrongest(a, PROTECT, { duration: HOLD, value: v, mods: protectMods, source: unit });
|
||||
holdProtect(battle, a, v, HOLD, unit);
|
||||
const mult = isRhine(a) ? 2 : 1;
|
||||
if (maxHp > 0) battle.applyStrongest(a, MAXHP_KEY, { duration: HOLD, value: maxHp * mult, mods: (x) => ({ hpPct: x }), source: unit });
|
||||
if (regenRatio > 0 && a.hpRatio < regenBelow - 1e-9) {
|
||||
|
||||
@@ -22,12 +22,19 @@
|
||||
// may). Module TRP-X "部署费用更低(-1)…可同时部署的陷阱数量提升(+1)": the 棋子 variant's cost 2 (the DP of its returns) and
|
||||
// deploy limit 7 (the hand count — the match's); its attributes in the stats.
|
||||
// - T1 铸子 (cnt / attack@max_spawn_cnt; "最多拥有7枚"): the 棋子 are hand pieces the player places; they deploy with the board
|
||||
// for free and without using her stock (stock = cnt at the start, at most STOCK_CAP; the skills add to it). 棋子 / 跟子
|
||||
// for free. Her stock (持有库存: the 棋子 in her hand — cnt at the start, at most STOCK_CAP; the skills add to it) counts
|
||||
// them — the owner's decision of 2026-10-06, a deliberate deviation from PRTS 卫戍协议/帮助 (placed summons "无视所属干员的
|
||||
// 持有状态,不消耗持有数量", which left her stock at cnt: one S1 / S2 cast reached the cap and 阻回 held her SP for the rest
|
||||
// of the battle): every deployment of a 棋子 (the battle start's and each return) takes one from it, like one she deployed
|
||||
// herself (never below 0 [ASSUMED: a 7th placed piece of TRP-X's deploy limit takes none]), and a 棋子 that leaves the
|
||||
// field (set off, or gone with her) goes back into it at once by the official summon rule — its card back in her hand
|
||||
// while its redeploy time runs (as shared/summoner.js's recall) —, at most the cap [ASSUMED: one over the cap is lost].
|
||||
// So "立即获得两枚棋子" and the 阻回 at the cap keep cycling through the battle. 棋子 / 跟子
|
||||
// that touch on a side (上下 / 左右) activate each other and stay active once activated [ASSUMED from the S2 备注]; an
|
||||
// enemy (air units too) on an active one's tile sets it off: its effect, then it is used up (a 棋子 leaves the field; a
|
||||
// 跟子 is gone) [ASSUMED: a trap is spent by its trigger]. A spent 棋子 comes back on its tile ("原地再部署") after its
|
||||
// redeploy time (2 s), paying its cost, while 望 is on the field — its own card returns to the stock as it leaves, so the
|
||||
// stock does not change [ASSUMED]. That return is the mode's deployment of her card: it counts as a 手动部署 for 铸子 —
|
||||
// redeploy time (2 s), paying its cost and one of her stock, while 望 is on the field. That return is the mode's
|
||||
// deployment of her card: it counts as a 手动部署 for 铸子 —
|
||||
// one 跟子 on a tile next to it (the PRTS order above), at most attack@max_spawn_cnt on the field [ASSUMED: the battle-start
|
||||
// deployment does not count]. When 望 leaves the field her 棋子 and 跟子 vanish (PRTS 分支特性信息); the 棋子 come back
|
||||
// with her.
|
||||
@@ -195,7 +202,7 @@ export default {
|
||||
const at = battle.time + Math.max(0, num(stone.base.respawnTime));
|
||||
battle.every(RETRY, (b, sched) => {
|
||||
if (stone.alive || stone.removed || b.finished) { sched.cancel(); return; }
|
||||
if (b.time + 1e-9 < at || !up(unit)) return;
|
||||
if (b.time + 1e-9 < at || !up(unit) || unit.mem.wang.stock < 1) return; // (one of her stock: the deployment takes it)
|
||||
const r = stone.homeR, c = stone.homeC;
|
||||
const s3on = unit.skill?.id === S3 && unit.skill.active && inHerRange(unit, r, c);
|
||||
if (groundFoeOn(b, r, c) && !s3on) return; // "陷阱无法放置于敌人已在的格子中"
|
||||
@@ -219,12 +226,16 @@ export default {
|
||||
battle.addBuff(unit, { key: 'trait:wangStone', flags: { untargetable: true }, persist: true, allowDead: true });
|
||||
battle.on('deploy', (ctx) => {
|
||||
if (ctx.unit !== unit) return;
|
||||
unit.mem.wangNode = { seq: ++owner.mem.wang.seq, act: false, h: false, v: false, stacks: 0 };
|
||||
const w = owner.mem.wang;
|
||||
unit.mem.wangNode = { seq: ++w.seq, act: false, h: false, v: false, stacks: 0 };
|
||||
w.stock = Math.max(0, w.stock - 1); // it occupies her stock (the owner's decision of 2026-10-06)
|
||||
}, { owner: unit });
|
||||
battle.on('death', (ctx) => {
|
||||
if (ctx.unit !== unit || battle.finished) return;
|
||||
unit.removed = false; // the piece is kept (Battle.redeploy accepts it; its hooks stay)
|
||||
unit.mem.wangNode = null;
|
||||
const w = owner.mem.wang;
|
||||
w.stock = Math.min(stockCap, w.stock + 1); // its card goes back into her stock (the official summon rule)
|
||||
scheduleReturn(battle, owner, unit);
|
||||
}, { owner: unit, priority: -10 });
|
||||
},
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
// she is stunned `stun` s (zumama_s_3 ON_BUFF_FINISH 'stun'; a stunned operator blocks nobody).
|
||||
// - Melee physical, ground-only (data canHitFly false), block 1, range 1-1; ground enemies target her (no 起飞 / 迷彩).
|
||||
|
||||
import { num, traitBb, skillRec, toggleBuff, batMod, up } from '../shared/tier1.js';
|
||||
import { num, traitBb, skillRec, toggleBuff, batMod, up, holdProtect } from '../shared/tier1.js';
|
||||
|
||||
const S1 = 'skchr_zumama_1';
|
||||
const S2 = 'skchr_zumama_2';
|
||||
@@ -51,9 +51,6 @@ const S3 = 'skchr_zumama_3';
|
||||
const T1_PERIOD = 0.1;
|
||||
/** 庇护 refresh: a little longer than the check period, so it never lapses while it holds. */
|
||||
const PROTECT_HOLD = T1_PERIOD + 0.05;
|
||||
/** 庇护 (ba.protect): one "同名效果取最高" effect per unit, whoever grants it (battle.applyStrongest). */
|
||||
const PROTECT = 'protect';
|
||||
const protectMods = (v) => ({ physTakenMul: 1 - v, artsTakenMul: 1 - v });
|
||||
/** S2's blockee stun, renewed every tick while it holds (three ticks long). */
|
||||
const STUN_PULSE = 0.1;
|
||||
const VALOR = 'talent:zumama:valor';
|
||||
@@ -101,7 +98,7 @@ export default {
|
||||
const has = unit.findBuff(VALOR);
|
||||
if (high && !has && scale !== 1) battle.addBuff(unit, { key: VALOR, mods: { atkScaleMul: scale }, tags: ['talent'] });
|
||||
else if (!high && has) battle.removeBuff(unit, VALOR);
|
||||
if (up(unit) && !high && dr > 0) battle.applyStrongest(unit, PROTECT, { duration: PROTECT_HOLD, value: dr, mods: protectMods, source: unit });
|
||||
if (up(unit) && !high) holdProtect(battle, unit, dr, PROTECT_HOLD, unit); // 庇护: the shared effect
|
||||
};
|
||||
battle.every(T1_PERIOD, check, { owner: unit, immediate: true });
|
||||
battle.on('deploy', (ctx) => { if (ctx.unit === unit) check(); }, { owner: unit });
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// server/sim/content/kits/shared/summoner.js — the 召唤师 (summoner) branch in 卫戍: the summon deck the 自选 kits of 麦哲伦
|
||||
// (ops/op-mgllan.js), 令 (ops/op-ling.js) and 电弧 (ops/op-radian.js) share — the holding (持有), the return of a placed piece
|
||||
// that left the field, recalls (回收) and the summons vanishing with their owner. Kit contract and rules: ../README.md.
|
||||
// that left the field, recalls (回收), the summons vanishing with their owner, and the skills that cast on an enemy in a
|
||||
// summon's area (summonTriggerArea: the owner's larger-range rule, 2026-10-06). Kit contract and rules: ../README.md.
|
||||
//
|
||||
// Sources: the client's battle data (charpack char_248_mgllan / char_2023_ling / char_4195_radian: Talents/1
|
||||
// charge_token[born] — RechargeToken `cnt` at every deployment of the owner; CommonAbilities die_to_kill_token — KillTokens
|
||||
@@ -42,6 +43,35 @@ export function holdBuff(battle, u, key, want, mods, extra = null) {
|
||||
battle.addBuff(u, { key, mods, tags: ['skill'], ...extra });
|
||||
}
|
||||
|
||||
/**
|
||||
* The owner's larger-range rule through summons (the owner's decision of 2026-10-06; ACTIVE_RANGE, server/sim/skills.js:
|
||||
* "a skill whose effect reaches farther than the operator's own range casts when an enemy is inside the larger area"):
|
||||
* when `owner`'s picked skill is `skillId`, it also casts while an enemy is inside the area it acts through around one of
|
||||
* the owner's summons standing on the field — on top of its data rule (DEFAULT: an enemy in the owner's own range, about
|
||||
* to attack). A content trigger range (SkillRuntime.addTriggerRange), checked every tick: `area(piece)` gives that
|
||||
* summon's area as `{ keys, profile }` (absolute tile keys; the enemy profile the effect selects by — `canHitFly` false
|
||||
* when it cannot reach air units) or null. Used by 麦哲伦 S1 (her drones' ranges), 令 S3 (each summon's x-5) and 电弧 S2 /
|
||||
* S3 (赛柯's / 桑特拉's ranges). Returns the unregister fn, or null when the skill is another one.
|
||||
* @param {object} battle
|
||||
* @param {object} owner the summoner unit (its deck: owner.mem.summonDeck)
|
||||
* @param {string} skillId
|
||||
* @param {(piece: object) => ({ keys: number[], profile?: object } | null)} area
|
||||
*/
|
||||
export function summonTriggerArea(battle, owner, skillId, area) {
|
||||
const sk = owner?.skill;
|
||||
if (!sk || sk.id !== skillId) return null;
|
||||
return sk.addTriggerRange(() => {
|
||||
const deck = owner.mem.summonDeck;
|
||||
if (!deck || !up(owner) || battle.finished) return [];
|
||||
const out = [];
|
||||
for (const t of deck.standing()) {
|
||||
const a = area(t);
|
||||
if (a && Array.isArray(a.keys) && a.keys.length) out.push(a);
|
||||
}
|
||||
return out;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A field of a summon's token record at its owner's form and module (data/backups.json `tokens[id].variants[<charId>@
|
||||
* <status>]`, `byModule[uniEquipId]`): the stats the normalised def drops (`deployLimit`, `deckStack`).
|
||||
|
||||
+11
-6
@@ -8,7 +8,8 @@
|
||||
// Trigger rules (the official 技能策略, PRTS 卫戍协议/帮助 §作战阶段 技能操作; data: tools/build-data.mjs resolveTrigger):
|
||||
// DEFAULT — the basic strategy: ready + about to attack/heal + enemy / injured ally in the INITIAL range (or blocked by
|
||||
// a melee unit) — or, checked every tick, an enemy inside one of the content trigger ranges added with
|
||||
// addTriggerRange: 海嗣, 流形;
|
||||
// addTriggerRange: 海嗣, 流形, 谬因 S2's beam, the summons' areas a skill acts through (麦哲伦 S1, 令 S3, 电弧 S2 / S3 —
|
||||
// the owner's larger-range rule, 2026-10-06: kits/shared/summoner.js summonTriggerArea);
|
||||
// SKILL_RANGE — a MANUAL skill with a 技能范围 of its own: "不通过普通攻击/治疗触发技能,仅在技能范围内存在敌人(无视其
|
||||
// 不可选中)时释放技能": any living enemy on the trigger grid (the skill range; stealthed / untargetable / flying ones
|
||||
// too), checked every tick, no attack needed. Kit option `trigger.allies` (+ `hpAtMost`, default 1): a healable,
|
||||
@@ -135,9 +136,12 @@ export class SkillRuntime {
|
||||
|
||||
/**
|
||||
* Extra DEFAULT-trigger range (海嗣 "攻击范围视为自身攻击范围的延伸", 流形): `fn(battle, unit)` returns a list whose
|
||||
* entries are ally units (their current `rangeKeys` count while they are on the field) or arrays of absolute tile
|
||||
* keys. A targetable enemy (flyers included) on those tiles satisfies the DEFAULT rule (and unknown DEFAULT-like
|
||||
* rules); it is checked every tick, since the unit itself may have nothing to attack. Returns an unregister fn.
|
||||
* entries are ally units (their current `rangeKeys` count while they are on the field), arrays of absolute tile
|
||||
* keys, or `{ keys, profile }` — tile keys with the enemy profile the effect selects by (`canHitFly` false: ground
|
||||
* enemies only — the owner's larger-range rule through a summon's area, kits/shared/summoner.js summonTriggerArea;
|
||||
* 0.2.0 WV, additive). A targetable enemy (flyers included unless the entry's profile says otherwise) on those tiles
|
||||
* satisfies the DEFAULT rule (and unknown DEFAULT-like rules); it is checked every tick, since the unit itself may
|
||||
* have nothing to attack. Returns an unregister fn.
|
||||
*/
|
||||
addTriggerRange(fn) {
|
||||
if (typeof fn !== 'function') return () => {};
|
||||
@@ -153,10 +157,11 @@ export class SkillRuntime {
|
||||
const list = b._safe(() => fn(b, u), 'skill.triggerRange', u);
|
||||
if (!list || typeof list[Symbol.iterator] !== 'function') continue;
|
||||
for (const x of list) {
|
||||
let keys = null;
|
||||
let keys = null, prof = TRIGGER_PROFILE;
|
||||
if (Array.isArray(x)) keys = x;
|
||||
else if (x && typeof x === 'object' && x.side === 'ally' && x.alive && x.deployed && !x.hidden) keys = x.rangeKeys;
|
||||
if (keys && keys.length && b.enemiesInKeys(keys, u, TRIGGER_PROFILE).length) return true;
|
||||
else if (x && typeof x === 'object' && Array.isArray(x.keys)) { keys = x.keys; if (x.profile) prof = x.profile; }
|
||||
if (keys && keys.length && b.enemiesInKeys(keys, u, prof).length) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { readFileSync, readdirSync } from 'node:fs';
|
||||
import { makeBattle, enemyRec, checkInvariants } from '../helpers/battleHarness.js';
|
||||
import { PROTECT, holdProtect } from '../../server/sim/content/kits/shared/tier1.js';
|
||||
import { getDefaultSource } from '../../server/sim/simdata.js';
|
||||
@@ -79,3 +79,14 @@ test('余 (blocking), 缪尔赛思\'s melee copies, 赫拉格 / 左乐 (SBL-X, b
|
||||
assert.equal(u.findBuff(PROTECT), null, 'gone above 50 %');
|
||||
done(h);
|
||||
});
|
||||
|
||||
test('0.2.0 WV: no kit keeps its own copy of the shared 庇护 key or mods — 淬羽赫默, 黍, 斥罪, 森蚺, 娜斯提 hold it through holdProtect, 遥\'s bubbles share only the mods', () => {
|
||||
const dir = new URL('../../server/sim/content/kits/ops/', import.meta.url);
|
||||
for (const f of readdirSync(dir).filter((x) => x.endsWith('.js'))) {
|
||||
const s = readFileSync(new URL(f, dir), 'utf8');
|
||||
assert.doesNotMatch(s, /const (PROTECT|protectMods) =|applyStrongest\([^)]*['"]protect['"]|applyStrongest\(\w+, PROTECT\b/, `${f}: the shared tier1.js PROTECT / protectMods / holdProtect`);
|
||||
}
|
||||
for (const f of ['op-slent2.js', 'op-shu.js', 'op-judge.js', 'op-zumama.js', 'op-nasti.js']) {
|
||||
assert.match(readFileSync(new URL(f, dir), 'utf8'), /holdProtect\(/, `${f} uses holdProtect`);
|
||||
}
|
||||
});
|
||||
@@ -3,12 +3,17 @@
|
||||
// grid.canStand for its position) lands on low ground only, never on a 高台; on 战场#08 (act2 m04) it may land on a 围墙 tile
|
||||
// (tile_fence_bound: LOW, buildable ALL — deployable, it attacks from there and blocks no ground enemy, DESIGN §21.23), which
|
||||
// the board draws as a raised concrete area inside an orange railing: what the screenshot most likely shows.
|
||||
// Updated on purpose by 0.2.0 WV #3 (the owner's decision of 2026-10-06): a melee member that blocks lands where its block
|
||||
// applies — a tile ground units pass (not a 围墙) with an enemy ground path through it (Battle.groundPathTiles) or its enemy
|
||||
// on it — whenever such a tile covers its enemy, before a nearer one where it would block nothing; a 围墙 tile only when
|
||||
// nothing else does.
|
||||
// Run: node --test test/content/feedback5-we2-raid-148.test.js
|
||||
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { makeBattle, chessRec, enemyRec } from '../helpers/battleHarness.js';
|
||||
import { getData } from '../../server/data.js';
|
||||
import { COLS } from '../../server/sim/constants.js';
|
||||
|
||||
const D = getData({ log: { warn() {}, error() {}, info() {} } });
|
||||
const STAGES = Object.keys(D.stages).filter((id) => D.stages[id].kind !== 'unite');
|
||||
@@ -17,9 +22,21 @@ const defs = {
|
||||
enemies: { e: enemyRec({ key: 'e', hp: 1e9, speed: 0, mass: 0 }) },
|
||||
};
|
||||
const RAID = { raidShip: { count: 3, active: true, tier: 1, layers: 1 } };
|
||||
/** The tiles raidTile looks at for an enemy on (er, ec): its range [[0, 0], [0, 1]] facing RIGHT led back from the enemy. */
|
||||
function landingTiles(b, er, ec) {
|
||||
const out = [];
|
||||
for (const [dr, dc] of [[0, 0], [0, 1]]) {
|
||||
const r = er - dr, c = ec - dc;
|
||||
if (b.grid.inRect(r, c) && b.grid.canStand(r, c) && !b.isReservedTile(r, c)) out.push([r, c]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
/** Its block applies there: ground units pass the tile, and an enemy ground path runs through it or its enemy stands on it. */
|
||||
const blocksOn = (b, [r, c], er, ec) => b.grid.tile(r, c).pass === 'ALL' && (b.groundPathTiles().has(r * COLS + c) || (r === er && c === ec));
|
||||
const same = (t, r, c) => t[0] === r && t[1] === c;
|
||||
|
||||
test('#3 / GitHub #148: a melee 突袭 member never lands on a 高台 (any stage, any enemy tile of the field); 战场#08 lands it on 围墙 tiles', () => {
|
||||
let jumps = 0, fence = 0;
|
||||
test('#3 / GitHub #148: a melee 突袭 member never lands on a 高台 (any stage, any enemy tile of the field); it lands where it can block whenever such a tile covers its enemy (the owner\'s decision of 2026-10-06), a 围墙 tile only when nothing else does', () => {
|
||||
let jumps = 0, fence = 0, preferred = 0;
|
||||
for (const stageId of STAGES) {
|
||||
const st = D.stages[stageId];
|
||||
const tileAt = (r, c) => st.tiles[st.rows[r]?.[c]];
|
||||
@@ -35,14 +52,24 @@ test('#3 / GitHub #148: a melee 突袭 member never lands on a 高台 (any stage
|
||||
if (!t || t.height !== 'LOW' || (er === home[0] && ec === home[1])) continue;
|
||||
const h = makeBattle({ stageId, defs, bonds: RAID, enemies: [{ key: 'e', pos: [er, ec] }], units: [{ chessId: 'm', row: home[0], col: home[1] }], autoFinish: false, timeLimit: 60 });
|
||||
const u = h.unit('m');
|
||||
h.step();
|
||||
const tiles = landingTiles(h.b, er, ec);
|
||||
const blocking = tiles.filter((x) => blocksOn(h.b, x, er, ec));
|
||||
h.run(12);
|
||||
if (u.tileR === home[0] && u.tileC === home[1]) continue;
|
||||
jumps++;
|
||||
const at = `${stageId}: enemy ${er},${ec} → ${u.tileR},${u.tileC}`;
|
||||
const lt = tileAt(u.tileR, u.tileC);
|
||||
assert.ok(lt && lt.height === 'LOW' && (lt.buildable === 'ALL' || lt.buildable === 'MELEE'), `${stageId}: enemy ${er},${ec} → ${u.tileR},${u.tileC} ${lt?.tileKey}/${lt?.height}`);
|
||||
assert.ok(lt && lt.height === 'LOW' && (lt.buildable === 'ALL' || lt.buildable === 'MELEE'), `${at} ${lt?.tileKey}/${lt?.height}`);
|
||||
assert.ok(tiles.some((x) => same(x, u.tileR, u.tileC)), `${at}: a tile that covers its enemy`);
|
||||
if (blocking.length) {
|
||||
assert.ok(blocking.some((x) => same(x, u.tileR, u.tileC)), `${at}: a tile where it blocks was there (${JSON.stringify(blocking)})`);
|
||||
if (!blocksOn(h.b, tiles[0], er, ec)) preferred++; // the nearest one (its enemy's own) would block nothing
|
||||
}
|
||||
if (lt.tileKey === 'tile_fence_bound') fence++;
|
||||
}
|
||||
}
|
||||
assert.ok(jumps > 50, `${jumps} jumps checked`);
|
||||
assert.ok(fence > 0, 'some land on a 围墙 tile (the #148 look)');
|
||||
assert.ok(preferred > 0, `the preference decided ${preferred} landings`);
|
||||
assert.ok(fence > 0, 'some still land on a 围墙 tile (the #148 look) — where no tile it blocks on covers the enemy');
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
// test/content/feedback5-wv-sources.test.js — 0.2.0 WV #4: the questions settled by the sources with no rule change, pinned.
|
||||
// * 忍冬 — PRTS's "无法选中被自身阻挡而没有位于技能范围内的敌人" is the 备注 of S2 坠刃拷问 (技能范围 3-12; WE1 read it as S3's): its
|
||||
// kit selects on the skill range only, so an enemy she blocks off that range is never one of its targets. S3 has no such
|
||||
// note (its client selector is the standard 「同时攻击阻挡的所有敌人」 one).
|
||||
// * 深靛 S1 灯塔守卫者 — PRTS 深靛 S1 备注 "该技能的"每次攻击的攻击倍率"会实时应用在特性积攒的"攻击能量"抛射物上" (the client's
|
||||
// ChargeAttackS1 reads the same `atk_scale`): an energy she stored lands with S1's attack@atk_scale × ATK, not the
|
||||
// branch's general 100 % (PRTS 分支特性信息 秘术师 "由储存能量形成的弹道造成攻击力100%的法术普通伤害").
|
||||
// (阿 S2 / S3 — no ally condition in the data: no skillTriggerDataList row for him or 怪杰, the skill prefab casts with no
|
||||
// target and keeps the SP spent — is pinned by test/content/op_haak.test.js "爆发剂 edge cases".)
|
||||
// Run: node --test test/content/feedback5-wv-sources.test.js
|
||||
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { makeBattle, enemyRec, checkInvariants } from '../helpers/battleHarness.js';
|
||||
import { getDefaultSource } from '../../server/sim/simdata.js';
|
||||
|
||||
const ds = getDefaultSource();
|
||||
const dummy = (key, o = {}) => enemyRec({ key, hp: 1e9, speed: 0, mass: 0, ...o });
|
||||
const approx = (a, b, msg, eps = 1e-6) => assert.ok(Math.abs(a - b) <= eps * Math.max(1, Math.abs(b)), `${msg}: ${a} vs ${b}`);
|
||||
const done = (h) => { checkInvariants(h.b); assert.equal(h.b.errors.length, 0, JSON.stringify(h.b.errors[0])); };
|
||||
const skillIndexOf = (id, skillId) => ds.rawChess(id).skills.find((s) => s.skillId === skillId).index;
|
||||
|
||||
test('#4 忍冬 S2 坠刃拷问 (PRTS 备注 "无法选中被自身阻挡而没有位于技能范围内的敌人"): an enemy she blocks off her 3-12 is never hit; the one inside is', () => {
|
||||
for (const id of ['chess_char_3_18_a', 'chess_char_3_18_b']) {
|
||||
const h = makeBattle({
|
||||
seed: 3, autoFinish: false, timeLimit: 60, hooks: ['damaged'], captureNoisy: true, defs: { enemies: { e: dummy('e') } },
|
||||
units: [{ chessId: id, row: 10, col: 5, skillIndex: skillIndexOf(id, 'skchr_vulpis_2') }],
|
||||
});
|
||||
h.step();
|
||||
const u = h.unit(id);
|
||||
const behind = h.spawn('e', { pos: [10, 4] });
|
||||
behind.x = 4.4; // in contact (0.6 < 0.71) but on the tile behind her: off the 3-12
|
||||
h.step();
|
||||
assert.equal(behind.blockedBy, u, `${id}: she blocks it`);
|
||||
const inside = h.spawn('e', { pos: [10, 7] });
|
||||
h.step();
|
||||
assert.ok(u.skill.activate('test', { free: true }), `${id}: cast`);
|
||||
h.step();
|
||||
const hit = h.hooksOf('damaged').filter((c) => c.source === u && c.dmg?.tags?.includes('vulpisTorture'));
|
||||
assert.ok(hit.some((c) => c.target === inside), `${id}: the enemy inside the 3-12`);
|
||||
assert.ok(!hit.some((c) => c.target === behind), `${id}: not the blocked one off the skill range`);
|
||||
done(h);
|
||||
}
|
||||
});
|
||||
|
||||
test('#4 深靛 S1 灯塔守卫者 (PRTS 备注): the energies she stored land with S1\'s attack@atk_scale × ATK, like its main hit', () => {
|
||||
const id = 'chess_char_1_17_a';
|
||||
const r = ds.rawChess(id);
|
||||
const rec = { ...r, talents: r.talents.map((t) => ({ ...t, bb: { ...t.bb, prob: 0 } })) }; // no random 柔光缚目 bind
|
||||
const h = makeBattle({
|
||||
seed: 3, autoFinish: false, timeLimit: 120, hooks: ['damaged', 'skillStart'], captureNoisy: true,
|
||||
defs: { chess: { [id]: rec }, enemies: { e: dummy('e') } },
|
||||
units: [{ chessId: id, row: 10, col: 4, skillIndex: skillIndexOf(id, 'skchr_indigo_1') }],
|
||||
});
|
||||
h.step();
|
||||
const u = h.unit(id);
|
||||
const scale = ds.getChess(id, { skillIndex: skillIndexOf(id, 'skchr_indigo_1') }).skill.bb['attack@atk_scale'];
|
||||
assert.ok(scale > 0 && scale < 1, 'S1 strikes below 100 %');
|
||||
assert.ok(h.runUntil(() => u.trait.stored === 3, 15), 'three energies stored with no target');
|
||||
u.skill.gainSp(999);
|
||||
h.spawn('e', { pos: [10, 6] });
|
||||
assert.ok(h.runUntil(() => u.skill.active, u.s.interval + 1), 'S1 cast at her next attack check');
|
||||
h.run(1);
|
||||
const first = h.hooksOf('damaged').filter((c) => c.source === u && c.dmg.isAttack);
|
||||
const id0 = first[0].dmg.attackId;
|
||||
const volley = first.filter((c) => c.dmg.attackId === id0);
|
||||
assert.equal(volley.length, 1 + 3, 'the S1 attack + its 3 energies');
|
||||
for (const c of volley) approx(c.amount, u.s.atk * scale, 'S1\'s 攻击倍率 on each');
|
||||
done(h);
|
||||
});
|
||||
@@ -0,0 +1,123 @@
|
||||
// test/content/feedback5-wv-summon-triggers.test.js — 0.2.0 WV #2: the owner's larger-range rule through summons (the
|
||||
// owner's decision of 2026-10-06: "a skill whose effect reaches farther than the operator's own range casts when an enemy is
|
||||
// inside the larger area"). A skill that acts through its owner's summons casts on an enemy inside such an area of a summon
|
||||
// standing on the field, on top of its data rule (DEFAULT: an enemy in the owner's own range) — kits/shared/summoner.js
|
||||
// summonTriggerArea (a content trigger range, server/sim/skills.js addTriggerRange with a `{ keys, profile }` entry):
|
||||
// * 麦哲伦 S1 高效制冷模块 — her drones' ranges (air units too: its 停顿 / 束缚 reach them);
|
||||
// * 令 S3 宁作吾 — each summon's x-5 (ground enemies only: its pulses "不可对空");
|
||||
// * 电弧 S2 环形鳞地 — 赛柯's range (ground only: its bullets reach no air unit); S3 手牵手 — 桑特拉's range (air too).
|
||||
// Run: node --test test/content/feedback5-wv-summon-triggers.test.js
|
||||
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { makeBattle, enemyRec, checkInvariants } from '../helpers/battleHarness.js';
|
||||
import { COLS } from '../../server/sim/constants.js';
|
||||
|
||||
const SLOT = { 5: 'chess_char_5_diy1_a', 6: 'chess_char_6_diy1_a' };
|
||||
const dummy = (key, o = {}) => enemyRec({ key, hp: 1e9, speed: 0, mass: 0, ...o });
|
||||
const ENEMIES = { enemy_dummy: dummy('enemy_dummy'), enemy_fly: dummy('enemy_fly', { motion: 'FLY' }) };
|
||||
const MG = 'char_248_mgllan', LING = 'char_2023_ling', RADIAN = 'char_4195_radian';
|
||||
const DRONE_F = 'token_10005_mgllan_drone1';
|
||||
const SOUL3 = 'token_10020_ling_soul3';
|
||||
const TOWER2 = 'token_10052_radian_tower2', TOWER3 = 'token_10053_radian_tower3';
|
||||
function done(h) {
|
||||
checkInvariants(h.b);
|
||||
assert.equal(h.b.errors.length, 0, JSON.stringify(h.b.errors[0]));
|
||||
}
|
||||
|
||||
/** `charId` as uid 1 at (9, 2) facing RIGHT (her 3-1: rows 8–10, cols 2–5) with skill `skill`; `pieces` = [[tokenId, r, c]]. */
|
||||
function field(charId, skill, pieces = [], { tier = 6, elite = true } = {}) {
|
||||
const h = makeBattle({
|
||||
defs: { enemies: ENEMIES }, timeLimit: 900, autoFinish: false, seed: 5,
|
||||
flags: { dpInit: 99, dpPerSec: 0, dpMax: 999, startOpCooldown: 0 }, hooks: ['skillStart', 'skillEnd', 'death'], captureNoisy: true,
|
||||
units: [{ uid: 1, diy: { slot: SLOT[tier], charId, skillIndex: skill, uniEquipId: null }, elite, row: 9, col: 2 },
|
||||
...pieces.map(([tokenId, r, c], i) => ({ uid: 10 + i, kind: 'token', tokenId, ownerUid: 1, row: r, col: c, dir: 'RIGHT' }))],
|
||||
});
|
||||
h.step();
|
||||
const u = h.unit(1);
|
||||
return { h, u, ps: h.b.allyUnits.filter((a) => a.kind === 'token' && a.ownerUnit === u) };
|
||||
}
|
||||
/** Fill the skill and run `s` seconds; true when it was cast. */
|
||||
function casts(h, u, s = 2) {
|
||||
u.skill.gainSp(999);
|
||||
h.run(s);
|
||||
return u.skill.activations > 0;
|
||||
}
|
||||
const outOfHerRange = (u, r, c) => !u.rangeKeySet.has(r * COLS + c);
|
||||
|
||||
test('#2 麦哲伦 S1: an enemy on a standing drone\'s range (air units too) casts it; none there or with the drone gone: no cast; S2 / S3 get no such area', () => {
|
||||
{ // a ground enemy on 龙腾.F's x-4, far from her 3-1
|
||||
const { h, u, ps } = field(MG, 0, [[DRONE_F, 12, 9]]);
|
||||
assert.equal(u.skill.rule, 'DEFAULT');
|
||||
assert.ok(ps[0].alive && ps[0].rangeKeySet.has(12 * COLS + 10) && outOfHerRange(u, 12, 10), 'the setup');
|
||||
h.spawn('enemy_dummy', { pos: [11, 13] }); // outside every area
|
||||
assert.ok(!casts(h, u), 'nobody in her range or a drone\'s: no cast');
|
||||
h.spawn('enemy_dummy', { pos: [12, 10] });
|
||||
assert.ok(h.runUntil(() => u.skill.activations === 1, 1), 'an enemy on the drone\'s range casts S1');
|
||||
done(h);
|
||||
}
|
||||
{ // a flyer there too
|
||||
const { h, u } = field(MG, 0, [[DRONE_F, 12, 9]]);
|
||||
h.spawn('enemy_fly', { pos: [11, 10] });
|
||||
assert.ok(casts(h, u), 'a flyer on the drone\'s range');
|
||||
done(h);
|
||||
}
|
||||
{ // the drone off the field: nothing
|
||||
const { h, u, ps } = field(MG, 0, [[DRONE_F, 12, 9]]);
|
||||
h.b.retreat(ps[0], { reason: 'retreat' });
|
||||
h.spawn('enemy_dummy', { pos: [12, 10] });
|
||||
assert.ok(!casts(h, u), 'no standing drone: no cast');
|
||||
done(h);
|
||||
}
|
||||
for (const skill of [1, 2]) {
|
||||
const { h, u } = field(MG, skill, []);
|
||||
assert.equal(u.skill.triggerRanges.length, 0, `S${skill + 1}`);
|
||||
done(h);
|
||||
}
|
||||
});
|
||||
|
||||
test('#2 令 S3: a ground enemy on a standing summon\'s x-5 casts it; a flyer there, or a ground enemy off the x-5, does not; S1 / S2 get no such area', () => {
|
||||
{ // 弦惊 at (12, 9): its x-5 = (12, 9) and its four side neighbours
|
||||
const { h, u, ps } = field(LING, 2, [[SOUL3, 12, 9]]);
|
||||
assert.equal(u.skill.rule, 'DEFAULT');
|
||||
assert.ok(ps[0].alive && outOfHerRange(u, 11, 9), 'the setup');
|
||||
h.spawn('enemy_fly', { pos: [11, 9] }); // on the x-5, but air
|
||||
h.spawn('enemy_dummy', { pos: [11, 10] }); // diagonal: off the x-5
|
||||
assert.ok(!casts(h, u), 'a flyer on the x-5 / a ground enemy off it: no cast');
|
||||
h.spawn('enemy_dummy', { pos: [11, 9] });
|
||||
assert.ok(h.runUntil(() => u.skill.activations === 1, 1), 'a ground enemy on the summon\'s x-5 casts S3');
|
||||
done(h);
|
||||
}
|
||||
for (const skill of [0, 1]) {
|
||||
const { h, u } = field(LING, skill, []);
|
||||
assert.equal(u.skill.triggerRanges.length, 0, `S${skill + 1}`);
|
||||
done(h);
|
||||
}
|
||||
});
|
||||
|
||||
test('#2 电弧 S2: a ground enemy on 赛柯\'s range casts it (a flyer there does not); S3: an enemy on 桑特拉\'s range, air units too; S1 gets no such area', () => {
|
||||
{ // 赛柯 at (12, 6) facing RIGHT: its 3-2 = (12, 6) … (12, 9)
|
||||
const { h, u, ps } = field(RADIAN, 1, [[TOWER2, 12, 6]]);
|
||||
assert.equal(u.skill.rule, 'DEFAULT');
|
||||
assert.ok(ps[0].alive && ps[0].rangeKeySet.has(12 * COLS + 9) && outOfHerRange(u, 12, 9), 'the setup');
|
||||
h.spawn('enemy_fly', { pos: [12, 9] });
|
||||
assert.ok(!casts(h, u), 'a flyer on 赛柯\'s range: no cast');
|
||||
h.spawn('enemy_dummy', { pos: [12, 9] });
|
||||
assert.ok(h.runUntil(() => u.skill.activations === 1, 1), 'a ground enemy on 赛柯\'s range casts S2');
|
||||
done(h);
|
||||
}
|
||||
{ // 桑特拉 at (12, 6) facing RIGHT: its 3-1 = rows 11–13, cols 6–9
|
||||
const { h, u, ps } = field(RADIAN, 2, [[TOWER3, 12, 6]]);
|
||||
assert.ok(ps[0].alive && ps[0].rangeKeySet.has(12 * COLS + 9) && outOfHerRange(u, 12, 9), 'the setup');
|
||||
h.spawn('enemy_dummy', { pos: [11, 13] }); // outside every area
|
||||
assert.ok(!casts(h, u), 'nobody in an area: no cast');
|
||||
h.spawn('enemy_fly', { pos: [12, 9] });
|
||||
assert.ok(h.runUntil(() => u.skill.activations === 1, 1), 'a flyer on 桑特拉\'s range casts S3');
|
||||
done(h);
|
||||
}
|
||||
{
|
||||
const { h, u } = field(RADIAN, 0, []);
|
||||
assert.equal(u.skill.triggerRanges.length, 0, 'S1');
|
||||
done(h);
|
||||
}
|
||||
});
|
||||
@@ -797,7 +797,7 @@ test('星熊 module PRO-X 护身符: DEF +20 % while blocking', () => {
|
||||
approx(def(null, true), def(null, false), 1e-9);
|
||||
});
|
||||
|
||||
test('泥岩 S1 防御力强化·γ型 (TAKE_DAMAGE) and S3 秽壤的血脉 (dormant & invulnerable & blocking, slow; then stun, buffs, hits all blocked)', () => {
|
||||
test('泥岩 S1 防御力强化·γ型 (TAKE_DAMAGE) and S3 秽壤的血脉 (闭锁: invulnerable, no attack, blocks nobody — the enemies she held walk on —, slow; then stun, buffs, hits all blocked)', () => {
|
||||
for (const id of pair('chess_char_4_18_a')) {
|
||||
const b1 = D(id, 0).skill.bb, sk = D(id, 2).skill, b3 = sk.bb;
|
||||
let h = battle([U(id, 10, 4, 0)], { enemies: { enemy_hitter: dummy({ key: 'enemy_hitter', atk: 300, bat: 1 }) } });
|
||||
@@ -812,21 +812,32 @@ test('泥岩 S1 防御力强化·γ型 (TAKE_DAMAGE) and S3 秽壤的血脉 (dor
|
||||
for (let i = 0; i < 3; i++) h.spawn('e_walk', { routeIndex: 0 });
|
||||
u = h.unit(id);
|
||||
assert.ok(h.runUntil(() => u.blocking.length === 3, 30), 'blocks three walkers');
|
||||
const walkers = u.blocking.slice();
|
||||
const hp0 = u.hp;
|
||||
assert.ok(u.skill.activate('test', { free: true }));
|
||||
const t0 = h.b.time;
|
||||
h.run(b3.sleep - 1);
|
||||
h.step();
|
||||
// 闭锁 (PRTS 备注 "实际将会进入闭锁状态"; PRTS 异常效果 闭锁 = 强制缴械 + 无敌 + 不可阻挡, 不可阻挡 "无法阻挡/被阻挡,自动解除阻挡")
|
||||
assert.ok(u.blocking.length === 0 && walkers.every((e) => e.blockedBy !== u), `${id}: 闭锁 lets go of the enemies she held`);
|
||||
assert.ok(walkers.every((e) => e.findBuff(`mudrok:slow:${u.id}`)), 'enemies around slowed');
|
||||
const x0 = walkers.map((e) => e.x);
|
||||
h.run(1);
|
||||
assert.ok(walkers.every((e, i) => e.removed || e.x < x0[i] - 0.05), `${id}: they walk on`);
|
||||
h.run(b3.sleep - 2.5);
|
||||
assert.equal(u.hp >= hp0 - 1e-6, true, `${id}: no damage while dormant`);
|
||||
assert.equal(u.blocking.length, 3, 'keeps blocking');
|
||||
assert.equal(u.blocking.length, 0, `${id}: blocks nobody while dormant`);
|
||||
assert.equal(h.hooksOf('attack').filter((c) => c.attacker === u && c.t > t0).length, 0, 'cannot act');
|
||||
assert.ok(u.blocking.every((e) => e.findBuff(`mudrok:slow:${u.id}`)), 'enemies around slowed');
|
||||
h.run(1.2);
|
||||
assert.ok(u.findBuff('mudrok:awake'), 'awake');
|
||||
for (const e of u.blocking) assert.ok(e.s.flags.stun, 'ground enemies around stunned');
|
||||
const near = [0, 1, 2].map(() => h.spawn('enemy_dummy', { pos: [9, 5] })); // on her tile before she wakes
|
||||
h.step();
|
||||
assert.equal(u.blocking.length, 0, `${id}: not blocked before she wakes`);
|
||||
assert.ok(h.runUntil(() => !!u.findBuff('mudrok:awake'), 2), 'awake');
|
||||
h.run(0.2);
|
||||
for (const e of near) assert.ok(e.s.flags.stun, 'ground enemies around stunned');
|
||||
approx(u.s.atk, u.base.atk * (1 + b3.atk) * (u.findBuff('mudrok:module') ? 1 + (u.def.traitBb.atk ?? 0) : 1), 1e-6, 'ATK');
|
||||
approx(u.s.interval, (u.base.bat + b3.base_attack_time) * 100 / u.s.aspd, 1e-6, 'BAT −0.3 s');
|
||||
assert.ok(h.runUntil(() => h.hooksOf('attack').some((c) => c.attacker === u && c.t > t0), 5));
|
||||
assert.equal(h.hooksOf('attack').find((c) => c.attacker === u && c.t > t0).targets.length, 3, 'attacks every blocked enemy');
|
||||
assert.ok(h.runUntil(() => u.blocking.length === 3, 4), `${id}: she blocks again once awake (their stun over)`);
|
||||
h.runUntil(() => !u.skill.active, sk.duration);
|
||||
assert.ok(!u.findBuff('mudrok:awake'));
|
||||
checkInvariants(h.b);
|
||||
|
||||
@@ -216,7 +216,8 @@ test('S1 取势 (AUTO, SP_FULL): the triggering enemy is 停顿 6.5 s and takes
|
||||
const sk = skillOf(tier, elite, S1);
|
||||
assert.deepEqual([sk.spCost, sk.bb.cnt, sk.bb['attack@atk_scale'], sk.bb['attack@sluggish']], elite ? [20, 2, 1.2, 6.5] : [21, 2, 1.05, 6.5], `T${tier}`);
|
||||
const { h, u, st } = field({ tier, elite, skill: 0, stones: [[10, 6], [10, 7]] });
|
||||
assert.deepEqual([u.skill.kind, u.skill.rule, u.mem.wang.stock], ['instant', 'SP_FULL', 6]);
|
||||
// her stock: 6 less the 2 placed 棋子 (the owner's decision of 2026-10-06 — see the stock test below)
|
||||
assert.deepEqual([u.skill.kind, u.skill.rule, u.mem.wang.stock], ['instant', 'SP_FULL', 4]);
|
||||
const e = h.spawn('enemy_dummy', { pos: [10, 7] });
|
||||
h.step();
|
||||
const slug = h.hooksOf('statusApplied').find((c) => c.target === e && c.status === 'sluggish');
|
||||
@@ -238,7 +239,7 @@ test('S1 取势 (AUTO, SP_FULL): the triggering enemy is 停顿 6.5 s and takes
|
||||
h.step();
|
||||
h.step();
|
||||
assert.equal(e2.buffs.filter((b) => b.key === 'wang:qushi').length, 2, `T${tier}: independent`);
|
||||
// the active part: +2 stock (6 → 7: the cap), then 阻回
|
||||
// the active part: +2 stock (6 → 7: the cap — both pieces are off the field, their cards back in her hand), then 阻回
|
||||
u.skill.gainSp(999);
|
||||
assert.ok(h.runUntil(() => u.skill.activations === 1, 1), `T${tier}: cast at full SP`);
|
||||
assert.equal(u.mem.wang.stock, 7, `T${tier}: 最多拥有7枚`);
|
||||
@@ -248,6 +249,56 @@ test('S1 取势 (AUTO, SP_FULL): the triggering enemy is 停顿 6.5 s and takes
|
||||
}
|
||||
});
|
||||
|
||||
test('her stock (the owner\'s decision of 2026-10-06): the placed 棋子 occupy it like ones she deployed; a 棋子 that goes off goes back into it at once and its return takes one again; at the cap one that goes off is lost to the cap, so 阻回 lifts with its return and S1 / S2 keep casting', () => {
|
||||
for (const skill of [0, 1]) {
|
||||
const S = `S${skill + 1}`;
|
||||
const { h, u, st } = field({ tier: 6, elite: true, skill, stones: [[10, 6], [10, 7]] });
|
||||
const w = u.mem.wang;
|
||||
assert.equal(w.stock, 6 - 2, `${S}: 6 less the 2 placed`);
|
||||
const a = at(st, 10, 6), b = at(st, 10, 7);
|
||||
let e = h.spawn('enemy_dummy', { pos: [10, 7] });
|
||||
h.step();
|
||||
assert.ok(!b.alive, `${S}: set off`);
|
||||
assert.equal(w.stock, 5, `${S}: its card is back in her stock at once`);
|
||||
h.b.kill(e, null);
|
||||
assert.ok(h.runUntil(() => b.alive, 5), `${S}: back on its tile`);
|
||||
assert.equal(w.stock, 4, `${S}: its return takes one`);
|
||||
// two casts: 4 → 6 → 7 (8, over the cap); 阻回 at the cap only
|
||||
u.skill.gainSp(999);
|
||||
h.step();
|
||||
assert.deepEqual([u.skill.activations, w.stock], [1, 6], `${S}: 立即获得两枚棋子`);
|
||||
h.step();
|
||||
assert.ok(!u.s.flags.noSp, `${S}: below the cap, no 阻回`);
|
||||
u.skill.gainSp(999);
|
||||
h.step();
|
||||
assert.deepEqual([u.skill.activations, w.stock], [2, 7], `${S}: 最多拥有7枚`);
|
||||
h.step();
|
||||
assert.ok(u.s.flags.noSp, `${S}: 阻回 at the cap`);
|
||||
const sp0 = u.skill.sp;
|
||||
h.run(2);
|
||||
assert.equal(u.skill.sp, sp0, `${S}: no SP under 阻回`);
|
||||
// at the cap: the piece that goes off is lost to the cap, its return takes one ⇒ 阻回 lifts, SP comes back
|
||||
e = h.spawn('enemy_dummy', { pos: [10, 6] });
|
||||
h.step();
|
||||
assert.ok(!a.alive, `${S}: set off at the cap`);
|
||||
assert.equal(w.stock, 7, `${S}: still the cap`);
|
||||
h.b.kill(e, null);
|
||||
assert.ok(h.runUntil(() => a.alive, 5), `${S}: back`);
|
||||
assert.equal(w.stock, 6, `${S}: its return took one`);
|
||||
h.step();
|
||||
assert.ok(!u.s.flags.noSp, `${S}: 阻回 lifted`);
|
||||
const sp1 = u.skill.sp;
|
||||
h.run(2);
|
||||
assert.ok(u.skill.sp > sp1, `${S}: her SP recovers again`);
|
||||
done(h);
|
||||
}
|
||||
// TRP-X: 7 placed 棋子 (its deploy limit) on a stock of 6 ⇒ 0, never below
|
||||
const { h, u, st } = field({ tier: 6, elite: true, mod: X, skill: 0, stones: [[10, 3], [10, 4], [10, 5], [10, 6], [10, 7], [10, 8], [10, 9]] });
|
||||
assert.ok(st.length === 7 && st.every((s) => s.alive), 'TRP-X: all 7 deploy');
|
||||
assert.equal(u.mem.wang.stock, 0, 'TRP-X: 7 placed on a stock of 6');
|
||||
done(h);
|
||||
});
|
||||
|
||||
test('S2 连星 (AUTO, SP_FULL): a triggered piece hits every enemy on its connected lines (its tile ± 3; air too) for 420 % / 480 % ATK arts and slows them 35 % / 40 % for 6 s — each slow on its own timer, added up, speed ≥ 0.1', () => {
|
||||
for (const [tier, elite] of [[5, false], [6, true]]) {
|
||||
const sk = skillOf(tier, elite, S2);
|
||||
@@ -308,7 +359,7 @@ test('S3 天下劫 (MANUAL, ACTIVE_RANGE 4-12, 20 bullets): passive — the piec
|
||||
assert.equal(u.skill.attackOverride()?.noAttack, true, `T${tier}: 停止攻击`);
|
||||
assert.equal(u.mem.wang.stock, 7, `T${tier}: +8, capped`);
|
||||
const fl = placed(h).map(([r, c]) => `${r},${c}`);
|
||||
assert.equal(fl.length, 7, `T${tier}: 6 + 8 − 7 over the cap`);
|
||||
assert.equal(fl.length, 5, `T${tier}: (6 − 2 placed) + 8 − 7 over the cap`);
|
||||
assert.deepEqual(fl.slice(0, 2).sort(), ['10,7', '9,5'], `T${tier}: the enemies' tiles first (${fl})`);
|
||||
assert.ok(h.hooksOf('damaged').some((c) => c.target === a && c.source === u && c.dmg.tags.includes('wang:stone')), `T${tier}: they set off`);
|
||||
// inside her range a 棋子 comes back onto an enemy ("可部署至敌人所在位置") — and sets off again
|
||||
|
||||
+274
-234
@@ -139,42 +139,42 @@
|
||||
"killed": 7,
|
||||
"total": 8,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": 2303707,
|
||||
"rngDraws": 882,
|
||||
"bossHpLeft": 2323494,
|
||||
"rngDraws": 861,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":7,"total":8,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":602609,"bossDmg":333143,"heal":20719,"deaths":0,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":913438,"bossDmg":360254,"heal":6843,"deaths":1,"layerGains":{}}
|
||||
"p1": {"killed":7,"total":8,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":591887,"bossDmg":312274,"heal":19641,"deaths":0,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":878330,"bossDmg":361136,"heal":6843,"deaths":1,"layerGains":{}}
|
||||
},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",3907,1,9,0,186260,1132,15,78,3],
|
||||
["p1",2,"op","chess_char_4_01_b",2,"uniequip_002_rmixer",5482.35,1,11,0,723,12774,265,37,1],
|
||||
["p1",3,"op","chess_char_5_14_b",1,"none",1994,1,7,0,26917,2238,333,59,14],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",2738,1,13,0,13424,0,0,85,1],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",1170,1,1,0,76572,0,1021,32,9],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",2418.5,1,3,0,73698,0,0,44,4],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",2769.3,1,17,0,26447,0,0,45,2],
|
||||
["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",1611,1,19,4,164686,2047,1463,55,21],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",1610,1,5,0,0,0,17579,24,3],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",1695,1,15,0,33883,1393,44,34,2],
|
||||
["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",3907,1,9,0,176503,1132,0,72,3],
|
||||
["p1",2,"op","chess_char_4_01_b",2,"uniequip_002_rmixer",5482.35,1,11,0,723,12906,183,34,1],
|
||||
["p1",3,"op","chess_char_5_14_b",1,"none",1994,1,7,0,26692,1028,261,54,14],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",2738,1,13,0,13640,0,0,80,1],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",1170,1,1,0,59962,0,1515,33,6],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",2418.5,1,3,0,72626,0,0,43,4],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",2769.3,1,17,0,28364,0,0,57,3],
|
||||
["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",1611,1,19,4,174454,2047,1463,57,21],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",1610,1,5,0,0,0,16175,20,3],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",1695,1,15,0,38923,1393,44,40,2],
|
||||
["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",599.39,1,12,0,0,3929,1201,0,2],
|
||||
["p2",12,"op","chess_char_4_04_b",1,"uniequip_002_ines",3545.85,1,49,1,259634,511,511,291,8],
|
||||
["p2",12,"op","chess_char_4_04_b",1,"uniequip_002_ines",3545.85,1,48,1,241366,511,511,284,8],
|
||||
["p2",13,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",1898.31,1,8,0,2347,1249,764,15,6],
|
||||
["p2",14,"op","chess_char_4_16_b",2,"uniequip_002_texas2",2671.35,1,48,1,116398,2806,1366,164,11],
|
||||
["p2",14,"op","chess_char_4_16_b",2,"uniequip_002_texas2",2671.35,1,47,1,101686,2806,1366,162,10],
|
||||
["p2",15,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",1931.91,1,10,0,56922,1270,424,53,3],
|
||||
["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,2,0,264370,0,0,175,2],
|
||||
["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,2,0,275392,0,0,175,2],
|
||||
["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",1636.54,1,18,1,51064,3170,2575,44,4],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,41,0,69587,1991,2,105,28],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1626,1,6,0,93116,0,0,61,17],
|
||||
["p2",18,"op","chess_char_4_12_b",2,"uniequip_002_glady",1636.54,1,18,1,44668,3170,2575,41,4],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,41,0,62779,1991,2,96,26],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1626,1,6,0,93170,0,0,61,17],
|
||||
["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,3187,62190],"enemy_1430_lrrook":[2,1,1,0,760564],"enemy_9017_achunt":[2,0,0,31321,696293]},
|
||||
"hooks": [1,47,6000,1396,1412,2975,3026,5410,9,23,141,136,23,38184,1056,0,10,1,1,9,0,13,0],
|
||||
"events": {"atk":1421,"deploy":37,"die":22,"dmg":3018,"engage":17,"fx":634,"heal":55,"leak":1,"skill":277,"spawn":32,"status":527},
|
||||
"fx": {"aoe":38,"appear":2,"blink":14,"burst":13,"catShield":1,"charge":6,"counter":23,"crit":98,"dilemma":3,"disappear":2,"explosion":17,"frostNova":28,"garrisonGrant":1,"iceSpike":41,"overclock":2,"pull":3,"quadShot":2,"ripple":14,"sentry":5,"sermon":1,"shadowWeave":10,"shield":6,"soul":6,"sp":10,"stealth":8,"swordRain":105,"swordStorm":11,"tornado":4,"tornadoPulse":17,"weightless":4,"zone":139},
|
||||
"snaps": "fd90838e 1a32ad53 fa1fb93e d4cb9fb5 9a558a4f 03f789d7 0b46d96b 279a307a f3103ed5 faa4fc49 0d6b6cef 9490511c 094c0736 c2256243 08e7fbb2 8ae85b69 5490f959 95e4ec90 acf8698a 8140cf80"
|
||||
"enemies": {"enemy_1005_yokai_2":[6,6,0,3187,62190],"enemy_1430_lrrook":[2,1,1,0,734721],"enemy_9017_achunt":[2,0,0,30243,676506]},
|
||||
"hooks": [1,46,6000,1359,1379,2883,2933,5284,9,22,136,129,20,37832,1034,0,10,1,1,9,0,12,0],
|
||||
"events": {"atk":1384,"deploy":36,"die":21,"dmg":2925,"engage":17,"fx":608,"heal":50,"leak":1,"skill":265,"spawn":32,"status":505},
|
||||
"fx": {"aoe":38,"appear":2,"blink":13,"burst":12,"catShield":1,"charge":6,"counter":20,"crit":105,"dilemma":3,"disappear":2,"explosion":17,"frostNova":26,"garrisonGrant":1,"iceSpike":53,"overclock":2,"pull":3,"quadShot":2,"ripple":20,"sentry":5,"sermon":1,"shadowWeave":10,"shield":5,"soul":6,"sp":8,"stealth":8,"swordRain":91,"swordStorm":10,"tornado":4,"tornadoPulse":16,"weightless":4,"zone":114},
|
||||
"snaps": "fd90838e 1a32ad53 fa1fb93e d4cb9fb5 9a558a4f 03f789d7 0b46d96b 279a307a f3103ed5 faa4fc49 6fb7ae55 ce7f1071 c23efccb a5e804fd d5357397 7ac01e1e 1e658876 0bdd07d6 825d32ce b6f61819"
|
||||
},
|
||||
"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",
|
||||
@@ -222,64 +222,102 @@
|
||||
"round": 14,
|
||||
"seed": 1428555614,
|
||||
"waveId": "act1autochess_h07_03",
|
||||
"time": 101.33,
|
||||
"ticks": 3040,
|
||||
"time": 103.6,
|
||||
"ticks": 3108,
|
||||
"reason": "cleared",
|
||||
"killed": 17,
|
||||
"total": 18,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": 0,
|
||||
"rngDraws": 761,
|
||||
"rngDraws": 781,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":17,"total":18,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":790828,"bossDmg":729593,"heal":1797,"deaths":0,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":1392939,"bossDmg":1270407,"heal":15259,"deaths":0,"layerGains":{}}
|
||||
"p1": {"killed":17,"total":18,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":804545,"bossDmg":740515,"heal":1513,"deaths":0,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":1379222,"bossDmg":1259485,"heal":18886,"deaths":0,"layerGains":{}}
|
||||
},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_6_03_b",2,"uniequip_002_yu",3430,1,7,0,0,0,0,0,0],
|
||||
["p1",2,"op","chess_char_6_06_b",2,"uniequip_002_pepe",2939,1,11,0,0,0,0,0,0],
|
||||
["p1",3,"op","chess_char_6_07_b",2,"uniequip_002_siege2",3101,1,9,0,0,0,0,0,0],
|
||||
["p1",4,"op","chess_char_6_01_b",2,"uniequip_002_lemuen",2131.5,1,13,0,361107,0,0,32,4],
|
||||
["p1",5,"op","chess_char_6_02_b",2,"uniequip_002_sbell2",1933,1,17,1,183468,165,10,36,2],
|
||||
["p1",6,"op","chess_char_6_04_b",2,"uniequip_002_skadi2",1598,1,19,2,17072,4605,1256,0,2],
|
||||
["p1",7,"op","chess_char_6_05_b",2,"uniequip_002_pasngr",2307.2,1,21,3,165063,1184,530,48,4],
|
||||
["p1",4,"op","chess_char_6_01_b",2,"uniequip_002_lemuen",2131.5,1,13,1,353516,0,0,32,4],
|
||||
["p1",5,"op","chess_char_6_02_b",2,"uniequip_002_sbell2",1933,1,17,0,193845,39,5,38,2],
|
||||
["p1",6,"op","chess_char_6_04_b",2,"uniequip_002_skadi2",1533.97,1,19,1,17503,4365,1291,0,3],
|
||||
["p1",7,"op","chess_char_6_05_b",2,"uniequip_002_pasngr",2307.2,1,21,1,176549,712,217,50,4],
|
||||
["p1",8,"op","chess_char_6_08_b",2,"uniequip_002_reed2",1668,1,5,0,0,0,0,0,0],
|
||||
["p1",9,"op","chess_char_6_09_b",0,"uniequip_002_cello",1322,1,15,0,11,0,0,4,4],
|
||||
["p1",10,"op","chess_char_6_11_b",2,"uniequip_002_mlyss",1893,1,23,0,43052,0,0,104,3],
|
||||
["p1",9,"op","chess_char_6_09_b",0,"uniequip_002_cello",1322,1,15,1,10,0,0,3,3],
|
||||
["p1",10,"op","chess_char_6_11_b",2,"uniequip_002_mlyss",1893,1,23,0,45158,0,0,106,3],
|
||||
["p1",11,"token","token_10017_skadi2_dedant",null,null,130.4,0,26,0,0,0,0,0,null],
|
||||
["p2",12,"op","chess_char_6_15_b",2,"uniequip_002_qiubai",3801.6,1,31,4,225239,0,0,107,2],
|
||||
["p2",13,"op","chess_char_6_19_b",2,"uniequip_002_blkkgt",2767,1,12,0,15,0,0,2,1],
|
||||
["p2",14,"op","chess_char_5_01_b",1,"uniequip_002_excu2",521.56,1,10,1,8,2572,480,8,1],
|
||||
["p2",15,"op","chess_char_6_17_b",2,"uniequip_002_nearl2",5928.45,1,32,0,217377,4502,431,59,2],
|
||||
["p2",16,"op","chess_char_6_12_b",1,"uniequip_002_rosmon",3117.74,1,16,0,101420,1458,124,36,2],
|
||||
["p2",17,"op","chess_char_6_13_b",1,"uniequip_002_angel2",2392.2,1,20,5,724323,2664,802,199,3],
|
||||
["p2",18,"op","chess_char_6_14_b",2,"uniequip_002_lumen",2050.92,1,22,0,0,2006,3059,33,1],
|
||||
["p2",19,"op","chess_char_6_16_b",2,"uniequip_002_halo2",1554.12,1,25,0,24405,0,0,47,2],
|
||||
["p2",20,"op","chess_char_6_18_b",2,"uniequip_002_whitw2",1541,1,6,2,78481,0,0,8,2],
|
||||
["p2",21,"op","chess_char_6_20_b",2,"uniequip_002_agoat2",1631.88,1,18,0,0,0,10363,34,1],
|
||||
["p2",12,"op","chess_char_6_15_b",2,"uniequip_002_qiubai",3801.6,1,31,1,230732,8103,1186,110,2],
|
||||
["p2",13,"op","chess_char_6_19_b",2,"uniequip_002_blkkgt",2767,1,12,1,16446,0,0,3,1],
|
||||
["p2",14,"op","chess_char_5_01_b",1,"uniequip_002_excu2",1653.08,1,10,1,6,1222,360,6,1],
|
||||
["p2",15,"op","chess_char_6_17_b",2,"uniequip_002_nearl2",6215.89,1,32,0,146091,836,0,41,2],
|
||||
["p2",16,"op","chess_char_6_12_b",1,"uniequip_002_rosmon",3117.74,1,16,3,104892,856,166,37,2],
|
||||
["p2",17,"op","chess_char_6_13_b",1,"uniequip_002_angel2",2392.2,1,20,2,743197,2712,799,206,3],
|
||||
["p2",18,"op","chess_char_6_14_b",2,"uniequip_002_lumen",2050.92,1,22,0,0,2064,2819,24,1],
|
||||
["p2",19,"op","chess_char_6_16_b",2,"uniequip_002_halo2",1554.12,1,25,2,34678,579,0,67,2],
|
||||
["p2",20,"op","chess_char_6_18_b",2,"uniequip_002_whitw2",1541,1,6,4,84942,0,0,11,2],
|
||||
["p2",21,"op","chess_char_6_20_b",2,"uniequip_002_agoat2",1631.88,1,18,0,0,0,13556,24,1],
|
||||
["-","~1","device","trap_1105_accrate",null,null,100,1,1,0,0,0,0,0,null],
|
||||
["-","~2","device","trap_1105_accrate",null,null,100,1,2,0,0,0,0,0,null],
|
||||
["-","~3","device","trap_1105_accrate",null,null,100,1,3,0,0,0,0,0,null],
|
||||
["-","~4","device","trap_1105_accrate",null,null,100,1,4,0,0,0,0,0,null],
|
||||
["p1","~1","token","token_10030_mlyss_wtrman",null,null,1557.36,1,24,0,21054,1020,0,45,1],
|
||||
["p2","~1","token","token_10019_nearl2_sword",null,null,7824,0,41,0,10835,0,0,0,null],
|
||||
["p1","~2","token","token_10030_mlyss_wtrman",null,null,1880.37,0,42,0,0,0,0,0,null],
|
||||
["p1","~1","token","token_10017_skadi2_dedant",null,null,100,0,49,0,0,0,0,0,null],
|
||||
["p1","~3","token","token_10030_mlyss_wtrman",null,null,1557.36,0,51,0,0,0,0,0,null],
|
||||
["p2","~2","token","token_10019_nearl2_sword",null,null,6000,0,52,0,10835,0,0,0,null]
|
||||
["p1","~1","token","token_10030_mlyss_wtrman",null,null,0,0,24,0,8296,1880,0,17,1],
|
||||
["p2","~1","token","token_10019_nearl2_sword",null,null,7824,0,41,0,9120,0,0,0,null],
|
||||
["p1","~2","token","token_10030_mlyss_wtrman",null,null,860.02,0,42,0,1348,1020,0,2,null],
|
||||
["p1","~1","token","token_10017_skadi2_dedant",null,null,100,0,47,0,0,0,0,0,null],
|
||||
["p1","~3","token","token_10030_mlyss_wtrman",null,null,1557.36,1,51,0,8320,0,0,18,1],
|
||||
["p2","~2","token","token_10019_nearl2_sword",null,null,6480,0,52,0,9120,0,0,0,null],
|
||||
["p1","~4","token","token_10030_mlyss_wtrman",null,null,1557.36,1,54,0,0,0,0,0,null]
|
||||
],
|
||||
"enemies": {
|
||||
"enemy_1197_sfshu_2": [2,2,0,0,28809],
|
||||
"enemy_1198_msfshu_2": [6,6,0,0,24],
|
||||
"enemy_1209_sfden_2": [2,2,0,5522,154793],
|
||||
"enemy_1209_sfden_2": [2,2,0,11003,154793],
|
||||
"enemy_1210_msfden_2": [2,2,0,0,90],
|
||||
"enemy_9021_acduml": [1,1,0,0,2000000],
|
||||
"enemy_9023_acdums": [6,5,0,8235,50]
|
||||
"enemy_9023_acdums": [6,5,0,6838,51]
|
||||
},
|
||||
"hooks": [1,52,3040,808,808,1748,1978,1530,18,26,37,29,207,23013,905,3,19,0,1,17,0,1,0],
|
||||
"events": {"atk":924,"deploy":29,"die":26,"dmg":1822,"engage":14,"fx":558,"heal":152,"skill":66,"spawn":50,"status":318},
|
||||
"fx": {"airstrike":83,"beam":5,"blink":2,"bombard":29,"bombardShell":29,"buff":3,"burst":1,"copy":1,"displace":1,"dp":3,"drone":153,"droneLock":16,"drones":2,"explode":83,"finale":1,"garrisonGrant":1,"lightning":45,"link":2,"lock":29,"lure":2,"phase":11,"radiantSword":2,"slash":11,"snow":11,"split":2,"steal":3,"storm":4,"summon":10,"sunBurst":1,"talent":4,"telegraph":3,"tide":2,"wanted":3},
|
||||
"snaps": "e7a827a7 3396c380 e8117486 1db9371a 549e90ec e1d51c02 b030ac35 77f14ab3 681cd5f3 f01f899e 1985493f"
|
||||
"hooks": [1,53,3108,805,805,1752,1974,1761,19,26,38,30,214,23319,943,4,19,0,1,18,0,1,0],
|
||||
"events": {"atk":900,"deploy":30,"die":26,"dmg":1813,"engage":16,"fx":571,"heal":175,"skill":68,"spawn":51,"status":333},
|
||||
"fx": {
|
||||
"airstrike": 76,
|
||||
"appear": 1,
|
||||
"beam": 5,
|
||||
"blink": 2,
|
||||
"bombard": 30,
|
||||
"bombardShell": 30,
|
||||
"buff": 3,
|
||||
"burst": 1,
|
||||
"copy": 2,
|
||||
"disappear": 1,
|
||||
"displace": 2,
|
||||
"dp": 3,
|
||||
"drone": 164,
|
||||
"droneLock": 13,
|
||||
"drones": 2,
|
||||
"explode": 86,
|
||||
"extraAttack": 1,
|
||||
"finale": 1,
|
||||
"garrisonGrant": 1,
|
||||
"lightning": 42,
|
||||
"link": 4,
|
||||
"lock": 30,
|
||||
"lure": 2,
|
||||
"phase": 11,
|
||||
"radiantSword": 2,
|
||||
"slash": 11,
|
||||
"snow": 11,
|
||||
"split": 2,
|
||||
"steal": 3,
|
||||
"storm": 4,
|
||||
"summon": 10,
|
||||
"sunBurst": 1,
|
||||
"talent": 4,
|
||||
"telegraph": 4,
|
||||
"tide": 3,
|
||||
"wanted": 3
|
||||
},
|
||||
"snaps": "f2137fd0 c04d9051 f10f9b96 29aa5d2c 2dae50e9 376aaf70 de60a0fc 9ba08ca9 8d4ba472 13c48fe0 cfe736f1"
|
||||
},
|
||||
"boss-boss_3-solo": {
|
||||
"about": "假想敌:管 solo pool 500000: chess_char_5_08_b chess_char_5_11_b chess_char_5_05_b chess_char_5_06_b chess_char_5_13_b chess_char_5_07_b chess_char_5_02_b chess_char_5_03_b chess_char_5_10_b chess_char_5_12_b",
|
||||
@@ -344,81 +382,81 @@
|
||||
"time": 200,
|
||||
"ticks": 6000,
|
||||
"reason": "forced",
|
||||
"killed": 10,
|
||||
"killed": 9,
|
||||
"total": 14,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": 3196571,
|
||||
"rngDraws": 664,
|
||||
"bossHpLeft": 3401883,
|
||||
"rngDraws": 496,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":10,"total":14,"perfect":false,"leaks":2,"leaksUncounted":0,"coins":0,"dmg":963373,"bossDmg":352189,"heal":27540,"deaths":16,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":false,"leaks":2,"leaksUncounted":0,"coins":0,"dmg":1055788,"bossDmg":651240,"heal":3664,"deaths":16,"layerGains":{}}
|
||||
"p1": {"killed":9,"total":14,"perfect":false,"leaks":3,"leaksUncounted":0,"coins":0,"dmg":832066,"bossDmg":272991,"heal":24644,"deaths":21,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":false,"leaks":2,"leaksUncounted":0,"coins":0,"dmg":815098,"bossDmg":525125,"heal":3151,"deaths":24,"layerGains":{}}
|
||||
},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",3439.01,1,64,2,75564,8397,115,9,1],
|
||||
["p1",2,"op","chess_char_4_01_b",2,"uniequip_002_rmixer",1398.68,1,55,0,21340,9850,1188,14,2],
|
||||
["p1",3,"op","chess_char_5_14_b",1,"none",1811.48,1,61,0,49407,6992,844,3,8],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",625.33,1,60,0,4008,10852,126,2,1],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",799.26,1,57,5,436442,3258,9173,105,19],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",967.4,1,59,0,78457,10700,423,39,4],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",0,0,19,1,107923,2424,24,135,4],
|
||||
["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",0,0,3,0,76490,1980,369,31,12],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",0,0,53,0,0,4347,15134,31,3],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",0,0,15,0,113742,3448,144,48,2],
|
||||
["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",0,0,50,0,1132,6938,196,3,1],
|
||||
["p2",12,"op","chess_char_4_04_b",1,"uniequip_002_ines",1582.42,1,52,0,198239,4882,115,197,7],
|
||||
["p2",13,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",1921.21,1,63,0,36646,5595,157,54,13],
|
||||
["p2",14,"op","chess_char_4_16_b",2,"uniequip_002_texas2",884.56,1,56,0,96817,10407,339,153,6],
|
||||
["p2",15,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",2777.6,1,58,0,224940,4816,131,57,5],
|
||||
["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",0,0,54,0,179380,3695,573,161,3],
|
||||
["p2",17,"op","chess_char_4_10_b",1,"uniequip_002_aroma",0,0,14,0,0,3546,153,0,0],
|
||||
["p2",18,"op","chess_char_4_12_b",2,"uniequip_002_glady",2232,1,62,0,64945,4286,817,75,4],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,66,1,69829,2713,724,72,22],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1189.54,1,65,1,183859,2521,459,69,13],
|
||||
["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",0,0,51,3,138264,7838,24,22,1],
|
||||
["p1",2,"op","chess_char_4_01_b",2,"uniequip_002_rmixer",0,0,5,0,16815,6179,893,10,1],
|
||||
["p1",3,"op","chess_char_5_14_b",1,"none",0,0,62,0,49407,10951,912,3,8],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",0,0,59,0,4545,12126,187,2,1],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",751.16,1,66,2,302889,4343,4325,83,13],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",0,0,60,1,81029,10790,504,39,4],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",0,0,19,0,91590,2005,24,110,3],
|
||||
["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",0,0,56,2,61149,3914,692,30,11],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",0,0,57,0,0,4410,17059,32,3],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",0,0,15,0,86379,2071,24,36,2],
|
||||
["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",0,0,50,0,0,6877,135,0,1],
|
||||
["p2",12,"op","chess_char_4_04_b",1,"uniequip_002_ines",1827.12,1,68,0,125101,9355,115,125,6],
|
||||
["p2",13,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",0,0,65,0,26395,7425,67,37,9],
|
||||
["p2",14,"op","chess_char_4_16_b",2,"uniequip_002_texas2",0,0,63,0,103636,9247,100,151,6],
|
||||
["p2",15,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",0,0,55,0,185661,6408,233,40,4],
|
||||
["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",0,0,58,0,114013,3511,389,114,2],
|
||||
["p2",17,"op","chess_char_4_10_b",1,"uniequip_002_aroma",0,0,14,0,0,3417,24,0,0],
|
||||
["p2",18,"op","chess_char_4_12_b",2,"uniequip_002_glady",0,0,64,0,61768,6768,1277,69,4],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",0,0,61,0,53260,4339,361,56,16],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",0,0,67,1,145265,3703,451,68,13],
|
||||
["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,2365,200612],"enemy_1438_dspred":[10,6,4,20724,815120],"enemy_1521_dslily":[1,0,0,80759,1003429]},
|
||||
"hooks": [1,64,6000,1204,1275,3102,3214,5218,42,48,130,128,14,32649,1247,15,15,4,1,44,0,22,8],
|
||||
"events": {"atk":1422,"deploy":49,"die":44,"dmg":3203,"engage":18,"fx":852,"heal":212,"leak":4,"skill":258,"spawn":37,"status":817},
|
||||
"enemies": {"enemy_1010_demon":[4,4,0,1913,200612],"enemy_1438_dspred":[10,5,5,22724,648434],"enemy_1521_dslily":[1,0,0,93299,798117]},
|
||||
"hooks": [1,66,6000,1002,1068,2527,2646,4783,54,61,108,107,10,27478,1110,16,15,5,1,57,0,24,2],
|
||||
"events": {"atk":1226,"deploy":51,"die":56,"dmg":2639,"engage":17,"fx":653,"heal":160,"leak":5,"skill":215,"spawn":37,"status":755},
|
||||
"fx": {
|
||||
"aoe": 22,
|
||||
"appear": 11,
|
||||
"aoe": 21,
|
||||
"appear": 9,
|
||||
"blink": 2,
|
||||
"burst": 22,
|
||||
"charge": 13,
|
||||
"counter": 14,
|
||||
"crit": 76,
|
||||
"dilemma": 5,
|
||||
"disappear": 11,
|
||||
"burst": 24,
|
||||
"charge": 9,
|
||||
"counter": 10,
|
||||
"crit": 44,
|
||||
"dilemma": 4,
|
||||
"disappear": 9,
|
||||
"displace": 28,
|
||||
"dodge": 8,
|
||||
"dodge": 2,
|
||||
"explosion": 13,
|
||||
"frostNova": 22,
|
||||
"frostNova": 16,
|
||||
"grow": 1,
|
||||
"iceSpike": 106,
|
||||
"iceSpike": 88,
|
||||
"overclock": 1,
|
||||
"pull": 4,
|
||||
"quadShot": 3,
|
||||
"ripple": 14,
|
||||
"rockfall": 14,
|
||||
"sentry": 2,
|
||||
"sermon": 2,
|
||||
"shadowWeave": 7,
|
||||
"shield": 4,
|
||||
"soul": 2,
|
||||
"sp": 15,
|
||||
"stealth": 7,
|
||||
"swordRain": 32,
|
||||
"quadShot": 2,
|
||||
"ripple": 9,
|
||||
"rockfall": 11,
|
||||
"sentry": 4,
|
||||
"sermon": 1,
|
||||
"shadowWeave": 5,
|
||||
"shield": 3,
|
||||
"soul": 3,
|
||||
"sp": 9,
|
||||
"stealth": 6,
|
||||
"swordRain": 40,
|
||||
"swordStorm": 6,
|
||||
"tentacle": 6,
|
||||
"tide": 5,
|
||||
"tornado": 4,
|
||||
"tornadoPulse": 20,
|
||||
"weightless": 4,
|
||||
"zone": 346
|
||||
"zone": 230
|
||||
},
|
||||
"snaps": "5dcb7728 ddb8e20d 3f32c53b b98db57d a6836556 681bc60e 94680558 f0805b17 5e447379 90906ab2 3cb79e2c 549d2d6d b9ccface 793eaba3 fdaab791 0167ee7d 2bdb20d3 5f084543 14b87276 5f72f51a"
|
||||
"snaps": "55a3d863 705ac967 e815eea0 1a348247 c3de7555 507edda3 3afb1adb 03717bd5 8abcf4ac b28c884f 25956015 b1d7cf6f 1c11c8b3 a11f49b2 b58e3f47 632c829c a5e0d79c da3519b8 783a1f55 c42321eb"
|
||||
},
|
||||
"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",
|
||||
@@ -614,86 +652,86 @@
|
||||
"time": 200,
|
||||
"ticks": 6000,
|
||||
"reason": "forced",
|
||||
"killed": 5,
|
||||
"killed": 4,
|
||||
"total": 6,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": 2625306,
|
||||
"rngDraws": 696,
|
||||
"bossHpLeft": 2680590,
|
||||
"rngDraws": 559,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":5,"total":6,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":1185295,"bossDmg":592165,"heal":491,"deaths":3,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":1405740,"bossDmg":762529,"heal":681,"deaths":11,"layerGains":{}}
|
||||
"p1": {"killed":4,"total":6,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":1051226,"bossDmg":642651,"heal":3896,"deaths":5,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":1151422,"bossDmg":656759,"heal":1055,"deaths":12,"layerGains":{}}
|
||||
},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",3907,1,3,2,167588,0,0,41,3],
|
||||
["p1",1,"op","chess_char_5_19_b",2,"uniequip_002_mlynar",3907,1,3,2,107043,0,0,26,3],
|
||||
["p1",2,"op","chess_char_4_01_b",2,"uniequip_002_rmixer",3537,1,1,0,0,0,0,0,0],
|
||||
["p1",3,"op","chess_char_5_14_b",1,"none",1994,1,5,1,54262,0,0,0,15],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",4654.6,1,11,1,336,0,0,1,1],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",1170,1,7,1,306280,0,491,75,12],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",1382,1,13,0,209403,0,0,73,6],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",1629,1,15,0,55551,0,0,88,3],
|
||||
["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",1611,1,50,0,325660,1611,0,84,29],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",0,0,39,0,5827,3220,0,0,0],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",1695,1,9,0,60388,0,0,48,2],
|
||||
["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",2644,1,38,0,0,12169,268,0,1],
|
||||
["p2",12,"op","chess_char_4_04_b",1,"uniequip_002_ines",0,0,43,0,212750,8595,321,245,6],
|
||||
["p1",3,"op","chess_char_5_14_b",1,"none",1994,1,5,0,38065,0,0,0,13],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",4654.6,1,11,0,2464,0,0,3,1],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",1170,1,7,2,332249,0,1482,73,12],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",1382,1,13,0,198299,0,0,75,6],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",0,0,15,0,28901,1629,0,50,2],
|
||||
["p1",8,"op","chess_char_5_22_b",1,"uniequip_002_nymph",0,0,47,0,287701,3222,0,85,28],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",0,0,49,0,2900,3220,2414,4,1],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",1695,1,9,0,53605,0,0,40,2],
|
||||
["p2",11,"op","chess_char_4_11_b",1,"uniequip_002_cathy",2644,1,46,0,0,12182,281,0,1],
|
||||
["p2",12,"op","chess_char_4_04_b",1,"uniequip_002_ines",0,0,41,0,136097,9003,729,279,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,51,0,70300,8045,25,154,6],
|
||||
["p2",15,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",2777.6,1,14,0,233538,0,0,116,6],
|
||||
["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,8,0,486378,0,0,138,2],
|
||||
["p2",14,"op","chess_char_4_16_b",2,"uniequip_002_texas2",1619,1,43,0,57804,9849,44,187,5],
|
||||
["p2",15,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",2777.6,1,14,0,239542,0,0,118,6],
|
||||
["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,8,0,456796,0,0,132,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,80747,0,0,167,6],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",0,0,47,0,123467,3978,0,112,28],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",0,0,48,0,198560,3319,67,63,12],
|
||||
["p2",18,"op","chess_char_4_12_b",2,"uniequip_002_glady",0,0,48,0,37231,4464,0,91,4],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",0,0,44,0,120920,3978,0,113,27],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1626,1,52,0,103033,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_10028_vtswd": [5,5,0,0,0],
|
||||
"enemy_10029_vtshld": [2,2,0,0,0],
|
||||
"enemy_10030_vtwand": [2,2,0,0,0],
|
||||
"enemy_10085_hllevi_2": [2,1,1,0,1035729],
|
||||
"enemy_1010_demon": [4,4,0,12169,200612],
|
||||
"enemy_9032_aclionk": [1,0,0,28767,1354694]
|
||||
"enemy_10030_vtwand": [1,1,0,0,0],
|
||||
"enemy_10085_hllevi_2": [2,0,2,0,702625],
|
||||
"enemy_1010_demon": [4,4,0,15134,200612],
|
||||
"enemy_9032_aclionk": [1,0,0,35665,1299410]
|
||||
},
|
||||
"hooks": [1,49,6000,1346,1386,2558,2587,515,27,30,138,136,0,39195,1495,3,15,1,1,23,0,6,0],
|
||||
"events": {"atk":1422,"deploy":34,"die":29,"dmg":2571,"engage":14,"fx":716,"heal":4,"leak":1,"skill":274,"spawn":37,"status":1085},
|
||||
"hooks": [1,50,6000,1291,1314,2325,2345,811,29,33,125,123,0,36836,1303,4,15,2,1,25,0,5,0],
|
||||
"events": {"atk":1354,"deploy":35,"die":31,"dmg":2324,"engage":14,"fx":616,"heal":20,"leak":2,"skill":248,"spawn":37,"status":889},
|
||||
"fx": {
|
||||
"aoe": 51,
|
||||
"aoe": 48,
|
||||
"appear": 4,
|
||||
"blink": 2,
|
||||
"burst": 6,
|
||||
"crit": 87,
|
||||
"burst": 5,
|
||||
"crit": 75,
|
||||
"dilemma": 6,
|
||||
"disappear": 4,
|
||||
"displace": 19,
|
||||
"equip": 10,
|
||||
"explosion": 12,
|
||||
"frostNova": 28,
|
||||
"equip": 9,
|
||||
"explosion": 6,
|
||||
"frostNova": 27,
|
||||
"garrisonGrant": 1,
|
||||
"iceSpike": 83,
|
||||
"iceSpike": 44,
|
||||
"overclock": 1,
|
||||
"pull": 6,
|
||||
"pull": 4,
|
||||
"quadShot": 2,
|
||||
"revive": 2,
|
||||
"ripple": 18,
|
||||
"sentry": 3,
|
||||
"shadowWeave": 4,
|
||||
"shadowWeave": 2,
|
||||
"shield": 1,
|
||||
"soul": 6,
|
||||
"sp": 20,
|
||||
"soul": 5,
|
||||
"sp": 18,
|
||||
"stealth": 6,
|
||||
"sword": 2,
|
||||
"swordRain": 49,
|
||||
"swordStorm": 6,
|
||||
"telegraph": 16,
|
||||
"tornado": 6,
|
||||
"tornadoPulse": 30,
|
||||
"sword": 4,
|
||||
"swordRain": 21,
|
||||
"swordStorm": 5,
|
||||
"telegraph": 14,
|
||||
"tornado": 4,
|
||||
"tornadoPulse": 20,
|
||||
"vest": 2,
|
||||
"weightless": 6,
|
||||
"zone": 217
|
||||
"zone": 228
|
||||
},
|
||||
"snaps": "cacb813f 39918738 3f7856dd f356867c 0eddd32e ba395ef8 34755e05 0812b2a3 e7dee4b0 6c23b2fa 776da0eb 448f9baa 07467855 055c9e65 0346714b f791a88b deff2a04 42b5f4bd cf3b3ba4 058edc46"
|
||||
"snaps": "a5dd1d4a baa7b7db 7c505a8e a4224e3d d53319fe 5b811158 536cda3e 52938381 3a7db0e7 6d0ad629 52d45c14 98ee7b24 5d759658 0207119c a227cfea dc0605ed 7a6f9851 53a205a7 a69e6594 bc79ec80"
|
||||
},
|
||||
"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",
|
||||
@@ -755,58 +793,60 @@
|
||||
"round": 14,
|
||||
"seed": 120974514,
|
||||
"waveId": "act1autochess_h07_07",
|
||||
"time": 153.2,
|
||||
"ticks": 4596,
|
||||
"time": 144.33,
|
||||
"ticks": 4330,
|
||||
"reason": "cleared",
|
||||
"killed": 16,
|
||||
"total": 16,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": 0,
|
||||
"rngDraws": 616,
|
||||
"rngDraws": 666,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":16,"total":16,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":657821,"bossDmg":550703,"heal":25237,"deaths":1,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":1815159,"bossDmg":1449297,"heal":19812,"deaths":5,"layerGains":{}}
|
||||
"p1": {"killed":16,"total":16,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":630171,"bossDmg":586902,"heal":20762,"deaths":0,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":1842809,"bossDmg":1413098,"heal":34015,"deaths":0,"layerGains":{}}
|
||||
},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_6_03_b",2,"uniequip_002_yu",3430,1,5,0,0,0,0,0,0],
|
||||
["p1",2,"op","chess_char_6_06_b",2,"uniequip_002_pepe",2939,1,7,0,0,0,0,0,0],
|
||||
["p1",3,"op","chess_char_6_07_b",2,"uniequip_002_siege2",3101,1,11,0,0,0,0,0,0],
|
||||
["p1",4,"op","chess_char_6_01_b",2,"uniequip_002_lemuen",1470,1,1,1,191195,0,0,83,0],
|
||||
["p1",5,"op","chess_char_6_02_b",2,"uniequip_002_sbell2",1933,1,9,0,0,0,0,0,0],
|
||||
["p1",6,"op","chess_char_6_04_b",2,"uniequip_002_skadi2",1598,1,17,0,39305,17679,1300,0,4],
|
||||
["p1",7,"op","chess_char_6_05_b",2,"uniequip_002_pasngr",1442,1,3,0,0,0,0,0,0],
|
||||
["p1",8,"op","chess_char_6_08_b",2,"uniequip_002_reed2",1668,1,13,0,145558,481,23170,106,3],
|
||||
["p1",9,"op","chess_char_6_09_b",0,"uniequip_002_cello",1322,1,15,1,214113,862,0,40,40],
|
||||
["p1",10,"op","chess_char_6_11_b",2,"uniequip_002_mlyss",0,0,19,0,54307,12010,767,92,3],
|
||||
["p1",1,"op","chess_char_6_03_b",2,"uniequip_002_yu",4472.72,1,5,0,0,0,0,0,0],
|
||||
["p1",2,"op","chess_char_6_06_b",2,"uniequip_002_pepe",3832.46,1,7,0,0,0,0,0,0],
|
||||
["p1",3,"op","chess_char_6_07_b",2,"uniequip_002_siege2",4043.7,1,11,0,0,0,0,0,0],
|
||||
["p1",4,"op","chess_char_6_01_b",2,"uniequip_002_lemuen",1916.88,1,1,1,185852,0,0,78,0],
|
||||
["p1",5,"op","chess_char_6_02_b",2,"uniequip_002_sbell2",2520.63,1,9,0,0,0,0,0,0],
|
||||
["p1",6,"op","chess_char_6_04_b",2,"uniequip_002_skadi2",2083.79,1,17,0,32940,15589,1256,0,4],
|
||||
["p1",7,"op","chess_char_6_05_b",2,"uniequip_002_pasngr",1880.37,1,3,0,0,0,0,0,0],
|
||||
["p1",8,"op","chess_char_6_08_b",2,"uniequip_002_reed2",2175.07,1,13,0,113952,0,17614,101,3],
|
||||
["p1",9,"op","chess_char_6_09_b",0,"uniequip_002_cello",1723.89,1,15,1,193562,539,0,38,38],
|
||||
["p1",10,"op","chess_char_6_11_b",2,"uniequip_002_mlyss",2468.47,1,19,0,81362,11533,1148,139,4],
|
||||
["p1",11,"token","token_10017_skadi2_dedant",null,null,130.4,0,22,0,0,0,0,0,null],
|
||||
["p1",12,"token","token_10030_mlyss_wtrman",null,null,0,0,20,0,5792,2876,0,17,1],
|
||||
["p2",13,"op","chess_char_6_15_b",2,"uniequip_002_qiubai",2913.79,1,26,7,380120,3165,0,142,3],
|
||||
["p2",14,"op","chess_char_6_19_b",2,"uniequip_002_blkkgt",2767,1,2,0,0,0,0,0,0],
|
||||
["p2",15,"op","chess_char_5_01_b",1,"uniequip_002_excu2",2314,1,6,0,0,0,0,0,0],
|
||||
["p2",16,"op","chess_char_6_17_b",2,"uniequip_002_nearl2",4556.87,1,31,1,173246,2773,0,63,3],
|
||||
["p2",17,"op","chess_char_6_12_b",1,"uniequip_002_rosmon",0,0,51,3,220347,11041,0,35,4],
|
||||
["p2",18,"op","chess_char_6_13_b",1,"uniequip_002_angel2",2192.85,1,21,3,701971,6761,5337,235,5],
|
||||
["p2",19,"op","chess_char_6_14_b",2,"uniequip_002_lumen",1899,1,8,0,0,0,0,0,0],
|
||||
["p2",20,"op","chess_char_6_16_b",2,"uniequip_002_halo2",1439,1,12,0,110676,0,0,89,3],
|
||||
["p2",21,"op","chess_char_6_18_b",2,"uniequip_002_whitw2",1541,1,14,1,228800,0,0,62,2],
|
||||
["p2",22,"op","chess_char_6_20_b",2,"uniequip_002_agoat2",0,0,49,0,0,4230,14475,21,1],
|
||||
["p1","~1","token","token_10030_mlyss_wtrman",null,null,0,0,34,0,4801,1724,0,8,null],
|
||||
["p1","~2","token","token_10030_mlyss_wtrman",null,null,0,0,41,0,519,1322,0,2,1],
|
||||
["p1",12,"token","token_10030_mlyss_wtrman",null,null,0,0,20,0,5321,2876,0,18,1],
|
||||
["p2",13,"op","chess_char_6_15_b",2,"uniequip_002_qiubai",4502.02,1,26,4,275746,0,0,93,3],
|
||||
["p2",14,"op","chess_char_6_19_b",2,"uniequip_002_blkkgt",3608.17,1,2,0,0,0,0,0,0],
|
||||
["p2",15,"op","chess_char_5_01_b",1,"uniequip_002_excu2",3017.46,1,6,0,0,0,0,0,0],
|
||||
["p2",16,"op","chess_char_6_17_b",2,"uniequip_002_nearl2",7020.72,1,31,2,91620,12855,0,29,3],
|
||||
["p2",17,"op","chess_char_6_12_b",1,"uniequip_002_rosmon",2898.35,1,16,4,305737,8640,0,53,3],
|
||||
["p2",18,"op","chess_char_6_13_b",1,"uniequip_002_angel2",2888.36,1,21,4,841731,3871,1843,250,5],
|
||||
["p2",19,"op","chess_char_6_14_b",2,"uniequip_002_lumen",2476.3,1,8,0,0,0,0,0,0],
|
||||
["p2",20,"op","chess_char_6_16_b",2,"uniequip_002_halo2",1876.46,1,12,0,108450,0,0,89,3],
|
||||
["p2",21,"op","chess_char_6_18_b",2,"uniequip_002_whitw2",2009.46,1,14,0,219525,0,0,55,2],
|
||||
["p2",22,"op","chess_char_6_20_b",2,"uniequip_002_agoat2",1970.34,1,18,0,0,1120,32171,49,2],
|
||||
["p1","~1","token","token_10030_mlyss_wtrman",null,null,893.08,0,34,1,6541,1574,743,16,null],
|
||||
["p1","~2","token","token_10030_mlyss_wtrman",null,null,0,0,41,0,3698,2070,0,8,1],
|
||||
["p1","~1","token","token_10017_skadi2_dedant",null,null,100,0,42,0,0,0,0,0,null],
|
||||
["p1","~3","token","token_10030_mlyss_wtrman",null,null,0,0,45,0,2231,1322,0,7,1],
|
||||
["p1","~2","token","token_10017_skadi2_dedant",null,null,100,0,50,0,0,0,0,0,null]
|
||||
["p1","~3","token","token_10030_mlyss_wtrman",null,null,0,0,46,0,2081,1322,0,6,1],
|
||||
["p1","~2","token","token_10017_skadi2_dedant",null,null,130.4,0,48,0,0,0,0,0,null],
|
||||
["p1","~4","token","token_10030_mlyss_wtrman",null,null,1048.86,1,49,0,3949,1128,0,11,1],
|
||||
["p1","~5","token","token_10030_mlyss_wtrman",null,null,1723.89,1,50,0,912,0,0,2,null]
|
||||
],
|
||||
"enemies": {
|
||||
"enemy_1067_snslime": [8,8,0,12674,111795],
|
||||
"enemy_1081_sotisd": [4,4,0,5052,257989],
|
||||
"enemy_1067_snslime": [8,8,0,9423,111795],
|
||||
"enemy_1081_sotisd": [4,4,0,708,257989],
|
||||
"enemy_1249_lysdb_2": [4,4,0,0,103196],
|
||||
"enemy_9033_acdeer": [1,1,0,31851,2000000]
|
||||
"enemy_9033_acdeer": [1,1,0,32950,2000000]
|
||||
},
|
||||
"hooks": [1,49,4596,1011,1011,2649,2941,1623,27,32,74,70,182,26660,1344,6,17,0,1,26,0,14,0],
|
||||
"events": {"atk":1140,"deploy":32,"die":32,"dmg":2682,"engage":14,"fx":420,"heal":235,"skill":144,"spawn":44,"status":502},
|
||||
"fx": {"airstrike":63,"beam":3,"blink":2,"burst":14,"column":39,"copy":3,"dp":3,"drone":234,"droneLock":10,"drones":2,"explode":7,"garrisonGrant":1,"link":3,"phase":1,"scorchBurst":6,"shieldBreak":4,"snow":5,"split":1,"steal":4,"sunBurst":4,"talent":4,"tide":4,"wanted":3},
|
||||
"snaps": "527acd3d 92bc6ca9 876af6f6 ea8c9a0e 8e9b8505 e81eae9b 0162cc52 7bfd274c a0189411 57757a4a eef674d5 623bffab 79e4a2a5 f38fb5dc 21a35db2 55c0fad0"
|
||||
"hooks": [1,48,4330,1042,1042,2602,2869,2311,20,26,74,65,201,28101,1210,4,17,0,1,19,0,10,0],
|
||||
"events": {"atk":1213,"deploy":31,"die":26,"dmg":2635,"engage":16,"fx":419,"heal":416,"skill":139,"spawn":46,"status":432},
|
||||
"fx": {"airstrike":72,"beam":3,"blink":2,"burst":10,"column":36,"copy":4,"dp":4,"drone":235,"droneLock":12,"drones":2,"explode":6,"garrisonGrant":1,"link":1,"phase":1,"shieldBreak":4,"snow":5,"split":2,"steal":5,"sunBurst":4,"talent":4,"tide":4,"wanted":2},
|
||||
"snaps": "3159bc57 5a868dfc 1317f752 766b1ac3 ae4704fd 8b8561f0 0cf3e025 1cc4fae8 2ab8c69e 1c36a709 27dce433 db53cc68 922ea938 44d1d981 4325d4fb"
|
||||
},
|
||||
"boss-boss_7-solo": {
|
||||
"about": "“萨米的意志” solo pool 500000: chess_char_5_08_b chess_char_5_11_b chess_char_5_05_b chess_char_5_06_b chess_char_5_13_b chess_char_5_07_b chess_char_5_02_b chess_char_5_03_b chess_char_5_10_b chess_char_5_12_b",
|
||||
@@ -1179,62 +1219,63 @@
|
||||
"killed": 12,
|
||||
"total": 12,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": 6820572,
|
||||
"rngDraws": 999,
|
||||
"bossHpLeft": 6905955,
|
||||
"rngDraws": 1001,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":12,"total":12,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":378748,"bossDmg":211503,"heal":8474,"deaths":1,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":735184,"bossDmg":567925,"heal":8676,"deaths":6,"layerGains":{}}
|
||||
"p1": {"killed":12,"total":12,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":358279,"bossDmg":203660,"heal":4886,"deaths":1,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":670269,"bossDmg":490385,"heal":8820,"deaths":8,"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,18743,6114,2287,41,1],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",1989,1,11,2,158666,0,5115,25,5],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",1382,1,19,2,60570,957,0,64,6],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",1629,1,48,0,95409,3032,116,219,6],
|
||||
["p1",4,"op","chess_char_5_17_b",1,"uniequip_002_f12yin",2738,1,17,1,24417,1893,995,40,1],
|
||||
["p1",5,"op","chess_char_5_15_b",1,"uniequip_002_thorn2",1989,1,11,2,129281,0,2712,20,4],
|
||||
["p1",6,"op","chess_char_5_20_b",2,"uniequip_002_aglina",1382,1,19,1,62301,949,20,64,6],
|
||||
["p1",7,"op","chess_char_5_21_b",1,"uniequip_002_sntlla",1629,1,51,2,105321,2848,231,226,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,957,1,1],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",1695,1,13,0,45360,0,0,30,3],
|
||||
["p1",9,"op","chess_char_5_23_b",1,"uniequip_002_reckpr",1610,1,7,0,0,0,929,2,1],
|
||||
["p1",10,"op","chess_char_4_02_b",2,"uniequip_002_mostma",1695,1,13,0,36960,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,113544,5807,112,174,5],
|
||||
["p2",13,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",0,0,47,0,7612,5859,855,7,3],
|
||||
["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",1135.93,1,18,5,202412,2387,745,84,5],
|
||||
["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,12,2,158149,0,0,271,4],
|
||||
["p2",17,"op","chess_char_4_10_b",1,"uniequip_002_aroma",0,0,20,1,9410,2337,673,8,2],
|
||||
["p2",18,"op","chess_char_4_12_b",2,"uniequip_002_glady",1142.27,1,22,0,50507,7380,6290,122,5],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,4,0,29201,0,0,31,10],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1626,1,8,2,55371,0,0,22,6],
|
||||
["p2",12,"op","chess_char_4_04_b",1,"uniequip_002_ines",2149,1,54,0,113346,5807,112,174,5],
|
||||
["p2",13,"op","chess_char_4_07_b",1,"uniequip_002_bpipe",0,0,49,0,4,5859,855,2,2],
|
||||
["p2",14,"op","chess_char_4_16_b",2,"uniequip_002_texas2",1619,1,50,0,42778,7059,344,190,5],
|
||||
["p2",15,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",1268.93,1,18,5,204995,2254,745,84,5],
|
||||
["p2",16,"op","chess_char_4_06_b",1,"uniequip_002_kroos2",1561,1,12,3,160077,0,0,271,4],
|
||||
["p2",17,"op","chess_char_4_10_b",1,"uniequip_002_aroma",1449.33,1,20,0,9408,888,673,8,2],
|
||||
["p2",18,"op","chess_char_4_12_b",2,"uniequip_002_glady",1532.27,1,22,0,50178,6810,6090,122,4],
|
||||
["p2",19,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,4,1,30075,0,0,34,11],
|
||||
["p2",20,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1626,1,8,1,59410,0,0,24,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,5169,173864],
|
||||
"enemy_9010_acpupp": [2,2,0,3869,160520],
|
||||
"enemy_9021_acduml_2": [1,0,0,343,779428],
|
||||
"enemy_9022_acdumm": [1,0,0,453,0],
|
||||
"enemy_9023_acdums": [12,12,0,18180,120]
|
||||
"enemy_1402_tgshd_2": [2,2,0,6652,173864],
|
||||
"enemy_9010_acpupp": [2,2,0,1619,160520],
|
||||
"enemy_9021_acduml_2": [1,0,0,0,694045],
|
||||
"enemy_9022_acdumm": [1,0,0,877,0],
|
||||
"enemy_9023_acdums": [12,12,0,19360,120]
|
||||
},
|
||||
"hooks": [1,49,6000,1174,1314,2552,2708,5457,23,25,64,60,0,30019,1462,5,18,0,1,25,0,6,0],
|
||||
"events": {"atk":1269,"deploy":29,"die":25,"dmg":2697,"engage":14,"fx":970,"heal":49,"skill":124,"spawn":42,"status":564},
|
||||
"hooks": [1,52,6000,1110,1260,2516,2697,5451,25,27,65,62,0,30164,1499,5,18,0,1,27,0,7,1],
|
||||
"events": {"atk":1215,"deploy":32,"die":27,"dmg":2691,"engage":14,"fx":1023,"heal":31,"skill":127,"spawn":42,"status":602},
|
||||
"fx": {
|
||||
"beam": 13,
|
||||
"blink": 2,
|
||||
"burst": 6,
|
||||
"charge": 3,
|
||||
"crit": 126,
|
||||
"burst": 7,
|
||||
"charge": 2,
|
||||
"crit": 135,
|
||||
"dilemma": 5,
|
||||
"dodge": 1,
|
||||
"ember": 2,
|
||||
"explode": 191,
|
||||
"explode": 195,
|
||||
"explosion": 6,
|
||||
"expose": 182,
|
||||
"frostNova": 10,
|
||||
"expose": 200,
|
||||
"frostNova": 11,
|
||||
"garrisonGrant": 1,
|
||||
"iceSpike": 182,
|
||||
"iceSpike": 190,
|
||||
"levitate": 5,
|
||||
"phase": 33,
|
||||
"pull": 4,
|
||||
@@ -1245,19 +1286,18 @@
|
||||
"shield": 1,
|
||||
"shieldBreak": 1,
|
||||
"slippery": 2,
|
||||
"sp": 1,
|
||||
"splash": 2,
|
||||
"stealth": 5,
|
||||
"summon": 8,
|
||||
"swordRain": 7,
|
||||
"swordStorm": 2,
|
||||
"swordRain": 37,
|
||||
"swordStorm": 5,
|
||||
"telegraph": 2,
|
||||
"tornado": 5,
|
||||
"tornado": 4,
|
||||
"tornadoPulse": 20,
|
||||
"weightless": 6,
|
||||
"zone": 95
|
||||
"zone": 76
|
||||
},
|
||||
"snaps": "2d13cea7 e9e5501a 1907eb82 5ba81caf 5ee8b538 524f35a5 1425a1ad a9b7b4be 5b58af92 8c83af8a 2d164054 4c1fa05e ab022cf5 36aac114 a5eadb46 3f794fc7 1c295490 94ffeeec 47451168 f6114af3"
|
||||
"snaps": "b2c8103f 91059bdb 14558c87 9a8c7aca 84358f47 3307ce1d c68d6ed2 f8846121 9987dee1 d785c1eb 47303c18 d7e164d1 f3923884 43b344b2 01ede284 10404dbc a9d562ec 8a8c176e 62612be1 a62fd897"
|
||||
},
|
||||
"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",
|
||||
|
||||
+15
-15
@@ -2460,18 +2460,18 @@
|
||||
"total": 65,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": null,
|
||||
"rngDraws": 299,
|
||||
"rngDraws": 300,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {"p1":{"killed":27,"total":65,"perfect":false,"leaks":38,"leaksUncounted":0,"coins":4,"dmg":520678,"bossDmg":0,"heal":2131,"deaths":24,"layerGains":{}}},
|
||||
"players": {"p1":{"killed":27,"total":65,"perfect":false,"leaks":38,"leaksUncounted":0,"coins":4,"dmg":532691,"bossDmg":0,"heal":2131,"deaths":24,"layerGains":{}}},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_4_01_a",1,null,0,0,3,0,1745,2638,0,25,1],
|
||||
["p1",2,"op","chess_char_4_17_a",2,null,0,0,6,0,3603,2849,0,5,1],
|
||||
["p1",3,"op","chess_char_4_18_a",2,null,0,0,8,1,13840,3440,573,16,1],
|
||||
["p1",1,"op","chess_char_4_01_a",1,null,0,0,3,0,2694,2638,0,47,1],
|
||||
["p1",2,"op","chess_char_4_17_a",2,null,0,0,6,0,10584,2849,0,16,1],
|
||||
["p1",3,"op","chess_char_4_18_a",2,null,0,0,8,1,15145,3440,573,17,1],
|
||||
["p1",4,"op","chess_char_4_04_a",2,null,0,0,94,2,31268,7040,0,24,4],
|
||||
["p1",5,"op","chess_char_4_07_a",2,null,0,0,83,0,6702,7655,0,9,1],
|
||||
["p1",6,"op","chess_char_4_16_a",1,null,857.6,1,96,3,66532,8961,1097,21,9],
|
||||
["p1",7,"op","chess_char_4_09_a",2,null,969.81,1,87,0,19950,1702,0,21,1],
|
||||
["p1",8,"op","chess_char_3_19_b",1,"none",0,0,4,7,58645,1648,0,68,1],
|
||||
["p1",8,"op","chess_char_3_19_b",1,"none",0,0,4,7,61423,1648,0,72,1],
|
||||
["p1",9,"op","chess_char_3_21_b",1,"uniequip_004_archet",0,0,95,6,166061,3180,0,86,9],
|
||||
["p1",10,"op","chess_char_4_02_a",1,null,0,0,86,2,57313,2856,0,16,1],
|
||||
["p1",11,"op","chess_char_4_12_a",1,null,0,0,11,4,37850,2214,460,36,1],
|
||||
@@ -2482,21 +2482,21 @@
|
||||
],
|
||||
"enemies": {
|
||||
"enemy_1005_yokai": [24,12,12,0,46985],
|
||||
"enemy_1005_yokai_2": [27,10,13,8055,87836],
|
||||
"enemy_1005_yokai_3": [6,1,4,19583,242123],
|
||||
"enemy_1005_yokai_2": [27,10,13,8037,87836],
|
||||
"enemy_1005_yokai_3": [6,1,4,18726,244901],
|
||||
"enemy_10065_ftzlc": [1,1,0,0,16339],
|
||||
"enemy_10162_mnctpt": [1,0,1,7074,47489],
|
||||
"enemy_10162_mnctpt": [1,0,1,6996,48110],
|
||||
"enemy_1119_vofsd": [1,1,0,170,47298],
|
||||
"enemy_1196_msfyin_2": [1,1,0,0,3],
|
||||
"enemy_1254_lypa_2": [1,0,1,8330,24869],
|
||||
"enemy_1367_dseed": [1,0,1,0,1582],
|
||||
"enemy_1254_lypa_2": [1,0,1,9283,32765],
|
||||
"enemy_1367_dseed": [1,0,1,0,2300],
|
||||
"enemy_1517_xi": [1,0,1,6203,6145],
|
||||
"enemy_9016_acstmr": [1,1,0,0,8]
|
||||
},
|
||||
"hooks": [1,95,5100,608,608,959,992,323,53,86,31,31,15,9466,320,13,65,33,1,63,0,2,21],
|
||||
"events": {"atk":684,"bounty":2,"deploy":28,"die":53,"dmg":984,"engage":12,"fx":104,"heal":2,"leak":33,"skill":62,"spawn":80,"status":184},
|
||||
"fx": {"beam":4,"buff":2,"burst":2,"coldWind":1,"dodge":21,"dp":1,"explode":1,"iceSpike":1,"overclock":1,"overload":1,"palsy":1,"revive":3,"ripple":1,"rockfall":1,"sentry":6,"shadowWeave":14,"shield":7,"shieldBreak":7,"stone":1,"swordStorm":9,"telegraph":3,"volley":9,"wake":1,"wolfShadow":2,"wolfShadowLost":3,"zone":1},
|
||||
"snaps": "b82d753d 9cf4ba99 fcad021b 654db731 d77e82d7 9f8f33f9 017d7bbc 96acf49e 6fb2359b 1c86069b 9ddc6975 6ce15810 e8f0b7f7 11dd93da a2b48e05 18e63893 1e4df384"
|
||||
"hooks": [1,95,5100,640,640,1007,1043,323,53,86,31,31,21,9432,318,15,65,33,1,63,0,2,21],
|
||||
"events": {"atk":725,"bounty":2,"deploy":28,"die":53,"dmg":1036,"engage":12,"fx":105,"heal":2,"leak":33,"skill":62,"spawn":80,"status":184},
|
||||
"fx": {"beam":4,"block":1,"buff":2,"burst":2,"coldWind":1,"dodge":21,"dp":1,"explode":1,"iceSpike":1,"overclock":1,"overload":1,"palsy":1,"revive":3,"ripple":1,"rockfall":1,"sentry":6,"shadowWeave":14,"shield":7,"shieldBreak":7,"stone":1,"swordStorm":9,"telegraph":3,"volley":9,"wake":1,"wolfShadow":2,"wolfShadowLost":3,"zone":1},
|
||||
"snaps": "b82d753d 9cf4ba99 fcad021b 654db731 bb6a3dff 378d28e1 47603a0d 144d6b03 599f2544 522197cf 268e0f04 30a6df9f d0f8683b 3c7d6f84 a71a9576 12b08084 610181fa"
|
||||
},
|
||||
"roster-041": {
|
||||
"about": "pass 2 band 5: chess_char_4_23_a chess_char_4_01_b chess_char_4_19_a chess_char_4_22_a chess_char_4_04_b chess_char_4_07_b chess_char_4_09_b chess_char_4_20_a chess_char_4_24_a chess_char_4_25_a chess_char_4_02_b chess_char_4_12_b",
|
||||
|
||||
Reference in new issue
Block a user