Files
ark-stronghold-protocol/tools/assets/local-enemy-spines.json
T
sganggs 04634f5bf7 feedback1d WN: the local-client slug models are an optional overlay; the manifest never depends on the extraction
data/assets.json pointed 灼热源石虫 / 炽焰源石虫 at /assets/local/ files that only exist
where tools/local-extract ran, with no fallback: without the extraction the
asset tests failed, setup re-ran fetch-assets (rewriting the tracked manifest)
and the slugs drew as icon diamonds.

- The web model stays the 源石虫 alias (spine + spineAliasOf). The official
  model is enemies[id].spineLocal: file names in the data/local-assets.json
  group spine/enemy/<id> plus the parsed metadata, from the committed
  tools/assets/local-enemy-spines.json (fetch-assets --local-spines refreshes
  it from the extracted files, read only). The manifest is byte-identical with
  or without the extraction and has no /assets/local/ URL.
- Client: assets.js spineEntry uses spineLocal only when the local manifest
  lists every file (createFieldView awaits assets.local() with the manifest);
  UnitView loads the web model when the local one fails.
- extract.py writes the atlas with size: / pma: true itself (the same text as
  atlas.mjs normalizeAtlas), so the extraction is usable without a fetch pass.
- setup notes when an older extraction lacks the enemy models.
2026-10-03 05:18:31 +08:00

114 lines
2.4 KiB
JSON

{
"about": "Spine metadata of the enemy models only the local client has (tools/local-extract/extract.py ENEMY_SPINES); data/assets.json enemies[id].spineLocal. Written by node tools/fetch-assets.mjs --local-spines (docs/ASSETS.md \"Enemy aliases\").",
"models": {
"enemy_1305_mhslim": {
"skel": "enemy_1305_mhslim.skel",
"atlas": "enemy_1305_mhslim.atlas",
"textures": [
"enemy_1305_mhslim.png"
],
"pma": true,
"anims": {
"idle": "Idle",
"deploy": "Idle",
"attack": {
"begin": null,
"loop": "Attack",
"end": null
},
"attackDown": null,
"skill": {
"begin": null,
"loop": "Attack",
"end": null,
"via": "attack",
"index": 0,
"idle": null
},
"die": "Die",
"move": {
"begin": null,
"loop": "Move",
"end": null
},
"stun": null
},
"animations": {
"Attack": 1,
"Default": 0,
"Die": 1,
"Idle": 2,
"Move": 1
},
"events": [
"OnAttack"
],
"hits": {
"Attack": [
0.667
]
},
"bounds": {
"x": -118.121,
"y": -1.969,
"width": 230,
"height": 164
}
},
"enemy_1305_mhslim_2": {
"skel": "enemy_1305_mhslim_2.skel",
"atlas": "enemy_1305_mhslim_2.atlas",
"textures": [
"enemy_1305_mhslim_2.png"
],
"pma": true,
"anims": {
"idle": "Idle",
"deploy": "Idle",
"attack": {
"begin": null,
"loop": "Attack",
"end": null
},
"attackDown": null,
"skill": {
"begin": null,
"loop": "Attack",
"end": null,
"via": "attack",
"index": 0,
"idle": null
},
"die": "Die",
"move": {
"begin": null,
"loop": "Move",
"end": null
},
"stun": null
},
"animations": {
"Attack": 1,
"Default": 0,
"Die": 1,
"Idle": 2,
"Move": 1
},
"events": [
"OnAttack"
],
"hits": {
"Attack": [
0.667
]
},
"bounds": {
"x": -118.121,
"y": -1.969,
"width": 230,
"height": 164
}
}
}
}