Maerz 2026 war der Monat wo ich das Wort “fast” endgueltig losgeworden bin. Am 24. Maerz: 68 Tests gruen, alle Phase-3-Features implementiert. Feature Complete. Ich hab kurz auf den gruenen Balken geschaut. Dann hab ich einen Kaffee gemacht. Dann hab ich weitergemacht, weil es noch mehr zu tun gab als eingeplant.
Der Maerz hatte drei grosse Baustellen gleichzeitig: Ein fundamentales Refactoring das laengst ueberfaellig war, die Formalisierung des Design-Systems, und die Cockpit-Architektur als neue visuelle Leitstruktur des gesamten Spiels. Keine davon ist ein Feature das ein Spieler direkt sieht. Alle drei entscheiden ob das Spiel in einem Jahr noch wartbar und erweiterbar ist.
Das grosse Refactoring — 2.749 Zeilen werden 198
Der CareerRuntimeService war ueber die Monate zu einem Monster geworden. 2.749 Zeilen Code in einer einzigen Klasse. Alles was irgendwie mit dem Spielablauf zu tun hatte landete dort. Spieltag-Simulation, Transferlogik, Gehaltsabrechnung, Saisonabschluss, Verletzungs-Updates, Moral-Updates, KI-Manager-Aktionen, Spielstand-Persistierung — alles in einer Klasse. Das ist das klassische Muster wie Software verrottet. Nicht durch schlechte Absichten. Sondern weil jedes neue Feature irgendwo angebaut werden muss, und wenn es schon eine Klasse gibt die alles kennt ist es verlockend sie nochmal ein bisschen zu erweitern.
Ich hab den Service in vier spezialisierte Services aufgeteilt:
CareerBootstrapService — alles was beim Start einer neuen Karriere passiert. MasterDB-Daten in SaveDB kopieren, Startbudget setzen, erste Saison anlegen, KI-Manager initialisieren. Laeuft genau einmal pro Karriere. CareerReadService — alle Lesezugriffe auf den Spielstand. Keine Schreiboperationen. Gibt Daten zurueck, veraendert nichts. Kann aus Tests einfach gemockt werden ohne vollstaendigen SaveDB-Zustand. CareerMutationService — alle Operationen die den Spielstand veraendern: Spieler transferieren, Gehaelter anpassen, Verletzungen registrieren, Moral-Updates einspielen. Jede Mutation laeuft als Transaktion. CareerAdvanceService — die Orchestrierung: Spieltag simulieren, Saison abschliessen, neue Saison anlegen, KI-Manager-Runde durchfuehren.
Das Ergebnis: Der urspruengliche CareerRuntimeService ist jetzt 198 Zeilen — eine Koordinationsschicht die die vier Services zusammenbringt und nichts anderes tut. Das Refactoring hat eine Woche gedauert. In dieser Woche hab ich keine neuen Features gebaut. Kein einziger Spieler haette den Unterschied bemerkt. Aber ohne dieses Refactoring waere das Projekt in einem Jahr nicht mehr wartbar gewesen. Das ist die Arbeit die niemand sieht und die trotzdem entscheidend ist.
Das Design-System — Tokens statt verstreuter Pixel-Werte
Parallel zum Refactoring hab ich das UI-Design-System endgueltig formalisiert. Das Problem: Ueber Monate hatte ich Farbwerte, Abstaende und Font-Groessen direkt in Screen-Code geschrieben. “245, 180, 42” fuer den Akzent-Ton an zehn verschiedenen Stellen. Was passiert wenn ich den Ton anpassen will? Zehn Stellen suchen, zehn Stellen aendern — und trotzdem eine vergessen. Das ist keine Wartbarkeit.
Vier Klassen die alle visuellen Entscheidungen zentralisieren:
TaktikManagerTheme — alle Farben an einem Ort. Primary, Secondary, Accent, Danger, Warning, Success — jeweils als Dark/Normal/Light Variante. Hintergrundfarben nach Zone. Textfarben nach Hierarchie-Ebene. Kein Farbwert mehr der irgendwo im Screen-Code steht. Ein Farbton aendern bedeutet eine Zeile in dieser Klasse. TaktikManagerMetrics — alle Abstaende, Typografie-Groessen und Component-Hoehen als benannte Konstanten. Referenzaufloesung 2560×1440. Spacing-Tokens XS/S/M/L/XL. Font-Groessen fuer Caption, Body, Subhead, Head, Display. TaktikManagerLayoutResolver — Breakpoint-Logik fuer die drei Aufloesung-Profile. Die Metriken werden auf die aktive Aufloesung skaliert mit Ausnahme-Regeln fuer nicht-linear-skalierbare Elemente. TaktikManagerViewportProfile — Viewport-Geometrie und Safe-Areas fuer die drei Cockpit-Zonen.
Ohne dieses System beginnt jede neue Screen-Implementierung wieder von vorne: Welche Farbe? Welcher Abstand? Welche Font-Groesse? Mit dem System zieht jeder neue Screen dieselben Tokens und sieht dadurch automatisch aus wie der Rest des Spiels. Man entscheidet einmal richtig und muss danach nie wieder entscheiden.
Die Cockpit-Shell — drei Zonen, ein Arbeitsplatz
Die Cockpit-Shell ist die visuelle Leitstruktur des Spiels. Das Grundkonzept: Der Spieler sitzt nicht an einem Desktop-Interface mit Menues. Er sitzt an einem Arbeitsplatz mit konkreten physischen Zonen.
Drei Zonen: Das Tablet als Hauptarbeitsbereich in der Mitte — 1.59:1 Aspect-Ratio, alle Haupt-Screens laufen hier. Das Handy als Kommunikations- und Benachrichtigungskanal seitlich — kurzfristige Messages, Transfer-Angebote, Vorstandsnachrichten. Die Reminder-Zone fuer laufende Aufgaben — offene Scouting-Auftraege, bevorstehende Vertragsverlaengerungen, naechste Spieltage.
Diese Aufteilung macht das Interface lesbar: Das Tablet ist der Fokus. Das Handy ist der Peripherieblick. Die Reminder-Zone ist das Gedaechtnis. Man weiss immer wohin man schaut und warum — statt dass alle Informationen gleichzeitig um Aufmerksamkeit konkurrieren.
Block D war die Migration aller neun Hauptscreens auf die gemeinsame Cockpit-Chrome: Finance, Scouting, Presse, Transfer, Setup, Kader, Taktik, Match, Post-Match-Analyse. Jeder Screen benutzt jetzt dieselbe Tablet-Chrome mit gemeinsamem Panel-Header, gemeinsamen Tab-Farben und gemeinsamen Button-Positionen. Vier Slices, fuenfzehn verifizierte Arbeitspakete, jeder Screen einzeln getestet. Danach sehen alle Screens aus wie Teile desselben Systems — nicht mehr wie unabhaengige Loesungen die zufaellig auf demselben Bildschirm gelandet sind.
Infrastruktur die niemand sieht, aber jeder braucht
TaktikManagerJson zentralisiert alle JSON-Serialisierungseinstellungen. Das klingt wie eine Kleinigkeit. War es bis zu dem Punkt wo ich gemerkt hab dass zehn verschiedene Stellen im Code zehn verschiedene JsonSerializerOptions-Instanzen mit teilweise inkonsistenten Einstellungen hatten — mal CamelCase, mal PascalCase, mal mit NullHandling, mal ohne. Das fuehrt zu schwer findbaren Fehlern beim Laden aelterer Spielstaende. Jetzt: Eine zentrale Instanz, konfiguriert einmal, ueberall referenziert.
AppDiagnostics ist das Produktions-Logging-System. Wenn die Beta draussen ist und jemand einen Bug erlebt brauche ich Informationen. Crash-Zeitstempel, Stack-Traces, letzter bekannter Spielzustand, OS-Version, Grafikkarten-Info — alles geht in %LOCALAPPDATA%TaktikManagerLogs. Die Log-Datei rotiert taeglich und behaelt die letzten sieben Tage. Das ist der Unterschied zwischen “das Spiel crashed bei mir” und “ich kann reproduzieren warum”.
Beta angekündigt — und die drei Planungsdokumente
Mit dem Feature-Stand Ende Maerz hab ich die Planungsdokumente endgueltig aufgeraeumt. Drei klare Dokumente mit klaren Grenzen:
Das Beta-Dokument listet was in die oeffentliche Beta kommt — der vollstaendige Stand Ende Maerz. Das Phase-4-Dokument listet was fuer v1.0 noch dazukommt — fehlende kleinere Features, Balancing, QA-Runden, erste Community-Rueckmeldungen einarbeiten. Das Post-Release-Dokument listet was bewusst aus v1.0 ausgespart wird: 3D-Modus, Vulkan-Renderer, Steam Workshop fuer Mods, vollstaendiger Kommentator, internationale Karriere-Mode.
Warum so konsequent raus aus v1.0? Weil jedes dieser Features hochriskant und zeitintensiv ist. 3D bedeutet eine komplett andere Rendering-Pipeline. Vulkan bedeutet Monate an Low-Level-Grafik. Steam Workshop bedeutet ein komplettes Infrastruktur-System. Wenn ich vor dem ersten Release anfange diese Features zu bauen gibt es keinen ersten Release. Besser ein vollstaendiges spielbares v1.0 als ein ewiges “bald fertig” mit immer neuen grossen Baustellen.
Die Beta ist angekuendigt. Via Mega Download, kostenlos, ohne Account. Das Spiel ist spielbar. Es ist nicht perfekt — aber es ist da. Jetzt koennen andere es sehen. Das war ein seltsamer Moment. Zehn Monate solo gearbeitet und dann: ein Download-Link ins Netz stellen. Ich freu mich. Ich bin nervoes. Beides gleichzeitig. Das ist wohl das richtige Gefuehl.