# Ashen Realms – Vertical Slice Items Implementation Spec **Status:** Ready for implementation **Purpose:** Implement the currently defined and generated item set for the first playable Ashen Realms progression slices. **Primary source of truth:** existing balancing/item design plus the generated item artwork created for the project. --- # 1. Goal Implement the first Ashen Realms item set as real, persistent, server-authoritative game content. The implementation must support this loop: ```text item definition → icon shown in UI → item can be granted / looted / purchased where configured → CharacterItem is created → item appears in inventory → equipment item can be equipped into the correct slot → effective character stats update ``` The item system must remain data-driven. Do not hard-code individual items into Angular components or combat logic. --- # 2. Current item philosophy The Vertical Slice uses a deliberately simple item model: - fixed handcrafted item values - clearly readable upgrades - no random affixes - no durability - no repair system - no sockets - no +1 to +10 upgrade levels - no crafting requirements for these items - no client-authoritative stats The important gameplay principle is: > A good item must create a noticeable character upgrade and should have a clear identity. Equipment slots currently used: ```text WEAPON HEAD CHEST HANDS LEGS FEET AMULET ``` Non-equipment item types used by the current asset set: ```text CONSUMABLE MATERIAL BAG ``` --- # 3. Important progression note Some older project documents still describe XP, level requirements and direct monster Silver rewards. The current project direction replaces the old kill-XP progression with the newer reputation/fame progression and material turn-in loop. Therefore: - do not add new XP dependencies as part of this item implementation - do not add `requiredLevel` checks to these items unless an already implemented legacy field must temporarily remain for compatibility - equipment power should come from the item stats themselves - reputation/shop unlock requirements belong to the merchant/reputation systems, not to `ItemDefinition` - material items must remain usable by the newer bag/material/reputation flow Do not perform a large unrelated migration in this task. If legacy fields already exist, keep them backward-compatible and migrate them separately when the reputation refactor is executed. --- # 4. Canonical item data model Use the existing `ItemDefinition` model if it already exists. Extend it only where necessary. Conceptually, an item definition should support: ```ts interface ItemDefinition { id: string; key: string; name: string; description: string; type: ItemType; equipmentSlot: EquipmentSlot | null; rarity: ItemRarity; tier: number | null; weaponDamage: number; bonusHp: number; bonusAttack: number; bonusArmor: number; stackable: boolean; maxStack: number; iconPath: string; enabled: boolean; } ``` Recommended enums: ```ts enum ItemType { WEAPON = 'WEAPON', ARMOR = 'ARMOR', AMULET = 'AMULET', CONSUMABLE = 'CONSUMABLE', MATERIAL = 'MATERIAL', BAG = 'BAG', } enum EquipmentSlot { WEAPON = 'WEAPON', HEAD = 'HEAD', CHEST = 'CHEST', HANDS = 'HANDS', LEGS = 'LEGS', FEET = 'FEET', AMULET = 'AMULET', } enum ItemRarity { COMMON = 'COMMON', RARE = 'RARE', EPIC = 'EPIC', } ``` If equivalent enums already exist, reuse them instead of introducing duplicates. --- # 5. Asset rules All item artwork follows the Ashen Realms item-art direction: - square image - item centered - transparent PNG background - no text embedded in image - no rarity frame embedded in image - no UI panel embedded in image - realistic / lightly painterly dark-fantasy rendering - worn steel, leather, cloth, fur and restrained metal accents - readable at small inventory size The UI owns: - rarity border - selected state - hover state - quantity - equipped marker - comparison arrows - tooltip The PNG itself contains only the illustrated object. Recommended asset folder: ```text apps/web/public/assets/items/ ``` Recommended naming convention: ```text .png ``` Example: ```text worn-short-sword.png raider-blade.png ash-blade.png ``` --- # 6. Starter equipment These items form the initial character equipment. ## 6.1 Abgenutztes Kurzschwert ```yaml key: worn-short-sword name: Abgenutztes Kurzschwert type: WEAPON equipmentSlot: WEAPON rarity: COMMON tier: 1 weaponDamage: 8 bonusHp: 0 bonusAttack: 0 bonusArmor: 0 stackable: false iconPath: /assets/items/worn-short-sword.png ``` **Role:** Starter weapon. Intentionally weak so the first weapon upgrade is immediately noticeable. **Suggested description:** > Ein schlichtes, vielfach geschärftes Kurzschwert. Die Klinge ist voller Kerben, aber noch zuverlässig genug für die Straße vor Graufurt. --- ## 6.2 Einfache Lederweste ```yaml key: simple-leather-vest name: Einfache Lederweste type: ARMOR equipmentSlot: CHEST rarity: COMMON tier: 1 weaponDamage: 0 bonusHp: 0 bonusAttack: 0 bonusArmor: 3 stackable: false iconPath: /assets/items/simple-leather-vest.png ``` **Role:** Starter chest armor. **Suggested description:** > Eine einfache, mehrfach geflickte Lederweste. Kein Meisterwerk, aber besser als ungeschützt in die Aschenfelder zu ziehen. --- ## 6.3 Stoffhandschuhe ```yaml key: cloth-gloves name: Stoffhandschuhe type: ARMOR equipmentSlot: HANDS rarity: COMMON tier: 1 weaponDamage: 0 bonusHp: 0 bonusAttack: 0 bonusArmor: 1 stackable: false iconPath: /assets/items/cloth-gloves.png ``` **Role:** Starter hand slot. --- ## 6.4 Abgetragene Hose ```yaml key: worn-trousers name: Abgetragene Hose type: ARMOR equipmentSlot: LEGS rarity: COMMON tier: 1 weaponDamage: 0 bonusHp: 0 bonusAttack: 0 bonusArmor: 1 stackable: false iconPath: /assets/items/worn-trousers.png ``` **Role:** Starter leg slot. --- ## 6.5 Alte Lederstiefel ```yaml key: old-leather-boots name: Alte Lederstiefel type: ARMOR equipmentSlot: FEET rarity: COMMON tier: 1 weaponDamage: 0 bonusHp: 0 bonusAttack: 0 bonusArmor: 1 stackable: false iconPath: /assets/items/old-leather-boots.png ``` **Role:** Starter feet slot. --- # 7. Tier-1 Aschenfelder equipment These are the first meaningful equipment upgrades. ## 7.1 Räuberklinge ```yaml key: raider-blade name: Räuberklinge type: WEAPON equipmentSlot: WEAPON rarity: COMMON tier: 1 weaponDamage: 11 bonusAttack: 1 bonusHp: 0 bonusArmor: 0 stackable: false iconPath: /assets/items/raider-blade.png ``` **Known source:** Straßenräuber. A merchant source is also allowed by the existing balancing document. **Gameplay role:** First obvious weapon upgrade from the starter sword. --- ## 7.2 Räuberhaube ```yaml key: raider-hood name: Räuberhaube type: ARMOR equipmentSlot: HEAD rarity: COMMON tier: 1 weaponDamage: 0 bonusHp: 5 bonusAttack: 0 bonusArmor: 3 stackable: false iconPath: /assets/items/raider-hood.png ``` **Gameplay role:** Particularly valuable early because the character starts with an empty head slot. --- ## 7.3 Plündererhandschuhe ```yaml key: looter-gloves name: Plündererhandschuhe type: ARMOR equipmentSlot: HANDS rarity: COMMON tier: 1 weaponDamage: 0 bonusHp: 0 bonusAttack: 1 bonusArmor: 3 stackable: false iconPath: /assets/items/looter-gloves.png ``` **Note:** The item is defined in balancing and must be implemented. If the final icon asset has not yet been placed in the repository, use a temporary development placeholder only until the generated final asset is added. Do not omit the item from content data. --- ## 7.4 Verstärkte Lederjacke ```yaml key: reinforced-leather-jacket name: Verstärkte Lederjacke type: ARMOR equipmentSlot: CHEST rarity: RARE tier: 1 weaponDamage: 0 bonusHp: 10 bonusAttack: 0 bonusArmor: 7 stackable: false iconPath: /assets/items/reinforced-leather-jacket.png ``` --- ## 7.5 Wachmannsbeinkleid ```yaml key: watchman-legwear name: Wachmannsbeinkleid type: ARMOR equipmentSlot: LEGS rarity: RARE tier: 1 weaponDamage: 0 bonusHp: 5 bonusAttack: 0 bonusArmor: 5 stackable: false iconPath: /assets/items/watchman-legwear.png ``` --- ## 7.6 Aschenstiefel ```yaml key: ash-boots name: Aschenstiefel type: ARMOR equipmentSlot: FEET rarity: RARE tier: 1 weaponDamage: 0 bonusHp: 5 bonusAttack: 0 bonusArmor: 4 stackable: false iconPath: /assets/items/ash-boots.png ``` --- ## 7.7 Zeichen der Grenzwacht ```yaml key: border-watch-sign name: Zeichen der Grenzwacht type: AMULET equipmentSlot: AMULET rarity: RARE tier: 1 weaponDamage: 0 bonusHp: 10 bonusAttack: 3 bonusArmor: 0 stackable: false iconPath: /assets/items/border-watch-sign.png ``` **Gameplay role:** First substantial amulet upgrade and another way to fill an initially empty slot. --- ## 7.8 Aschenklinge ```yaml key: ash-blade name: Aschenklinge type: WEAPON equipmentSlot: WEAPON rarity: RARE tier: 1 weaponDamage: 15 bonusHp: 0 bonusAttack: 2 bonusArmor: 0 stackable: false iconPath: /assets/items/ash-blade.png ``` **Known source in older balancing:** Plündererhauptmann and regional progression currency. **Current implementation rule:** Do not hard-code the old currency requirement into the item itself. Merchant/reputation availability belongs to the shop/reputation content definitions. **Gameplay role:** Target weapon for the end of the Aschenfelder progression. --- # 8. Consumable ## 8.1 Kleiner Heiltrank ```yaml key: small-healing-potion name: Kleiner Heiltrank type: CONSUMABLE equipmentSlot: null rarity: COMMON tier: 1 stackable: true maxStack: 99 iconPath: /assets/items/small-healing-potion.png ``` Existing combat behavior: ```text heal = 35 % of maximum HP ``` The effect must be calculated server-side. The client must never send the amount healed. Conceptually: ```json { "action": "USE_CONSUMABLE", "itemId": "character-item-id" } ``` The combat service validates ownership, availability and combat-bag access and then applies the configured effect. Do not encode `35 %` only in the Angular client. --- # 9. Material item ## 9.1 Aschenratten-Fell ```yaml key: ash-rat-pelt name: Aschenratten-Fell type: MATERIAL equipmentSlot: null rarity: COMMON tier: 1 stackable: true maxStack: 99 iconPath: /assets/items/ash-rat-pelt.png ``` **Source:** Aschenratte. **Current role:** Material loot for the newer bag / trader / reputation progression loop. This item must not be equipable. It should be compatible with the monster-category / bag-category design used by the bag system. Recommended category linkage: ```text materialCategory = PELT sourceMonsterCategory = BEAST / ASH_RAT as defined by the monster-category system ``` Use existing enums if the bag specification already introduced them. Do not create a second incompatible material-category system. --- # 10. Bag item ## 10.1 Kleine Felltasche ```yaml key: small-pelt-bag name: Kleine Felltasche type: BAG equipmentSlot: null rarity: COMMON tier: 1 stackable: false iconPath: /assets/items/small-pelt-bag.png ``` This is not normal combat equipment. Its capacity and accepted material categories must be defined by the existing bag system, not as armor stats. Conceptually: ```text acceptedCategory = PELT capacity = bag-definition value ``` Do not add `bonusArmor`, `bonusHp` or `bonusAttack` to the bag. --- # 11. Tier-2 Dämmerwald preview items These assets have already been created and can be seeded now even if Dämmerwald gameplay is implemented later. They must not be exposed in Aschenfelder loot tables merely because their definitions already exist. ## 11.1 Waldläuferklinge ```yaml key: ranger-blade name: Waldläuferklinge type: WEAPON equipmentSlot: WEAPON rarity: COMMON tier: 2 weaponDamage: 18 bonusAttack: 1 bonusHp: 0 bonusArmor: 0 stackable: false iconPath: /assets/items/ranger-blade.png ``` --- ## 11.2 Gehärteter Waldharnisch ```yaml key: hardened-forest-harness name: Gehärteter Waldharnisch type: ARMOR equipmentSlot: CHEST rarity: RARE tier: 2 weaponDamage: 0 bonusHp: 20 bonusAttack: 0 bonusArmor: 12 stackable: false iconPath: /assets/items/hardened-forest-harness.png ``` --- ## 11.3 Dornenleder-Beinschutz ```yaml key: thorn-leather-legguards name: Dornenleder-Beinschutz type: ARMOR equipmentSlot: LEGS rarity: RARE tier: 2 weaponDamage: 0 bonusHp: 15 bonusAttack: 0 bonusArmor: 9 stackable: false iconPath: /assets/items/thorn-leather-legguards.png ``` --- ## 11.4 Talisman des Jägers ```yaml key: hunters-talisman name: Talisman des Jägers type: AMULET equipmentSlot: AMULET rarity: RARE tier: 2 weaponDamage: 0 bonusHp: 15 bonusAttack: 4 bonusArmor: 0 stackable: false iconPath: /assets/items/hunters-talisman.png ``` --- # 12. Items intentionally not implemented by this file This document does not define new values for items that have not yet been selected for the current generated asset batch. Examples from the broader balancing document that remain separate future content include: ```text Anhänger des verbrannten Hauptmanns Schwarzmähnenzahn Fang des Schattenalphas Dämmerjäger-Kapuze Dämmerjäger-Handschuhe Dämmerjäger-Stiefel Herz des Graufangs Tier-3 Ruins equipment ``` Do not invent new stats for them in this implementation task. --- # 13. Seed implementation Create or extend an idempotent item seed. Recommended location: ```text apps/api/src/database/seeds/items.seed.ts ``` or reuse the project's existing vertical-slice seed structure. Use stable keys, never names, for code/data references. Example: ```ts await upsertItem({ key: 'raider-blade', name: 'Räuberklinge', type: ItemType.WEAPON, equipmentSlot: EquipmentSlot.WEAPON, rarity: ItemRarity.COMMON, tier: 1, weaponDamage: 11, bonusAttack: 1, bonusHp: 0, bonusArmor: 0, stackable: false, maxStack: 1, iconPath: '/assets/items/raider-blade.png', }); ``` Seed requirements: - repeatable without duplicates - update changed definition data by stable key - do not delete player-owned CharacterItem rows - never use display name as the primary content identity --- # 14. Starter character integration A newly created test/vertical-slice character should initially own and equip: ```text WEAPON → worn-short-sword CHEST → simple-leather-vest HANDS → cloth-gloves LEGS → worn-trousers FEET → old-leather-boots HEAD → empty AMULET → empty ``` Starting equipment stats should therefore contribute: ```text weaponDamage = 8 armor = 6 ``` before other base-stat calculations. Do not create hidden starter armor in empty slots. The intentionally empty HEAD and AMULET slots make early loot visibly meaningful. --- # 15. Inventory behavior All persistent owned items must use the existing `CharacterItem` state. Equipment: ```text CharacterItem → references ItemDefinition → may be equipped exactly once → item remains owned while equipped ``` Stackable content: ```text healing potion materials ``` must use the project's existing stack/quantity representation if one already exists. Do not create a parallel inventory structure. --- # 16. Equipment validation The server validates all equip requests. At minimum: ```text item belongs to character item is equipment item's EquipmentSlot matches requested slot item is not disabled ``` Do not trust client-submitted stat values. Valid request concept: ```json { "characterItemId": "uuid" } ``` Invalid request concepts: ```json { "itemId": "ash-blade", "weaponDamage": 999 } ``` The server derives all stats from `ItemDefinition`. --- # 17. CharacterStatsService integration The effective stat service must aggregate equipped items. Conceptually: ```ts const equipmentBonuses = equippedItems.reduce( (sum, item) => ({ hp: sum.hp + item.definition.bonusHp, attack: sum.attack + item.definition.bonusAttack, armor: sum.armor + item.definition.bonusArmor, weaponDamage: item.definition.equipmentSlot === EquipmentSlot.WEAPON ? item.definition.weaponDamage : sum.weaponDamage, }), initialBonuses, ); ``` Do not duplicate equipment-stat calculation in CombatService, InventoryService and Angular. `CharacterStatsService` remains the single source of truth for effective character stats. --- # 18. Angular inventory presentation Every item should render through one reusable item component. Recommended reusable components: ```text ItemIconComponent ItemTooltipComponent ItemStatsComponent ItemComparisonComponent InventorySlotComponent EquipmentSlotComponent ``` Required item display: ```text icon name rarity item type / slot stats quantity if stackable ``` For an equipment comparison, show only meaningful changed values. Example: ```text Räuberklinge 11 Waffenschaden +1 Angriff Compared with Abgenutztes Kurzschwert: +3 Waffenschaden +1 Angriff ``` Do not show internal IDs, stable keys or raw JSON in player-facing UI. --- # 19. Rarity presentation Rarity belongs to the UI around the icon, not inside the item PNG. Use the existing Ashen Realms design system. Conceptually: ```text COMMON → restrained neutral/metal frame RARE → stronger but controlled rare accent EPIC → premium special frame/accent ``` Avoid: - neon borders - rainbow effects - huge particle glows - mobile-game rarity explosions --- # 20. Loot integration Do not rewrite the entire loot system in this task. Where existing loot definitions already reference these items, update them to stable item keys / definition IDs. Known early examples from the existing balancing content include: ```text Aschenratte → Aschenratten-Fell / material Straßenräuber → Räuberklinge → Räuberhaube → Plündererhandschuhe → Kleiner Heiltrank ``` The authoritative roll is server-side. Angular receives only the result. The newer material/reputation system may later replace portions of old direct currency reward tables. Do not reintroduce direct XP/Silver rewards while implementing these item definitions. --- # 21. Merchant integration Items may be offered by a merchant through `ShopOffer` or the project's current equivalent. The item itself must not store its merchant price. Correct separation: ```text ItemDefinition → what the item is ShopOffer → who sells it → which currency / reputation requirement applies → price → availability ``` This is important because the same item may later be: - loot - quest reward - shop offer - reputation unlock without duplicating the item definition. --- # 22. Asset mapping checklist Place the generated PNG files into the canonical asset folder and rename them to stable filenames. Expected final files: ```text apps/web/public/assets/items/worn-short-sword.png apps/web/public/assets/items/simple-leather-vest.png apps/web/public/assets/items/cloth-gloves.png apps/web/public/assets/items/worn-trousers.png apps/web/public/assets/items/old-leather-boots.png apps/web/public/assets/items/raider-blade.png apps/web/public/assets/items/raider-hood.png apps/web/public/assets/items/looter-gloves.png apps/web/public/assets/items/reinforced-leather-jacket.png apps/web/public/assets/items/watchman-legwear.png apps/web/public/assets/items/ash-boots.png apps/web/public/assets/items/border-watch-sign.png apps/web/public/assets/items/ash-blade.png apps/web/public/assets/items/small-healing-potion.png apps/web/public/assets/items/ash-rat-pelt.png apps/web/public/assets/items/small-pelt-bag.png apps/web/public/assets/items/ranger-blade.png apps/web/public/assets/items/hardened-forest-harness.png apps/web/public/assets/items/thorn-leather-legguards.png apps/web/public/assets/items/hunters-talisman.png ``` If a final PNG is missing, do not silently substitute an unrelated icon. Use an explicit development placeholder and leave a TODO tied to the stable item key. --- # 23. Required backend tests Add tests for at least: ### Seed ```text item seed is idempotent all stable keys are unique all equipment items have a valid slot all icon paths are populated ``` ### Character stats Verify examples: ```text starter sword gives 8 weapon damage starter armor pieces total 6 armor raider blade gives 11 weapon damage +1 attack ash blade gives 15 weapon damage +2 attack reinforced leather jacket gives +7 armor +10 HP ``` ### Equipment ```text owned item can be equipped wrong slot is rejected non-equipment item cannot be equipped foreign CharacterItem is rejected replacing an equipped item updates stats ``` ### Consumable ```text small healing potion is stackable server calculates healing potion quantity decreases when consumed cannot consume nonexistent item ``` ### Material / bag ```text ash-rat-pelt cannot be equipped small-pelt-bag cannot be equipped as armor bag/material services can resolve their definitions by stable key ``` --- # 24. Required frontend tests At minimum: ```text item icon uses ItemDefinition.iconPath item tooltip renders configured stats empty stats are not displayed as '+0' rarity styling is derived from rarity field stack quantity is visible for materials/consumables inventory can distinguish equipment, consumable, material and bag comparison UI correctly compares current vs candidate equipment ``` --- # 25. Definition of Done This item implementation is complete when: - all item definitions in this document exist in persistent content data - stable keys are used consistently - generated PNG assets are placed under `/assets/items/` - the starter character receives the five starter equipment pieces - HEAD and AMULET remain empty initially - inventory shows name, icon, rarity and stats correctly - equipment can be equipped server-authoritatively - effective stats update through `CharacterStatsService` - the healing potion is represented as a consumable - Aschenratten-Fell is represented as material content - Kleine Felltasche is represented as bag content - Tier-2 preview items exist but are not accidentally exposed in Tier-1 loot - no random affixes, durability, sockets or item-upgrade system are added - no new XP/level gating is introduced by this task - tests pass --- # 26. Implementation handoff prompt Use this document together with the current repository and existing item/inventory/equipment/bag specifications. Implementation agent instruction: > Inspect the existing item, inventory, equipment, loot, bag and character-stat code before changing anything. Reuse current entities, enums, repositories, components and APIs where possible. Treat the stable item keys and stats in this document as content requirements. Do not build a parallel item system. Implement the data migrations/seeds, asset mappings, inventory presentation and server-authoritative equipment/stat integration required to make these items real game content. Preserve the current Ashen Realms architecture and write tests for all added behavior.