feedback2 WJ: enemy splash, blasts and area skills no longer hit a 隐匿 operator that does not block the enemy (one area selector, targeting.js areaSelectable; 迷彩 is still hit)

This commit is contained in:
sganggs committed 2026-10-03 23:23:10 +08:00
1 parent 47df17171a
commit 6f4278a357
3 files changed
+222 -108

No files matched your search

+32 -5
View File
@@ -11,6 +11,7 @@
// (3) higher enemy taunt, (4) least remaining path distance to the goal, (5) earliest spawned. Air units
// (Unit.isFlying: FLY, 近地悬浮, 浮空) need a profile that can hit them (`canHitFly`, never `groundOnly`). Enemy
// priority: sortAllyTargets. 起飞 (an ally's flag `liftoff`) = 对地规避: no ground enemy selects it (evadesGround).
// An enemy's area effects select allies with areaSelectable (no unblocking 隐匿 ally; 迷彩 is hit — DESIGN §22.12).
import { COLS, ROWS } from './constants.js';
import { normDir, rotateOffset } from './dir.js';
@@ -72,9 +73,9 @@ export function canTargetEnemy(attacker, e, profile) {
* 概念 "敌人会在自身被干员阻挡情况下强行无视对方可选性发动攻击" (the term text "不阻挡时…" is the short form; 异常效果:
* "隐匿与'阻挡时解除'没有直接关系"). Devices are never targets (阻隔工事: obstacles nobody can select; “双眼皮”: 迷彩 and
* off the enemy paths — PRTS). 迷彩 (flag `camou`, term ba.camou "不阻挡时不成为敌方普通攻击的目标") works the same way:
* PRTS 异常效果 gives both anomalies the note "与'阻挡时解除'没有直接关系" [ASSUMED: enemy skills and splash selectors
* treat 迷彩 like target selection — officially splash and selectors without a projectile ignore it]. An airborne ally
* (起飞, flag `liftoff`) is never a target of a ground enemy (evadesGround).
* PRTS 异常效果 gives both anomalies the note "与'阻挡时解除'没有直接关系" — for this target selection (an attack, a skill
* pick, a cast condition: PRTS 选择器 "所有触发选择器通常不无视迷彩"); an area effect selects with areaSelectable, where
* 迷彩 no longer protects. An airborne ally (起飞, flag `liftoff`) is never a target of a ground enemy (evadesGround).
*/
export function canTargetAlly(e, a, ranged) {
if (!a.alive || !a.deployed || a.hidden || a.kind === 'device') return false;
@@ -85,6 +86,32 @@ export function canTargetAlly(e, a, ranged) {
return true;
}
/**
* May an AREA effect of enemy-side `src` select ally `a` — a splash, a blast, an area skill or status, a pulse, a zone it
* leaves, a chain / bounce jump, a 周围四格 addition (content/enemies.js areaAllies / areaAlliesInTiles / fieldAllies)?
* PRTS 作战机制 §AOE伤害判定 "AOE的判定是对攻击范围内的每个可以被选中的敌人进行判定"; §隐匿 "隐匿效果使得获得该效果的单位无法被
* 任何敌方的能力索敌选中"; PRTS 选择器 (可选判定): a selector checks 无法选择 by default — "站内所记载的大部分“无视可选性”指
* 的正是不进行这次可选判定"; PRTS 异常效果 §无法选择 = 隐匿, 不可选中, 无敌 (沉睡 is 无敌), 对地规避. So not:
* - a 隐匿 ally (flag `stealth`: 伪装服, 叙拉古 6, 伊内丝 S2, the 排气格栅 tile) unless it blocks `src` — a blocked enemy
* attacks its blocker whatever its selectability (PRTS 作战机制 "因为“阻挡优先级最高”的效果,敌人会无视一切可选性对该干员
* 进行攻击"; read for its area abilities too [ASSUMED]); a dead `src` (death blasts) blocks nobody;
* - an untargetable (不可选中) or sleeping (沉睡: 无敌) ally;
* - an airborne 起飞 ally when `src` walks (evadesGround — the same refusal the damage pipeline makes).
* 迷彩 (flag `camou`) does not protect: gamedata_const ba.camou "(无法躲避溅射类攻击)"; PRTS 异常效果 迷彩 "所有光环类能力、以及
* 涉及中点判定/格子判定的效果均不受迷彩制约"; PRTS 选择器 "非弹道类型的溅射攻击会自动无视迷彩". `src` null (an effect
* with no selecting enemy): 隐匿 still applies, 对地规避 not. Abilities PRTS marks "无视无法选择 / 无视(目标)可选性" never
* call this (【污染秽蚀】, 【盲信之誓】, 萨卡兹悖谬暴虐兵长's 暴击, 假想敌:淤困's burst spread, 远眺's 暴露 — DamageInfo
* `ignoreSelect`); neither do map / terrain effects nor the buff auras kept as they were (DESIGN §22.12).
*/
export function areaSelectable(src, a) {
if (!a || !a.alive || !a.deployed || a.hidden || a.kind === 'device') return false;
const f = a.s.flags;
if (f.untargetable || f.sleep) return false;
if (f.stealth && !(src && src.alive && src.blockedBy === a)) return false;
if (f.liftoff && evadesGround(src, a)) return false;
return true;
}
/**
* 对地规避 of an airborne ally (起飞, buff flag `liftoff` — 蒂比's skills): true when `src` is an enemy whose 行动方式 is
* ground, which then cannot select `a` (gamedata_const ba.liftoff "不阻挡地面敌人且不会被地面敌人攻击,可以阻挡飞行敌人";
@@ -93,8 +120,8 @@ export function canTargetAlly(e, a, ranged) {
* 行动方式: a hovering unit "是真正的飞行单位", a levitated one is seen as a flyer) still select it; it stays a ground unit
* itself ("起飞的干员仍然是地面单位"), so they need no 对空 check. Used by every enemy selection (canTargetAlly), the damage
* pipeline and Battle.applyStatus (a ground enemy's area damage, statuses and hits under way skip it — PRTS 作战机制 "AOE
* 的判定是对攻击范围内的每个可以被选中的敌人进行判定"), and the content picks and one-shot areas that bypass canTargetAlly
* (chain / bounce jumps, 周围四格 additions, shells, barrages, 沙狱, death blasts). Not selections, so they still reach it:
* 的判定是对攻击范围内的每个可以被选中的敌人进行判定"), and every enemy area selection (areaSelectable: splash, blasts,
* chain / bounce jumps, 周围四格 additions, barrages, 沙狱, death blasts). Not selections, so they still reach it:
* sourceless damage and DamageInfo / applyStatus `ignoreSelect` — abilities that "无视无法选择" (【污染秽蚀】, 【盲信之誓】,
* 萨卡兹悖谬暴虐兵长's 暴击 splash), direct picks (碎铳之簧's counter on its attacker: PRTS 异常效果 "'直接选中'的能力…不受这些
* 仅在选择时生效的异常效果制约"), the blasts of flying units credited to a ground leader (刺胄之弹, 斩胄之剑 / 破胄之锤) and