From 1aed315579b3450f31659721b464e1c71682dbeb Mon Sep 17 00:00:00 2001 From: sganggs Date: Sat, 3 Oct 2026 23:43:28 +0800 Subject: [PATCH] =?UTF-8?q?feedback2=20WG:=20=E5=8F=B2=E5=B0=94=E7=89=B9?= =?UTF-8?q?=E5=B0=94's=20=E4=BD=99=E7=83=AC=20gives=20her=20a=20visible=20?= =?UTF-8?q?=E7=A6=81=E7=96=97=20until=20she=20leaves=20=E2=80=94=20medics?= =?UTF-8?q?=20heal=20others,=20her=20own=20heals=20stop,=20HP=20regen=20an?= =?UTF-8?q?d=20S3's=20start=20heal=20(=E6=97=A0=E8=A7=86=E7=A6=81=E7=96=97?= =?UTF-8?q?)=20still=20reach=20her=20(GitHub=20#52)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/js/render/style.js | 2 ++ public/js/render/textures.js | 10 +++++++++- server/sim/content/kits/tier5.js | 13 +++++++++++-- server/sim/damage.js | 8 +++++++- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/public/js/render/style.js b/public/js/render/style.js index 8729b145..28a006b1 100644 --- a/public/js/render/style.js +++ b/public/js/render/style.js @@ -125,6 +125,8 @@ export const STATUS_ICON = Object.freeze({ silence: 'silence', slow: 'slow', sluggish: 'slow', bind: 'bind', fear: 'fear', tremble: 'fear', weaken: 'weaken', levitate: 'levitate', taunt: 'taunt', defDown: 'weaken', resDown: 'weaken', aspdDown: 'slow', disarm: 'silence', burn: 'burn', burnBurst: 'burn', neural: 'neural', neuralBurst: 'neural', necrosis: 'necrosis', apoptosis: 'necrosis', + // 禁疗 (sim status 'healFree': 史尔特尔's 余烬 — no heal reaches her until she leaves) + healFree: 'healFree', }); /** Keyword fallbacks for namespaced / content status keys ('ab:frost', 'reed2:scorch', 'skill:shotst_shred' …). */ diff --git a/public/js/render/textures.js b/public/js/render/textures.js index 725f2f6e..a8fd0309 100644 --- a/public/js/render/textures.js +++ b/public/js/render/textures.js @@ -835,7 +835,7 @@ export function fxAtlas() { return _fx; } -export const STATUS_KEYS = ['stun', 'freeze', 'cold', 'stealth', 'shield', 'fragile', 'sleep', 'invuln', 'silence', 'slow', 'bind', 'fear', 'weaken', 'levitate', 'taunt', 'burn', 'neural', 'necrosis', 'blocked', 'skill']; +export const STATUS_KEYS = ['stun', 'freeze', 'cold', 'stealth', 'shield', 'fragile', 'sleep', 'invuln', 'silence', 'slow', 'bind', 'fear', 'weaken', 'levitate', 'taunt', 'burn', 'neural', 'necrosis', 'blocked', 'skill', 'healFree']; function drawStatusIcon(c, key, x, y, s) { const cx = x + s / 2, cy = y + s / 2; @@ -930,6 +930,14 @@ function drawStatusIcon(c, key, x, y, s) { c.fillStyle = '#ffe066'; star(c, cx, cy, 10, 4.5); break; } + case 'healFree': { // 禁疗: a green heal cross struck through in red + disc('rgba(15,40,20,0.92)', '#7ee08a'); + c.fillStyle = '#9dffa8'; + c.fillRect(cx - 2.5, cy - 9, 5, 18); c.fillRect(cx - 9, cy - 2.5, 18, 5); + c.strokeStyle = '#ff5a5a'; c.lineWidth = 3; + c.beginPath(); c.moveTo(cx - 10, cy + 10); c.lineTo(cx + 10, cy - 10); c.stroke(); + break; + } default: disc('rgba(30,30,30,0.9)', '#ccc'); } } diff --git a/server/sim/content/kits/tier5.js b/server/sim/content/kits/tier5.js index b6859140..5ab0711c 100644 --- a/server/sim/content/kits/tier5.js +++ b/server/sim/content/kits/tier5.js @@ -1050,7 +1050,8 @@ const KITS = { // --------------------------------------------------------------------------------------------------------------- // 史尔特尔 — S3 黄昏 (toggle, 持续时间无限): full heal, ATK +, range +2, 3 targets, max HP +5000 (flat), HP loss ramping - // to 20 % max HP/s over 60 s. T1 熔火: ignores 20 RES. T2 余烬: lethal damage keeps HP ≥ 1 for 8 s, then she withdraws. + // to 20 % max HP/s over 60 s. T1 熔火: ignores 20 RES. T2 余烬: lethal damage keeps HP ≥ 1 for 8 s (不死 + 禁疗), then she + // withdraws. // Module (elite): ASPD +8 while not blocking. // S1 烈焰魔剑 (instant, attack SP): next attack atk_scale × ATK; a kill refills all SP at once. // S2 熔核巨影 (duration): ATK +, range +1, 2 targets; an attack that hits a single enemy is ×critical atk_scale. @@ -1084,7 +1085,8 @@ const KITS = { onStart({ battle, unit }) { unit.mem.twilightT = 0; unit.mem.twilightAcc = 0; - battle.heal(unit, unit, unit.s.maxHp, { self: true }); + // "立即恢复所有生命" — PRTS 技能3 备注 "(无视禁疗)": it reaches her during 余烬 too + battle.heal(unit, unit, unit.s.maxHp, { self: true, ignoreHealFree: true }); battle.fx('aoe', { x: unit.x, y: unit.y, id: unit.id, r: 1, skill: 'surtr' }); }, onTick({ battle, unit, dt }) { @@ -1101,6 +1103,12 @@ const KITS = { talents: [ { install(battle, unit) { permBuff(battle, unit, 'surtr:magma', { resIgnoreFlat: num(t0.magic_resist_penetrate_fixed) }); } }, { install(battle, unit) { // 余烬 + // PRTS 天赋备注: "持有不死的情况下不会触发此天赋" (a 不死 that prevented the blow first: `c.prevented` — 坚固维式重锤's + // lock, PRIO_REVIVE −100, runs after this −60 on the same first lethal blow [ASSUMED order], so it never starts + // while 余烬 is unused). "触发本天赋后,获得禁疗与不死": 不死 = every later lethal blow is prevented (`mem.ember`); + // 禁疗 (异常效果 HEAL_FREE "无法成为治疗类能力的目标,且受到的治疗量变为0", an HP-regen attribute excepted) = flags + // noHeal (no heal pick, no heal from others) + healFree (her own heals too; S3's start heal "无视禁疗"), shown as + // the status 'healFree' until she leaves. "强制退出战场视为撤回干员": a retreat (Battle.retreat drops the buff). const wait = num(t1['surtr_t_2[withdraw].interval'], 8); battle.on('deploy', (c) => { if (c.unit === unit) unit.mem.ember = false; }, { owner: unit }); battle.on('fatal', (c) => { @@ -1109,6 +1117,7 @@ const KITS = { if (unit.mem.ember) return; unit.mem.ember = true; const dep = unit.deploySeq; + battle.addBuff(unit, { key: 'surtr:ember', status: 'healFree', flags: { noHeal: true, healFree: true } }); battle.fx('ember', { x: unit.x, y: unit.y, id: unit.id }); battle.after(wait, () => { if (unit.alive && unit.deploySeq === dep) battle.retreat(unit, { reason: 'retreat' }); }, { owner: unit }); }, { owner: unit, priority: -60 }); diff --git a/server/sim/damage.js b/server/sim/damage.js index 2399ef2e..12f647d5 100644 --- a/server/sim/damage.js +++ b/server/sim/damage.js @@ -500,11 +500,17 @@ export function reduceElement(target, amount, el = null) { return removed; } -/** Heal pipeline. Returns the HP actually restored. */ +/** + * Heal pipeline. Returns the HP actually restored. `noHeal` stops heals from others (`self` heals pass); `healFree` (禁疗, + * PRTS 异常效果 HEAL_FREE "受到的治疗量变为0") stops the unit's own too — except an HP-regeneration attribute (`regen`: + * "增减生命回复速度或生命回复速度(百分比)属性的效果不会被识别为治疗类能力") and a heal that ignores it (`ignoreHealFree`: + * 史尔特尔 S3's start heal, PRTS "无视禁疗"). + */ export function heal(battle, source, target, amount, opts = {}) { if (!target || !target.alive || target.removed || !target.deployed || target.bossPool) return 0; const self = source === target || !!opts.self; if (!self && (target.s.flags.noHeal || (target.profile && target.profile.noHeal))) return 0; + if (target.s.flags.healFree && !opts.regen && !opts.ignoreHealFree) return 0; let amt = amount * (source && source.s ? source.s.healingDealtMul : 1) * target.s.healingTakenMul; if (!(amt > 0) || !Number.isFinite(amt)) return 0; if (battle._hooks.heal) {