feedback1e WP: live attack range on the battle card; 烛煌 S3 splash 1.7

Community report "干员烛煌开启3技能时候攻击范围不会变". The sim already attacked
with S3's 4-11 while it ran (real matches, and every attack-range change of
the mode); what stayed the same was the battle detail card: its 攻击范围
mini-map kept the base 3-1 grid while the live stats beside it moved.

- Battle._refreshRange keeps the relative grid behind rangeKeys as
  unit.liveRangeGrid (targeting.js extendedGrid: rangeExtend grown on);
  shared/protocol.js unitStatsEntry carries it as `range`; the detail card
  draws it (cardRangeGrid) in battle and in the prep preview, and names a
  whole-field range (纯烬艾雅法拉 S3) 全场 instead of drawing it.
- 烛煌 S3 "攻击变为群体攻击" is one target + a 1.7 splash (PRTS 技能3 备注
  "攻击溅射半径1.7"), not every enemy inside 4-11; the burst bonus hits
  every enemy of the attack; a burn burst's +2 ammo stops at the skill's
  ammo ("补充后的弹药数量无法超过上限").
- Tests: test/sim/feedback1e-skillrange.test.js (S3 range, splash, ammo
  cap, live grid, the audit of every attack-range change, a real spec),
  test/ui/feedback1e-range.test.js (the card).
This commit is contained in:
sganggs committed 2026-10-03 05:03:07 +08:00
1 parent 7f134737ce
commit 8b0e672bb8
10 files changed
+471 -20

No files matched your search

+7 -3
View File
@@ -28,7 +28,7 @@ import { Grid } from './grid.js';
import { Unit } from './units.js';
import { makeBuff, STATUS, RESIST_STATUSES } from './buffs.js';
import { dealDamage as pipeDamage, heal as pipeHeal, applyHpLoss, makeDamageInfo, reduceElement, palsyBuff, elementView, leaderHitCancelled } from './damage.js';
import { absoluteRangeKeys, canTargetEnemy } from './targeting.js';
import { absoluteRangeKeys, canTargetEnemy, extendedGrid } from './targeting.js';
import { bodyKeys, bodyInKeys, bodyInRadius } from './body.js';
import { normDir, mirrorDir, localOrder, localBefore } from './dir.js';
import { ProjectileSystem } from './projectiles.js';
@@ -1592,8 +1592,11 @@ export class Battle {
* Recompute a unit's absolute range tile keys: `rangeKeys` / `rangeKeySet` = current range (skill range override +
* rangeExtend) ∪ `unit.extraRangeKeys` (content extra targets — setExtraRange); `baseRangeKeys` = the INITIAL range
* of the DEFAULT skill trigger: the unit's own grid + its permanent rangeExtend (`s.baseRangeExtend`: persistent,
* never-expiring buffs — talents, modules, bonds), no skill range, no temporary extend, no extra keys. Rebuilt on
* deploy / relocate / skill range switches and whenever either extend changes (rangeChanged).
* never-expiring buffs — talents, modules, bonds), no skill range, no temporary extend, no extra keys;
* `liveRangeGrid` = the relative grid (facing RIGHT) behind `rangeKeys` without the extra keys (targeting.js
* extendedGrid) — the detail card's live 攻击范围 (shared/protocol.js unitStatsEntry `range`; community report E1
* after 0.1.0: the card kept the base grid while 烛煌 S3 attacked with 4-11). Rebuilt on deploy / relocate / skill
* range switches and whenever either extend changes (rangeChanged).
*/
_refreshRange(u) {
const tg = u.skill && u.skill.active ? u.skill.spec.targeting : null;
@@ -1607,6 +1610,7 @@ export class Battle {
if (extra) for (const k of extra) if (!set.has(k)) { set.add(k); keys.push(k); }
u.rangeKeys = keys;
u.rangeKeySet = set;
u.liveRangeGrid = extendedGrid(grid, ext);
if (u.kind !== 'device') u.baseRangeKeys = absoluteRangeKeys(u.rangeGrid || [[0, 0]], u.tileR, u.tileC, u.dir, u.s.baseRangeExtend);
if (u.skill) u.skill._trigKeys = null; // CUSTOM_RANGE trigger grid is relative to the tile
}