# Project: FreeExile High-Fidelity PBR PoT Texture Atlas VFX & Cocos 3.8.x Pipeline

## Architecture
- **Asset Synthesis & Texture Packing Engine (`tools/asset_pipeline/`)**:
  - `produce_all_missing_skills_vfx.py`: High-fidelity VFX synthesis for 12 Active Skills and 5 Support Sigils.
  - `pbr_texture_synthesizer.py`: PoT packing ($1024 \times 1024$ / $2048 \times 2048$), Tangent-Space Sobel Normal Maps with BGR channel ordering ($N_z$ in Blue, mean $> 128.0$), 8-iteration morphological Dilation Padding.
  - `astc_compressor.py`: ASTC 4x4 binary generator with canonical 16-byte header and WebP companion files for Apple Metal iOS.
  - `generate_monster_and_character_pipelines.py`: Directory structure and extensible templates for 10 Monster Archetypes (8-dir) and 6 Exile Character classes + Song Binh weapon pairs.
- **Cocos Creator 3.8.x Client Engine (`client/cocos/assets/`)**:
  - `scripts/animation/SpriteAtlasRenderer.ts`: Zero-allocation hot path update loop with reusable scratch Rect/Vec2 and flexible manifest adapter.
  - `scripts/combat/SkillVfxPlayer.ts`: Event-driven pooled VFX player listening to `CombatController:skillCasted` and rendering PBR sprite quads with pivot `[0.5, 0.90]`.
  - `resources/shaders/sprite_pbr.effect`: PBR shader sampling Albedo, Tangent Normal map, and Emissive map with Blinn-Phong specular and rim lighting.
  - `resources/vfx/`: Binary atlases (`savage_primal_skills_vfx_atlas.png`, `_normal.png`), UV manifest (`.json`), and ASTC companions.
- **Verification & Test Track (`tests/`)**:
  - `tests/e2e_cocos/test_vfx_texture_atlas_pipeline_e2e.py`: Opaque-box requirement verification (Tiers 1-4).
  - `tests/e2e/test_asset_campaign_and_pipeline_e2e.py`: Asset campaign integrity and Blue-channel mean validation.

## Feature Inventory
| # | Feature | Description | Milestone | Source |
|---|---------|-------------|-----------|--------|
| 1 | 12 Active Skills High-Fidelity VFX | Render complete frame strips for skills 1001 to 1012 | M1 | R1 |
| 2 | 5 Support Sigils High-Fidelity VFX | Render complete frame strips for sigils 2001, 2002, 2004, 2005, 2006 | M1 | R1 |
| 3 | Power-of-Two (PoT) Texture Packing | Pack strips into 1024x1024 or 2048x2048 PoT binary textures | M1 | R2 |
| 4 | Tangent-Space Sobel Normal Maps | Generate Sobel normals with BGR channel fix (B=Nz, Blue mean > 128.0) | M1 | R2 |
| 5 | Dilation Padding Algorithm | 8-iteration morphological dilation to eliminate black halos/alpha bleed | M1 | R2 |
| 6 | Unified UV JSON Manifest | Emit frame coordinates, size, duration, indices, pivot [0.5, 0.90] | M1 | R4 |
| 7 | Binary Asset Export to Cocos Resources | Export albedo, normal map, JSON to `client/cocos/assets/resources/vfx/` | M1 | R3 |
| 8 | ASTC 4x4 Mobile Compression | Support ASTC 4x4 containers (8.0 bpp) for Apple Metal iOS | M1 | R3 |
| 9 | Monster & Character Pipeline Structure | Extensible directory layout and templates for 10 monsters & 6 heroes | M1 | R5 |
| 10 | Zero-Allocation SpriteAtlasRenderer | Refactor update loop to eliminate `new Rect` allocations at 120 FPS | M2 | R4 |
| 11 | Flexible Manifest Adapter | Support both sequential and explicit frame lookup in Cocos | M2 | R4 |
| 12 | SkillVfxPlayer Event Component | Pool-based VFX player listening to `skillCasted` from CombatController | M2 | R4 |
| 13 | PBR Shader Material Binding | Ensure `sprite_pbr.effect` and material bind Albedo + Normal + Emissive | M2 | R3, R4 |
| 14 | E2E Requirement Test Suite | Comprehensive multi-tier test suite verifying 100% of requirements | M3 | Acceptance |

## Milestones
| # | Name | Scope | Dependencies | Status |
|---|------|-------|-------------|--------|
| M1 | VFX Asset Generation & PBR PoT Pipeline | Features 1, 2, 3, 4, 5, 6, 7, 8, 9 | none | DONE |
| M2 | Cocos 3.8 SpriteAtlasRenderer & SkillVfxPlayer | Features 10, 11, 12, 13 | M1 | DONE |
| M3 | E2E Testing Track & Test Infrastructure | Feature 14 (Tiers 1-4 test suite, TEST_READY.md) | none | DONE |
| M4 | Final Milestone: 100% E2E Pass & Forensic Audit | Verification pass of all tiers, Challenger tests, Forensic Audit | M1, M2, M3 | DONE |

## Interface Contracts

### Python Asset Pipeline ↔ Cocos Creator Manifest
- **File**: `client/cocos/assets/resources/vfx/savage_primal_skills_vfx_atlas.json`
- **Schema**:
```json
{
  "name": "savage_primal_skills_vfx_atlas",
  "textureWidth": 2048,
  "textureHeight": 2048,
  "frameWidth": 128,
  "frameHeight": 128,
  "defaultPivot": [0.5, 0.90],
  "clips": {
    "skill_1001_lightning_sword": {
      "frameCount": 8,
      "fps": 16,
      "loop": false,
      "frames": [
        {"index": 0, "x": 0, "y": 0, "w": 128, "h": 128, "pivot": [0.5, 0.90]},
        {"index": 1, "x": 128, "y": 0, "w": 128, "h": 128, "pivot": [0.5, 0.90]}
      ]
    }
  }
}
```

### CombatController ↔ SkillVfxPlayer Event Contract
- **Event**: `EventBus.emit('skillCasted', { skillId: number, targetPos?: Vec2, isCrit?: boolean, ctx?: any })`
- **Handler**: `SkillVfxPlayer.onSkillCasted(data)` grabs available pooled `Node` with `Sprite` + `SpriteAtlasRenderer`, sets clip to `skill_${skillId}_*`, positions at player/target with pivot `[0.5, 0.90]`, and returns to pool on clip completion.

## Code Layout
- `tools/asset_pipeline/produce_all_missing_skills_vfx.py`: VFX synthesizer for all 12 skills + 5 sigils
- `tools/asset_pipeline/pbr_texture_synthesizer.py`: PoT packing, Sobel normal map generator, dilation padding
- `tools/asset_pipeline/astc_compressor.py`: ASTC 4x4 container generator
- `tools/asset_pipeline/monster_character_pipeline_scaffold.py`: Directory and templates for monsters and exile classes
- `client/cocos/assets/scripts/animation/SpriteAtlasRenderer.ts`: Cocos sprite atlas component
- `client/cocos/assets/scripts/combat/SkillVfxPlayer.ts`: Cocos skill VFX player component
- `client/cocos/assets/resources/vfx/`: Output binary atlases, normal maps, manifests, ASTC containers
- `tests/e2e_cocos/test_vfx_texture_atlas_pipeline_e2e.py`: Requirement verification test suite
