You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
autohero/docs/specification-content-catal...

307 lines
20 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# AutoHero Content Catalog (MVP Companion)
Aligned with `specification.md` sections 2.32.4, 4, **5.3**, **6.36.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 §0b0c 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).