feedback1 integrate: WI flying enemies are static bodies (never displaced); 胄 parts, 守墓石像 and 喷气人 flight
# Conflicts: # data/enemies.json # server/sim/content/enemies.js
This commit is contained in:
commit
f55de593a3
12 files changed
+511
-27
No files matched your search
+12
-4
@@ -1875,16 +1875,24 @@ export class Battle {
|
||||
return this.pull(e, force, { to: { x: unit.x + f[1] * PULL_ORIGIN, y: unit.y + f[0] * PULL_ORIGIN }, center: unit, stop: PULL_STOP_RADIUS });
|
||||
}
|
||||
|
||||
/** Can `e` be displaced at all: a living enemy, not a leader part of the boss pool, not 失衡免疫 (近地悬浮, 浮空). */
|
||||
/**
|
||||
* Can `e` be displaced at all: a living enemy, not a leader part of the boss pool, not 失衡免疫 (flag `noDisplace`:
|
||||
* 近地悬浮, 浮空, the 胄 parts …) and not a 静态刚体 (data `staticBody`). PRTS 特殊机制 静态刚体: such a unit "可以进入
|
||||
* 失衡状态 … 但物理层面上无法产生任何速度或移动" — every air unit of the mode except “炎佑”, plus the boss 昆图斯 (build-data
|
||||
* STATIC_BODIES; player report after 0.1.0, "飞机可以被薄绿的技能拉走"). A skill that reaches it still hits it (its targeting
|
||||
* is the skill's own: 锏 S3, 薄绿, the 钩索师 …); only the movement is 0, so distance-based effects (drag damage, 见行者 S2's
|
||||
* wall stun) come to nothing. [ASSUMED] the 0.1 s 失衡硬直 a 静态刚体 still gets is not modelled (no displacement models it).
|
||||
*/
|
||||
_displaceable(e) {
|
||||
return !!(e && e.alive && e.side === 'enemy' && !e.isBoss && !e.s.flags.noDisplace);
|
||||
return !!(e && e.alive && e.side === 'enemy' && !e.isBoss && !e.s.flags.noDisplace && !(e.def && e.def.staticBody));
|
||||
}
|
||||
|
||||
/**
|
||||
* Move an enemy `distance` tiles along `dir` = {x, y} (normalised internally) over passable tiles — the raw mover of
|
||||
* push() / pull(), which apply the official 力度 − 重量 rules (content uses those; the old `force` option is gone).
|
||||
* 失衡免疫 (flag `noDisplace`: 近地悬浮, 浮空 — PRTS 异常效果 "不会被位移影响") and leaders ⇒ no movement. The tiles it may
|
||||
* cross follow its movement (`motion`): a hovering enemy walks the ground, so it stays on ground-passable tiles.
|
||||
* 失衡免疫 (flag `noDisplace`: 近地悬浮, 浮空 — PRTS 异常效果 "不会被位移影响"), 静态刚体 (data `staticBody`) and leaders
|
||||
* ⇒ no movement (_displaceable). The tiles it may cross follow its movement (`motion`): a hovering enemy walks the
|
||||
* ground, so it stays on ground-passable tiles.
|
||||
*/
|
||||
displace(e, dir, distance) {
|
||||
if (!this._displaceable(e) || !dir) return 0;
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
// level's blink route, fly at the lowest-ATK operator (3×3 stun + DoT); 15 hits shoot it
|
||||
// down (瘫痪: stun 10 s, ground unit, damage ×1.3). Either way a new 初始模式 copy with its HP
|
||||
// replaces it at home. Every damage it takes costs 胄 as much (PART_TRANSFER, 无来源, 等量) —
|
||||
// grounded per both texts, during the dive per the PRTS talent [ASSUMED].
|
||||
// grounded per both texts, during the dive per the PRTS talent [ASSUMED]. The shell, 剑 and
|
||||
// 锤 are 失衡免疫 + 静态刚体 (PRTS 天赋): no push or pull moves them.
|
||||
// boss_2/9 假想敌:铳 unblockable; highest-DEF target in range; erosion; ASPD ramp (+80 × 5) on the same target
|
||||
// (floor 20); 最终之罚 charge at the highest-DEF ground unit (disabled by the h07_02 override).
|
||||
// boss_9: damage ×0.2 while springs live, 盲信之誓 links (100 phys/s on the lines), 末日布道 dash.
|
||||
@@ -418,7 +419,10 @@ function fireShell(b, boss, target) {
|
||||
function kitShell(ab, e) {
|
||||
const stun = T(ab, 'killed.duration') ?? 0, dot = T(ab, 'killed.value') ?? 0;
|
||||
return [{
|
||||
spawn(b, e2) { setHits(e2, e2.def.maxHp); hitCount(b, e2, true); }, // 需要数次攻击击倒
|
||||
spawn(b, e2) {
|
||||
setHits(e2, e2.def.maxHp); hitCount(b, e2, true); // 需要数次攻击击倒
|
||||
b.addBuff(e2, { key: 'boss:shellGuard', persist: true, flags: { noDisplace: true } }); // 失衡免疫 (PRTS 天赋; also 静态刚体)
|
||||
},
|
||||
tick(b, e2, a, dt) {
|
||||
const s = e2.mem.ab.shell;
|
||||
if (!s || a.done) return;
|
||||
@@ -479,7 +483,8 @@ function kitBlade(ab, e, b, tpl) {
|
||||
{
|
||||
spawn(b2, e2) {
|
||||
hover(b2, true);
|
||||
b2.addBuff(e2, { key: 'boss:anchor', persist: true, flags: { noMove: true, unblockable: true } }); // 自缚 (moved by hand) · 不可阻挡
|
||||
// 自缚 (moved by hand) · 不可阻挡 · 失衡免疫 (PRTS 天赋 "{{特殊机制|静态刚体}},不可阻挡、失衡免疫…" — data `staticBody` too)
|
||||
b2.addBuff(e2, { key: 'boss:anchor', persist: true, flags: { noMove: true, unblockable: true, noDisplace: true } });
|
||||
if (BLADE_ATK_SCALE[e2.defId]) e2.profile.atkScale = BLADE_ATK_SCALE[e2.defId];
|
||||
},
|
||||
before(c, b2, e2) { const l = targetsNear(b2, e2, e2.base.rangeRadius || 1.6, { ranged: false }); if (l.length) c.targets = l; }, // 范围物理伤害
|
||||
|
||||
@@ -655,7 +655,8 @@ const refraction = (res, hpPct = 0) => ({
|
||||
* splash, ground traps and terrain skip it; ranged attacks hit it) with 失衡免疫 (`noDisplace`, "初始模式:近地悬浮,失衡
|
||||
* 免疫" on the enemies' PRTS pages) — its `motion` stays WALK, so it keeps the ground path (and 浮空 can still lift it:
|
||||
* Battle.applyStatus refuses data flyers only). Losing the float is each
|
||||
* enemy's own ability (PRTS; 缚地 "使部分近地悬浮敌人掉落" is "实为敌人自身的能力"): kitSyufo, kitParrot.
|
||||
* enemy's own ability (PRTS; 缚地 "使部分近地悬浮敌人掉落" is "实为敌人自身的能力"): kitSyufo, kitParrot. 喷气人's 飞行模式 is
|
||||
* the same state for 7 s (its 'ab:takeoff' buff carries the flags; kitLeaderMisc).
|
||||
*/
|
||||
const FLOAT_KEY = 'ab:float';
|
||||
const setFloat = (b, e, on) => {
|
||||
@@ -895,12 +896,14 @@ function husk({ hits, delay, stealthy = true, unblock = false, onHusk = null, ke
|
||||
}
|
||||
|
||||
/**
|
||||
* 守墓石像 (PRTS 守墓石像 天赋): 地面模式 — melee attacks only while blocked; the first defeat is an instant 重生 (statuses
|
||||
* cleared: rebirthCleanse) to 100 % HP into 转换模式 for stone.duration s — unblockable, 自缚 (immobile), 失衡免疫, immune
|
||||
* to 浮空, DEF +stone.def, RES +stone.magic_resistance, no attack [ASSUMED: PRTS lists none] — then 飞行模式: a flyer
|
||||
* (失衡免疫) whose ranged attacks (the
|
||||
* data's 1.6 radius) deal arts damage and never target flyers; the HP is not refilled again. fx forms 'stone' / 'fly'
|
||||
* (its Sleep and *_2 clips, render/units.js FORMS). <破碎支柱> (an event device) has no counterpart in this mode.
|
||||
* 守墓石像 / 愤怒的守墓石像 (PRTS 天赋): 地面模式 — melee attacks only while blocked; the first defeat is an instant 重生
|
||||
* (statuses cleared: rebirthCleanse) to 100 % HP into 转换模式 for stone.duration s — "无法被阻挡,自缚,失衡免疫,免疫浮空。
|
||||
* 防御力增加800,法术抗性增加30", no attack [ASSUMED: PRTS lists none] — then 飞行模式, "变为飞行单位,失衡免疫": a flyer
|
||||
* no push or pull moves, whose ranged attacks (the data's 1.6 radius) deal arts damage and never target flyers; the HP is
|
||||
* not refilled again. Its pages list no 静态刚体 (data `staticBody` stays off), so the 失衡免疫 of the flight is a persistent
|
||||
* `noDisplace` buff. 浮空 is refused from the statue on (`ab.immune`; data flyers refuse it anyway). [ASSUMED] a 浮空 it
|
||||
* already carries at the knock-out runs out. fx forms 'stone' / 'fly' (its Sleep and *_2 clips, render/units.js FORMS).
|
||||
* <破碎支柱> (an event device) has no counterpart in this mode.
|
||||
*/
|
||||
function statue(ab) {
|
||||
const dur = T(ab, 'stone.duration') ?? 0;
|
||||
@@ -1790,9 +1793,18 @@ function kitLeaderMisc(key, ab, e) {
|
||||
}, { cond: (b, e2) => cands(b, e2).length > 0 })];
|
||||
}
|
||||
case 'enemy_2004_balloon': {
|
||||
// 喷气人 · 升空 when blocked → 飞行模式 for `duration` s: PRTS 喷气人 "近地悬浮,不可阻挡,失衡免疫,移动速度+50%,不进行
|
||||
// 攻击" — an air unit meanwhile (flag `float`: melee cannot hit it; it keeps the ground path, as setFloat), never
|
||||
// displaced; "切换为飞行模式后,1.5秒内移动速度最终降低90% … 结束后,1.333秒内不可阻挡,移动速度最终降低90%" (PRTS numbers:
|
||||
// the blackboard has only the duration and the +50 %).
|
||||
const s = ab.sk.TakeOff;
|
||||
const BRAKE = { moveMul: 0.1 }, BRAKE_UP = 1.5, LANDING = 1.333;
|
||||
return [skill(s, (b, e2) => {
|
||||
b.addBuff(e2, { key: 'ab:takeoff', duration: s.bb.duration ?? 0, flags: { unblockable: true }, mods: { moveMul: 1 + (s.bb['balloon_s[fly].move_speed'] ?? 0) }, visible: true });
|
||||
b.addBuff(e2, {
|
||||
key: 'ab:takeoff', duration: s.bb.duration ?? 0, flags: { unblockable: true, float: true, noDisplace: true }, mods: { moveMul: 1 + (s.bb['balloon_s[fly].move_speed'] ?? 0) }, visible: true,
|
||||
onExpire: ({ battle }) => { if (e2.alive) battle.addBuff(e2, { key: 'ab:landing', duration: LANDING, flags: { unblockable: true }, mods: BRAKE }); },
|
||||
});
|
||||
b.addBuff(e2, { key: 'ab:takeoffBrake', duration: BRAKE_UP, mods: BRAKE });
|
||||
b.fx('telegraph', { x: e2.x, y: e2.y, r: 0.5, kind: 'takeoff', id: e2.id });
|
||||
}, { cond: (b, e2) => !!e2.blockedBy })];
|
||||
}
|
||||
@@ -2576,7 +2588,7 @@ export const KITS = Object.freeze({
|
||||
enemy_1513_dekght_2: (ab, e) => kitLeaderMisc('enemy_1513_dekght_2', ab, e), // 凋零骑士 · 2 targets; rage when 腐败骑士 dies
|
||||
enemy_1539_reid: (ab, e) => kitLeaderMisc('enemy_1539_reid', ab, e), // “复仇者” · ATK up below half; revives once at 50 %
|
||||
enemy_2003_rockman: (ab, e) => kitLeaderMisc('enemy_2003_rockman', ab, e), // 迷路的巨像 · long-stun boulder on a non-stunned unit
|
||||
enemy_2004_balloon: (ab, e) => kitLeaderMisc('enemy_2004_balloon', ab, e), // 喷气人 · takes off (unblockable) when blocked
|
||||
enemy_2004_balloon: (ab, e) => kitLeaderMisc('enemy_2004_balloon', ab, e), // 喷气人 · takes off when blocked: 7 s hovering, unblockable, 失衡免疫
|
||||
enemy_2005_axetro: (ab, e) => kitLeaderMisc('enemy_2005_axetro', ab, e), // “遗弃者” · attack stacks, reset after 4 s idle
|
||||
enemy_2008_flking: (ab, e) => kitLeaderMisc('enemy_2008_flking', ab, e), // “墓碑” · operators' ATK/DEF halved; periodic barrier
|
||||
enemy_2048_smgrd: (ab, e) => kitLeaderMisc('enemy_2048_smgrd', ab, e), // “邪魔的利刃” · 国度 ASPD-down around it, ×2.5 inside
|
||||
|
||||
@@ -710,7 +710,7 @@ const KITS = {
|
||||
|
||||
// ---- 3_07 见行者 · 推击手 (hidden) — S2 惊爆射击: push every enemy in the skill range forward + stun (longer when
|
||||
// slammed into a wall, collided enemies stunned too; air units too [ASSUMED: "范围内所有敌人", no 对空 note on
|
||||
// PRTS] — a 失衡免疫 enemy is not pushed but still stunned); 技巧射击: ignore DEF vs heavy enemies;
|
||||
// PRTS] — a 失衡免疫 enemy or a 静态刚体 (the drones) is not pushed but still stunned); 技巧射击: ignore DEF vs heavy enemies;
|
||||
// 精锐 module PUS-X: redeployed on a ranged tile ⇒ half the deployment cost back
|
||||
chess_char_3_07_a: (bb, chess, def) => {
|
||||
const d = defOf(chess, def);
|
||||
@@ -818,7 +818,9 @@ const KITS = {
|
||||
onHit({ battle, unit, target }) {
|
||||
if (!target || !target.alive || target.side !== 'enemy') return;
|
||||
// PRTS 备注: "此技能的“拖拽”机制实际为反方向(指向薄绿方向)的推开" — a radial push towards her by the
|
||||
// official 力度 − 重量 push distance (小力 vs weight 1: 0.44 tiles), never past her (Battle.push inward)
|
||||
// official 力度 − 重量 push distance (小力 vs weight 1: 0.44 tiles), never past her (Battle.push inward). Her
|
||||
// attack reaches air units (阵法术师 "攻击时可对空"), but the drones of the mode are 静态刚体 (PRTS 特殊机制): hit,
|
||||
// never dragged (player report after 0.1.0, "飞机可以被薄绿的技能拉走")
|
||||
if (battle.push(target, pullForce, { from: unit, inward: true }) > 0) fx(battle, 'pull', target, { src: unit.id });
|
||||
},
|
||||
},
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
// while they roam; 头狼 stage 2 "特殊能力失效" = silence; stage 3 = +1 drone (normal attacks hit once
|
||||
// more, S3 releases one more drone). Base drone count 1.
|
||||
// 6_19 锏 10 slashes every d_hit_interval, pulls every p_hit_interval, final blow (skill range) at the end;
|
||||
// S3 slashes and pulls air units too (PRTS 备注 "可对空").
|
||||
// S3 slashes and pulls air units too (PRTS 备注 "可对空"; a 静态刚体 — every drone of the mode — is hit
|
||||
// but stays put: Battle._displaceable).
|
||||
// 6_20 纯烬艾雅法拉 5 shots are padded by cycling targets when fewer injured allies exist.
|
||||
//
|
||||
// Operator loadouts (DESIGN §16): every visible chess also authors its selectable NON-default skills in `skills`
|
||||
@@ -2939,7 +2940,7 @@ function blkkgt(bb, chess, def) {
|
||||
// removes the skill's range
|
||||
const skillKeys = (unit) => unit.rangeKeys || [];
|
||||
// S3 hits and pulls air units too — PRTS 锏 S3 备注 "※可对空。不会拖拽自身中心半径0.6708范围内的敌人" (her attacks and S1 /
|
||||
// S2 stay ground-only: "地面敌人")
|
||||
// S2 stay ground-only: "地面敌人"); the air units of the mode are 静态刚体, so the pull leaves them in place (Battle.pull)
|
||||
const victims = (battle, unit) => {
|
||||
const c = battle.enemiesInKeys(skillKeys(unit), unit, { ...unit.profile, canHitFly: true, groundOnly: false });
|
||||
sortEnemyTargets(battle, unit, c, null);
|
||||
|
||||
@@ -261,6 +261,7 @@ export function normalizeEnemy(key, e) {
|
||||
hpRecoveryPerSec: num(st.hpRecoveryPerSec ?? extra.hpRecoveryPerSec ?? e.hpRecoveryPerSec, 0),
|
||||
notCountInTotal: !!(e.notCountInTotal),
|
||||
hitArea: normHitArea(e.hitArea), // huge units only (body.js); null = a point
|
||||
staticBody: !!e.staticBody, // 静态刚体: pushes / pulls never move it (Battle._displaceable)
|
||||
tags: e.tags ?? [],
|
||||
abilities: e.abilities ?? [],
|
||||
skills: e.skills ?? [],
|
||||
|
||||
Reference in new issue
Block a user