Playtest #3 fixes: lost models, picking, live LP, temp overflow, 蕾缪安 S3, 回环射手, FX, detail card, spinners
- #1 lost operator models: the Spine store no longer hands out a skeleton whose unload is in flight (PIXI.Assets.unload is async); eviction runs 1 s after a release and the empty-scene budget only after 3 s - #7 picking: one shared rule (render/pick.js, pixel probe where bodies overlap) for prep/battle clicks, hover, the enemy pen and equipment drops; the drag ghost stands on its drop tile; hover probes capped at one per frame - #2 the top-bar LP drops live as the own battle's enemies enter the blue gate (−N, 联防中), teammates' pending LP in the team panel - #3 temp overflow pieces that arrive after a prep deadline survive through the next prep (tempDue); temp-row warning and ready-button reason - #4 蕾缪安 S3: locks every 0.5 s, then one shell every 0.3 s in lock order (PRTS notes), bombardShell fx - #5 回环射手: real boomerang (out 15, back 3.75 tiles/s, attack only when every boomerang is caught) - #6 visible projectiles, muzzle flashes, slashes, skill bursts and auras at unchanged frame cost - #8 特质 right under the detail card header, with its official type icon - #9 no spinning busy cursors / spinners next to texts; game data warmed before the match - docs, recordings and tests updated (2414 unit tests, all browser suites green)
This commit is contained in:
1 parent
01a44cd288
commit
0aba602ecf
72 files changed
+5132
-571
No files matched your search
+3
-2
@@ -16,8 +16,9 @@
|
||||
// --rehearsal N layouts each bot rehearses per prep with the real sim (default: the Match default, 3; 0 = off,
|
||||
// faster sweeps with the heuristic placement only)
|
||||
// --check audit every match: engine invariants at every phase change + rule checks (server/match/audit.js:
|
||||
// income, upgrade price, freeze, shop odds/bans, drafts, 联防 helpers, settle LP, final assault
|
||||
// pairing/pool, hidden core, titles, deadlines). Exit code 1 when anything is violated.
|
||||
// income, upgrade price, freeze, shop odds/bans, temp overflow lifetime (no piece outlives the prep it is
|
||||
// due at), drafts, 联防 helpers, settle LP, final assault pairing/pool, hidden core, titles, deadlines).
|
||||
// Exit code 1 when anything is violated.
|
||||
// --errors per-source error summary over all runs: sim/content errors grouped by content module + handler label
|
||||
// (+ unit) with occurrence and battle counts, meta handler errors by registry key, match engine errors
|
||||
// --odds shop tier distribution of rolled chess slots per shop level (all runs)
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
// enemy-pen demo (render-demo ?pen=<name>). Also writes public/dev/recordings/index.json.
|
||||
//
|
||||
// Usage: node tools/record-battle.mjs [--only name,name] [--out dir] [--seed n] [--max seconds]
|
||||
// (`--max` caps every scenario; without it a scenario's own `max` — else 90 game s — applies, so a plain run
|
||||
// reproduces the committed recordings byte for byte.)
|
||||
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
@@ -39,6 +41,8 @@ const OUT = path.resolve(ROOT, typeof opt.out === 'string' ? opt.out : 'public/d
|
||||
const ONLY = typeof opt.only === 'string' ? new Set(opt.only.split(',')) : null;
|
||||
const SEED = Number(opt.seed ?? 20260927) >>> 0;
|
||||
const MAX_SECONDS = Number(opt.max ?? 90);
|
||||
/** Game seconds recorded at most for scenario `sc`: `--max`, else its own `max`, else 90. */
|
||||
const maxSecondsOf = (sc) => (opt.max != null ? MAX_SECONDS : Number(sc.max ?? MAX_SECONDS));
|
||||
|
||||
const quiet = { warn() {}, error() {}, info() {}, debug() {} };
|
||||
const ds = getDefaultSource();
|
||||
@@ -111,7 +115,7 @@ const SCENARIOS = [
|
||||
},
|
||||
{
|
||||
name: 'late-m01-r13', title: '常规作战 · 源石流发生装置 · R13(官方波次)', kind: 'normal', stageId: 'act2autochess_m01', modeId: 'mode_multi_hard', round: 13,
|
||||
wave: 'official', waveSeed: 5,
|
||||
wave: 'official', waveSeed: 5, max: 110, // the whole round (55 real s = 110 game s)
|
||||
players: () => [{ playerId: 'P1', seat: 0, side: 'L', colOffset: 0, units: lineup('act2autochess_m01', ['星熊*', '银灰*', '斯卡蒂*', '莫斯提马*', '白面鸮', '寒芒克洛丝*', '阿罗玛', '远牙*']) }],
|
||||
},
|
||||
{
|
||||
@@ -169,7 +173,7 @@ function record(sc) {
|
||||
const frames = [];
|
||||
let field = null;
|
||||
let ticks = 0;
|
||||
const maxT = Math.min(MAX_SECONDS, sc.kind === 'boss' ? timeLimit : timeLimit + 1);
|
||||
const maxT = Math.min(maxSecondsOf(sc), sc.kind === 'boss' ? timeLimit : timeLimit + 1);
|
||||
while (!b.finished) {
|
||||
b.step();
|
||||
ticks++;
|
||||
|
||||
Reference in new issue
Block a user