feedback3: merge WH — ground operators are melee-position, 叙拉古 rolls on every normal hit, off bonds show as disabled, prep-end items merge next prep
This commit is contained in:
commit
1005754bf3
28 files changed
+746
-98
No files matched your search
@@ -129,7 +129,7 @@ const BY_KEY = {
|
||||
});
|
||||
},
|
||||
|
||||
// 休谟斯 回收利用
|
||||
// 休谟斯 回收利用 ("地面干员技能结束时…": a melee-position operator on any tile — support isGroundOp)
|
||||
act1autochess_band18_buff(battle, ps, p, bandId) {
|
||||
const sp = num(p.sp);
|
||||
if (!(sp > 0)) return;
|
||||
|
||||
@@ -441,6 +441,8 @@ export function install(battle) {
|
||||
// next time she leaves the field (knocked out, withdrawn) she is back at once and free (`u.mem.indomFreeDeploy`)
|
||||
// [ASSUMED: one such deployment at a time, spent by her next deployment whatever brings it]. Tier 2 (+sp SP to every
|
||||
// operator on the field) stays a knock-out effect: its own line ("地面干员被击倒时使场上所有干员技力+5") was not corrected.
|
||||
// Both lines take a 地面干员 = a melee-position operator on any tile (support isGroundOp: 歌蕾蒂娅 on a 高台 counts, a
|
||||
// ranged operator on a melee tile does not — community report 「不屈盟约效果高台干员也错误的吃到了」, 0.1.3).
|
||||
if (has(ID.indom)) {
|
||||
const INDOM_EXITS = new Set(['killed', 'retreat', 'merchant']);
|
||||
const stOf = (u) => { const st = isGroundOp(u) ? byPid[u.ownerId] : null; return st && st.tiers[ID.indom] ? st : null; };
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
// 5: the first max_free_respawn_cnt members by position (the devour's order, fixed at battle
|
||||
// start) each redeploy at once (free) on their first knock-out
|
||||
// 叙拉古 siracusaShip every member deployment: ASPD +(base + per·L) for (base_duration + per·L) s; 6: 隐匿 for the same
|
||||
// time, and while hidden / end_duration s after, attacks proc (PRD, nominal `prob`) base_damage +
|
||||
// damage_per_stack·L true damage + fear `fear` s
|
||||
// time, and while hidden / end_duration s after, every 普通伤害 hit (siracusaRolls) procs (PRD,
|
||||
// nominal `prob`) base_damage + damage_per_stack·L true damage + fear `fear` s
|
||||
// 卡西米尔 kazimierzShip every deployment of one of the player's operators (initial ones included): members ATK
|
||||
// +atk_when_born, total ≤ base_max_atk_when_born + max_atk_when_born_per_stack·L; 6: blocking
|
||||
// members pulse damage_atk_scale×ATK true damage + stun around them every damage_interval s,
|
||||
@@ -476,6 +476,29 @@ function installEgir(battle, pid, bb, members) {
|
||||
// =====================================================================================================================
|
||||
// 叙拉古
|
||||
|
||||
/**
|
||||
* Does a member's damage instance try the tier-6 proc? PRTS 盟约记录 叙拉古: "※仅在造成普通伤害时尝试造成来源为干员自身的
|
||||
* 真实附加伤害和恐惧", "每次造成普通伤害时尝试触发" — 普通伤害 is the attack type NORMAL (PRTS 伤害分类: the default type,
|
||||
* group damage included unless it is 溅射), not "a normal attack" (community report 「叙拉古盟约真伤概率数值没有正确递增
|
||||
* 成长」, GitHub #79: it rolled on normal attacks only). So skill hits roll — 德克萨斯 剑雨, 缄默德克萨斯's bursts and
|
||||
* sword rain, 阿罗玛 S1 / S2, 忍冬 S1 / S2, 伺夜 S3 — and so do 荒芜拉普兰德's S3 drone attacks (PRTS 备注 "不属于普通攻击/
|
||||
* 技能直接伤害": neither an attack nor skill damage, still 普通伤害). Not: 溅射 (`isSplash`); 持续伤害 (tags dot / periodic:
|
||||
* 荒芜拉普兰德's S3 pulse, PRTS 备注 "持续法术伤害"; 缄默德克萨斯 S1, "伤害分类为法术持续伤害"); 附加伤害 (tag `addition`:
|
||||
* 拉普兰德's module, 忍冬's 追凶 — PRTS "法术附加伤害"; item procs and the bonds' riders, own proc included [ASSUMED: 附加,
|
||||
* PRTS gives no class]); element damage; 无来源 damage (坚守's thorns); 流失.
|
||||
*/
|
||||
function siracusaRolls(dmg) {
|
||||
if (!dmg || dmg.isSplash || dmg.sourceless || dmg.type === 'element' || dmg.type === 'elemental') return false;
|
||||
const tags = dmg.tags;
|
||||
if (!Array.isArray(tags)) return true;
|
||||
for (let i = 0; i < tags.length; i++) {
|
||||
const t = tags[i];
|
||||
if (t === 'dot' || t === 'periodic' || t === 'addition' || t === 'item' || t === 'hpLoss') return false;
|
||||
if (typeof t === 'string' && t.startsWith('bond:')) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function installSiracusa(battle, pid, bb, members) {
|
||||
const memberSet = new Set(members);
|
||||
const six = reached(battle, pid, 'siracusaShip', bb.power_bond_char_cnt);
|
||||
@@ -497,7 +520,7 @@ function installSiracusa(battle, pid, bb, members) {
|
||||
const st = { n: 0 };
|
||||
const onDmg = (ctx) => {
|
||||
const u = ctx.source, t = ctx.target, dmg = ctx.dmg;
|
||||
if (!dmg || !dmg.isAttack || dmg.isSplash || !isEnemyTarget(t) || ownTag(dmg, 'bond:siracusa')) return;
|
||||
if (!isEnemyTarget(t) || !siracusaRolls(dmg)) return;
|
||||
const hidden = u.s.flags.stealth || battle.time <= num(u.mem.siraStealthEnd, -Infinity) + end + 1e-9;
|
||||
if (!hidden) return;
|
||||
st.n++;
|
||||
@@ -609,6 +632,8 @@ export function payHammers(ctx) {
|
||||
ctx.setCounter(VICTORIA_COUNTER, paid + 1);
|
||||
for (let i = 0; i < count; i++) {
|
||||
const id = ctx.rollItem({ pool: p.pool });
|
||||
// onPrepEnd: grantItem stows this and does not merge until the next prep start, so a second copy does not
|
||||
// take an equipped hammer off for the fight (effectsMeta _deferItemMerge). [ASSUMED] every item that hook grants.
|
||||
if (id && ctx.grantItem(id, { source: 'bond:victoriaShip' })) granted++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ function hammerAcquire(battle, rt, u) {
|
||||
const m = hammerMul(battle, rt, u, hs, 'burn');
|
||||
if (m > 0) battle.dealDamage(u, c.target, { type: 'element', element: 'burn', amount: c.amount * num(p.damage_scale) * m, tags: procTags('hammer_burn') });
|
||||
});
|
||||
// 战栗: ground carrier, on attack prob × m ⇒ 战栗 disarmed_duration s
|
||||
// 战栗: 地面干员 carrier (melee position, any tile — support isGroundOp), on attack prob × m ⇒ 战栗 disarmed_duration s
|
||||
S.on('attack', (c) => {
|
||||
if (c.attacker !== u || !isGroundOp(u)) return;
|
||||
const p = hammerParams(hs, 'tremble');
|
||||
|
||||
@@ -40,7 +40,7 @@ function onDefaultSkill(chess) {
|
||||
* `liftoff` (no ground enemy blocked — Battle._blockerFor; 对地规避 — targeting.js evadesGround: no ground enemy selects
|
||||
* her, while what selects nobody still lands — 无视无法选择 abilities, direct picks, flying units' blasts, 无来源 damage, the
|
||||
* ticks of a debuff already on her) and `blockFly` (blocks flyers at the air radius). She stays a ground unit on her tile (PRTS 行动方式 "起飞的
|
||||
* 干员仍然是地面单位": `unit.ground` unchanged — 隐德来希's 血镰, 地面干员 bonds / items still count her).
|
||||
* 干员仍然是地面单位": `unit.ground` unchanged — 隐德来希's 血镰 still counts her; 地面干员 bonds / items read her position).
|
||||
*/
|
||||
const LIFTOFF_FLAGS = Object.freeze({ blockFly: true, liftoff: true });
|
||||
/** 蒂比 take-off: the ground enemies she blocked walk on. */
|
||||
@@ -721,7 +721,8 @@ export default {
|
||||
if (num(t.duration) > 0) trait.onHitStatus = { key: 'silence', duration: num(t.duration) };
|
||||
if (num(tb.atk_scale_m) > 0) {
|
||||
trait.afterHit = (battle, u, target) => {
|
||||
if (target && target.alive && target.side === 'enemy') battle.dealDamage(u, target, { amount: u.s.atk * num(tb.atk_scale_m), type: 'arts', tags: ['module'] });
|
||||
// PRTS 特性备注 "造成预计算的法术附加伤害": 附加伤害 (tag addition — no 叙拉古 6 roll)
|
||||
if (target && target.alive && target.side === 'enemy') battle.dealDamage(u, target, { amount: u.s.atk * num(tb.atk_scale_m), type: 'arts', tags: ['module', 'addition'] });
|
||||
};
|
||||
}
|
||||
return {
|
||||
|
||||
@@ -1389,7 +1389,8 @@ const KITS = {
|
||||
if (t == null) { marks.set(e.id, battle.time); return; }
|
||||
if (battle.time - t <= num(t0.interval, 10) + 1e-9 && e.alive) {
|
||||
busy = true;
|
||||
try { battle.dealDamage(unit, e, { amount: unit.s.atk * num(t0.atk_scale), type: 'arts', canDodge: false, tags: ['talent', 'vulpisHunt'] }); } finally { busy = false; }
|
||||
// PRTS 备注 "伤害类型为法术附加伤害": tag addition (no 叙拉古 6 roll)
|
||||
try { battle.dealDamage(unit, e, { amount: unit.s.atk * num(t0.atk_scale), type: 'arts', canDodge: false, tags: ['talent', 'vulpisHunt', 'addition'] }); } finally { busy = false; }
|
||||
}
|
||||
}, { owner: unit });
|
||||
battle.on('kill', (ctx) => { if (ctx.killer === unit && unit.skill?.active) unit.mem.vulpisKill = true; }, { owner: unit });
|
||||
|
||||
@@ -2972,11 +2972,13 @@ function whitw2(bb, chess, def) {
|
||||
// 信息 驭械术师 "浮游单元攻击不同目标…时,上述的伤害立刻恢复至初始值"). That damage is arts and neither a normal attack
|
||||
// nor skill damage (PRTS S3 备注 "该技能释放的浮游单元造成的伤害不属于普通攻击/技能直接伤害", which for this skill
|
||||
// overrides the branch note "通过技能释放的浮游单元造成技能直接伤害": no 'attack' hook, isAttack / isSkill false — the
|
||||
// 叙拉古 6 assassin proc and the on-attack items skip it), and 缴械 does not stop it (PRTS 驭械术师 "…不受缴械类效果
|
||||
// on-attack items skip it; it is still 普通伤害, so the 叙拉古 6 proc rolls on it, bonds/core.js siracusaRolls), and
|
||||
// 缴械 does not stop it (PRTS 驭械术师 "…不受缴械类效果
|
||||
// 制约"); [ASSUMED] nor do her stun, freeze or silence (PRTS names only 缴械) — the skill ticks on and so do the drones.
|
||||
// Around every drone (attack@range_radius): move speed attack@move_speed and, once per second, attack@magic_atk_scale
|
||||
// × ATK arts (不叠加: one hit per enemy whatever the number of drones); [ASSUMED] that area hit keeps `isSkill` (a skill
|
||||
// DoT — the 备注 speaks of 直接伤害). A knocked-out / withdrawn wolf (onEnd cleared the drones mid-tick, e.g. from a
|
||||
// DoT — the 备注 speaks of 直接伤害) and is 持续伤害 (tag dot: PRTS 备注 "持续法术伤害" — no 叙拉古 6 roll, 锡人's
|
||||
// 凋敝魂灵 raises it). A knocked-out / withdrawn wolf (onEnd cleared the drones mid-tick, e.g. from a
|
||||
// kill hook) deals nothing more in that tick.
|
||||
skill: {
|
||||
kind: 'duration',
|
||||
@@ -3009,7 +3011,7 @@ function whitw2(bb, chess, def) {
|
||||
unit.mem.droneAcc -= 1;
|
||||
for (const e of near) {
|
||||
if (gone()) return;
|
||||
if (e.alive) battle.dealDamage(unit, e, { amount: unit.s.atk * dmgScale, type: 'arts', isSkill: true, tags: ['skill', 'drone'] });
|
||||
if (e.alive) battle.dealDamage(unit, e, { amount: unit.s.atk * dmgScale, type: 'arts', isSkill: true, tags: ['skill', 'drone', 'dot'] });
|
||||
}
|
||||
// (a drone on its target already pulses with each of its attacks)
|
||||
for (const d of D) if (d.phase !== 'lock') battle.fx('drone', { x: d.x, y: d.y, id: unit.id });
|
||||
|
||||
@@ -151,8 +151,14 @@ export function tierOf(u) {
|
||||
if (u.ownerUnit) return tierOf(u.ownerUnit);
|
||||
return 1;
|
||||
}
|
||||
/** Operator standing on a ground (LOW, not elevated) tile — "地面干员" (engine flag set at deployment). */
|
||||
export const isGroundOp = (u) => isOp(u) && u.ground === true;
|
||||
/**
|
||||
* "地面干员": a melee-position (地面位, deploy class MELEE) operator, whatever tile it stands on — the official vocabulary
|
||||
* names the deploy class, not the tile (game data: this mode's map card 「可以部署高台干员和地面干员的地面」, 「可将高台干员
|
||||
* 部署于其上」, 「所有地面干员阻挡数+2」; PRTS corrected 琴柳's 地面干员 to 地面位干员). Read by 不屈, the 战栗维式重锤 proc and
|
||||
* 休谟斯 回收利用 (community report 「不屈盟约效果高台干员也错误的吃到了」, 0.1.3). The tile (`unit.ground`) stays what the
|
||||
* enemies' 地面单位 targeting reads.
|
||||
*/
|
||||
export const isGroundOp = (u) => isOp(u) && u.def?.position === 'MELEE';
|
||||
/** Base (normal) chess id of an operator (normal and elite share it). */
|
||||
export const baseChessId = (u) => String(u?.def?.baseId ?? u?.defId ?? '').replace(/_b$/, '_a');
|
||||
|
||||
|
||||
Reference in new issue
Block a user