feedback1 final: six 重装 skills cast with an enemy in range, a deliberate deviation from the official TAKE_DAMAGE row (GitHub issue #4, PR #12)

The owner's decision (2026-10-03, after community feedback): 深巡 S2 行动能力剥夺, 雷蛇 S2 反击电弧, 号角 S2 暴风号令
and S3 终极防线, 灰毫 S1 攻击力强化·γ型 and S2 专注轰击 take the basic strategy (DEFAULT) instead of the 下半 TANK class
row's TAKE_DAMAGE. Every other MANUAL 重装 skill, 深巡 S1 included, still waits for a hit.

- tools/build-data.mjs TRIGGER_DEVIATIONS: a small table keyed by the normal chess id and the skill id (the elite
  follows through baseId), never by the skill id alone - 灰毫 S1 is the generic skcom_atk_up[3]. resolveTrigger applies
  it last; rawRule keeps the official TAKE_DAMAGE; validateAll fails the build when an entry no longer meets a
  TAKE_DAMAGE row. data/chess.json rebuilt with --offline: exactly the 12 records' rule changes.
- PR #12's kit lines (trigger 'DEFAULT' on 深巡 / 雷蛇 S2) stay and agree with the data; their comments and tests now
  give this reason instead of the community summary.
- Tests: test/sim/feedback1-tank-triggers.test.js (the data, kit = data, a real battle on 战场#01(下半) in which each of
  the six casts with an enemy in range before any hit and each of the other 46 MANUAL 重装 records casts on the first
  hit); data.test.js trigger expectations; the 灰毫 / 号角 kit tests follow; docs-consistency.
- Docs: DESIGN §21.29 (new), §5.6, §19.2, §20.2, §21.20 (settled row), §21.23; DATA, SIM, PLAYING, CHANGELOG 0.1.1;
  research 03 §1.4 drops the arknights.wiki.gg "offensive / defensive" summary and records the activity_table history
  (上半 had no TANK row, 下半 added it) and this deviation; research 00-INDEX.
This commit is contained in:
sganggs committed 2026-10-03 19:13:35 +08:00
1 parent e6ab4e1ff8
commit 2dba6da598
20 files changed
+325 -58

No files matched your search

+6 -4
View File
@@ -364,7 +364,7 @@ test('史尔特尔 S3 黄昏: full heal, max HP +5000, ATK +210 %, range +2, 3 t
});
// ------------------------------------------------------------------------------------------------------------------
test('号角 S3: ATK +25 %, BAT −1.2 s, then overload ATK +50 % with HP loss; T1 Defenders ATK +20 %; T2 血战', () => {
test('号角 S3: cast with an enemy in range (DEFAULT, DESIGN §21.29); ATK +25 %, BAT −1.2 s, then overload ATK +50 % with HP loss; T1 Defenders ATK +20 %; T2 血战', () => {
const h = makeBattle({
defs: { enemies: { enemy_dummy: dummy() }, chess: { t_tank: ally('t_tank', { profession: 'TANK', stats: { atk: 100 } }) } },
units: [{ chessId: 'chess_char_5_08_a', row: 9, col: 3 }, { chessId: 't_tank', row: 12, col: 3 }],
@@ -376,10 +376,12 @@ test('号角 S3: ATK +25 %, BAT −1.2 s, then overload ATK +50 % with HP loss;
approx(h.unit('t_tank').s.atk, 100 * (1 + t0.atk), 1e-6, '军事要塞 on another Defender');
approx(u.s.atk, u.base.atk * (1 + t0.atk), 1e-6, '… and on herself');
u.skill.gainSp(1000);
h.run(1);
assert.equal(u.skill.activations, 0, '重装 TAKE_DAMAGE: not before a hit');
h.b.dealDamage(h.enemies()[0], u, { amount: 10, type: 'phys' });
// cast at her next attack with the enemy in range, no hit needed: DEFAULT — the owner's deliberate deviation from the
// 重装 TAKE_DAMAGE row (DESIGN §21.29)
assert.equal(u.skill.rule, 'DEFAULT');
assert.ok(h.runUntil(() => u.skill.active, 5));
assert.equal(h.hooksOf('skillStart').find((c) => c.unit === u).reason, 'DEFAULT');
assert.equal(u.stats.taken, 0, 'nothing hit her');
const start = h.b.time;
const total = u.def.skill.duration, ov = bb['horn_s_3[overload_start].damage_duration'];
approx(u.s.atk, u.base.atk * (1 + t0.atk + bb.atk));