Files
ark-stronghold-protocol/test/render/playtest6_hitcap.test.js
T
sganggs 620f88c0d8 Playtest #6 follow-up (v2.5.1): leader HP review — 直接乘算, one debuff instance, 999 layer cap, 限伤; elite to the board; 假想敌:胄 kit
- co-op leaders died within seconds: leader HP is the official data (40 values pinned); bond / strategy / item /
  机变 / 特质 "+X%" bonuses now add up (PRTS 直接乘算) instead of compounding; a same-named enemy debuff keeps one
  (strongest) instance per target (奥术 across a pair field); leader parts pass damage 1:1; fixed co-op pool (the user's call)
- official limits read from the client: each bond stops at 999 layers (MAX_GARRISON_STACK); a leader hit of 300000+ in
  boss / hidden battles is cancelled (MAX_BATTLE_DAMAGE, 限伤) — shared/constants.js switches, research 11
- a merge that consumes a deployed copy puts the elite on that tile and facing (user-confirmed); gold target highlight,
  promotion effect
- 假想敌:胄 per PRTS: one shell, shells within range, any drone death costs 2 % max HP, 剑/锤 sorties and 瘫痪
- DESIGN §20.10–§20.14; 2842 unit tests, all 28 browser suites green; Chrome = Node on boss fields
2026-10-02 04:19:28 +08:00

37 lines
2.0 KiB
JavaScript

// 限伤 on screen (docs/research/11-limits-official.md §2, DESIGN §20.12): a leader's hit of ≥ 300000 in a boss battle
// is cancelled by the sim (server/sim/damage.js leaderHitCancelled), which emits ['fx', 'hitCap', x, y, { id, n }] and
// no 'dmg' event. The official shows no number for it [ASSUMED]; the renderer draws nothing for the event.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { FxSystem, FX_KINDS, fxSpec } from '../../public/js/render/fx.js';
import { presetCamera } from '../../public/js/render/projection.js';
function recordingFx() {
const cam = presetCamera('boss', { width: 1280, height: 720 });
const calls = [];
const fx = Object.create(FxSystem.prototype);
const rec = (name) => (...a) => { calls.push(name); return name === '_where' || name === '_point' ? { x: a[0], y: a[1], z: 0, v: null } : undefined; };
Object.assign(fx, {
ctx: { cam: () => cam, heightAt: () => 0, fieldRect: () => ({ r0: 0, r1: 5, c0: 0, c1: 20 }), timeScale: () => 2 },
_p: { x: 0, y: 0, s: 0, depth: 0 }, _q: { x: 0, y: 0, s: 0, depth: 0 }, locks: [],
_where: rec('_where'), _point: rec('_point'), particle: rec('particle'), ring: rec('ring'), burst: rec('burst'),
explosion: rec('explosion'), flashScreen: rec('flashScreen'), tileFlash: rec('tileFlash'),
});
fx._chest = (v, out) => Object.assign(out, cam.project(0, 0, 0.5, out));
return { fx, calls };
}
test('hitCap: listed in FX_KINDS as a kind that draws nothing', () => {
assert.equal(FX_KINDS.hitCap.a, 'none');
assert.equal(fxSpec('hitCap', { id: 3, n: 300000 }).a, 'none');
});
test('hitCap: simFx draws nothing (no number, no spark); an unknown kind still gets its generic sparkle', () => {
const { fx, calls } = recordingFx();
fx.simFx('hitCap', 10, 3, { id: 7, n: 412345 });
assert.deepEqual(calls, [], 'nothing drawn for a cancelled leader hit');
fx.simFx('zzzUnknownKind', 10, 3, {});
assert.ok(calls.includes('particle'), 'the generic sparkle still works');
});