# Interaktive Objektportale im TravelGraph Stand 26.10.2026. Diese Erweiterung bildet einen normalen Klick auf ein festes Portal-GameObject als gerichtete TravelGraph-Kante `portal_use` ab. Die Nodes behalten den Typ `portal`. AreaTrigger-Portale (`portal_at_…`) und deren bestehender Import bleiben unverändert. ## Unterstützter erster Interaktionstyp Unterstützt werden statisch gespawnte GameObjects vom Typ 22 (`SPELLCASTER`), deren direkt benutzter Zauber genau einen Teleporteffekt mit einem festen `TARGET_DEST_DB`-Ziel besitzt. Spawn, Objekt-Entry, Zauber und Ziel werden aus den geladenen nativen Core-/DB-Daten ermittelt. Nicht jeder klickbare Teleporter erfüllt diese Voraussetzungen. NPC-Gossip, Gossip-Auswahl an Objekten, GOOBER-Skripte, ausgelöste Zauberketten und dynamisch gewählte Ziele benötigen weitere Interaktionsvarianten. Der Importer weist solche Fälle zurück, anstatt ein Ziel zu erraten. Beispielsweise hat der Shattrath-Teleporter zur Insel von Quel’Danas einen anders aufgebauten Zauber und ist nicht durch diesen direkten Import abgedeckt. Vashj’ir mit seinen besonderen Wasserreiseangeboten bleibt gemäß Nutzerentscheidung eine spätere Erweiterung. Schwimmen/Tauchen gehört zur lokalen Navigation; Ruhesteine und eigene Teleportzauber sind nicht Teil dieser TravelGraph-Erweiterung. ## Einrichtung und gezielter Import Einmalig die neue Tabelle auf der lokalen Test-Weltdatenbank anlegen: ```text sql/custom/world/2026_10_26_02_clientless_portal_use.sql ``` Die Datei legt nur `vcore_clientless_portal_use` an; sie aktiviert keine Verbindung. Nach Installation des neuen Builds ein konkretes Objekt auswählen. Im Spiel hilft `.gobject near 30` bei der Suche nach vorhandenen Objekten. Benötigt wird die Datenbank-Spawn-ID, nicht die Objekt-Entry-ID. Im GM-Spielchat: ```text .clientless portal object import ``` Oder in der Testserver-Konsole ohne Punkt: ```text clientless portal object import ``` Beispiel Dunkles Portal (Scherbenweltseite) → Sturmwind: ```text clientless portal object import 170 ``` Der Import erzeugt: - `portal_go_170_source` an der nativen Objektposition. - `portal_go_170_target` am nativen Zauberziel. - Eine gerichtete Kante `portal_use`, Kosten 1, ohne automatische Rückrichtung. - Eine Bindung der Kanten-ID an Spawn 170, Entry 195139 und Zauber 17334. Ein vorhandener Node oder eine vorhandene Kante wird nicht überschrieben. Insbesondere bleiben nachbearbeitete Anlaufpositionen und `enabled=0` erhalten. Die Transaktion kann wiederholt werden, ohne zusätzliche Nodes/Kanten zu produzieren. Der Import lädt Graph und Weltpunkte anschließend neu. Eine ungültige oder deaktivierte Verbindung wird ausdrücklich als nicht aktiv angezeigt; Details stehen im Navigationlog. Rückreisen benötigen ein tatsächlich vorhandenes anderes Portal und eine eigene Definition. Ein Portal nach Sturmwind erzeugt keine Rückfahrt nach Shattrath. Der Graph verwirft `portal_use`-Kanten mit `bidirectional=1`, fehlender oder veralteter Bindung und einem unpassenden Zielnode. Der zusätzlich untersuchte Shattrath-Spawn **83** ist im Testgraph deaktiviert: Sein nativer Zauber verwirft die Effekte bei der Sichtlinienprüfung. Das trat bei Level 20 und 60 sowie an zwei Anlaufpositionen auf. Es wurde keine native Sichtlinienprüfung umgangen und keine GO-/Zauberdefinition verändert. Ein Wiederholungsimport soll diese Deaktivierung erhalten. ## Anlauf und Reiseauftrag Der Quellnode muss per normaler lokaler Navigation erreichbar sein und nahe genug am tatsächlichen Objekt liegen. Bei Bedarf den Source-Node mit einem GM auf einen begehbaren Punkt innerhalb der Interaktionsreichweite verschieben: ```text .clientless node move portal_go_170_source ``` Ein Wiederholungsimport behält diese Anpassung bei. Falls der Source-Node anschließend über Groundwege angeschlossen werden muss, diese separat aufnehmen. Die Kante selbst enthält keine erfundenen Laufwege. Ein normaler Lua-Reiseauftrag verwendet den Zielnode: ```lua queue_action("travel_to_node", { node = "portal_go_170_target", hard_destination = true }) ``` Der Executor prüft das konkrete gespawnte Objekt, Phase, Sichtbarkeit, Sperr-/Auswahlflags und die normale Interaktionsreichweite. Er stoppt die Bewegung, steigt gegebenenfalls vom Bodenreittier ab und ruft den normalen `CMSG_GAMEOBJ_USE`-Handler auf. Die native Objekt-AI, Gruppenprüfungen und Zauberbedingungen entscheiden weiterhin, ob der Klick funktioniert. Level- oder Questanforderungen werden durch den Executor nicht umgangen. Nach dem Klick wartet der Bot auf einen bestätigten Clientless-Teleport. Ein Session-Zähler erfasst erfolgreich abgeschlossene Near-/Far-ACKs, auch wenn der allgemeine Session-Lifecycle den ACK vor dem nächsten Executor-Tick bearbeitet hat. Erst bei neuer Bestätigung, abgeschlossenem Teleport, richtiger Zielkarte und höchstens 5 Yards Zielfehler gilt die Kante als fertig. Nach 10 Sekunden ohne bestätigte Ankunft schlägt die Aktion fehl. Kein wiederholtes Klicken pro Tick, kein künstlicher Ersatzteleport. Der Planner prüft derzeit nicht sämtliche individuellen Zauberbedingungen vorab. Eine geplante Verbindung kann deshalb bei der tatsächlichen Benutzung abgewiesen werden. Die Ablehnung ist kein erfolgreicher Reiseabschluss. ## Diagnose und Tests ```text .clientless actioninfo 26 ``` Navigationlog: - `PORTAL_USE_START`: konkretes Objekt wurde an den Klick-Handler übergeben. - `EDGE_COMPLETE … edgeType='portal_use'`: Ankunft einschließlich ACK bestätigt. - `PORTAL_USE_FAILED`: Objekt/Spielerzustand ungeeignet oder Teleport nicht bestätigt. - `PORTAL_USE_BINDING_INVALID` / `PORTAL_USE_EDGE_UNAVAILABLE`: Definition beim Reload verworfen. Automatisierte Regressionen: ```text python3 tests/clientless/test_portal_use.py python3 tests/clientless/test_portal_transfer.py ``` Sie führen die tatsächlichen Produktionsmethoden mit Core-Doubles aus: Quellobjektprüfung, normaler Klick-Handler, Near/Far, bereits global bearbeiteter ACK, Ablehnung, Timeout, falsche Zielkarte/-position, native Zielauflösung und ACK-Sequenzzähler. Sie ersetzen keine Live-Fahrt oder visuelle Ingame-Abnahme. Live-Ergebnisse des ersten Tests werden in [interactive-portals.md](../doc/clientless/interactive-portals.md) festgehalten.