feedback5 CB2: the countdown summons (医疗探机, 诅咒娃娃, 海嗣; 自选 工程蓄水炮, 沙地兽, 打字机, 本能的召唤) take no damage — 活性源石 included —, are never healed, and their bar shows the life left (community report of 2026-10-06 「赫默的无人机、浊心斯卡蒂的海嗣等这种召唤物不会受到外来伤害…血量随时间减少」)

Official: PRTS 斯卡蒂的海嗣 备注 「持有禁疗、无敌」, the token prefabs of 海嗣 and 沙地兽 carry abnormal flags 5 + 7 (无敌,
禁疗), 工程蓄水炮 7 (禁疗); the report describes the official mode for the drone too — [ASSUMED] 无敌 + 禁疗 for the summons
the base prefabs give no flag (医疗探机, 诅咒娃娃, 打字机, 本能的召唤), and the bar as a timer.
Cause: content/tokens.js / the kits only made them untargetable: a 海嗣 on 活性源石 lost 70 of its 100 HP every second, a
hurt drone drew every medic's heals, and the bar was plain HP. Now: COUNTDOWN_SUMMONS / startCountdown (called where each
lifetime is scheduled: tokens.js scheduleLifetime, 浊心斯卡蒂, 温蒂, 莱伊, 鸿雪, 酒神 kits) give 无敌 + 禁疗 and
Unit.countdown; snapshot.js sends hp = maxHp × the share of the life left (the sim HP stays full, so no selector sees a
low-HP summon). Attacked summons (沙之碑, 狼群 …) are unchanged. The 吟游者 trait therefore cannot refill such a bar (item 32).

Golden: snapshot hashes only (the bar) — roster-003, -016, -018, -035, -045, -046, bond-visiShip-low / -high,
boss-boss_1 / 3 / 5 / 7-pair, unite-1; gameplay too — roster-005 (medics no longer heal the drone), roster-037 and
hidden-boss_9-pair (a 海嗣 / drone under enemy and leader damage stays up: fights change).
Tests: test/sim/feedback5-countdown-summons.test.js (7; fails on the parent: no COUNTDOWN_SUMMONS — and there the 海嗣
lost 70 HP to an 活性源石 tick). Docs: SIM.md token pieces, PLAYING.md 作战中.
This commit is contained in:
sganggs committed 2026-10-07 02:27:33 +08:00
1 parent 64f8bf912a
commit 17c96843ee
15 files changed
+230 -96

No files matched your search

@@ -4,6 +4,7 @@
import { aggregateMods } from '../../../buffs.js';
import { COLS } from '../../../constants.js';
import { bardRegen } from '../../../professions.js';
import { startCountdown } from '../../tokens.js';
import {
num, bv, tbb, tdesc, moduleBb, parseN, live, enemiesIn, isTok, onDefaultSkill, selectedSkill, aura,
} from '../shared/tier6.js';
@@ -148,6 +149,7 @@ function skadi2(bb, chess, def) {
if (t.profile) t.profile.noAttack = true;
const dur = num(t.def?.talents?.[0]?.bb?.duration, parseN(tdesc(def, 0), /持续(\d+(?:\.\d+)?)秒/, 25));
const seq = t.deploySeq, r = t.tileR, c = t.tileC;
startCountdown(battle, t, dur); // a countdown summon: 无敌, 禁疗, its bar = the life left (content/tokens.js)
battle.after(dur, () => {
if (!t.alive || t.deploySeq !== seq) return;
battle.retreat(t, { reason: 'expired', permanent: true });
+4 -1
View File
@@ -44,6 +44,7 @@ import { bodyKeys, bodyInKeys } from '../../../body.js';
import { toLocal } from '../../../dir.js';
import { hasHp } from '../../../damage.js';
import { COLS } from '../../../constants.js';
import { startCountdown } from '../../tokens.js';
const S1 = 'skchr_bgsnow_1';
const S2 = 'skchr_bgsnow_2';
@@ -141,9 +142,11 @@ function typewriterKit(t, owner, chess) {
} }],
install(battle, unit) {
if (sk?.id === TS1) installIamb(battle, unit, num(tb.prob), num(tb.atk_scale, 1), skillOn);
// 持续25秒: leaves `life` s after each deployment
// 持续25秒: leaves `life` s after each deployment — a countdown summon (content/tokens.js startCountdown): 无敌,
// 禁疗 [ASSUMED], its bar = the life left
battle.on('deploy', (ctx) => {
if (ctx.unit !== unit || !(life > 0)) return;
startCountdown(battle, unit, life);
const seq = unit.deploySeq;
battle.after(life, () => { if (unit.alive && unit.deploySeq === seq) battle.retreat(unit, { reason: 'expired', permanent: true }); }, { owner: unit });
}, { owner: unit });
+2 -1
View File
@@ -63,7 +63,7 @@
import { num, up, traitBb, talentBb, skillRec, once } from '../shared/tier1.js';
import { isElite, onElementHit, elementDmg } from '../shared/tier6.js';
import { releaseSkillSummon } from '../../tokens.js';
import { releaseSkillSummon, startCountdown } from '../../tokens.js';
import { absoluteRangeKeys } from '../../../targeting.js';
import { bodyInKeys } from '../../../body.js';
import { hasHp, burstLocked } from '../../../damage.js';
@@ -124,6 +124,7 @@ function callKit(t, owner, b2) {
lured = [];
endAt = battle.time + life;
atk = owner.s.atk; // 缓存攻击力: her ATK at the deployment (PRTS 备注)
startCountdown(battle, tok, life); // a countdown summon (content/tokens.js): 无敌, 禁疗 [ASSUMED], its bar = the life left
const seq = tok.deploySeq;
battle.after(life, () => { if (tok.alive && tok.deploySeq === seq) battle.retreat(tok, { reason: 'expired', permanent: true }); }, { owner: tok });
}, { owner: tok });
+2
View File
@@ -62,6 +62,7 @@ import { acquireTargets, effectiveProfile } from '../../../ai.js';
import { sortEnemyTargets } from '../../../targeting.js';
import { bodyInKeys } from '../../../body.js';
import { PUSH_DIRECTIONAL_MIN_DIST } from '../../../constants.js';
import { startCountdown } from '../../tokens.js';
const S1 = 'skchr_ray_1';
const S2 = 'skchr_ray_2';
@@ -225,6 +226,7 @@ export default {
m.rayBullets = 0;
m.rayCounted = 0;
battle.setExtraRange(unit, m.rayAreaKeys);
startCountdown(battle, t, life); // a countdown summon (content/tokens.js): its bar = the life left
const seq = t.deploySeq;
battle.after(life, () => { if (t.alive && t.deploySeq === seq) battle.retreat(t, { reason: 'expired', permanent: true }); }, { owner: unit });
}, { owner: unit });
+3 -1
View File
@@ -48,6 +48,7 @@
import { num, traitBb, skillRec, up, giveSp } from '../shared/tier1.js';
import { absoluteRangeKeys } from '../../../targeting.js';
import { COLS } from '../../../constants.js';
import { startCountdown } from '../../tokens.js';
const S1 = 'skchr_weedy_1';
const S2 = 'skchr_weedy_2';
@@ -174,9 +175,10 @@ function cannonKit(t, owner) {
},
install(battle, unit) {
battle.addBuff(unit, { key: 'trait:weedyCannon', flags: { noHeal: true }, persist: true, allowDead: true }); // 持有禁疗
// 部署后20秒自动撤退
// 部署后20秒自动撤退 — a countdown summon (content/tokens.js startCountdown): 无敌 [ASSUMED], 禁疗, its bar = the life left
battle.on('deploy', (ctx) => {
if (ctx.unit !== unit || !(life > 0)) return;
startCountdown(battle, unit, life);
const seq = unit.deploySeq;
battle.after(life, () => { if (unit.alive && unit.deploySeq === seq) battle.retreat(unit, { reason: 'expired', permanent: true }); }, { owner: unit });
}, { owner: unit });