# AutoHero Content Catalog (MVP Companion)

Aligned with `specification.md` sections 2.3–2.4, 4, **5.3**, **6.3–6.4**, 8, 11, and 12. Section **0a**: `gear.form.*`; section **0d**: `gear.ammo.*` и слот `quiver`. **Item scaling** (`ilvl`, `M(rarity)`, `L(ilvl)`) — канон в `specification.md` §6.4.  
Goal: provide engineering-ready IDs and mappings for models, sounds, and VFX intent.

## 0) Equipment Slot Catalog (gear)

Naming convention:
- `gear.slot.<slug>` — canonical slot keys (see `specification.md` §6.3)
- Item instances reference exactly one slot; item family IDs may use `item.<category>.<slug>.v1` when introduced in implementation

| slotId | displayName (EN) | notes |
|---|---|---|
| `gear.slot.main_hand` | Main hand | weapons |
| `gear.slot.off_hand` | Off hand | shield or off-hand weapon |
| `gear.slot.head` | Head | helmet, hood, hat |
| `gear.slot.chest` | Chest | body armor |
| `gear.slot.legs` | Legs | leggings, greaves |
| `gear.slot.feet` | Feet | boots |
| `gear.slot.cloak` | Cloak | cloak, cape, mantle |
| `gear.slot.neck` | Neck | amulet, medallion |
| `gear.slot.finger` | Finger | rings (implementation may use `finger_1` / `finger_2`) |
| `gear.slot.wrist` | Wrist | bracers, bracelets |
| `gear.slot.quiver` | Quiver | arrows/bolts; active only with bow or crossbow in `main_hand` (see §5.3) |

### 0a) Equipment form catalog (виды / подтипы по слотам)

Назначение: стабильные ключи **формы предмета** (визуальный и дизайн-архетип), привязанные к **ровно одному** `gear.slot.*`.  
Используются в данных лута, UI-иконках, генерации имён и связке с `modelId` одежды.

Naming convention:
- `gear.form.<slotKey>.<formSlug>` — канонический ID вида; `<slotKey>` совпадает с суффиксом `gear.slot.<slotKey>`
- Предмет в инвентаре ссылается на `slotId` + опционально `formId` = `gear.form.*`
- Новые виды добавляются только сюда; произвольные строки в коде не вводить

| formId | slotId | displayName (EN) | displayName (RU) | notes |
|---|---|---|---|---|
| `gear.form.main_hand.sword` | `gear.slot.main_hand` | Sword | Меч | baseline blade |
| `gear.form.main_hand.axe` | `gear.slot.main_hand` | Axe | Топор | heavy swing |
| `gear.form.main_hand.dagger` | `gear.slot.main_hand` | Dagger | Кинжал | fast, low base |
| `gear.form.main_hand.mace` | `gear.slot.main_hand` | Mace | Булава | blunt |
| `gear.form.main_hand.staff` | `gear.slot.main_hand` | Staff | Посох | two-handed caster vibe |
| `gear.form.main_hand.spear` | `gear.slot.main_hand` | Spear | Копьё | reach |
| `gear.form.main_hand.bow` | `gear.slot.main_hand` | Bow | Лук | ranged; pairs with `gear.slot.quiver` |
| `gear.form.main_hand.crossbow` | `gear.slot.main_hand` | Crossbow | Арбалет | ranged; pairs with `gear.slot.quiver` |
| `gear.form.off_hand.shield` | `gear.slot.off_hand` | Shield | Щит | block / defense |
| `gear.form.off_hand.buckler` | `gear.slot.off_hand` | Buckler | Баклер | small shield |
| `gear.form.off_hand.orb` | `gear.slot.off_hand` | Orb | Сфера | off-hand caster |
| `gear.form.head.helmet` | `gear.slot.head` | Helmet | Шлем | full head metal |
| `gear.form.head.hood` | `gear.slot.head` | Hood | Капюшон | cloth/leather |
| `gear.form.head.hat` | `gear.slot.head` | Hat | Шляпа | wide brim / travel |
| `gear.form.head.circlet` | `gear.slot.head` | Circlet | Диадема | light headband |
| `gear.form.head.mask` | `gear.slot.head` | Mask | Маска | face cover |
| `gear.form.head.coif` | `gear.slot.head` | Coif | Койф | mail under-helmet |
| `gear.form.chest.plate` | `gear.slot.chest` | Plate cuirass | Латы / кираса | heavy plate |
| `gear.form.chest.mail` | `gear.slot.chest` | Mail hauberk | Кольчуга | ring mail |
| `gear.form.chest.leather` | `gear.slot.chest` | Leather jack | Кожаный доспех | light |
| `gear.form.chest.robe` | `gear.slot.chest` | Robe | Роба | cloth / caster |
| `gear.form.chest.brigandine` | `gear.slot.chest` | Brigandine | Брига | riveted plates on cloth |
| `gear.form.legs.greaves` | `gear.slot.legs` | Greaves | Наколенники / латы ног | plate legs |
| `gear.form.legs.chausses` | `gear.slot.legs` | Chausses | Поножи (кольч.) | mail legs |
| `gear.form.legs.pants` | `gear.slot.legs` | Pants | Штаны | cloth/leather legs |
| `gear.form.legs.tassets` | `gear.slot.legs` | Tassets | Тассы | hanging plates |
| `gear.form.feet.boots` | `gear.slot.feet` | Boots | Сапоги | default footwear |
| `gear.form.feet.sabatons` | `gear.slot.feet` | Sabatons | Сабатоны | plate boots |
| `gear.form.feet.shoes` | `gear.slot.feet` | Shoes | Ботинки / туфли | light |
| `gear.form.feet.sandals` | `gear.slot.feet` | Sandals | Сандалии | open |
| `gear.form.cloak.cloak` | `gear.slot.cloak` | Cloak | Плащ | back slot mantle |
| `gear.form.cloak.cape` | `gear.slot.cloak` | Cape | Накидка | short back |
| `gear.form.cloak.mantle` | `gear.slot.cloak` | Mantle | Мантия | heavy drape |
| `gear.form.neck.amulet` | `gear.slot.neck` | Amulet | Амулет | default neck |
| `gear.form.neck.medallion` | `gear.slot.neck` | Medallion | Медальон | disk |
| `gear.form.neck.pendant` | `gear.slot.neck` | Pendant | Кулон | gem drop |
| `gear.form.neck.talisman` | `gear.slot.neck` | Talisman | Талисман | charm |
| `gear.form.finger.ring` | `gear.slot.finger` | Ring | Кольцо | default ring |
| `gear.form.finger.signet` | `gear.slot.finger` | Signet | Перстень | heavy ring |
| `gear.form.finger.band` | `gear.slot.finger` | Band | Обручь | slim band |
| `gear.form.wrist.bracers` | `gear.slot.wrist` | Bracers | Наручи | armor wrist |
| `gear.form.wrist.bracelet` | `gear.slot.wrist` | Bracelet | Браслет | jewelry |
| `gear.form.wrist.vambraces` | `gear.slot.wrist` | Vambraces | Рукава (латные) | plate forearm |

### 0d) Ammunition catalog (боеприпасы, слот `gear.slot.quiver`)

Naming convention:
- `gear.ammo.<slug>.v1` — каноническое семейство боеприпасов
- Экземпляр несёт `ilvl`, `rarity`; **первичный** бонус к атаке: `primaryOut = round(basePrimary × L(ilvl) × M(rarity))` (§6.4.3)
- **Вторичные** поля (`baseCritBps`, `baseArmorPenBps`): `secondaryOut = round(base × M(rarity))` (§6.4.4). Базисные пункты (bps): `100 = 1.00%`.
- `deltaSpeed` — целое, добавляется к стату **Speed** героя с предмета **без** масштабирования по `ilvl` (только знак и величина из каталога; при необходимости позже — отдельный баланс-пас)

| ammoId | basePrimary | baseCritBps | baseArmorPenBps | deltaSpeed | displayName (EN) | displayName (RU) | notes |
|---|---:|---:|---:|---:|---|---|---|
| `gear.ammo.crude_wood.v1` | 2 | 0 | 0 | 0 | Crude Wood Arrows | Грубые деревянные стрелы | стартовый/дешёвый дроп |
| `gear.ammo.hunting_standard.v1` | 3 | 15 | 0 | 0 | Standard Hunting Arrows | Охотничьи стрелы | лёгкий крит |
| `gear.ammo.flint_tipped.v1` | 4 | 35 | 0 | 0 | Flint-Tipped Arrows | Стрелы с кремнёвым наконечником | универсал |
| `gear.ammo.iron_bodkin.v1` | 5 | 0 | 80 | 0 | Iron Bodkin | Железные бодкины | упор в пробитие, без крита |
| `gear.ammo.steel_broadhead.v1` | 7 | 55 | 40 | -1 | Steel Broadheads | Стальные широкие наконечники | тяжелее, −1 Speed |
| `gear.ammo.silver_anointed.v1` | 6 | 25 | 100 | 0 | Silver-Anointed Bolts | Освящённые серебряные болты | тег `holy` для будущих модификаторов против нежити |
| `gear.ammo.glass_razor.v1` | 6 | 140 | 0 | -1 | Glass-Razor Quills | Стеклянные бритвенные оперения | высокий крит, хрупкий стиль |
| `gear.ammo.rune_fletched.v1` | 8 | 70 | 50 | 0 | Rune-Fletched Arrows | Стрелы с руническим оперением | маг. среда |
| `gear.ammo.manticore_barb.v1` | 10 | 90 | 70 | 0 | Manticore Barb Shafts | Шипы мантикоры | сильный mid/high family |
| `gear.ammo.starfall_sabot.v1` | 12 | 110 | 90 | 0 | Starfall Sabots | Сабо падающей звезды | top family base для лейт-дропа |

**Баланс-якорь:** при `ilvl ≈ 25`, `Common`, семейство `steel_broadhead`: `primaryOut ≈ round(7 × 1.72 × 1.00) = 12` к Attack; при `Rare`, `ilvl ≈ 14`: `round(7 × 1.39 × 1.30) ≈ 13` — редкость компенсирует более низкий ilvl (см. §6.4.3).

## 0b) World encounter & social content (map)

Naming convention:
- `encounter.player_meet.v1` — abstract meeting of two heroes (payload names players, positions)
- `event.duel.offer.v1` — optional duel prompt UI contract
- `event.social.pass.v1` — talk/walk / emote-only resolution
- `event.quest.alms.v1` — NPC mini-quest: pay gold → random garment

| contentKey | type | summary |
|---|---|---|
| `encounter.player_meet.v1` | encounter | Two heroes in proximity; server rolls outcome bucket (social vs duel prompt vs silent) |
| `event.social.pass.v1` | event | Emote / short line; no combat |
| `event.duel.offer.v1` | event | Show duel accept/decline; both must accept |
| `event.quest.alms.v1` | event | NPC asks for coins; success grants random `gear.slot.*` item |

## 0c) Non-hostile NPC catalog (minimal)

Naming convention:
- `npc.<role>.<slug>.v1`
- `modelId` follows `monster.*` style but for neutral: `npc.model.<slug>.v1` (neutral rigs)

| npcId | displayName | role | modelId | defaultInteraction |
|---|---|---|---|---|
| `npc.traveler.worn_merchant.v1` | Worn Merchant | quest_giver | `npc.model.worn_merchant.v1` | `event.quest.alms.v1` |
| `npc.hermit.ash_sage.v1` | Ash Sage | flavor_talk | `npc.model.ash_sage.v1` | `event.social.pass.v1` |
| `npc.child.lost_acorn.v1` | Lost Acorn Kid | flavor_talk | `npc.model.lost_acorn.v1` | `event.social.pass.v1` |

## 1) Monster Model Catalog

Naming convention:
- `monster.<rarity_or_type>.<slug>.v1`
- `levelBand` is inclusive and matches `specification.md`
- `levelBand` is also the anchor for enemy in-band scaling: scaling starts from `minLevel` of the band, not from a global all-level multiplier
- `visualStyleTags` are lightweight art-direction tags for batching/filtering

| enemyId | displayName | class | levelBand | modelId | visualStyleTags |
|---|---|---|---|---|---|
| `enemy.wolf_forest` | Forest Wolf | base | `1-5` | `monster.base.wolf_forest.v1` | `beast,forest,fast,low-hp,gray-brown` |
| `enemy.boar_wild` | Wild Boar | base | `2-6` | `monster.base.boar_wild.v1` | `beast,forest,tanky,charge,earthy` |
| `enemy.zombie_rotting` | Rotting Zombie | base | `3-8` | `monster.base.zombie_rotting.v1` | `undead,decay,slow,poison,green-fog` |
| `enemy.spider_cave` | Cave Spider | base | `4-9` | `monster.base.spider_cave.v1` | `arachnid,cave,very-fast,crit,purple-dark` |
| `enemy.orc_warrior` | Orc Warrior | base | `5-12` | `monster.base.orc_warrior.v1` | `orc,midgame,armored,brutal,green-metal` |
| `enemy.skeleton_archer` | Skeleton Archer | base | `6-14` | `monster.base.skeleton_archer.v1` | `undead,ranged,bone,dodge,desaturated` |
| `enemy.lizard_battle` | Battle Lizard | base | `7-15` | `monster.base.lizard_battle.v1` | `reptile,defense,tank,scales,olive` |
| `enemy.demon_fire` | Fire Demon | elite | `10-20` | `monster.elite.demon_fire.v1` | `demon,fire,elite,burn,red-orange` |
| `enemy.guard_ice` | Ice Guard | elite | `12-22` | `monster.elite.guard_ice.v1` | `elemental,ice,elite,defense,frost-blue` |
| `enemy.skeleton_king` | Skeleton King | elite | `15-25` | `monster.elite.skeleton_king.v1` | `undead,bosslike,summoner,regeneration,gold-bone` |
| `enemy.element_water` | Water Element | elite | `18-28` | `monster.elite.element_water.v1` | `elemental,water,slow,aura,cyan` |
| `enemy.guard_forest` | Forest Guardian | elite | `20-30` | `monster.elite.guard_forest.v1` | `nature,guardian,very-tanky,regen,moss` |
| `enemy.titan_lightning` | Lightning Titan | elite | `25-35` | `monster.elite.titan_lightning.v1` | `titan,lightning,burst,stun,blue-yellow` |

## 2) Object Model Catalog (Map Objects)

Naming convention:
- `obj.<category>.<variant>.v1`
- Keep collision simple in MVP: `road` non-blocking, all others blocking unless flagged

| objectType | variantId | modelId | gameplayTag | notes |
|---|---|---|---|---|
| `road` | `dirt_straight` | `obj.road.dirt_straight.v1` | `path` | default biome path |
| `road` | `dirt_curve` | `obj.road.dirt_curve.v1` | `path` | curve segment |
| `road` | `stone_straight` | `obj.road.stone_straight.v1` | `path` | higher tier area visual |
| `road` | `stone_intersection` | `obj.road.stone_intersection.v1` | `path` | junction tile |
| `tree` | `pine_small` | `obj.tree.pine_small.v1` | `nature_blocker` | forest filler |
| `tree` | `pine_tall` | `obj.tree.pine_tall.v1` | `nature_blocker` | silhouette depth |
| `tree` | `dead_tree` | `obj.tree.dead_tree.v1` | `nature_blocker` | corrupted zone accent |
| `bush` | `bush_round` | `obj.bush.round.v1` | `nature_soft` | low silhouette |
| `bush` | `bush_berries` | `obj.bush.berries.v1` | `nature_soft` | color variation |
| `rock` | `rock_small` | `obj.rock.small.v1` | `stone_blocker` | edge clutter |
| `rock` | `rock_large` | `obj.rock.large.v1` | `stone_blocker` | hard blocker |
| `rock` | `rock_crystal` | `obj.rock.crystal.v1` | `stone_accent` | elite-zone hint |
| `prop` | `campfire_off` | `obj.prop.campfire_off.v1` | `poi` | non-interactive MVP |
| `prop` | `cart_broken` | `obj.prop.cart_broken.v1` | `poi` | roadside storytelling |
| `prop` | `sign_wood` | `obj.prop.sign_wood.v1` | `poi` | route marker |
| `prop` | `totem_bone` | `obj.prop.totem_bone.v1` | `poi_dark` | undead area marker |

## 3) Sound Cue Catalog (Gameplay + UI)

Naming convention:
- `sfx.<domain>.<intent>.v1`
- `ambient.*` loops; all others one-shots

| soundCueId | category | trigger | defaultMixNotes |
|---|---|---|---|
| `sfx.combat.hit.v1` | combat | normal successful hit | short, dry, high frequency |
| `sfx.combat.crit.v1` | combat | critical hit | layered transient + brighter tail |
| `sfx.combat.death_enemy.v1` | combat | enemy dies | medium tail, low-mid body |
| `sfx.loot.pickup.v1` | reward | loot granted/picked | fast sparkle, non-intrusive |
| `sfx.status.buff_activate.v1` | status | any buff applied | uplifting whoosh/chime |
| `sfx.status.debuff_apply.v1` | status | any debuff applied | dark stinger, short |
| `sfx.ambient.forest_loop.v1` | ambient | forest biome active | birds/wind, low distraction |
| `sfx.ui.click.v1` | ui | button tap/click | soft click, no low-end |
| `sfx.progress.level_up.v1` | progression | player level increases | celebratory stinger |
| `sfx.social.emote.v1` | social | player meet / NPC short interaction | light chirp, non-combat |
| `sfx.ui.duel_prompt.v1` | ui | duel offer shown | subtle tension, not alarm |

## 4) Enemy/Object -> Sound + VFX Intent Mapping

MVP guidance:
- Use generic combat cues first; add per-enemy overrides only for elites.
- VFX rarity colors should follow `specification.md` section 11.

| sourceType | sourceId | onHitSoundCueId | onDeathSoundCueId | statusSoundCueId | vfxIntent |
|---|---|---|---|---|---|
| `enemy` | `enemy.wolf_forest` | `sfx.combat.hit.v1` | `sfx.combat.death_enemy.v1` | *(none)* | `quick claw slash, light dust` |
| `enemy` | `enemy.boar_wild` | `sfx.combat.hit.v1` | `sfx.combat.death_enemy.v1` | *(none)* | `heavy impact spark, dirt kick` |
| `enemy` | `enemy.zombie_rotting` | `sfx.combat.hit.v1` | `sfx.combat.death_enemy.v1` | `sfx.status.debuff_apply.v1` (Poison) | `green poison puff` |
| `enemy` | `enemy.spider_cave` | `sfx.combat.hit.v1` | `sfx.combat.death_enemy.v1` | *(none)* | `fast bite streak, dark venom speck` |
| `enemy` | `enemy.orc_warrior` | `sfx.combat.hit.v1` | `sfx.combat.death_enemy.v1` | *(none)* | `weapon arc trail, medium impact` |
| `enemy` | `enemy.skeleton_archer` | `sfx.combat.hit.v1` | `sfx.combat.death_enemy.v1` | *(none)* | `bone shard burst` |
| `enemy` | `enemy.lizard_battle` | `sfx.combat.hit.v1` | `sfx.combat.death_enemy.v1` | *(none)* | `scale spark, shield-like flicker` |
| `enemy` | `enemy.demon_fire` | `sfx.combat.hit.v1` | `sfx.combat.death_enemy.v1` | `sfx.status.debuff_apply.v1` (Burn) | `fire embers + orange burn overlay` |
| `enemy` | `enemy.guard_ice` | `sfx.combat.hit.v1` | `sfx.combat.death_enemy.v1` | `sfx.status.debuff_apply.v1` (Freeze/AS slow) | `frost shards + blue slow ring` |
| `enemy` | `enemy.skeleton_king` | `sfx.combat.crit.v1` | `sfx.combat.death_enemy.v1` | `sfx.status.buff_activate.v1` (self-heal/summon pulse) | `gold-purple necro pulse` |
| `enemy` | `enemy.element_water` | `sfx.combat.hit.v1` | `sfx.combat.death_enemy.v1` | `sfx.status.debuff_apply.v1` (Slow) | `water splash + cyan slow ripple` |
| `enemy` | `enemy.guard_forest` | `sfx.combat.hit.v1` | `sfx.combat.death_enemy.v1` | `sfx.status.buff_activate.v1` (regen tick) | `green regen aura + bark particles` |
| `enemy` | `enemy.titan_lightning` | `sfx.combat.crit.v1` | `sfx.combat.death_enemy.v1` | `sfx.status.debuff_apply.v1` (Stun) | `lightning arc + yellow stun stars` |
| `object` | `road:*` | *(none)* | *(none)* | *(none)* | `subtle dust under movement` |
| `object` | `tree:*` | *(none)* | *(none)* | *(none)* | `sway only; no combat VFX` |
| `object` | `bush:*` | *(none)* | *(none)* | *(none)* | `minor rustle if traversed nearby` |
| `object` | `rock:*` | *(none)* | *(none)* | *(none)* | `static; optional tiny pebbles` |
| `object` | `prop:campfire_off` | *(none)* | *(none)* | *(none)* | `optional smoke wisps` |

## 5) JSON-Ready Schema Examples (Map Payload)

### 5.1 Minimal Entity Schemas

```json
{
  "enemy": {
    "id": "spawn-000123",
    "enemyId": "enemy.demon_fire",
    "level": 14,
    "modelId": "monster.elite.demon_fire.v1",
    "soundCueId": "sfx.combat.hit.v1"
  },
  "object": {
    "id": "obj-00421",
    "objectType": "tree",
    "variantId": "pine_tall",
    "modelId": "obj.tree.pine_tall.v1",
    "soundCueId": null
  }
}
```

### 5.2 Map Chunk Payload Example

```json
{
  "chunkId": "forest_01_03",
  "ambientSoundCueId": "sfx.ambient.forest_loop.v1",
  "enemies": [
    {
      "id": "e-1001",
      "enemyId": "enemy.wolf_forest",
      "level": 3,
      "modelId": "monster.base.wolf_forest.v1",
      "soundCueId": "sfx.combat.hit.v1"
    },
    {
      "id": "e-1002",
      "enemyId": "enemy.demon_fire",
      "level": 12,
      "modelId": "monster.elite.demon_fire.v1",
      "soundCueId": "sfx.combat.hit.v1"
    }
  ],
  "objects": [
    {
      "id": "o-2201",
      "objectType": "road",
      "variantId": "dirt_curve",
      "modelId": "obj.road.dirt_curve.v1",
      "soundCueId": null
    },
    {
      "id": "o-2202",
      "objectType": "tree",
      "variantId": "pine_small",
      "modelId": "obj.tree.pine_small.v1",
      "soundCueId": null
    },
    {
      "id": "o-2203",
      "objectType": "prop",
      "variantId": "totem_bone",
      "modelId": "obj.prop.totem_bone.v1",
      "soundCueId": null
    }
  ]
}
```

## MVP Defaults (Recommended)

1. Use one shared hit/death sound for all base enemies; add unique status sounds for elites only.
2. Keep `soundCueId` optional per entity; use `ambientSoundCueId` at chunk/biome level.
3. Start with one model per enemy archetype (`.v1`), then skin variants later (`.v2`, `.v3`).
4. Map objects may remain non-interactive in early MVP; **NPCs and player-meet events** use `npc.*` / `event.*` keys from §0b–0c when wired.
5. Preserve stable IDs (`enemyId`, `modelId`, `soundCueId`, `gear.slot.*`, `gear.form.*`, `gear.ammo.*`, `npc.*`, `event.*`) as content-contract keys across backend/client.
6. Optional duel/social flow: prefer one generic UI sound for accept/decline (e.g. extend catalog with `sfx.ui.duel_prompt.v1` when implemented).
