Implement dynamic clientless free-flight travel

Integrate transient flight alternatives with graph routing, native flying mounts, phased terrain and collision checks, bounded avoidance and confirmed landing. Add safe-return recovery, node and location integration, profile settings, diagnostic commands, regression tests and flight documentation.
This commit is contained in:
Nico committed 2026-10-26 17:35:58 +01:00
1 parent 4474714c00
commit 8df9591c99
21 files changed
+1536 -16

No files matched your search

@@ -0,0 +1,140 @@
# Freie Flugreisen
Die Umsetzung ergänzt die Planungsgrundlage in [free-flying.md](free-flying.md).
Freies Fliegen ist eine vorübergehend berechnete Alternative im Fernreisesystem.
Es werden dafür weder Nodes noch Kanten in der Datenbank aufgezeichnet.
## Reiseplanung
Ein Flug kann an einem regulären Graphnode oder einem virtuellen Straßenausstieg
beginnen und an einem regulären Node oder einer Location enden. Virtuelle
Straßeneinstiege sind keine Flugziele. Der Abflugpunkt muss tatsächlich erreicht
sein; ein Bot außerhalb des Graphen erhält keinen beliebigen direkten Luftstart.
Normale Straßenreisen haben einen Kostenvorteil. Flug wird bei genügend großem
Vorteil berücksichtigt; bevorzugte Flugzonen senken Mindestdistanz und Kosten.
Damit können dort auch die Anschlussstrecken zwischen Nodes und Locations fliegen.
Die Vorgabe meint insbesondere Gebiete, deren Aufbau und gefährliche Gegner
Bodenreisen ungeeignet machen. Die Kosten sind Planungsgewichte, keine Sekunden.
Scheitert eine Flugoption am Boden, wird nur diese Option für die aktuelle Reise
gesperrt und mit den übrigen Möglichkeiten erneut geplant.
Die Planung berücksichtigt Kartentyp, bekannte Gebietsregeln, Reitfähigkeit und
Lizenzen. Instanzen sowie bekannte Flugverbote wie Immersangwald und Geisterlande
werden ausgeschlossen. Dynamische Schlachtfeldregeln bleiben zur Laufzeit maßgeblich.
Unbekannte Gebietsmetadaten erlauben lediglich einen Planungsversuch: Beim Start
entscheiden die normalen Mountfähigkeiten und Zauberprüfungen des Servers.
Vashj'irs besondere Unterwasserreisen sind nicht enthalten.
## Profil und Konfiguration
Im `movement`-Abschnitt des Charakterprofils:
```lua
can_free_fly = true,
flight_mounts = { [32235] = 100 }, -- Zauber-ID: Goldener Greif; Gewicht 100
```
Flugmounts verwenden **gelernte Mountzauber**, im Unterschied zu den bisherigen
Display-IDs der Bodenmounts. Die Auswahl erfolgt gewichtet nach der Routenwahl.
Benötigt werden mindestens Expertenreiten (225), ein geeignetes gelerntes Flugtier
und die native Flugberechtigung. Für Karten 0/1 wird die Flugmeisterlizenz (90267),
für Nordend Kaltwetterflug (54197) berücksichtigt. Ein Profil allein erteilt keine
Fähigkeiten. Arthorans Profil enthält den bereits bereitgestellten Greifen.
```ini
Clientless.Flight.Enabled = 1
Clientless.Flight.Clearance = 60
Clientless.Flight.MinDistance = 600
Clientless.Flight.PreferredZones = "210 4197"
```
`Clearance` ist der nominelle Geländeabstand in Yards (begrenzt auf 20–200).
`MinDistance` gilt außerhalb bevorzugter Zonen, dort mindestens 100 Yards;
in bevorzugten Zonen sind Flüge ab 60 Yards planbar. Die voreingestellten
Zonen sind Eiskrone und Tausendwinter; aktuelle Flugverbote gelten weiterhin.
Konfigurationsänderungen können über `reload config` übernommen werden.
## Flugausführung
Nach dem normalen Mountzauber wartet die Steuerung auf die tatsächliche native
Flugfähigkeit. Es gibt keine künstliche Flugfreigabe und keinen Zielteleport.
Die Bewegung erfolgt in kurzen nativen Flugsplines mit Flugmountgeschwindigkeit.
Die Navigation prüft Gelände und Wasseroberfläche, native maximale Flughöhe,
VMAP-Geometrie und kollidierbare dynamische GameObjects in der jeweiligen Phase.
Mehrere versetzte Kollisionsstrahlen approximieren die Körperbreite und -höhe.
Vorausschau und geglättete Geländehöhe verhindern das Nachfahren jeder kleinen
Spitze; längere Absenkungen erhalten eine Verzögerung. Höhenänderungen erfolgen
diagonal. Hindernisse können moderate seitliche Umwege oder zusätzliche Steigung
auslösen; die maximale Flughöhe bleibt eine harte Grenze.
Für Landungen wird fester Boden mit freiem Luftraum gesucht. Ersatzpunkte liegen
höchstens 20 Yards neben dem Ziel und benötigen einen kurzen vollständigen
MMAP-Anschluss zum eigentlichen Ziel. Auf Wasser wird nicht gelandet. Nach
bestätigtem Bodenkontakt endet die Flugsteuerung, gegebenenfalls folgt die lokale
Bodenstrecke; danach setzt die normale Graph- beziehungsweise Intentlogik fort.
## Diagnosebefehle
In der Serverkonsole ohne führenden Punkt, ingame mit Punkt:
```text
clientless flight status 26
clientless flight probe 26 -10100 -600
clientless flight test_node 26 northshire
clientless flight abort 26
```
`status` zeigt Zustand, Fortschritt und Fehler; `probe` prüft Gelände und
Flughöhenbegrenzung auf der aktuellen Karte ohne Bewegung. `test_node` ist ein
isolierter Ausführungstest zwischen einem tatsächlich erreichten regulären
Abflugnode und einem regulären Zielnode derselben Karte. Er verlangt einen
untätigen Bot und ersetzt keinen Test der normalen Reiseplanung.
`abort` bricht einen ausstehenden Mountzauber ab oder versucht in der Luft eine
Rückkehr über die aufgezeichneten, erneut kollisionsgeprüften Flugabschnitte.
Erst nach der Landung wird abgestiegen. Ist auch die Rückstrecke blockiert,
stoppt der Bot gemountet und meldet den Fehler; dieser Sonderfall benötigt
weitere Betreuung. Neue Bodenaktionen werden in der Luft abgelehnt.
Das Log `adventurebot-navigation.log` enthält `FLIGHT_START`, `FLIGHT_SEGMENT`,
`FLIGHT_RETURN`, `FLIGHT_FAILED` und `FLIGHT_LANDED`.
## Grenzen und Prüfungen
Die erste Umsetzung verwendet begrenzte lokale Vorausschau und einen begrenzten
Umweg, keinen globalen dreidimensionalen Pfadsolver. Fehlende Geometriedaten
werden abgelehnt. Komplexe Gebäude, Schluchten und vollständig umschlossene Ziele
können eine Flugoption scheitern lassen. Spieler und NPC-Körper bilden keine
zusätzlichen Hindernisse über die native Weltgeometrie hinaus. Schauflüge und
Tagesroutinen gehören weiterhin in die spätere Verhaltenssteuerung.
Automatisierte Prüfungen:
```bash
python3 tests/clientless/test_free_flight.py
python3 tests/clientless/test_free_flight_planner.py
python3 tests/clientless/test_flight_policy.py
```
Sie prüfen die produktive Geometrie und Planungslogik mit kontrollierten Daten:
Start/Landung, geglättete Spitzen, Flughöhenlimit, seitliches/vertikales Ausweichen,
fehlende Geometrie, hohen Zielanflug, dynamische Flugoptionen, Straßenpräferenz,
virtuelle Ausstiege, Flugverbote und Fehlerbehandlung. Build und Servertests
ersetzen keine abschließende visuelle Abnahme im Spiel.
Serverseitige Testbeobachtungen am 26.10.2026 mit Arthoran (GUID 26):
- Goldhain → Nordhain und zurück: natives Aufmounten, Flugsegmente und bestätigte Landung.
- Manueller Abbruch in der Luft: Rückflug entlang der geprüften Spur und Landung am Ausgangspunkt.
- Reguläres `travel_to_location`: Kombination bestehender Wege mit Flug ab virtuellem Straßenausstieg, Landung und `travel-location-complete`.
- Ein nicht sicher fortsetzbarer Abflug am Node `taxi_12` führte zu Rückkehr und Neuplanung statt einer erfundenen Ankunft.
Das Testziel wurde nur temporär als Worldpoint angelegt. Dafür wurden keine
Flugnodes oder Flugkanten gespeichert. Die visuelle Abnahme bleibt offen.
Der abschließende reguläre Location-Test mit dem verbesserten Anflug endete um
16:44:19 mit `FLIGHT_LANDED` (32 Segmente, Zielabweichung 0,00) und anschließendem
`travel-location-complete`. Der Test lief über die normale Reiseaktion und den
virtuellen Straßenausstieg, nicht über `flight test_node`.
+48
View File
@@ -0,0 +1,48 @@
1. Freies Fliegen als eigenständige Reiseart
Freies Fliegen soll eine reguläre Reisemöglichkeit der AdventureBots werden, neben Laufen, Reiten und Greifenflügen. Es ist ausdrücklich von den festen Flugrouten zwischen Greifenmeistern zu unterscheiden.
2. Wann AdventureBots fliegen sollen
- Grundsätzlich sollen Bots aus RP-Gründen Straßen und Reittiere bevorzugen.
- Freies Fliegen soll bei einem deutlichen Reisevorteil infrage kommen.
- Besonders sinnvoll ist es in Gebieten, in denen Bodenreisen ungeeignet oder extrem umständlich sind, beispielsweise Eiskrone oder Tausendwinter.
- Zonenregeln dürfen ausdrücklich festlegen, dass Fliegen in bestimmten Gebieten bevorzugt werden soll.
- Auch kürzere Reisen können perspektivisch durch Laufen, Reiten oder freies Fliegen zurückgelegt werden.
3. Technische Flugnavigation
Freies Fliegen benötigt ein eigenes Navigationssystem und darf nicht einfach als gewöhnliche TravelGraph-Kante umgesetzt werden.
Wir hatten folgenden Ablauf festgelegt:
Start / Takeoff
3D-Luftnavigation
Zielanflug / Approach
Landung / Landing
Dabei müssen Flughöhe, Hindernisse, geeignete Landepunkte und die Übergänge zwischen Boden- und Flugbewegung berücksichtigt werden.
4. Auswahl des Flugmounts
Die Entscheidung, ob geflogen wird, ist von der Auswahl des konkreten Flugmounts getrennt.
Wählt die Reiseplanung freies Fliegen, darf das Charakterprofil bestimmen, welches passende Flugtier verwendet wird.
5. RP-Flüge und Tagesroutinen
Wir hatten auch gelegentliche Schauflüge hochstufiger Abenteurer über Sturmwind besprochen, beispielsweise mit einer passenden Landung vor dem Auktionshaus.
Dabei wurde ausdrücklich festgelegt: Solche RP-Schauflüge gehören in die spätere Tagesroutine beziehungsweise Verhaltenssteuerung, nicht in das Navigationssystem selbst.
Das Navigationssystem übernimmt lediglich die tatsächliche Durchführung des Fluges.
6. Entwicklungsreihenfolge
Wir hatten folgende Reihenfolge akzeptiert:
Portale und Instanzen → Schiffe und Luftschiffe → Tiefenbahn → freie Flugreisen.
Freies Fliegen war damit als späterer eigenständiger Navigationsschritt vorgesehen. Eine erfolgreiche Implementierung oder ein abgeschlossener Funktionstest wurde bislang nicht bestätigt.
Das ist der bisher besprochene Stand, ohne zusätzliche Umsetzungsvorschläge.