feedback1d WN: special Originium slugs drawn with their own official models (D3)

灼热源石虫 / 炽焰源石虫 (enemy_1305_mhslim / _2, the ELEMENT faction's slugs) were drawn with
the plain 源石虫 skeleton: no community dump carries their models, so the asset plan aliased
them to enemy_1007_slime. tools/local-extract/extract.py now extracts their official skeletons
from the client's enemy art bundles (ENEMY_SPINES, pages merged with their alpha textures) into
public/assets/local/spine/enemy/, and fetch-assets plans such a model before any alias
(spine.mjs findLocalEnemyModels, plan.mjs localEnemyModels). public/assets/local is never
pruned. An audit of all 249 enemies against the client's prefabs found no other enemy drawn
with another enemy's model.
This commit is contained in:
sganggs committed 2026-10-03 04:10:13 +08:00
1 parent 7f134737ce
commit 46ccfd55f6
7 files changed
+325 -18

No files matched your search

+13 -3
View File
@@ -20,7 +20,7 @@ npm run assets # = node tools/vendor.mjs && node tools/fetch-assets.mjs
| `--offline` | No network. Re-runs post-processing (atlas fixes, skeleton parsing, WOFF2) on what is already on disk, then rebuilds `data/assets.json`. |
| `--dry-run` | Print the plan (file and model counts, alias notes) and exit. |
| `--refresh-index` | Re-download the two upstream indexes: `audio_data.json` and `models_data.json`. |
| `--prune` | Delete files under `public/assets/` that the manifest no longer references, for example after a mapping change. Without this flag they are only listed in the report. |
| `--prune` | Delete files under `public/assets/` that the manifest no longer references, for example after a mapping change. Without this flag they are only listed in the report. `public/assets/local/` (written by `tools/local-extract`) is never pruned. |
The script is **idempotent**. A file on disk is kept, not re-downloaded, when any one of these holds:
- its size matches the ledger entry from a previous download (`.cache/assets-ledger.json`);
@@ -71,6 +71,7 @@ The research JSONs in `docs/research/` (03, 05, 07) define **which** ids are nee
| Operator battle Spine (Front, Back) | fexli/ArknightsResource `spine/{id}/{id}/{Front,Back}/` | `spine/op/{charId}/{front,back}/{stem}.{skel,atlas,png}` |
| Token Spine | fexli: the default model, or else the first skin variant (`spine/{tokenId}/{variant}/Spine/`) | `spine/token/{tokenId}/{stem}.*` |
| Enemy Spine (PC build, premultiplied alpha) | isHarryh/Ark-Models `models_enemies/{key}/`, file names from `models_data.json` | `spine/enemy/{enemyId}/{stem}.*` |
| Enemy Spine that no dump carries (灼热源石虫 / 炽焰源石虫) | the local client, when `tools/local-extract/extract.py` (`ENEMY_SPINES`) has extracted it; not downloaded | `local/spine/enemy/{enemyId}/{stem}.*` |
| BGM | AA2 `voice` branch `audio/sound_beta_2/music/**` | `audio/bgm/{file}.mp3` |
| SFX (UI, battle, per unit) | AA2 `voice` `audio/sound_beta_2/**`, mapped from `audio_data.json` banks | `audio/sfx/{same sub-path}.mp3` |
| Fonts: Bender Regular and Light, Novecento Wide | TimWangZi/The-font-of-Arknights | `public/fonts/*.{otf,ttf,woff2}`, `public/fonts/fonts.css` |
@@ -207,8 +208,17 @@ Other renderer rules from research 07 §5.4–5.5:
- **Attack speed:** set the attack `timeScale` to `duration / attackInterval`.
- **Model size:** every skeleton is drawn at one `UNIT.modelScale` (render/style.js, 320 skeleton units per tile), which stands for the official standard. The official client also scales each enemy model in its battle prefab: the Graphic / FaceSwitcher / Spine transforms multiply to 0.27 for most enemies and for the operators' battle skins, but not for all of them. For example, 威龙 is 0.16, 妖怪 0.20 and 青铜镜 0.6. The skeletons themselves carry no such scale, because every enemy SkeletonDataAsset uses 0.01. So an enemy is drawn × data/enemies.json `modelScale` (its prefab's product ÷ 0.27, see docs/DATA.md; user playtest #6: 威龙 used to be drawn 1.35× a 妖怪 instead of 1.08×), and its HP bar sits on that model: at its setup-pose bounds' height × the same factors, or, for a skeleton without bounds, at the chibi headroom × `modelScale` (bosses 2.2 tiles). `tools/local-extract/enemy_scales.py` reads the products from a local client, and `tools/build-data.mjs MODEL_SCALES` keeps them.
- **Enemy aliases:** `enemies[id].spineAliasOf` means the model belongs to another enemy. Two cases:
- `enemy_1305_mhslim` has no Spine anywhere, so it uses the slime model. Tint it.
- `_2` boss variants reuse the base model.
- `_2` variants whose official prefab is the base one (鸭爵, 高普尼克, 流泪小子, 圆仔, 假想敌:胄, 假想敌:铳): the base model, as in the game.
- an enemy whose own model no dump carries and that was not extracted from a local client: 灼热源石虫 / 炽焰源石虫
(`enemy_1305_mhslim` / `_2`) fall back to the plain 源石虫 (`plan.mjs ENEMY_SPINE_ALIAS`). Their official skeletons
are in the client's enemy art bundles (`refs/arts/enm_art_*.ab`); `tools/local-extract/extract.py` writes them to
`public/assets/local/spine/enemy/{enemyId}/` (page textures with their `[alpha]` texture merged in: premultiplied RGB
+ A, like Ark-Models), and `npm run assets` then plans that model instead of the alias (`spine.mjs
findLocalEnemyModels`, `plan.mjs localEnemyModels`; an upstream model still wins). The release bundle carries them.
User feedback after 0.1.0 (D3: "所有特殊源石虫的模型全表现为普通源石虫"): the ELEMENT faction spawns up to ten of them a
round. A 2026-10-03 audit of every enemy of `data/enemies.json` (249) against the client's battle prefabs (the
skeleton each prefab's Spine renderer draws) found no other enemy drawn with another enemy's model; 伊利昂的木驮兽
(`enemy_10159_mntrjn`) starts on its `Full` skin (five passengers) in the game and is drawn with the `default` one.
### Other fallbacks