feedback5: merge R19A — GitHub #232: a stunned or frozen enemy is blocked by contact where it stands (an operator redeployed beside a frozen 隐匿 enemy blocks it and reveals it; 沉睡 / 浮空 / 恐惧 / 不可阻挡 still refuse); golden as R19A's commit (52 scenarios: roster 15, bonds 5, fields 7, matches 9, diy 16 — each first diverges where a held enemy is blocked by a touching blocker with a free slot), the merged tree's golden equals the branch's

This commit is contained in:
sganggs committed 2026-10-07 11:36:02 +08:00
commit 8b780c1b5b
13 files changed
+958 -750

No files matched your search

+11 -5
View File
@@ -10,10 +10,10 @@
// changes (obstacles) or content displaces the enemy (route.pts = null). FLY legs fly straight between checkpoints; the
// path always follows `motion` — a hovering (近地悬浮) enemy is an air unit for targeting and blocking (Unit.isFlying)
// but walks the ground. An unblocked enemy touching an ally with free block capacity — within its block radius (0.7071
// ground, 0.8944 air, devices 0.4472; Battle._checkBlock) — is blocked, moving or not, so an enemy overlapping an
// operator is taken over once its blocker is gone; never one holding 不可阻挡 (恐惧, 诱导, 浮空, 沉睡): an enemy falling
// asleep is let go by its blocker, whose slot frees, and stays where it is until it wakes (DESIGN §24.9). Blocked
// enemies fight their blocker (ranged ones may pick anyone in
// ground, 0.8944 air, devices 0.4472; Battle._checkBlock) — is blocked, moving or not (stunned or frozen too: GitHub
// #232), so an enemy overlapping an operator is taken over once its blocker is gone; never one holding 不可阻挡 (恐惧,
// 诱导, 浮空, 沉睡): an enemy falling asleep is let go by its blocker, whose slot frees, and stays where it is until it
// wakes (DESIGN §24.9). Blocked enemies fight their blocker (ranged ones may pick anyone in
// range, blocker first); every blocker whose attack hits enemies — a ranged operator on a melee tile included — may
// always target the enemies it blocks, in range or not, whatever its facing, and targets them first (acquireTargets,
// Battle.blockedTargets; user playtest #6: "阻挡了就一定要能打到"); a heal attack keeps selecting injured allies while
@@ -543,10 +543,16 @@ export function updateEnemy(b, e, dt) {
// a stun / freeze / sleep cuts the attack clip short: no stand left once it ends [ASSUMED]. 沉睡 also holds 不可阻挡
// (PRTS 异常效果 SLEEPING = 无法行动+无敌+不可阻挡): a sleeper's blocker lets go — its swing was cut above; Battle.applyStatus
// (battle/status.js) releases it at once, this catches a sleep added as a plain buff (`flags.sleep` makes it `stun` too,
// units.js) — and it stays where it is until it wakes (DESIGN §24.9)
// units.js) — and it stays where it is until it wakes (DESIGN §24.9). 晕眩 / 冻结 hold no 不可阻挡 (PRTS 异常效果: the
// STUN / FROZEN state machines stop the enemy's moves and attacks, not its being blocked; 术语释义 冻结 names no block):
// it is still blocked by contact where it stands, like a standing enemy — an operator redeployed or deployed onto it,
// another one taking it over or one whose capacity frees up blocks it, and the block lifts its 隐匿 (GitHub #232; until
// 0.2.0 the check waited for the status to end). The contact rule of a moving enemy (Battle._checkBlock, which still
// refuses 沉睡 / 浮空 / 恐惧 / 不可阻挡): one stunned short of its blocker is blocked once it walks into contact
if (stunned && !e.hidden) {
e.atkStandUntil = -Infinity;
if (e.blockedBy && e.s.flags.sleep) b._unblock(e);
b._checkBlock(e);
return;
}
if (e.blockedBy) {
+6 -4
View File
@@ -13,10 +13,12 @@ export class BattleBlocking {
* devices 0.4472), and the blocker has free capacity for the enemy's block weight (and may block it at all: a unit on
* a fenced tile blocks no ground enemy, _blockerFor). Checked every tick for every
* unblocked enemy, moving or not, so an enemy overlapping an operator is taken over as soon as its blocker is gone or
* the operator's capacity frees up (user playtest #5 item 4). Several blockers in contact → the nearest [ASSUMED],
* ties → the first in row-then-column scan order. The air radius grows with the blocker's 阻挡半径倍率 (PRTS 游戏数据基础
* "飞行阻挡半径 = 0.8944 × 阻挡半径倍率"; mod `blockRadiusScale` = 倍率 − 1: 凯尔希·思衡托's 遗尘守望 / S1, +0.23); ground
* blocking ignores it (PRTS 数值范围 "对地面阻挡的单位不生效"). Below 1.5 tiles the 3×3 scan still finds every blocker.
* the operator's capacity frees up (user playtest #5 item 4) — a stunned or frozen one too, an operator redeployed
* onto it included (晕眩 / 冻结 hold no 不可阻挡: ai.js updateEnemy, GitHub #232). Several blockers in contact → the
* nearest [ASSUMED], ties → the first in row-then-column scan order. The air radius grows with the blocker's
* 阻挡半径倍率 (PRTS 游戏数据基础 "飞行阻挡半径 = 0.8944 × 阻挡半径倍率"; mod `blockRadiusScale` = 倍率 − 1: 凯尔希·思衡托's
* 遗尘守望 / S1, +0.23); ground blocking ignores it (PRTS 数值范围 "对地面阻挡的单位不生效"). Below 1.5 tiles the 3×3 scan
* still finds every blocker.
* Never blocked: an enemy holding 不可阻挡 (PRTS 异常效果 BLOCK_FREE 「无法阻挡/被阻挡,自动解除阻挡」) — the flag itself
* (恐惧 / 诱导 carry it), 浮空, and 沉睡 (SLEEPING = 无法行动+无敌+不可阻挡: a sleeper takes no block slot, DESIGN §24.9);
* once it wakes it is blocked again only by a blocker with room.