Files
rustkeep/.scratch/rustkeep-1.0/issues/15-progression-und-levelup.md

7.8 KiB

15 — Progression und Level-up

Type: grilling Status: resolved Blocked by: 02

Question

Was passiert beim Aufstieg, und wie sieht die Kurve aus?

Player hat bereits current_exp und next_level_exp, Stats::level_up() deckelt bei 50. Der Attributkatalog aus 01 steht. Offen ist, was ein Level überhaupt gibt:

  • Was gewährt ein Aufstieg? Feste Modifikatoren aus der Klasse, frei verteilbare Attributpunkte, oder beides? Freie Punkte heißen Zuweisungs-UI und die Gefahr, sich den Charakter zu verbauen.
  • Ist die Kurve Daten oder Formel? Eine Tabelle je Level in TOML (moddbar, explizit) oder eine Formel mit Parametern (kompakt, weniger schraubbar)?
  • Bleibt die Obergrenze bei 50, wenn 1.0 aus fünf Etagen besteht? Passt das zusammen?
  • Woher kommt Erfahrung? Nur Tötungen, auch Quests, auch erstmaliges Betreten einer Etage?
  • Skaliert Rasse oder Klasse mit? „+2 Konstitution je Level" ist ein Modifikator mit Level-Bezug — kann das Vokabular aus 01 das ausdrücken, oder braucht es dafür etwas Neues?
  • Werden Leben und Ausdauer beim Aufstieg aufgefüllt? Das ist eine Balancing-Entscheidung mit Folgen für die Etagen-Länge.

Ergebnis: Aufstiegsregel, Kurvenform (Daten oder Formel), Erfahrungsquellen und die Obergrenze.

Answer

Begriffe im Glossar. Dieses Ticket entscheidet Formen und Regeln — die konkreten Zahlen bleiben beim Balancing, das ein spielbares Spiel voraussetzt.

Ein Aufstieg gibt genau einen Punkt

Frei verteilbar auf die fünf Grundwerte: strength · dexterity · constitution · charisma · luck. Abgeleitete Größen wie damage oder hit_chance bleiben ausgeschlossen — Punkte direkt dorthin zu setzen umginge das ganze Modifikatorsystem aus 01.

current_exp und unspent_points leben an Game, nicht am Creature. Ticket 07 hatte die Platzierung ausdrücklich hierher delegiert; base.level bleibt am Wesen (Gegner haben echte Level, die Etagen-Skalierung liest sie), aber Erfahrung und unverteilte Punkte hat ausschließlich der Held. Ein Feld, das für 99 % der Exemplare bedeutungslos ist, wäre ein Kommentar in Feldform — und der Save schriebe es für jeden Gegner mit. Beide Werte werden ohnehin nur beim Aufstieg und in AssignPoints angefasst, und beides läuft über Game.

Verteilt wird im CharacterSheet aus Ticket 11, kein zwölfter Screen. Kein Umverteilen — ein Permadeath-Lauf ist kurz und endet endgültig, eine Respec-Mechanik löst ein Problem, das dabei gar nicht entsteht.

AssignPoints ist ein Command mit allen Punkten auf einmal und kostet damit einen Zug. Ein Command je Punkt hieße bei drei Stufen drei Züge, in denen ein Gift-Debuff tickt, während man ein Menü bedient; eine Ausnahme von der Zugregel wollte Ticket 11 ausdrücklich vermeiden. Dasselbe Muster wie Buy(item, 10).

Keine Obergrenze

Stats::level_up()s clamp(1, 50) fällt ersatzlos. Fünfzig Stufen über fünf Etagen wären bedeutungslos, und eine harte Grenze wäre der einzige Teil der Progression, der einen späteren Endlosmodus blockierte.

Die Kurve begrenzt sich selbst über steigende Kosten: exp_base und exp_exponent als zwei Felder in [balance] aus Ticket 14 — zwei Zahlen statt fünfzig Tabellenzeilen. Eine Tabelle ließe einen Modder Level 13 zum Sprung machen; falls das je gewünscht ist, ist sie der Ausbau.

Erfahrung aus Tötungen und Quests

exp_reward als Feld an der creatures-Registry aus 14, plus give_exp als zehnte Aktion für Questbelohnungen.

Das sind zwei Wege zum selben Ziel, gerechtfertigt nach demselben Muster, mit dem Ticket 01 armor als Kurzschreibweise für Resistenz zugelassen hat: exp_reward ist die Kurzform für einen Todes-Trigger, den sonst jede einzelne Gegnerdefinition mitschleppen müsste — samt einer is_self-Prüfung, die es gar nicht gibt.

Keine Erfahrung fürs Betreten einer Etage. Das belohnte das Durchrennen; wer Räume auslässt, soll schwächer ankommen — das ist die Spannung, von der ein Abstieg lebt.

Geprüft wird am Ende von Game::execute, nach dem Leerarbeiten der Warteschlange aus 08 — dann wirkt eine Questbelohnung noch im selben Zug. Reicht die Erfahrung für mehrere Stufen, wird in einer Schleife aufgestiegen; drei Stufen geben drei Punkte. Eine Stufe pro Ereignis erzeugte sonst die Frage, wann der Rest nachgeholt wird, plus einen Zustand „aufstiegsbereit", den niemand bestellt hat.

Die Zuwachs-Regel bleibt eng

Steigt max_health durch Progression um 10, steigt der Lebensstand um 10 mit — aber nur durch Progression.

Ticket 01 hat davor ausdrücklich gewarnt: „Ein Modifikator wirkt auf max_health, eine Aktion ändert den Lebensstand. Die Trennung muss scharf bleiben, sonst heilt ein Ring beim Anlegen." Eine allgemeine Regel „max ändert sich → Stand ändert sich mit" bräche das sofort.

Genau zwei Stellen erhöhen den Stand um den Zuwachs, beide im Spielkern benannt statt aus einer allgemeinen Regel gefolgert:

  1. der Aufstieg,
  2. AssignPoints — und das ist die unauffällige: max_health steigt erst, wenn constitution tatsächlich erhöht wird, also beim Verteilen und nicht schon beim Aufstieg.

Ausrüstung nie. Der Unterschied ist die Dauerhaftigkeit: Ein Ring kommt und geht, ein Punkt in Konstitution bleibt.

Rasse und Klasse bleiben flach

Das beantwortet die Skalierungsfrage aus dem Ticketkörper mit „gar nicht": per_level als Nachtrag an 01 entfällt ersatzlos. Charakteroptionen geben einen einmaligen, flachen Bonus.

Dass „Zwerg: +2 Konstitution" auf Level 30 nur noch Rauschen ist, ist gewollt. Was Charakteroptionen dauerhaft trägt, sind Fähigkeiten — die veralten nicht. Ticket 02 hat sie als „Modifikatoren und Fähigkeiten" definiert, und der interessante Teil ist die zweite Hälfte: Ein Magier bleibt ein Magier, weil er zaubern kann, nicht weil er +2 auf etwas hat.

level darf modifiziert werden

Creature.base.level steigt beim Aufstieg und ist die einzige Quelle für Punkte. attribute(wer, "level") darf durch Modifikatoren höher ausfallen und wird von Bedingungen („Level ≥ 3"), Formeln und Etagen-Skalierung gelesen.

Ein Ring mit +1 level macht den Helden also für alles, was Level liest, eine Stufe stärker — ohne einen Punkt zu schenken. Dieselbe Trennung wie zwischen max_health und Lebensstand. Modifikatoren auf level zu verbieten wäre die Bevormundung, die Ticket 02 abgeräumt hat, und nähme einem Modder ein hübsches Item, das keinen Schaden anrichtet.

Endlosrunner — neu aufgetaucht, bewusst hinter 1.0

In dieser Sitzung kam auf, dass das Fernziel ein Endlosrunner ist. Das berührt drei geschlossene Entscheidungen: die Siegbedingung aus 10, GameOver { outcome: Won } aus 14, und die floors-Registry, die einen Eintrag je Nummer hat — Etage 500 bräuchte eine Definition.

1.0 bleibt endlich. Die endliche Fassung ist vollständig durchentschieden, und ein Endlosmodus ist additiv: ein Feld repeat = true an der letzten Etage plus eine Skalierungsformel. Umgekehrt hieße es, 10 und 16 gegen ein Zielbild zu bauen, das noch niemand gespielt hat.

Die fehlende Level-Obergrenze ist der Teil, der davon jetzt schon profitiert — sie wäre der einzige Blocker gewesen.

Vier Nachträge an geschlossene Tickets

Ticket Nachtrag
01 give_exp als zehnte Aktion
07 current_exp und unspent_points: u32 an Game, nicht am Creature — die Platzierung, die 07 hierher delegiert hatte
11 AssignPoints als dreizehnter Command
14 exp_base und exp_exponent in [balance], dazu exp_reward an der creatures-Registry

Auflage an Ticket 16

Die Beute-Skalierung darf nicht gegen fünf feste Etagen fest verdrahtet werden — der Endlosmodus kommt später, und eine Skalierung, die nur bis Etage 5 denkt, wäre dann ein Umbau statt einer Erweiterung.