feedback1b WI: 喷气人's 飞行模式 hovers with 失衡免疫
PRTS 喷气人: "飞行模式:近地悬浮,不可阻挡,失衡免疫,移动速度+50%,不进行攻击". The take-off buff gave only 不可阻挡 + speed, so the flying 喷气人 stayed a ground unit: melee operators hit it and pulls moved it (较大力 vs weight 3: 1.4 tiles). It is now an air unit that keeps its ground path (flag `float`, as the other hovering enemies) and is never displaced while it flies.
This commit is contained in:
1 parent
f9f26cea52
commit
51fa7d7c84
3 files changed
+30
-4
No files matched your search
+1
-1
@@ -571,7 +571,7 @@ or guard with a per-unit flag while dealing it. When the guard trips, the logged
|
||||
| `redeploy(unit, { free=true, tile, keepSp })` | immediate (re)deployment of a dead/retreated ally (full HP, `deploy {initial:false}`); `free: false` pays `base.cost` DP (refused without it); `tile: [r, c]` lands on that tile once (home unchanged — later redeploys use the board tile; refused when off-rect or occupied, no fallback); `keepSp` keeps SP/charges (保留技力), restored before `deploy` fires — 突袭 raids, 阿戈尔 revive in place |
|
||||
| `refreshRange(unit)`, `setExtraRange(unit, keys)`, `rangeChanged(unit)` | rebuild the ranges after changing `unit.rangeGrid` (流形 copies); extra targetable tiles (absolute keys; merged into every later rebuild until set again; `null` clears; never in `baseRangeKeys`): 蕾缪安 wanted, 维娜 S3 |
|
||||
| `push(enemy, force, {from, dir, fixed, fixedAngle, inward, effect})`, `pull(enemy, force, {to, center, stop})`, `pullToFront(enemy, unit, force)`, `forceLevel(enemy, force)`, `pushDistance(enemy, force, {effect})` | the official 位移 (PRTS 游戏数据基础 §重量公式 / 推与拉; user playtest #6 item 14): 受力等级 = 力度 (微小力 −1, 小力 0, 中力 1, 较大力 2, 大力 3 …) − current 重量等级 (massLevel, 失重 counts). Push distance per level (`constants.js PUSH_TILES`, PRTS 推与拉's 弹道 column): ≤ −3 → 0, −2 → 0.12, −1 → 0.44, 0 → 1.7, 1 → 2.14, 2 → 2.96, ≥ 3 → 3.53 tiles; `effect` = a 特效 push (`PUSH_TILES_EFFECT`: −2 → 0.085, −1 → 0.374, 0 → 1.562, 1 → 1.987, 2 → 2.773, ≥ 3 → 3.331 — 见行者 S1 / S2, `PUSH_EFFECT_SKILLS`; every other pusher uses the 弹道 column [ASSUMED]); radial (away from `from`) unless `dir` (directional: 推击手, 朝部署方向 — > 45° off or < 0.25 tile ⇒ radial and level −2; `fixed` waives both (圣聆初雪 S1), `fixedAngle` only the angle (见行者 S2)); `inward` = a push towards `from` (薄绿 S2), stopping at the 急停 radius. Pull: level ≥ 0 → to `to` / the 急停 radius around `center`, −1 → 35 % of the way, −2 → 0.03, ≤ −3 → 0; `pullToFront` aims at the 拉力起点 0.5 tile ahead of the unit with the 急停 radius 0.6708 around it (never moves an enemy the unit itself blocks — nor does a pull towards an ally's centre, e.g. the 流形 S3 pulse). A 静态刚体 (data `staticBody`: every air unit of the mode except “炎佑”, plus 昆图斯 — PRTS 特殊机制 "可以进入失衡状态…但物理层面上无法产生任何速度或移动", "与单位的行动方式无关") moves 0 from every source while the skills that reach it still hit it (薄绿 S2, 锏 S3, the 钩索师 …; player report after 0.1.0) |
|
||||
| `displace(enemy, {x, y}, tiles)` | the raw mover behind push / pull: along passable tiles (by `motion`: FLY in the rect, else ground-passable), no weight rule; nothing for 失衡免疫 (`noDisplace`: 近地悬浮, 浮空, the 胄 parts), 静态刚体 (`def.staticBody`) and leaders (`_displaceable`); unblocks + re-paths |
|
||||
| `displace(enemy, {x, y}, tiles)` | the raw mover behind push / pull: along passable tiles (by `motion`: FLY in the rect, else ground-passable), no weight rule; nothing for 失衡免疫 (`noDisplace`: 近地悬浮 incl. 喷气人's 飞行模式, 浮空, the 胄 parts), 静态刚体 (`def.staticBody`) and leaders (`_displaceable`); unblocks + re-paths |
|
||||
| `after(seconds, fn, {owner})`, `every(seconds, fn, {owner, immediate})` | return `{cancel()}`; fn(battle, sched) |
|
||||
| `fx(kind, params)`, `rng()` (+ `rng.int/range/chance/pick/shuffle/weighted`) | never use Math.random |
|
||||
| `forceAttack(unit, targets?, { noAmmo })` | an immediate attack with the current profile (hooks, attack SP, a running ammo skill's bullet); `noAmmo: true` = spends no bullet and emits no `ammoUsed` (圣约送葬人 extra attack). Returns true when it attacked |
|
||||
|
||||
@@ -618,7 +618,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) => {
|
||||
@@ -1721,9 +1722,12 @@ 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. [ASSUMED] not modelled: the −90 % move speed for 1.5 s after take-off and 1.333 s after landing.
|
||||
const s = ab.sk.TakeOff;
|
||||
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 });
|
||||
b.fx('telegraph', { x: e2.x, y: e2.y, r: 0.5, kind: 'takeoff', id: e2.id });
|
||||
}, { cond: (b, e2) => !!e2.blockedBy })];
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
// enemies.json `staticBody` (tools/build-data.mjs STATIC_BODIES) → Battle._displaceable: 0 tiles from every source.
|
||||
// - the skills keep their reach: 薄绿 (阵法术师 "攻击时可对空"), 锏 S3 ("※可对空"), the 钩索师 … still hit the drones.
|
||||
// - 刺胄之弹 / “斩胄之剑” / “破胄之锤” are also 失衡免疫 (PRTS 天赋 "{{特殊机制|静态刚体}},…失衡免疫…").
|
||||
// - 喷气人's 飞行模式 (PRTS 喷气人 "近地悬浮,不可阻挡,失衡免疫,移动速度+50%,不进行攻击") hovers like the two 近地悬浮 enemies.
|
||||
// Unchanged: ground enemies keep the 力度 − 重量 tables (DESIGN §20.3); the hovering 吉兆飞鳞 / 掠海漂移体 are 失衡免疫 while they
|
||||
// hover and displaceable once grounded (no 静态刚体 on their pages). [ASSUMED] the 0.1 s 失衡硬直 of a 静态刚体 is not modelled.
|
||||
|
||||
@@ -30,7 +31,7 @@ const AGENT = 'enemy_1046_agent'; // 步兵: ground, weight 1
|
||||
const PARROT = 'enemy_10045_parrot'; // 吉兆飞鳞: 近地悬浮, weight 0
|
||||
const SYUFO = 'enemy_2025_syufo'; // 掠海漂移体: 近地悬浮, weight 4
|
||||
const SHELL = 'enemy_9016_acstmr'; // 刺胄之弹: FLY, weight 2, 静态刚体 + 失衡免疫
|
||||
const BALLOON = 'enemy_2004_balloon'; // 喷气人: ground, weight 3
|
||||
const BALLOON = 'enemy_2004_balloon'; // 喷气人: ground, weight 3; 飞行模式 = 近地悬浮 + 失衡免疫
|
||||
const LOON = 'enemy_9012_acloon'; // “炎佑”: FLY, weight 10, no 静态刚体 on PRTS
|
||||
// synthetic bodies: the rule is the rigidbody, not the movement ("是否为静态刚体与单位的行动方式无关")
|
||||
const DYN_FLY = 'enemy_test_dynfly'; // a FLY body that is not static (none in this mode but “炎佑”)
|
||||
@@ -353,3 +354,24 @@ test('B5: 刺胄之弹 / 斩胄之剑 / 破胄之锤 are 静态刚体 + 失衡
|
||||
}
|
||||
});
|
||||
|
||||
test('喷气人 飞行模式 = 近地悬浮 + 不可阻挡 + 失衡免疫 (PRTS 喷气人): an air unit nothing moves; on the ground again afterwards', REAL, () => {
|
||||
const ds = getDefaultSource();
|
||||
const s = ds.rawEnemy(BALLOON).skills.find((k) => k.prefabKey === 'TakeOff');
|
||||
const wall = chessRec({ id: 't_wall', profession: 'TANK', stats: { atk: 0, maxHp: 1e7, blockCnt: 3 }, rangeGrid: [[0, 0]], skill: null });
|
||||
const h = makeBattle({
|
||||
defs: { chess: { t_wall: wall } }, kits: { t_wall: () => ({ trait: { noAttack: true } }) },
|
||||
units: [{ chessId: 't_wall', row: 9, col: 5 }], autoFinish: false, timeLimit: 60,
|
||||
});
|
||||
h.step();
|
||||
const e = h.spawn(BALLOON, { pos: [9, 5], routeIndex: 0, mods: { speedMul: 0, atkMul: 0 } });
|
||||
assert.ok(h.runUntil(() => !!e.findBuff('ab:takeoff'), s.initCooldown + 1), 'takes off when blocked');
|
||||
h.step();
|
||||
assert.ok(e.isFlying && e.s.flags.unblockable && e.s.flags.noDisplace && !e.blockedBy, '近地悬浮, 不可阻挡, 失衡免疫');
|
||||
assert.equal(e.motion, 'WALK', 'keeps the ground path');
|
||||
// 较大力 (2) − weight 3 = −1 would move a ground 喷气人 35 % of the way
|
||||
assert.equal(h.b.pull(e, 2, { to: { x: 9, y: 9 }, stop: 0 }), 0, 'not pulled');
|
||||
assert.equal(h.b.push(e, 3, { from: { x: 3, y: 9 } }), 0, 'not pushed');
|
||||
h.run(s.bb.duration + 0.2);
|
||||
assert.ok(!e.findBuff('ab:takeoff') && !e.isFlying && !e.s.flags.noDisplace, 'landed: a ground unit');
|
||||
approx(h.b.push(e, 3, { from: { x: 3, y: 9 } }), PUSH_TILES[0], 1e-9, '大力 − 3 = 0 → 1.7 tiles');
|
||||
});
|
||||
Reference in new issue
Block a user