Files
ashen-realms/docs/Ashen_Realms_Vertical_Slice_Items_Implementation_Spec.md
Bastian Wagner 2526ac230d items
2026-08-20 17:07:40 +02:00

22 KiB
Raw Blame History

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:

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:

WEAPON
HEAD
CHEST
HANDS
LEGS
FEET
AMULET

Non-equipment item types used by the current asset set:

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:

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:

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:

apps/web/public/assets/items/

Recommended naming convention:

<stable-item-key>.png

Example:

worn-short-sword.png
raider-blade.png
ash-blade.png

6. Starter equipment

These items form the initial character equipment.

6.1 Abgenutztes Kurzschwert

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

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

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

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

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

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

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

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

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

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

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

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

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

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:

heal = 35 % of maximum HP

The effect must be calculated server-side.

The client must never send the amount healed.

Conceptually:

{
  "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

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:

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

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:

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

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

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

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

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:

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:

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:

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:

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:

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:

CharacterItem
→ references ItemDefinition
→ may be equipped exactly once
→ item remains owned while equipped

Stackable content:

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:

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:

{
  "characterItemId": "uuid"
}

Invalid request concepts:

{
  "itemId": "ash-blade",
  "weaponDamage": 999
}

The server derives all stats from ItemDefinition.


17. CharacterStatsService integration

The effective stat service must aggregate equipped items.

Conceptually:

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:

ItemIconComponent
ItemTooltipComponent
ItemStatsComponent
ItemComparisonComponent
InventorySlotComponent
EquipmentSlotComponent

Required item display:

icon
name
rarity
item type / slot
stats
quantity if stackable

For an equipment comparison, show only meaningful changed values.

Example:

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:

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:

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:

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:

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

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:

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

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

small healing potion is stackable
server calculates healing
potion quantity decreases when consumed
cannot consume nonexistent item

Material / bag

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:

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.