This commit is contained in:
Bastian Wagner
2026-08-22 16:41:47 +02:00
parent dfa62fd152
commit 081c9f83f9
137 changed files with 11594 additions and 1302 deletions

View File

@@ -151,6 +151,22 @@ Alle Materialien oder Handelswaren, die das Taschensystem verwenden, besitzen ei
V1 verwendet zunächst wenige breite Kategorien.
> **IMPLEMENTIERUNGSSTAND (Playable Slice 0.7.5).**
> Implementiert sind bisher nur `HIDE` und `RAIDER_TROPHY`. Die Slice-Spezifikation
> `docs/playable-slices/0.7.5-Monster-Categories-and-Loot-Bags.md` §3/§4 ist hier die
> neuere, verbindliche Quelle und benennt die Kategorie für Plündererabzeichen
> ausdrücklich `RAIDER_TROPHY` — nicht `TROPHY` und nicht `HUMANOID_SPOILS`.
>
> Damit weicht der implementierte Satz bewusst von der Liste unten ab:
> `TROPHY`, `HUMANOID_SPOILS` und `COIN` existieren im Code noch nicht. Sie sind
> nicht verworfen, sondern warten auf Content, der sie tatsächlich braucht
> (§5 dieses Dokuments). Beim Hinzufügen bitte klären, ob `RAIDER_TROPHY` in
> `HUMANOID_SPOILS` aufgeht oder danebensteht — das ist eine offene Design-Frage,
> keine Implementierungslücke.
>
> Gleiches gilt für Monster Categories (§6): implementiert sind `BEAST` und
> `HUMANOID`, nicht `UNDEAD`/`INSECT`/`ABERRATION`.
## HIDE
Tierhäute und Felle.

View File

@@ -1331,3 +1331,70 @@ Eine zentrale Condition Engine verbindet:
Der zentrale Grundsatz lautet:
> **NPCs sind datengetriebene Charaktere mit kombinierbaren Interaktionen keine voneinander getrennten Spezialklassen.**
---
# 40. Implementierungsstand (Slice 0.8)
Der V1-Scope aus §34 ist umgesetzt, mit drei bewussten Abweichungen. Sie sind
hier festgehalten statt still aufgelöst zu werden.
## Umgesetzt
```text
NpcDefinition apps/api/src/npcs/entities/
DialogueNode priorisiert, mit Conditions (§11)
CharacterNpcState vorbereitet, genutzt für first-met + Flags (§7, §35)
NpcShop / ShopOffer apps/api/src/shops/
NpcExchangeProfile / ExchangeRule apps/api/src/exchanges/
GameConditionService apps/api/src/conditions/
```
Erster NPC: **Borin, Quartermaster** an `south-gate` (Graufurt) mit
DIALOGUE + MERCHANT + RESOURCE_EXCHANGE gleichzeitig — der Kompositionsfall
aus §2/§26 in echt.
## Abweichung 1 — kein `NpcQuestAssignment`
§34 listet es im V1-Scope, aber es gibt noch kein Questsystem (Slice 0.9).
Eine Tabelle mit Fremdschlüssel auf eine nicht existierende `quests`-Tabelle
ist nicht baubar, und ein `questKey`-String ohne Validierung wäre spekulative
Architektur (AGENTS §1.7). Nachzuholen mit Slice 0.9, zusammen mit den
Dialog-Actions `START_QUEST` / `COMPLETE_QUEST`.
## Abweichung 2 — kein `NpcDialogueProfile`
§10 skizziert `NpcDialogueProfile` als Zwischenebene zwischen NPC und
`DialogueNode`. §34 verlangt dagegen nur "priorisierte DialogNodes +
Conditions", und das Profil hätte in V1 keine eigenen Felder. Nodes hängen
deshalb direkt am NPC. Ein Profil lässt sich später einziehen, ohne die Nodes
neu zu schreiben.
## Abweichung 3 — Conditions, die (noch) nichts beantworten kann
`GameConditionType` enthält die vollständige V1-Liste aus §19, aber nur
`REGION_REPUTATION`, `WORLD_RENOWN`, `FLAG_SET` und `HAS_ITEM` sind
auswertbar. `QUEST_ACTIVE`, `QUEST_COMPLETED`, `BOSS_DEFEATED` und
`LOCATION_DISCOVERED` haben noch kein System dahinter.
Sie werten **fail-closed** aus, also immer "nicht erfüllt". Für ein Gate ist
die sichere Richtung eines Fehlers zu, nicht offen — ein Quest-Gate darf
niemals aufgehen, nur weil es keine Quests gibt.
## Offene Designfrage — World Renown im Tausch
Slice 0.8 §4/§9 skizziert `worldRenownPerUnit`. Das ist mit dem
implementierten Renown-System nicht verträglich: Renown ist ein Rang 115,
der bei jeder Änderung baseHp/baseAttack aus einer festen Kurve neu setzt
(Slice 0.6.5 §4). Renown pro Fell würde einen Spieler in wenigen Trips ans
Statmaximum bringen.
`ExchangeRule.renownMilestoneKey` verweist deshalb auf einen
`RenownMilestoneDefinition` — die "batch rule"-Variante aus 0.8 §4, und
deckungsgleich mit 0.6.5 §6, das "first meaningful trophy returned" als
Renown-2-Meilenstein nennt. Nicht wiederholbar: der erste Tausch löst ihn
aus, jeder weitere zahlt weiter Silber und Reputation, ohne den Rang
anzufassen.
Falls Renown später doch als Punktwährung gedacht ist, muss das zuerst in
0.6.5 geändert werden — nicht hier.

View File

@@ -0,0 +1,285 @@
# Ashen Realms Playable Slice 0.7 V2
## Complete Burned Road
**Status:** Implementation Specification
**Depends on:** Slice 0.6.6
**Purpose:** Turn the Burned Road into the first complete repeatable hunt location using the new no-XP/no-direct-money progression model.
---
## 1. Goal
The Burned Road becomes the first place where Ashen Realms feels like a repeatable RPG activity rather than a combat test screen.
The player should be able to:
**Travel → Hunt → compare encounters → choose an enemy → fight → receive trade goods/equipment → hunt again.**
This slice replaces the previous reward assumption of direct XP and Silver from kills.
> Normal monster kills must not directly grant XP, Silver, regional reputation or World Renown.
---
## 2. Player Experience
When the player starts a hunt on the Burned Road, 23 encounter cards appear.
Possible enemies:
- Ash Rat
- Feral Road Hound
- Road Bandit
- rare: Charred Raider
Each enemy must feel mechanically and economically different.
The player can deliberately choose an easy target, a useful target, or a risky rare target.
---
## 3. Encounter Pool
Suggested initial weights:
| Monster | Weight | Role |
|---|---:|---|
| Ash Rat | 50 | basic safe target |
| Feral Road Hound | 30 | first status-effect enemy |
| Road Bandit | 18 | stronger humanoid with telegraph |
| Charred Raider | 2 | rare dangerous encounter |
Weights are balancing data and must not be hardcoded into the Angular UI.
The hunt should return 23 distinct encounter records where possible.
---
## 4. Monster Mechanics
### Ash Rat
Purpose: pure baseline combat.
- no special combat mechanic
- low danger
- short fight
- guaranteed basic trade good
### Feral Road Hound
Purpose: introduce Bleeding as a simple ongoing effect.
- normal bite
- occasional Bleeding application
- Bleeding has clear icon/status feedback
- Bleeding duration and damage are server-authoritative
### Road Bandit
Purpose: reinforce Telegraphing.
- normal attack
- Heavy Strike is announced before execution
- Shield Bash can interrupt the prepared attack
- Defend is a valid response if the player does not interrupt
### Charred Raider
Purpose: first rare encounter and visible future farming target.
- noticeably stronger than normal Burned Road enemies
- combines higher base stats with one known mechanic
- no entirely new subsystem
- visually marked as Rare / Strong
---
## 5. Trade Goods
Every normal enemy should provide a thematic trade good instead of money.
Initial content:
| Monster | Guaranteed Trade Good |
|---|---|
| Ash Rat | Ashen Pelt ×1 |
| Feral Road Hound | Tough Hide ×1 |
| Road Bandit | Raider Insignia ×1 |
| Charred Raider | Charred Raider Insignia ×1 |
These items represent loot that can later be exchanged with a merchant.
The trade goods must be persisted as actual player-owned loot.
Slice 0.7.5 will add category-specific carrying capacity and loot bags. Until then, existing inventory storage may temporarily hold these goods.
---
## 6. Equipment Drops
Trade goods are guaranteed; equipment remains an exciting additional roll.
Suggested initial drops:
### Ash Rat
- small chance for simple starter-slot equipment
### Feral Road Hound
- chance for Ashen Boots
- chance for a Small Healing Potion if potions are already lootable
### Road Bandit
- Bandit Blade
- Bandit Hood
- Plunderer Gloves
### Charred Raider
- Reinforced Leather Jacket
- Ashen Boots
- Mark of the Border Watch
- optional prestige drop later
Exact drop rates should remain data-driven and can initially follow existing Tier-1 balancing values where already implemented.
---
## 7. Reward Rules
After a normal victory, the server may grant:
- trade goods
- equipment
- consumables
- hunt/combat state progression
The server must **not** grant:
- XP
- Silver
- regional reputation
- World Renown
These economy/progression rewards are deliberately deferred to merchant exchange and milestone systems.
---
## 8. Backend Requirements
The existing content model must support:
- multiple monsters for one location
- weighted encounter generation
- rare encounter weighting
- guaranteed loot entries
- probabilistic equipment entries
- status-effect combat events
- telegraphed actions
Recommended behavior:
```text
POST /api/hunts
→ server validates current location
→ server selects encounter definitions from Burned Road pool
→ persisted HuntEncounter records are returned
```
Combat must still start only from a valid generated encounter.
---
## 9. Frontend Requirements
The Hunt screen must show for each encounter:
- monster artwork
- English name
- danger rating
- optional short flavor text
- clear Attack action
The player should immediately recognize the rare Charred Raider.
After victory, the loot summary should clearly separate:
- Trade Goods
- Equipment
- Consumables
Do not show old XP or Silver reward rows.
---
## 10. Hunt Refresh
The player can choose **Search Again**.
Rules:
- generates a new persisted hunt result
- old encounter IDs cannot be attacked indefinitely after being invalidated
- avoid client-side randomization
- no resource cost in this slice
---
## 11. Tests
At minimum:
### Hunting
- Burned Road produces only configured monsters
- rare encounter is selectable through deterministic injected random values
- encounter generation is server-authoritative
- invalid/stale encounter cannot start combat
### Combat
- Feral Road Hound can apply Bleeding
- Bleeding ticks correctly
- Road Bandit Heavy Strike is telegraphed
- Shield Bash can interrupt the telegraphed action
### Loot
- Ash Rat grants Ashen Pelt
- Road Bandit grants Raider Insignia
- normal kill grants no XP
- normal kill grants no Silver
- normal kill grants no reputation
- equipment drop roll remains independent from guaranteed trade good
---
## 12. Acceptance Criteria
- [ ] Burned Road offers 23 encounter choices per hunt.
- [ ] Four enemy definitions are available, including rare Charred Raider.
- [ ] Feral Road Hound demonstrates Bleeding.
- [ ] Road Bandit demonstrates Telegraphing / interrupt interaction.
- [ ] Every enemy grants a thematic trade good.
- [ ] Equipment can drop in addition to trade goods.
- [ ] Normal kills grant no XP, Silver, regional reputation or World Renown.
- [ ] Loot is persisted server-side.
- [ ] The player can repeatedly hunt without manual database changes.
- [ ] Existing travel and combat flows continue to work.
---
## 13. Out of Scope
Do not add yet:
- loot bag capacity
- merchant exchange
- reputation-gated shop offers
- first quest tutorial
- Abandoned Watchpost content
- area boss

View File

@@ -700,6 +700,23 @@ Not through special-case controller logic.
# 19. Turn-in foundation
> **IMPLEMENTIERUNGSSTAND (Slice 0.8):** `TurnInDefinition` und `TurnInService`
> wurden durch `ExchangeRule` / `ExchangeService` ersetzt (NPC-Spec §17).
> §20 sah das bereits vor ("Implement the domain service now even if the full
> NPC merchant UI comes later") — die NPC-Merchant-UI ist jetzt da, und Borin
> ist der NPC, der den Tausch besitzt.
>
> Übernommen wurde: item → faction → Silber → Reputation, datengetrieben.
> Ergänzt wurden: NPC-/Profil-Zuordnung, Conditions und `renownMilestoneKey` —
> letzteres ist genau das unten als optional gelistete `firstTurnInMilestoneKey`,
> das laut §19 erst hinzugefügt werden sollte, wenn es gebraucht wird. In 0.8
> wird es gebraucht: der erste Tausch ist der Renown-2-Meilenstein aus §6
> ("first meaningful trophy returned").
>
> Die alte Tabelle wurde gelöscht, nicht deaktiviert: zwei parallele Wege, ein
> Fell in Silber zu verwandeln, wären genau das zweite Progressionsmodell, das
> Slice 0.8 §6 ausschließt.
Create a reusable content definition for future trophy/material turn-ins.
Conceptually:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

View File

@@ -56,8 +56,19 @@ Directly implements spec §13's suggested "old Level 1 → Renown 1" mapping, cl
Spec §15 frames a direct currency drop as a legitimate *exception* mechanism ("unless the monster explicitly has a lore-valid direct currency drop... an exception rather than the default system"), not something to delete. The cleanest way to keep the mechanism available for a future lore-valid monster while making today's content compliant is: keep the `silverMin`/`silverMax` roll in code (a monster with both set to 0 always rolls 0 — harmless), but delete `experienceReward` and the `character.experience +=` line entirely, since XP has no "legitimate exception" carve-out anywhere in the spec — it is fully abolished (§1, §33). This is the more data-driven choice per §42 (no special-case code to gate the exception; content data alone decides), and required zero seed-monster stat redesign beyond zeroing two columns.
*Cost if wrong:* if the "exception" framing turns out unwanted, deleting the roll mechanism later is a small, contained change (one method body, one DTO field).
> **SUPERSEDED by Playable Slice 0.7 V2 (`docs/playable-slices/0.7-Complete-Burned-Road-V2.md` §7).**
> The "exception" framing did turn out unwanted. Slice 0.7 V2 states flatly that a normal
> victory must grant no Silver, and routes all currency through merchant exchange instead
> (slice 0.8). `MonsterDefinition.silverMin`/`silverMax`, `CombatReward.silverGranted`, and
> the silver roll in `CombatRewardService` are all gone as of migration
> `1793000000000-CompleteBurnedRoad`. A future lore-valid direct currency drop would be
> reintroduced deliberately rather than left standing as an unused code path.
**R8 — `CombatReward.experienceGranted` column and `CombatRewardDto.experience` field are both deleted.**
Follows directly from R7 — once XP is gone as a concept, persisting a granted-XP audit trail is dead weight. `CombatRewardDto` becomes `{ silver: number; items: CombatRewardItemDto[] }`.
> **Amended by Playable Slice 0.7 V2:** `CombatRewardDto` is now `{ items: CombatRewardItemDto[] }` —
> the `silver` field went the same way as `experience`, for the same reason.
*Cost if wrong:* trivial to re-add a column; no external consumer beyond this same slice's own new code.
**R9 — API surface: extend the existing `GET /api/characters/me` response with `renown: number` (replacing `level`/`experience`); add a new `GET /api/reputation` endpoint returning all enabled factions with the character's reputation (defaulting unrepresented factions to 0/Stranger); do not add a separate `GET /api/renown` endpoint.**