feedback7 R22-GHSIM: a 速射手 (优先攻击空中单位) blocking a ground enemy shoots a flyer in its range first; every other attacker keeps its blocked enemy first (GitHub #220, the owner's decision of 2026-10-08); golden: roster-026, roster-037 move

The owner's decision (relayed 2026-10-08): only the 速射手 air priority outranks the attacker's own blocked enemy — PRTS
索敌的概念 「阻挡(近战限定)→特殊优先级→…」 — while the user's playtest #6 rule 「阻挡了就一定要能打到」 keeps 'blocked first'
for every other attacker and priority. PR #220 by TsangAsuna (for #205) moved every special priority ahead of the block;
re-implemented for priority 'fly' only (targeting.js sortEnemyTargets: the fly key, then blocked, then the rest as
before) — the trait's priority and a skill's targeting priority 'fly' (新约能天使) alike. Seen (repro): 能天使 on a melee
tile blocking a walker kept shooting it with a flyer in range; now the flyer, and 远牙 (神射手, lowest DEF first) still hits
the enemy it blocks over a softer or a flying one. Docs: SIM.md (blocking), design/engine.md, PLAYING.md 阻挡.

Golden: roster-026 (流星, 速射手) and roster-037 (新约能天使's priority 'fly') now shoot flyers in range while blocking.
This commit is contained in:
sganggs committed 2026-10-08 20:29:45 +08:00
1 parent 895653fc10
commit 4bd154e326
6 files changed
+89 -51

No files matched your search

+8 -2
View File
@@ -193,7 +193,12 @@ const PRIORITY_FNS = {
};
/**
* Sort candidate enemies for an attacker (in place) and return them.
* Sort candidate enemies for an attacker (in place) and return them: the enemies it blocks first (the user's rule after
* playtest #6, "阻挡了就一定要能打到", for every blocker — DESIGN §20.3), then the special priority, taunt, the remaining
* route, the spawn order. One exception, the owner's decision of 2026-10-08 (GitHub #220 by TsangAsuna, #205): the 速射手 air priority
* (trait 优先攻击空中单位 — priority 'fly', a skill's too) comes before its own blocked enemy, so a 速狙 on a melee tile
* blocking a ground enemy shoots the flyer in its range (PRTS 索敌的概念 「阻挡(近战限定)→特殊优先级→…」); every other
* priority keeps the blocked enemy first.
* @param {object} attacker ally unit
* @param {object[]} cands enemies
* @param {string|null} priority profile/skill priority key
@@ -201,6 +206,7 @@ const PRIORITY_FNS = {
export function sortEnemyTargets(battle, attacker, cands, priority) {
if (cands.length <= 1) return cands;
const pf = priority ? (PRIORITY_FNS[priority] || (priority === 'nearest' || priority === 'farthest' ? null : null)) : null;
const airFirst = priority === 'fly';
const ax = attacker.x, ay = attacker.y;
const keyed = cands.map((e) => ({
e,
@@ -210,7 +216,7 @@ export function sortEnemyTargets(battle, attacker, cands, priority) {
d: battle.remainingDistance(e),
s: e.spawnSeq,
}));
keyed.sort((a, b) => a.b - b.b || a.p - b.p || a.t - b.t || a.d - b.d || a.s - b.s);
keyed.sort((a, b) => (airFirst ? a.p - b.p : 0) || a.b - b.b || a.p - b.p || a.t - b.t || a.d - b.d || a.s - b.s);
for (let i = 0; i < keyed.length; i++) cands[i] = keyed[i].e;
return cands;
}