The three PRs patched the same snapshot and HUD lines (Grok's review: do not merge three diffs), so this is one design
built from their code and tests; IceCodeNew is the commit author (#303, #378), Convey123 co-author (#383).
- b.snap gains three optional, display-only lists beside the unchanged 9-field tuples (snapshot.js ammoView / wolfView /
negView, called from battle/events.js snapshot(); a living, deployed, visible ally, only when it has one):
ammo [[id, rounds left, magazine]] (whole rounds; the magazine is the activation's real total that unitTuple's SP
fraction runs on, extras and refills included), wolves [[id, 狼影 left, talent maximum]] (mem.shadows of the new
mem.wolfCapacity, set by tokens.js wolfPack and the managed vigil kit), neg [[id, fill]] (unit.negFill(), a function
op-hsgma2.js sets: the pool is read when the snapshot is taken, no per-tick sync). UnitInfo.ammoSkill (an ally whose
skill is an ammo magazine) is known from the first appearance: fx events run before the frame's sample, so the aura
cannot wait for the first ammo row.
- render/interp.js keeps the lists per snapshot (malformed rows / unknown ids dropped) and sample() hands them out from the
older snapshot like flags (they step with the skill flag); render/units.js draws them: the ammo magazine replaces the
SP bar (a cell per round, thin cuts, exact fill, no cuts under 2 px a cell), a row of diamonds under the bars for the
wolves (the element gauge row moves below), the red bar over the drained HP bar for the pool. An ammo skill draws no
standing aura (rings.js _aura; the activation burst stays).
- PR #378's wolf-head avatars are NOT taken: the count is data (the talent text 至多3只, mem.shadows), the HUD art of the
official counter is in no game data we have, so the pips are plain diamonds [ASSUMED look]. The PRs' own tests are
folded in and extended (test/sim/hud-readouts.test.js, test/render/hud-readouts.test.js, op_hsgma2.test.js).
- Docs: network.md, SIM.md §9, client.md, PLAYING.md, types/core.js.
- Golden: unchanged (283 scenarios; the canon hashes units / down / elem only, no sim state moved).
- Tests: 4 + 14 new + 1 in op_hsgma2 (12), all fail on the parent; 344 related tests pass; lint 0 errors, typecheck,
check:imports, docs tests.
Co-authored-by: Convey123 <Convey123@users.noreply.github.com>
- server/sim/detmath.js: hypot (sqrt of the squares, rescaled outside 2^±500), powi (integer powers in double-double,
one rounding), sin / cos (fdlibm 5.3) and atan2 (fdlibm / FreeBSD msun) built only from correctly rounded IEEE
operations; the sim's Math.hypot / sin / cos / atan2 / pow calls go through it (65 files); eslint.config.js forbids
the approximated Math functions under server/sim and test/sim/detmath.test.js scans for them.
- sin / cos / atan2 are the algorithms V8 runs in Node, so the server's results stay; only hypot differs from V8's.
Golden: 2 moved — diy-027 (a hypot distance, damage +80) and coop3-ABYSS-5 (a later card pick from round 9, same end).
- Applied unchanged after review (Grok static review: MERGE; the diff read in full: no network, no new dependency).
- Tests: broad node --test 5155 / 5155 with the new file tracked (detmath 7 / 7, package 10 / 10); lint 0 errors,
typecheck, check:imports.
docs/history/0.2.0.md: §25.17 in §25's style (seen / official / cause / now / [ASSUMED] / golden / tests) and the intro list;
docs/design/engine.md cites §25.17.5 for the in-place revive; the header comments of 星熊, 斩业星熊, 年 and 余 say "every enemy
damage instance" instead of "every attack". No code change.
The report's 退行的潮涌者 is the 巢涌者 (深溟 / 富营养的巢涌者 in this mode): no normal attack, its talent hurts every operator in
range once a second. Official (ArknightsGameData buff_template_data): its pulse is an AdvancedApplyDamage with the enemy as
source (enemy_dsubrl_aoe[aura]); the counters fire on ON_TAKE_DAMAGE — philae_s_2 with no filter, inverse_damage (星熊 S2),
inverse_damage[magic] + nian_s_2 (年 S2), bubble_s_2 / bubble_t_1 (泡泡), vendla_s_2 (刺玫), yu_s_1[inverse_damage] (余 S1),
hsgma2_s_1 / hsgma2_e_003_tr_take (斩业星熊), mlynar_t_2[inverse] (玛恩纳) on a source of the other side; 棘刺 S2 (普通伤害
filter) and 信仰搅拌机 S3 already took any damage. Cause: the kits required dmg.isAttack. Now kits/shared/tier1.js
byEnemyAttack = any enemy damage instance but a 流失, an element 损伤, 无来源 damage or another counter / reflection (tags
'counter' / 'reflect'); 菲莱 S2 any instance but a 流失 or a counter. test/content/op_nian.test.js pinned "a non-attack hit
returns nothing" for 年 S2 — updated on purpose (answered now; a 流失 still is not).
Golden: 19 scenarios where an enemy's non-attack damage (skills, pulses, areas) reached one of these operators — their counter
now answers it (more damage, fx thorns / aoe): roster-002, -005, -008, -010, -012, -016, -033, -044; bond-lateranoShip-low;
fields boss-boss_2-solo, boss-boss_4-pair, boss-boss_4-solo, hidden-boss_8-pair, hidden-boss_8-solo; matches solo-FUNNY-1,
solo-FUNNY-2, coop4-ABYSS-7, coop2-ABYSS-10-boosted; diy-051. Tests: test/sim/feedback5-counters-any-damage.test.js (6; 5
fail on the parent, the first checks the 巢涌者 never attacks). Docs: docs/SIM.md (re-entrancy rule).
tools/build-data.mjs classifyAttack: a trait whose 法术伤害 comes only "技能开启时" keeps
the normal attack's phys (display / AI only — her kit already attacks physically
off-skill). Regenerated offline: 3 paths, the three forms of char_1044_hsgma2 dmgType
arts -> phys. Golden: no scenario moved.
Kits server/sim/content/kits/ops/op-nian.js, op-hsgma2.js and op-thumpy.js, appended to OPERATOR_KIT_FILES; tests
test/content/op_nian.test.js (10), op_hsgma2.test.js (11), op_thumpy.test.js (12). Kit-local code only: no engine or other
shared file changed.
- 年: S1 锡灼 (DEF / ATK, arts attacks), S2 铜印 (no attack, DEF, block +1, counter + 3 s silence on every enemy attack),
S3 铁御 (ATK; the other allied operators of her x-2: DEF, block +1, 抵抗); 积甲成山 (编入队伍时: her team's 重装 max HP
+16 / 21 %), 干明可鉴 (3 护盾 layers per deployment; PRO-X Lv3: ATK / DEF +7 % and +3 SP per broken layer); PRO-X DEF +20 %
while blocking, PRO-Y block 4 and at Lv3 max HP / healing received +4 % per 重装 on the field (≤ 3).
- 斩业星熊: physical attacks with no skill on, arts while one runs (the data's dmgType is the skill-on one); S1 恶业苦果
(toggle, fired at full SP: an AUTO self buff), S2 无始无明 (the throw, then the 365° shield: PRTS's 1.2 tile start, 90°/s,
−80 % near a target, 0.5 s pulses with 停顿 and the heal through 禁疗), S3 地狱变相 (x-2, HP / ATK, 2 hits on ≤ 2, air too;
a 主动关闭 keeps it 11 s as the 临死模式 — 4 hits, 阻回 / 沉默 / 不死, allies of her range 不死 with the excess as her 流失, then
a withdrawal; no strategy of the mode closes it since 下半); 业火 我执 (negative HP to 200 %, 禁疗, the 5 %/s
生命回复速度 after 5 s quiet), 鬼之架势 坚忍 (AST-X Lv3: full at 50 %, +15 % ATK); AST-X extra / returned 10 % ATK arts.
- 珊比: S1 (every blocked enemy struck and pushed radially with 小力), S2 (PRTS's glue order on her tile + 4, 0.7 s pulses of
停顿 then the hit, the 15 % 侵蚀 rider on other operators' physical damage), S3 (block +2, the 4-tile conveyor at 0.8 × 20 /
30 tile/s for unblocked ground enemies of 重量 ≤ 4, 1 s damage on her tile + 4 ahead + blocked, −30 DEF on a 侵蚀 burst
there); 探险理论 (元素损伤 taken ×0.85; 10 % ATK 侵蚀 per physical hit, or the burst −1 s), 坚硬脚板 (marks, DEF / ATK stack
and one growing barrier ≤ 300 % max HP); PRP-X ×1.15 element damage while blocking.
Golden: only test/golden/diy.json moved — diy-049 / 050 now field 年 (tiers 5 / 6), diy-051 斩业星熊 tier 5, diy-052 斩业星熊
tier 6 and 珊比's tier-5 normal entries, diy-053 the rest of 珊比 (every form × module × skill); the prototypes and reserves
moved from diy-049 … 052 to diy-054 … 057 (same packing). diy-001 … 048 and the roster, bonds, fields, matches and standins
families are unchanged.