feedback7 R22-RENDER: 琳琅诗怀雅's 香槟炸弹 never shows an HP bar — PRTS 备注 "即使自身生命值未满,模型下方也不会显示生命值槽" (owner item 11); golden: unchanged
The owner reported 「琳琅诗怀雅的2技能的香槟会掉血,会被治疗」. Allies always draw an HP bar (render/units.js _updateHud), so the bomb's every HP change showed. PRTS 香槟炸弹 (实体类型 装置, 1000 HP) says no HP bar is shown even below full HP; nothing there makes it invulnerable or unhealable. Its bar is now hidden at any HP (NO_HP_BAR). Its HP, the damage it takes (活性源石 hurts what stands on it — 70 true damage a second) and healing are left as they are: no invulnerability added; whether it should be unhealable is the owner's decision (no written source says so). Tests: test/render/champagne-hpbar.test.js (new, 2: no bar at full HP, hurt or healed; another summon keeps its bar) 2/2; render/unitview 35/35.
This commit is contained in:
1 parent
2669b6ab57
commit
dd23572b4a
2 files changed
+50
-1
No files matched your search
@@ -117,6 +117,12 @@ const nowMs = () => (globalThis.performance ? globalThis.performance.now() : Dat
|
||||
* 无头像; data/assets.json has no avatar or model for it, so the token fallback showed 圣聆初雪's own face) — the marker of a
|
||||
* frozen gate. */
|
||||
const ICE_TOKENS = new Set(['token_10058_sbell2_icetgt']);
|
||||
/**
|
||||
* Units that never show an HP bar: 琳琅诗怀雅's 香槟炸弹 — PRTS 香槟炸弹 备注 "即使自身生命值未满,模型下方也不会显示生命值槽"
|
||||
* (the owner's report of 2026-10-08, 「香槟会掉血,会被治疗」: the bar showed every change). Only the bar: its HP, the
|
||||
* damage it takes (活性源石 hurts what stands on it) and healing are unchanged — no source makes it invulnerable.
|
||||
*/
|
||||
const NO_HP_BAR = new Set(['token_10031_swire2_gdtrap']);
|
||||
const ICE_FRAME = 0x9fe6ff;
|
||||
/** How long a view waits for its avatar before showing the image-less placeholder diamond. */
|
||||
const PIC_WAIT_MS = 400;
|
||||
@@ -1249,7 +1255,7 @@ export class UnitView {
|
||||
const prep = this.prep;
|
||||
const showBars = !prep && this.alive && this.info.kind !== 'item';
|
||||
const damaged = this.hp < this.maxHp - 0.5;
|
||||
const showHp = showBars && (!this.isEnemy || damaged || this.isBoss);
|
||||
const showHp = showBars && (!this.isEnemy || damaged || this.isBoss) && !NO_HP_BAR.has(this.info.defId);
|
||||
const bw = clamp(s * (this.isBoss ? UNIT.bossBarWidth : UNIT.barWidth), 24, this.isBoss ? 260 : 96);
|
||||
const bh = clamp(s * (this.isBoss ? 0.12 : 0.075), 3, this.isBoss ? 12 : 7);
|
||||
// a knocked-down operator's HUD is its redeploy ring alone, drawn at full strength over the greyed model
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
// test/render/champagne-hpbar.test.js — 琳琅诗怀雅's 香槟炸弹 (token_10031_swire2_gdtrap) never shows an HP bar: PRTS 香槟炸弹
|
||||
// 备注 "即使自身生命值未满,模型下方也不会显示生命值槽" (the owner's report of 2026-10-08, 「香槟会掉血,会被治疗」). Allies
|
||||
// otherwise always draw one (render/units.js _updateHud). Only the bar changes; its HP and healing stay as they are.
|
||||
// Run: node --test test/render/champagne-hpbar.test.js
|
||||
|
||||
import { test, before, after } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { installFakePixi, fakeViewCtx } from './fakepixi.js';
|
||||
import { presetCamera } from '../../public/js/render/projection.js';
|
||||
|
||||
let fake, UnitView;
|
||||
before(async () => {
|
||||
fake = installFakePixi();
|
||||
({ UnitView } = await import('../../public/js/render/units.js'));
|
||||
});
|
||||
after(() => fake.restore());
|
||||
|
||||
const cam = () => presetCamera('normal', { width: 1280, height: 720 });
|
||||
const view = (defId, id) => new UnitView(fakeViewCtx(fake.P, { cam }), { id, side: 'ally', kind: 'summon', defId, tier: 1, x: 11, y: 10, maxHp: 1000, hp: 1000 }, {});
|
||||
const frames = (v) => { for (let i = 0; i < 2; i++) v.update(1 / 60, cam(), i / 60); };
|
||||
const bar = (v) => [v.hpBg.visible, v.hpFill.visible, v.hpGhost.visible];
|
||||
|
||||
test('香槟炸弹 shows no HP bar at full HP, below it, or healed back up', () => {
|
||||
const bomb = view('token_10031_swire2_gdtrap', 1);
|
||||
frames(bomb);
|
||||
assert.deepEqual(bar(bomb), [false, false, false], 'full HP');
|
||||
bomb.sync({ x: 11, y: 10, hp: 860, maxHp: 1000, sp: 0, spMax: 0, flags: 0, anim: 0 }, 1);
|
||||
frames(bomb);
|
||||
assert.equal(bomb.hp, 860, 'the view keeps its HP');
|
||||
assert.deepEqual(bar(bomb), [false, false, false], 'hurt (活性源石: 70 true damage a second)');
|
||||
bomb.sync({ x: 11, y: 10, hp: 1000, maxHp: 1000, sp: 0, spMax: 0, flags: 0, anim: 0 }, 2);
|
||||
frames(bomb);
|
||||
assert.deepEqual(bar(bomb), [false, false, false], 'healed');
|
||||
});
|
||||
|
||||
test('another summon still draws its HP bar, full or hurt', () => {
|
||||
const other = view('token_10000_silent_healrb', 2);
|
||||
frames(other);
|
||||
assert.deepEqual(bar(other), [true, true, true]);
|
||||
other.sync({ x: 11, y: 10, hp: 400, maxHp: 1000, sp: 0, spMax: 0, flags: 0, anim: 0 }, 1);
|
||||
frames(other);
|
||||
assert.deepEqual(bar(other), [true, true, true]);
|
||||
});
|
||||
Reference in new issue
Block a user