feedback5 WAA: the 孤岛风云 prisoners leave the gate confined and change model as their official prefabs do — grey while 【禁锢】, the blinking orange warning before the last confined attack, red once freed; the 4th attack already hits freed (community report of 2026-10-06 「囚徒类敌人出门就是已解放的模型」)
- Cause, client: the prisoner skeletons carry three clip sets whose collar light is grey, blinking orange and red. The official battle prefabs (local client battle/enm_pfb_6.ab: the Graphic component's anim key -> clip table, the modes' replace pairs, the clip the Spine starts on) draw mode Default (【禁锢】) on the grey set, mode R (the warning) on the orange set and mode L (【解放】) on the red one. The name-based role resolver gave 普通囚犯 / 老练囚犯 their unnumbered set — the red one — so they came out of the gate freed; no FORMS entry existed, so no prisoner ever changed (强壮囚犯 / 拳师囚犯 / 重犯 / 传奇重犯 stayed grey). - Cause, sim: buff_template_data enemy_confinement[atk_cnt] spends a charge ON_BEFORE_ATTACK (not while 麻痹) and switches to mode R when one is left; enemy_liberty_listener[warning] switches to mode L before the next attack (PRTS "进行第4次攻击前,切换至解放状态"). archetypes.js prisoner() counted on the 'attack' hook, after the damage, so the 4th attack still hit confined, and it sent no form. - Now: prisoner() counts in `before` (an attack 麻痹 interrupts never gets there, PRTS 拳师囚犯), setForm 'warning' (fx 'phase', drawn silently: kinds.js SILENT_PHASES) before attack times-1 and 'liberty' (fx 'liberate') before attack times; 重犯's free-all and 杰斯顿's KO switch the freed ones too. render/units.js FORMS maps 'warning' / 'liberty' for the six skeletons (普通 / 老练囚犯 *2 / unnumbered, 强壮囚犯 *2 / *3, 拳师囚犯 / 重犯 / 传奇重犯 *_orange / *_red). tools/assets/spine.mjs PREFAB_SPINE_ROLES gives 普通囚犯 / 老练囚犯 their grey *3 set; data/assets.json regenerated (fetch-assets --offline --add-only, JSON compare: only those two anims and the hash), data/enemies.json too (build-data --offline: only their attackAnim.clip Attack -> Attack3, same length and strike frame). The 3D board draws the same Pixi views. - Docs: ASSETS.md (PREFAB_SPINE_ROLES, the prisoner forms), SIM.md (the form fx), design/client.md (FORMS). - Tests: test/content/feedback5-prisoners.test.js (the six: warning before attack 3, attack 4 hits with ATK +50 %, the forms reach the client and UnitInfo; free-all; 麻痹), test/render/feedback5-prisoners.test.js (manifest = the prefab's grey set, FORMS sets, view clips, PREFAB_SPINE_ROLES = the committed manifest) — both fail on the parent but the 麻痹 pin; test/render/feedback5-prisoners.browser.test.js (RENDER_E2E=1: three prisoners on the 2D and the 3D board, each model's set follows its sim form). - Golden: 28 scenarios. Only the warning's new 'phase' fx (the prisoner fell before its 4th attack): roster-001, roster-003, roster-007, roster-024, roster-033, bond-miraShip-low. The 4th attack now hits freed, one attack earlier than before, so the fight after it moves: roster-004, roster-022, roster-026, bond-kazimierzShip-low, bond-raidShip-low, bond-soloShip-low, bond-victoriaShip-low, bond-visiShip-low, standin-01, diy-024, diy-061, diy-065, diy-066, diy-094, diy-097, diy-104, diy-105, diy-127; only the per-second snapshots besides the fx: roster-021, diy-017; and the bot matches whose battles field prisoners: solo-ABYSS-2, solo-HARD-9-boosted.
This commit is contained in:
1 parent
e1ffcd1b07
commit
6372f2892b
18 files changed
+788
-352
No files matched your search
+29
-2
@@ -107,8 +107,32 @@ export const LOCAL_SPINE_ROLES = Object.freeze({
|
||||
},
|
||||
});
|
||||
|
||||
/** The confined clips of 普通囚犯 / 老练囚犯: their grey *3 set (PREFAB_SPINE_ROLES). */
|
||||
const PRISONER_GREY_3 = Object.freeze({
|
||||
idle: 'Idle3', deploy: 'Idle3', attack: clipOf('Attack3'), skill: { ...clipOf('Attack3', 'attack'), index: 0, idle: null },
|
||||
die: 'Die3', move: clipOf('Move3'),
|
||||
});
|
||||
/**
|
||||
* `roles` with the fix of LOCAL_SPINE_ROLES applied: each fixed role whose clips all exist in `durations` replaces the
|
||||
* Role fixes of web enemy models from their official battle prefabs, for skeletons whose clip names mislead the resolver
|
||||
* (by name): model id → roles replacing the resolved ones (the others are kept); processModels applies them, so
|
||||
* data/assets.json carries them. A fix naming a clip the skeleton lacks is dropped and reported. Source: the prefab's
|
||||
* animation table (its Graphic component: anim key → clip) and the clip its Spine starts on, read from the local client's
|
||||
* battle/enm_pfb_*.ab (tools/local-extract, UnityPy).
|
||||
* - 普通囚犯 / 老练囚犯 (enemy_1116_liprr / _2, 孤岛风云 prisoners): three clip sets whose collar light is red (Idle, Move …),
|
||||
* blinking orange (Idle2 …) and grey (Idle3 …). The prefab maps its keys Idle / Move / Attack / Die to the grey *3 set
|
||||
* and starts on Default3 — mode Default, 【禁锢】 —, the orange *2 set is its mode R (the warning before the last
|
||||
* confined attack) and the red unnumbered set its mode L, 【解放】. The resolver took the unnumbered set, so they came out
|
||||
* of the gate already freed (community report of 2026-10-06). The other prisoners' names already resolve to their grey
|
||||
* set (强壮囚犯's Idle is its grey one; 拳师囚犯 / 重犯 / 传奇重犯 *_grey); every prisoner's later sets are the render/units.js
|
||||
* FORMS 'warning' / 'liberty' the sim switches to (content/enemies/archetypes.js prisoner).
|
||||
*/
|
||||
export const PREFAB_SPINE_ROLES = Object.freeze({
|
||||
enemy_1116_liprr: PRISONER_GREY_3,
|
||||
enemy_1116_liprr_2: PRISONER_GREY_3,
|
||||
});
|
||||
|
||||
/**
|
||||
* `roles` with the fix of LOCAL_SPINE_ROLES / PREFAB_SPINE_ROLES applied: each fixed role whose clips all exist in `durations` replaces the
|
||||
* resolved one; `missing` lists the roles left as resolved because a clip is missing.
|
||||
* @param {any} roles resolveRoles output
|
||||
* @param {Record<string, any>|undefined} fix
|
||||
@@ -293,7 +317,10 @@ export async function processModels(models, { root, dl, cachePath, download = tr
|
||||
nextCache[m.skel.rel] = { key: ck, info: sk };
|
||||
if (sk.missingRegions?.length) problems.push(`${m.key}: ${sk.missingRegions.length} attachment(s) not in atlas (e.g. ${sk.missingRegions[0]})`);
|
||||
if (!sk.animations.length) { problems.push(`${m.key}: skeleton has no animations`); continue; }
|
||||
const anims = resolveRoles(sk.animations, { skillIndices: m.skillIndices, durations: sk.durations });
|
||||
const id = String(m.key).startsWith('enemy:') ? String(m.key).slice('enemy:'.length) : null;
|
||||
const fixed = applyRoleFix(resolveRoles(sk.animations, { skillIndices: m.skillIndices, durations: sk.durations }), id ? PREFAB_SPINE_ROLES[id] : undefined, sk.durations);
|
||||
if (fixed.missing.length) problems.push(`${m.key}: role fix not applied (clip missing) for ${fixed.missing.join(', ')}`);
|
||||
const anims = fixed.roles;
|
||||
entries.set(m.key, {
|
||||
skel: assetUrl(m.skel.rel),
|
||||
atlas: assetUrl(m.atlas.rel),
|
||||
|
||||
Reference in new issue
Block a user