render/interp.js keeps the body tile of a b.snap `down` entry (row, col; only when both are integers, so a 4-element entry is unchanged) and render/units.js setDown moves the knocked-down view and its ring there: an operator that fell on another piece's home lies on its own home (PRTS 卫戍协议/帮助 "…尝试返回其自身的初始位置"), and a view built from the unit's deploy info (a field joined mid-battle) no longer stays on its first tile. Tests: test/render/feedback1f-down-tile.test.js (fake PIXI, the sim's own snapshot); opt-in test/render/feedback1f-down-tile.browser.test.js (real sim frames in headless Chrome: drawn, picked and redeployed on its own home).
65 lines
3.6 KiB
JavaScript
65 lines
3.6 KiB
JavaScript
// Player report F5 after the 0.1.0 release, client side: b.snap `down` entries carry the tile a knocked-out operator
|
|
// lies on ([id, respawnAt, respawnTime, state, row, col] — where it fell, or its own home when it fell on another board
|
|
// piece's home: PRTS 卫戍协议/帮助 "若干员被击倒的位置为其他干员或召唤物的初始位置,则在被击倒后,尝试返回其自身的初始
|
|
// 位置"; sim Battle._layBody). render/interp.js keeps them and render/units.js draws the knocked-down view on that tile
|
|
// (headless fake PIXI, test/render/fakepixi.js); older 4-element entries keep the view where it is.
|
|
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';
|
|
import { SnapshotBuffer, normalizeSnapshot } from '../../public/js/render/interp.js';
|
|
import { makeBattle, chessRec } from '../helpers/battleHarness.js';
|
|
|
|
let fake, UnitView, DOWN_STATE, groundZ;
|
|
before(async () => {
|
|
fake = installFakePixi();
|
|
({ UnitView, DOWN_STATE, groundZ } = await import('../../public/js/render/units.js'));
|
|
});
|
|
after(() => fake.restore());
|
|
|
|
const cam = () => presetCamera('normal', { width: 1280, height: 720 });
|
|
const view = (info = {}) => new UnitView(fakeViewCtx(fake.P, { cam }), { id: 1, side: 'ally', kind: 'chess', defId: 'char_x', tier: 3, x: 5, y: 10, maxHp: 1000, dir: 'RIGHT', ...info });
|
|
const frames = (v, n) => { for (let i = 0; i < n; i++) v.update(1 / 60, cam(), i / 60); };
|
|
|
|
test('interp keeps the body tile of a `down` entry (integers only); a 4-element entry stays as it was', () => {
|
|
const s = normalizeSnapshot({ t: 2, units: [], down: [[7, 20, 18, 0, 9, 8], [8, 21, 18, 0], [9, 22, 18, 0, 9.5, 'x']] });
|
|
assert.deepEqual(s.down, [[7, 20, 18, 0, 9, 8], [8, 21, 18, 0], [9, 22, 18, 0]]);
|
|
const buf = new SnapshotBuffer({ delay: 0 });
|
|
buf.push({ t: 1, units: [], down: [[7, 20, 18, 0, 10, 3]] }, 0);
|
|
assert.deepEqual(buf.downAt(1), [[7, 20, 18, 0, 10, 3]]);
|
|
});
|
|
|
|
test('the knocked-down view is drawn on the tile the entry names: a body back on its home moves there', () => {
|
|
const v = view({ x: 6, y: 12 }); // fell on another piece's home (12,6)
|
|
frames(v, 2);
|
|
v.setDown([1, 30, 20, DOWN_STATE.COUNTING, 10, 3], 10); // it lies on its own home (10,3)
|
|
assert.equal(v.alive, false);
|
|
assert.deepEqual([v.x, v.y], [3, 10]);
|
|
frames(v, 30);
|
|
assert.equal(v.z, groundZ(v.ctx, 3, 10), 'on that tile\'s ground');
|
|
assert.ok(v._downRing.root.visible, 'its ring follows');
|
|
// a 4-element entry (an older feed) leaves it where it is
|
|
const w = view({ id: 2, x: 4, y: 11 });
|
|
frames(w, 2);
|
|
w.setDown([2, 30, 20, DOWN_STATE.COUNTING], 10);
|
|
assert.deepEqual([w.x, w.y], [4, 11]);
|
|
});
|
|
|
|
test('end to end: the sim\'s snapshot names the tile the body lies on, the view follows it', () => {
|
|
const op = (id) => chessRec({ id, profession: 'WARRIOR', skill: null });
|
|
const h = makeBattle({ defs: { chess: { e_a: op('e_a'), e_b: op('e_b') } }, units: [{ chessId: 'e_a', row: 12, col: 3 }, { chessId: 'e_b', row: 10, col: 3 }], content: 'none', autoFinish: false });
|
|
h.step();
|
|
const b = h.b, A = h.unit('e_a'), B = h.unit('e_b');
|
|
b.retreat(A, { reason: 'raid' });
|
|
b.redeploy(A, { free: true, tile: [11, 6] });
|
|
b.retreat(B, { reason: 'raid' });
|
|
b.redeploy(B, { free: true, tile: [12, 3] }); // on A's home
|
|
const v = view({ id: B.id, x: B.x, y: B.y });
|
|
frames(v, 2);
|
|
b.kill(B);
|
|
const d = normalizeSnapshot(b.snapshot()).down.find((e) => e[0] === B.id);
|
|
assert.deepEqual(d.slice(4), [10, 3], 'back on its own home');
|
|
v.setDown(d, b.time);
|
|
assert.deepEqual([v.x, v.y], [3, 10]);
|
|
});
|