fix(kampf): Gegner bekommen endlich ihre Werte
Gemeldet als "Ratten vergiften zu 100 %". Dahinter lagen drei Fehler: 1. Creature::from_def parste Attributnamen mit toml::from_str, das eine ganze TOML-Datei erwartet. Der Aufruf schlug fuer jeden Namen fehl, der Zweig hiess Err(_) => continue — jeder Gegner hatte seit M3 still die Standardwerte. Die Riesenratte: 100 Leben statt 14, der Knochenfuerst war eine grosse Ratte. Kampf gegen den ersten Gegner: 22 Zuege statt 4. 2. attack_hit feuerte bei allen Traegern statt nur beim Angreifer, also vergiftete die Ratte auch bei eigenen Treffern. EventKind:: bound_to_source benennt die zwei seitengebundenen Ereignisse. 3. Action::Damage wuerfelte die Trefferformel auch bei Selbstschaden — ein flinker Held wich seinem eigenen Gift aus. Dazu ein Datenfehler: Das Gift stand in der Aktionsliste von rat_bite, und Aktionen haben kein chance. Es haengt jetzt am Trigger mit 25 %. Drei Regressionstests, darunter der, den es seit M3 haette geben muessen: ein Gegner bekommt die Werte aus seiner Definition.
This commit is contained in:
@@ -284,3 +284,52 @@ Initiativreihenfolge dieses Zuges. **Ein** Ansagepunkt, kein zweiter beim Kampfb
|
||||
Ausdrücklich **nicht** dazugekommen ist ein Ziel an der Ansage: Die `ai` greift ausschließlich den
|
||||
Helden an, `intent` trägt deshalb nur die Fähigkeits-ID. Ein Zielfeld käme mit dem ersten Gegner, der
|
||||
seine Verbündeten heilt.
|
||||
|
||||
### Befunde aus der zweiten Balancing-Runde — drei Fehler, ein Symptom
|
||||
|
||||
Gemeldet wurde „Ratten vergiften zu 100 %, kaum zu überleben". Dahinter lagen drei unabhängige Fehler,
|
||||
und der größte hatte mit Gift nichts zu tun.
|
||||
|
||||
**1. Jeder Gegner hatte seit M3 die Standardwerte.** `Creature::from_def` las die Attributnamen mit
|
||||
`toml::from_str::<Attribute>("\"max_health\"")` — und `toml::from_str` erwartet eine ganze TOML-*Datei*,
|
||||
kein nacktes Skalar. Der Aufruf schlug für **jeden** Namen fehl, der Zweig hieß `Err(_) => continue`,
|
||||
und damit behielt jedes Wesen still die Voreinstellung: Die Riesenratte hatte **100 Leben statt 14** und
|
||||
2 Schaden statt 3. Der Knochenfürst war eine große Ratte. Ein Kampf gegen den ersten Gegner dauerte 22
|
||||
Züge.
|
||||
|
||||
Kein Test hat das gesehen, weil alle Kampftests ihre Zahlen selbst setzen und nie eine
|
||||
Gegnerdefinition nachschlugen. Der Fehler ist ein stiller `continue` — die Sorte, gegen die Ticket 04
|
||||
„jeder Verlust bekommt eine Zeile" beschlossen hat, nur eben in `game/` statt im Lader.
|
||||
|
||||
**2. Seitengebundene Ereignisse feuerten bei allen.** Dieses Ticket und 08 trennen `attack_hit`
|
||||
(feuert beim Angreifer) von `damage_taken` (beim Getroffenen), ausdrücklich damit *„kein Trigger erst
|
||||
prüfen muss, auf welcher Seite er steht"*. Die Trägerschleife in `drain_events` legte aber jedes
|
||||
Ereignis jedem Beteiligten vor — der Gift-Trigger der Ratte feuerte deshalb auch, wenn der **Held**
|
||||
zuschlug. Dieselbe Lücke hätte den Dornenpanzer des Angreifers reflektieren lassen.
|
||||
|
||||
`EventKind::bound_to_source()` benennt die beiden. Alle übrigen bleiben offen: `turn_started` muss bei
|
||||
jedem ticken, sonst vergiftet sich nur der Spieler.
|
||||
|
||||
**3. Man verfehlte sich selbst.** Der M3-Befund „die Trefferformel war toter Code" wurde behoben, indem
|
||||
`Action::Damage` sie *immer* würfelt. Ein Gift-Tick ist aber kein Angriff, und die Formel liest die
|
||||
Geschicklichkeit des Ziels — ein flinker Held wich also seinem eigenen Gift aus. Im Log stand
|
||||
„M verfehlt M". Neue Regel, eine Zeile: **Man verfehlt sich nicht selbst.**
|
||||
|
||||
**Dazu ein Datenfehler, kein Codefehler:** `rat_bite` legte `core:poisoned` in seiner *Aktionsliste* ab,
|
||||
und Aktionen haben kein `chance` — das gibt es nur am Trigger (Ticket 08). Jeder Biss vergiftete also,
|
||||
und weil erneutes Auflegen die Dauer auffrischt, war der Held ab dem ersten Treffer dauerhaft vergiftet.
|
||||
Das Gift hängt jetzt am Trigger der Ratte mit `chance = 0.25` — genau der Fall, für den Ticket 08 das
|
||||
Feld erfunden hat („20 % Chance, Brennen auszulösen, braucht sonst ein Script").
|
||||
|
||||
**Danach gemessen**, Elf-Dieb auf Stufe 1, je 40 Kämpfe:
|
||||
|
||||
| Gegner | Züge | Lebensverlust | Tode |
|
||||
|---|---|---|---|
|
||||
| Riesenratte | 4,2 | 6 | 0/40 |
|
||||
| Skelett | 6,6 | 18 | 0/40 |
|
||||
| Ghul | 15,8 | 94 | 24/40 |
|
||||
| Knochenfürst | 9,9 | 110 | 40/40 |
|
||||
|
||||
Die Kurve *existiert* damit zum ersten Mal — vorher war jeder Gegner derselbe. Ob Etage 3 bis 5 fair
|
||||
sind, sagt diese Tabelle **nicht**: Sie vergleicht einen Helden auf Stufe 1 mit Startdolch gegen Gegner,
|
||||
denen er erst mit mehreren Aufstiegen und besserer Ausrüstung begegnet. Das entscheidet Spielen.
|
||||
|
||||
Reference in New Issue
Block a user