Handbuch Scroll-Listen entfernt. Handbuch offen und tabs eingefügt. Upgrades eingefügt. "Garage" eingefügt. Anbindung eines echten Gameplaymanager möglich (theoretisch)

This commit is contained in:
2026-10-15 03:24:48 +02:00
parent dadd1fcad0
commit 5486444dde
132 changed files with 55540 additions and 4807 deletions
+73
View File
@@ -0,0 +1,73 @@
# Kellerversorgung anschließen
## Für Tim
Die UI ist fertig vorbereitet. Der Kollege schreibt eine normale Unity-Komponente, die ISupplyGameplay implementiert. Diese Komponente wird auf ein dauerhaft aktives GameObject gelegt und anschließend in `Canvas_SupplyBasement > LiftCallButton > Supply Basement Controller > Supply Backend` gezogen. Sonstige UI-Scripts müssen dafür nicht bearbeitet werden.
Ohne Backend bleibt die bisherige Bedien- und Fahrvorschau erhalten. Mit Backend verwendet der Keller ausschließlich dessen Mengen, Verbindungen, Priorität und LKW-Fortschritt. Die Oberfläche berechnet oder verbraucht selbst keine Munition. Alle Anzeigen und Verbindungen sind außerhalb von Play im Inspector gespeichert.
In jedem Buildable gibt es `Kellerversorgung und Turmmagazin > Supply`: Typ, Magazin, Startfüllung, Nachfüllrate und Verbrauch pro echtem Schuss oder Feuersekunde. Die Werte sind vorläufig. Physische Waffen teilen zunächst Physical, Energiewaffen EnergyCells; sonstige Anlagen, Fallen und Einmalaktionen haben None. Special ist für spätere tatsächliche Sondermunition vorbereitet.
## Vertrag für die Gameplay-Implementierung
Namespace: `DepthsOfGreed.HandbookUI`.
Drei Methoden genügen:
```csharp
public sealed class MySupplyController : MonoBehaviour, ISupplyGameplay
{
public SupplyState ReadState() { /* Zustandskopie für die Anzeige zurückgeben */ }
public SupplyCommandResult SetConnected(long instanceId, bool connected)
{ /* prüfen, Zustand ändern oder mit Begründung ablehnen */ }
public SupplyCommandResult SetPriority(SupplyKind priority)
{ /* None = automatisch; ansonsten die gewünschte Sorte */ }
}
```
Das ist eine Signaturvorlage, noch kein lauffähiges Versorgungssystem. ReadState wird nur bei sichtbarem Keller ungefähr viermal pro Sekunde aufgerufen. Beim Unsichtbarwerden wird das Gameplay nicht deaktiviert. Der Controller muss deshalb unabhängig von der Keller-UI laufen. Snapshot-Listen dürfen nicht während des UI-Lesens verändert werden: Kopien / stabile Zustandsansichten zurückgeben. Unity-Objekte und Kommandos auf dem Hauptthread verwenden.
### Zustände
- `SupplyState.priority`: None = automatisch, Physical / EnergyCells / Special = bevorzugter Typ.
- `channels`: bis zu drei `SupplyChannelState`, jeweils nach `kind`, unabhängig von Listenreihenfolge. `storage/storageCapacity` sind die Bodenbehälter; `buffer/bufferCapacity` die Verteilerreserven. Fehlende Sorte zeigt einen Strich; echte 0 bleibt sichtbar.
- `towers`: versorgte Turminstanzen mit `instanceId`, Buildable-Asset `type`, `connected`, `magazine/magazineCapacity`. Dieselbe ID muss auch in `BuiltObjectSnapshot.instanceId` verwendet werden. Keine IDs nach Listenposition vergeben oder bei Sortierung ändern. ID 0 ist für freie UI-Plätze reserviert. Maximal acht versorgte Instanzen für die aktuell angezeigte Ebene liefern. Entfernte Türme aus der Liste nehmen. Neue Türme standardmäßig verbunden anlegen.
- `truck`: Phase Idle / Loading / Driving / Unloading; Ladung und Kapazität; `from/to` sind semantische Haltepunkte, `progress` der Fahrfortschritt 0..1. Beim Fahren interpoliert nur die UI zwischen ihren frei editierbaren Haltepositionen. Bei anderen Phasen steht der LKW an `to`. Leerlauf also `from = to = aktueller Halt`. `truck = null` zeigt LKW bereit.
- `consumedPerSecond` je Sorte/Turm ist optional für die spätere Statistik. `null` bedeutet unbekannt, 0 bedeutet gemessen kein Verbrauch. Diese Werte werden noch nicht im Keller angezeigt. Aus echten Entnahmen über ein Zeitfenster messen, nicht aus theoretischer Feuerrate hochrechnen.
### Kommandos und Rückmeldung
`SetConnected` und `SetPriority` geben `new SupplyCommandResult(true)` oder `new SupplyCommandResult(false, "Begründung")` zurück. Bei Erfolg muss ReadState danach den bestätigten Zustand liefern. Die UI übernimmt keinen optimistischen lokalen Wert, wenn ein Backend angeschlossen ist. Bei Ablehnung bleibt der alte Zustand erhalten, die Begründung erscheint kurz beim LKW-Status.
Die bisherigen `ConnectionChanged` und `PriorityChanged` bleiben als zusätzliche Benachrichtigungen für akzeptierte Bedienbefehle erhalten. Sie werden NICHT für externe Zustandsänderungen ausgelöst. Wer die Interface-Kommandos implementiert, darf dieselbe Änderung nicht zusätzlich über diese Events erneut ausführen.
### Welche Zahlen gehören wohin?
Das Buildable-Asset enthält nur feste Typwerte. Aktuelle Magazine, Behälterstände, LKW-Ladung und Anschlusszustände verwaltet ausschließlich das Gameplay pro Instanz / Ebene. Vier gleiche Türme teilen ein Asset, aber niemals ihren aktuellen Magazinstand.
Für den Magazinverbrauch gilt ausschließlich `type.supply`:
- `PerShot`: `unitsPerShot` nur für tatsächlich ausgelöste Schüsse abbuchen.
- `WhileFiring`: `unitsPerFiringSecond * tatsächliche Feuerzeit` abbuchen.
- `kind == None`: kein Anschluss und kein Keller-Magazinverbrauch.
Die älteren Werte `combat.ammoPerShot`, `combat.ammoPerSecond`, `combat.energyPerSecond` bleiben zur Kompatibilität erhalten. Sie sind KEINE zweite Abbuchung aus demselben Magazin. Ob ihr unabhängig davon einen elektrischen Unterhalt wollt, ist eine separate Designentscheidung. Die neue Kelleranbindung bezahlt auch keinen Baupreis: energyCost/entrailsCost bleiben Kaufressourcen und sind nicht die Kellerfüllstände.
Neue Magazine anhand initialAmmo <= magazineCapacity initialisieren. Verbunden darf das Backend mit höchstens refillPerSecond aus dem passenden Verteiler nachfüllen; bei getrenntem Anschluss ausschließlich dieses Nachfüllen stoppen. Vorhandene Munition darf weiter verschossen werden. Eine falsche Versorgungsart nicht zulassen. Die Oberfläche kann momentan nur die Verbindung zum im Asset festgelegten Pool ein- und ausschalten.
### Was der Kollege implementiert
Vorräte / Grenzen, tatsächliche Entnahme beim Schießen, Nachfüllen, Transportkapazität, Beladen / Fahren / Abladen, Prioritätsstrategie und alle Konsequenzen leerer Magazine. Die UI macht keine dieser Entscheidungen. Die 12 Waffen besitzen als Arbeitsgrundlage vorläufige Magazine für ungefähr zwölf Sekunden Dauerfeuer, mindestens 30 Einheiten; alle Werte sind frei anpassbar.
### Tests
`SupplyBindingValidation.Validate` prüft die Schnittstelle gegen eine Editor-Testkomponente: fremde stabile IDs, echte Anzeige von Füllständen, Befehle, Ablehnung, LKW-Fortschritt, Entfernen eines Turms. Die Testkomponente ist nicht in der gespeicherten Szene und nicht im Spieler-Build enthalten. `SupplyBasementValidation.Validate` prüft weiterhin die unabhängige Vorschau und Aufzugfahrten. Die einmalige Migration ist abgeschlossen und das Setup-Script entfernt. Szene und Version-3-Assets benötigen keinen erneuten Aufbau.
## Keller im Inspector bearbeiten
`Canvas_SupplyBasement / SupplyBasement` ist im gespeicherten Zustand deaktiviert. Außerhalb von Play zum Bearbeiten einschalten, danach wieder ausschalten. Darunter liegen die Deckenanschlüsse (`TowerConnections`), der Wandverteiler (`Distributor`), der LKW (`TruckLane/Truck`), die drei Bodenbehälter (`StorageTank_0` bis `_2`) und der Raumquerschnitt (`RoomArchitecture`). Alle Grafiken sind austauschbare Platzhalter.
`LiftCallButton` enthält das klappende Schild und den Controller mit allen zugewiesenen Referenzen; `ElevatorDoors` die Übergangstüren. Die Ansicht schaltet innerhalb derselben Szene um. Das Buch wird nur ausgeblendet; das Gameplay läuft weiter. Aufzug-Sound fehlt noch.
Ohne Backend zeigen die Mengen einen Strich. Anschluss- und Prioritätsklicks verändern dann nur die Bedienvorschau; der LKW fährt eine Vorschau. Ein zugewiesenes Backend ersetzt diese Vorschau vollständig durch seine Zustände. Abstecken muss dort das Nachfüllen stoppen, nicht vorhandene Restmunition löschen.