Files

80 lines
3.3 KiB
JavaScript

// Damage-number rendering: the default path still pops every hit; official mode shows only a marked red integer
// or a yellow MISS, and does not merge those into the typed running totals.
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, FX;
before(async () => {
fake = installFakePixi();
FX = await import('../../public/js/render/fx.js');
});
after(() => fake?.restore());
const cam = presetCamera('normal', { width: 1600, height: 900 });
function unit(id, x, y) {
return { id, x, y, z: 0, hover: 0, _headTiles: 1.2, alive: true, destroyed: false, maxHp: 3000, info: { defId: 'char_x' }, onHit() {} };
}
function makeFx(views) {
const map = new Map(views.map((v) => [v.id, v]));
const settings = { quality: 'high', damageNumbers: true, officialDamageNumbers: false };
const fx = new FX.FxSystem({
...fakeViewCtx(fake.P), settings, cam: () => cam, heightAt: () => 0, timeScale: () => 2,
loadLevel: () => 0, subProfOf: () => null, view: (id) => map.get(id) || null,
screenSize: () => ({ width: 1600, height: 900 }), fieldTop: () => 120,
});
return { fx, settings };
}
test('official mode hides ordinary hits and heals, and draws a marked red number without merging', () => {
const v = unit(1, 4, 9);
const { fx, settings } = makeFx([v]);
fx.damage(v, 40, 'phys', null);
fx.damage(v, 60, 'phys', null);
assert.equal(fx.nums.length, 1, 'default mode still merges same-style hits');
assert.equal(fx.nums[0].style, 'phys');
assert.equal(fx.nums[0].value, 100);
assert.equal(fx.nums[0].text.text, '100');
fx.heal(v, 15);
assert.ok(fx.nums.some((n) => n.style === 'heal' && n.text.text === '+15'));
for (const n of fx.nums.splice(0)) fx._releaseNum(n);
settings.officialDamageNumbers = true;
fx.damage(v, 40, 'phys', null);
fx.heal(v, 15);
assert.equal(fx.nums.length, 0, 'an unmarked hit and a heal draw no digits');
fx.damage(v, 40, 'phys', null, 'r');
fx.damage(v, 25, 'true', null, 'r');
assert.equal(fx.nums.length, 2, 'official reds are separate popups');
assert.deepEqual(fx.nums.map((n) => n.text.text), ['40', '25']);
assert.ok(fx.nums.every((n) => n.style === 'crit'));
fx.damage(v, 0, 'phys', null, 'r');
assert.equal(fx.nums.at(-1).text.text, '0');
assert.equal(fx.nums.at(-1).style, 'crit');
settings.damageNumbers = false;
const held = fx.nums.length;
fx.damage(v, 90, 'phys', null, 'r');
fx.simFx('dodge', v.x, v.y, { id: v.id, num: 'm' });
assert.equal(fx.nums.length, held, 'turning damage numbers off hides official digits too');
});
test('a dodge marked num:m shows MISS only while official numbers are on', () => {
const v = unit(3, 6, 10);
const { fx, settings } = makeFx([v]);
fx.simFx('dodge', v.x, v.y, { id: v.id, num: 'm' });
assert.equal(fx.nums.filter((n) => n.style === 'miss').length, 0);
settings.officialDamageNumbers = true;
fx.simFx('dodge', v.x, v.y, { id: v.id });
assert.equal(fx.nums.filter((n) => n.style === 'miss').length, 0);
fx.simFx('dodge', v.x, v.y, { id: v.id, num: 'm' });
const miss = fx.nums.filter((n) => n.style === 'miss');
assert.equal(miss.length, 1);
assert.equal(miss[0].text.text, 'MISS');
});