306 lines
16 KiB
Markdown
306 lines
16 KiB
Markdown
# Autonomes Verhalten: Implementierungsplan und Vertrag
|
||
|
||
Konzeptfortschreibung vom 27.10.2026: Der vereinbarte Umfang umfasst
|
||
[sieben Grundintents](intent-katalog.md). Die folgende Implementierungsbeschreibung
|
||
beschreibt vorwiegend die ursprünglichen drei technischen Intents; der neue
|
||
[Ruhe-Intent `rest`](rest-intent.md), der [Freizeit-Intent `leisure`](leisure-intent.md)
|
||
der [Wirtschaften-Intent `economy`](economy-intent.md) und der
|
||
[Abenteuer-Ausbau](adventure-intent.md) sind separat dokumentiert. Die zuvor
|
||
ausstehende visuelle Prüfung der Stuhlsitzposition hat der Nutzer inzwischen
|
||
erfolgreich abgeschlossen.
|
||
|
||
Dieser Stand ersetzt die Lua-Tagesroutinen-Annahme aus `mikroaction.md`.
|
||
Lua beschreibt Profile; der C++-Planer erzeugt daraus einen Tagesplan.
|
||
|
||
- 24 Stundenplätze nach lokaler Serverzeit, Reisezeit eingeschlossen. Ein Intent
|
||
belegt 1–4 zusammenhängende Stunden; Ziele dürfen stündlich wechseln oder bleiben.
|
||
Aufenthalte verlängern die festen Zeitfenster nicht.
|
||
- Gewichtete Auswahl berücksichtigt Persönlichkeit, Aktivitäten und Regionen.
|
||
- Locationtypen und Botaktionen werden in bearbeitbaren Katalogen mehreren Intents
|
||
zugeordnet. Unklare Orte bleiben `landmark`, erkennbare Namen werden großzügig
|
||
klassifiziert. Importierte Definitionen und manuelle Korrekturen werden erhalten.
|
||
- Der Reiseexecutor nähert sich unerreichbaren Zielen bestmöglich über den Graphen;
|
||
anschließend wird die nächste passende Ersatzlocation gesucht, ohne Entfernungsgrenze.
|
||
- Ein Gebietsintent benötigt einen erreichbaren Graphnode innerhalb des Gebiets.
|
||
Die lokale Erkundung darf das Gebiet nicht verlassen.
|
||
- Bei einem Planwechsel wird eine laufende Fernreise bis zum nächsten sicheren
|
||
regulären Graphnode beendet; Taxi, Portal, Schiff und Flug werden nicht gewaltsam
|
||
unterbrochen. Danach wird das neue Ziel geplant.
|
||
- Mikroaktionen: umsehen, erkunden, sitzen/rasten, trinken, essen, Emote, sprechen,
|
||
Arbeit darstellen. Aktions- und Variantenhistorien senken Wiederholungsgewichte.
|
||
Arbeit verändert weder Ressourcen noch Inventar. Echte Kampf-KI bleibt später.
|
||
- Der erste Test ist `social` in `goldshire_tavern`; Arthorans Tagesplan bleibt aus.
|
||
|
||
## Umsetzungsschritte
|
||
|
||
1. Ortsimport und Katalogmigration mit Herkunft, Gebiets-/Zonenmetadaten.
|
||
2. Profilgesteuerter Tagesplan, gespeicherte Stundenplätze und autonome Intent-Steuerung.
|
||
3. Sichere Reiseübergabe, Ersatzziele, kontextabhängige Mikroaktionen und Diagnose.
|
||
4. Automatisierte Prüfungen, Build, Installation und gezielter Tavernen-Servertest.
|
||
Visuelle Abnahme erfolgt durch den Nutzer.
|
||
|
||
## Bedienung
|
||
|
||
Einmalig die additive Migration auf der Test-Weltdatenbank ausführen:
|
||
`sql/custom/world/2026_10_26_03_adventure_behavior.sql`.
|
||
Nach Installation des Builds in der Serverkonsole (ingame mit führendem Punkt):
|
||
|
||
```text
|
||
clientless adventure import
|
||
clientless adventure reload
|
||
clientless adventure status 26
|
||
clientless adventure plan 26
|
||
clientless adventure intent 26 social goldshire_tavern 3600
|
||
clientless adventure schedule 26 on
|
||
clientless adventure schedule 26 off
|
||
clientless adventure stop 26
|
||
```
|
||
|
||
`plan` erzeugt beziehungsweise zeigt den Tagesplan, aktiviert ihn aber nicht.
|
||
`intent` fordert selbstständige Reise und anschließende Mikroaktionen an;
|
||
seine Dauer dient gezielten Tests und startet mit dem Auftrag. Die normale
|
||
Tagesplanung verwendet dagegen feste Stundenfenster. `stop` und Planwechsel
|
||
warten sichere Reisegrenzen ab. Weder Ressourcen noch Inventar werden für
|
||
Mikroaktionen verändert. Arbeit wird nur an sichtbaren passenden Objekten mit
|
||
geprüftem lokalen Anlauf dargestellt. Echte Kämpfe sind noch kein Teil des Katalogs.
|
||
|
||
Lua-Profile erhalten zusätzlich:
|
||
|
||
```lua
|
||
behavior = {
|
||
enabled = true,
|
||
daily_schedule = false,
|
||
initial_intent = "social",
|
||
initial_location = "goldshire_tavern",
|
||
initial_duration_seconds = 3600,
|
||
locale = "deDE",
|
||
},
|
||
micro_action_affinity = { drink = 1.5, rest = 1.2 },
|
||
```
|
||
|
||
`daily_schedule = true` startet stattdessen den Profilplaner. Ohne explizites
|
||
`behavior.enabled` bleiben bisherige Clientless-Controller unverändert.
|
||
`intend("social", {location="goldshire_tavern"})` bleibt als semantischer
|
||
manueller Auftrag möglich; Lua berechnet weder Tagesplan noch Mikroaktionen.
|
||
|
||
## Daten und Korrekturen
|
||
|
||
- `vcore_clientless_world_point`: Kategorie, Position, enabled wie bisher.
|
||
- `vcore_adventure_location`: Herkunft, Anzeigename, Gebiet, Zone, Region,
|
||
Gebietsmarkierung und optionaler Fraktionsfilter (0 beliebig, 1 Allianz, 2 Horde).
|
||
- `vcore_adventure_location_intent`: mehrere Intents mit Gewichten je Kategorie.
|
||
- `vcore_adventure_action` und `vcore_adventure_action_intent`: Dauer,
|
||
Umgebungsbedingung, Darstellung und mehrere passende Intents.
|
||
- `vcore_adventure_dialog`: gemeinsam verwendete Textvarianten pro Sprache und Intent.
|
||
- `vcore_adventure_day`: 24 gespeicherte Stundenplätze je Charakter und lokalem Datum.
|
||
|
||
Importer und Migration verwenden für Kataloge und Ortsdefinitionen `INSERT IGNORE`.
|
||
Damit bleiben manuelle Positions-, Typ-, Gewichts- und enabled-Korrekturen erhalten.
|
||
Anschließend `clientless adventure reload` ausführen; bei geänderten Worldpoints
|
||
zusätzlich deren bestehende Reload-Funktion verwenden oder den Import wiederholen.
|
||
|
||
Die Quellen sind `game_tele`, Wachposten-POIs und Gasthaus-/Berufsausbilder-Spawns.
|
||
Wachposten-POIs besitzen nur X/Y: Ihre Karte wird aus dem räumlich nächsten
|
||
Teleport-Ort geschätzt, ihre Höhe stammt aus der nativen Terrain-/VMAP-Abfrage.
|
||
Diese Einträge sind als `guard_poi_inferred` gekennzeichnet und dürfen später
|
||
korrigiert werden. Benannte Gesamtgebiete werden über native Gebietsmetadaten
|
||
erkannt. Ziele in Instanzkarten werden importiert, jedoch nicht als autonome
|
||
Aufenthaltsorte gewählt. Bekannte Instanzeingänge auf Außenweltkarten bleiben
|
||
gewöhnliche Reiseziele; eine vollständige Dungeon-Aktivität ist ein späterer Schritt.
|
||
|
||
## Prüfung
|
||
|
||
```bash
|
||
python3 tests/clientless/test_adventure_behavior_policy.py
|
||
python3 tests/clientless/test_adventure_intent_state.py
|
||
python3 tests/clientless/test_flight_area_query.py
|
||
```
|
||
|
||
Weitere Regressionen prüfen Lua-Reload, Graphplanung, Flug, Portale und Transporte.
|
||
Neue Logereignisse: `ADVENTURE_CATALOG`, `DAY_PLAN`, `INTENT_TRAVEL`,
|
||
`INTENT_FALLBACK`, `INTENT_ARRIVED`, `MICRO_START`.
|
||
|
||
Der erste Live-Test aktiviert ausschließlich Arthorans Geselligkeit in Goldhain.
|
||
Die sichtbare Abnahme sowie die weiteren Intent-/Tagesplan-Tests folgen mit dem Nutzer.
|
||
|
||
## Bisherige Servertests am 26.10.2026
|
||
|
||
- Import: 2.631 Definitionen (1.531 Teleport-Orte, 372 rekonstruierte
|
||
Wachposten-POIs, 728 Gasthaus-/Berufsausbilder-Spawns). Zusammen mit neun
|
||
bestehenden semantischen Locations stehen 2.640 Locations im Katalog.
|
||
Darunter 33 Gesamtgebietsziele. 231 POIs ohne brauchbare Koordinaten/Höhe
|
||
wurden übersprungen. Ein Wiederholungsimport erzeugte keine Duplikate.
|
||
- Bestehende Goldhainer Taverne unverändert; native Zone 12, Region `elwynn`.
|
||
- Arthoran reiste eigenständig von Goldhains Startpunkt in die Taverne.
|
||
Reiseabschluss, `INTENT_ARRIVED` und wiederholte `MICRO_START` bestätigt.
|
||
Beobachtete Aktionen im Log: sprechen, sitzen, winken, trinken, erkunden,
|
||
essen, lachen und nicken. Dies bestätigt serverseitige Ausführung, keine
|
||
visuelle Abnahme der Animationen.
|
||
- Tagesplan-Vorschau: genau 24 persistierte Stundenplätze mit mehrstündigen
|
||
Aufenthalten und wechselnden Zielen. `daily_schedule` bleibt für Arthoran aus.
|
||
- Die native Gebietsanfrage der Fluglogik verwendete die Argumentreihenfolge
|
||
des TerrainMgr statt TerrainInfo. Korrigiert und mit einer eigenen
|
||
Produktionsmethoden-Regression für Karte/Phase, Gebiet/Zone und Cache geprüft.
|
||
|
||
Weitere Reise-/Ersatzziel-, Gebiets-, Arbeitsdarstellungs- und Stundenwechseltests
|
||
bleiben für die nächsten gemeinsamen Testschritte vorgesehen. Automatisierte
|
||
Tests decken die Zustandsübergänge und Auswahlregeln bereits ab.
|
||
|
||
Zusätzliche Regressionen für Reisewechsel und Mikroaktionsbereinigung:
|
||
|
||
```bash
|
||
python3 tests/clientless/test_adventure_graph_handover.py
|
||
python3 tests/clientless/test_adventure_micro_reset.py
|
||
```
|
||
|
||
Die Bereinigung stoppt die tatsächliche lokale Spline, statt nur ihren
|
||
Navigationsdatensatz zu entfernen. Laufende Schiffsfahrten, Taxiflüge,
|
||
freie Flüge und Portaltransfers werden dabei weiterhin nicht abgebrochen.
|
||
|
||
## Vollständiger Geselligkeitskatalog
|
||
|
||
Migration nach der Grundmigration:
|
||
`sql/custom/world/2026_10_26_04_adventure_social.sql`.
|
||
|
||
Die neuen `social_*`-Szenen ergänzen Essen, Trinken, Umsehen, Platzwechsel und
|
||
kurze Emotes: NPC- und Botgespräch, Sitzplatzsuche, Tresen, Bestellung,
|
||
Begrüßung, Zuhören, Gesprächsreaktion, Anstoßen, Abschied, Kommentar,
|
||
seltenes Tanzen und Lagerfeuer mit Rast. Gesprächspartner werden selbstständig
|
||
angelaufen und anvisiert; `/reden`, Zuhören und Abschied bilden einen Ablauf.
|
||
NPCs und andere Bots werden dabei nicht künstlich zu Antworten gezwungen.
|
||
Menschliche Spieler sind keine gezielt ausgewählten Gesprächspartner.
|
||
|
||
Aktionsart, Variante, Dialogzeile und Ziel-GUID erhalten Wiederholungsdämpfung.
|
||
Sitzplätze werden mit der nativen GameObject-Benutzung verwendet; der Bot läuft
|
||
zuerst heran und wartet danach auf bestätigtes Sitzen. Möbel mit ausgelösten
|
||
Events werden nicht verwendet. Essen, Trinken und Rasten versuchen ebenfalls,
|
||
einen verfügbaren echten Stuhl zu nutzen; sonst bleibt die bisherige Darstellung.
|
||
|
||
Alle AdventureBots erhalten bei ihrem normalen Controller-Login den Spielerzauber
|
||
**818 – Cooking Fire**, unabhängig von Berufsprofil oder Kochkunstprüfung.
|
||
Ein eigenes Feuer wird ausschließlich über den normalen Zauber erzeugt und erst
|
||
nach Auftauchen des nativen Feuerobjekts bestätigt. Native Castbedingungen und
|
||
Cooldown gelten. Neue Feuer werden nur draußen, an einer kleinen ebenen Stelle
|
||
und außerhalb von Wasser erzeugt; vorhandene geeignete Feuer können auch ohne
|
||
neuen Cast genutzt werden. Die normale Lebensdauer des Feuerobjekts bleibt erhalten.
|
||
|
||
Gezielter Szenentest bei einem bereits am Ziel angekommenen AdventureBot:
|
||
|
||
```text
|
||
clientless adventure micro 26 social_npc
|
||
clientless adventure micro 26 social_order
|
||
clientless adventure micro 26 social_seat
|
||
clientless adventure micro 26 social_make_fire
|
||
clientless adventure status 26
|
||
```
|
||
|
||
Der Testbefehl verwendet dieselben Umgebungs-, Ziel-, Navigations- und nativen
|
||
Interaktionsprüfungen wie die automatische Auswahl. Ungeeignete oder fehlende
|
||
Ziele werden abgelehnt. Die automatische Tagesplanung wird dadurch nicht aktiviert.
|
||
|
||
Neue Diagnoseereignisse: `SOCIAL_START`, `SOCIAL_CUE`, `SOCIAL_SEATED`,
|
||
`SOCIAL_FIRE_CAST`, `SOCIAL_FIRE_CONFIRMED`, `SOCIAL_END`.
|
||
|
||
```bash
|
||
python3 tests/clientless/test_adventure_social.py
|
||
```
|
||
|
||
Die Regression führt die produktive Szenensteuerung aus: kein Reden während
|
||
des Anlaufs, vollständige Gesprächsfolge, Abbruch bei verschwundenen/feindlichen
|
||
Zielen, native Stuhlbenutzung mit Sitzbestätigung und Lagerfeuer-Cast ohne
|
||
erfundene Erfolgsmeldung bei fehlendem Feuerobjekt.
|
||
|
||
Die Möbel-Suche verlangt noch keine freie Sicht vom ursprünglichen Standpunkt:
|
||
Stühle in angrenzenden Räumen dürfen über einen vollständigen lokalen Laufweg
|
||
gefunden werden. Am gewählten Anlaufpunkt und unmittelbar vor der Benutzung
|
||
wird die native Sichtlinie geprüft. Gesprächspartner dürfen beim Umrunden von
|
||
Hindernissen kurz aus dem Blick geraten; Gesten beginnen erst nach Ankunft.
|
||
Dynamische Lagerfeuer werden zusätzlich über die native erzeugende Zauber-ID
|
||
818 erkannt, unabhängig vom lokalisierten Objektnamen.
|
||
|
||
Zusätzliche Prüfung:
|
||
|
||
```bash
|
||
python3 tests/clientless/test_adventure_social_fire.py
|
||
```
|
||
|
||
## Servertest Geselligkeitsausbau am 26.10.2026
|
||
|
||
- Nativer NPC-Gesprächsanlauf und vollständige Folge aus Begrüßung, `/reden`,
|
||
Zuhören, Reaktion, erneutem Reden und Abschied bestätigt.
|
||
- Bestellung und Tresenaufenthalt beim tatsächlichen Goldhainer Gastwirt
|
||
(Creature-Entry 295) bestätigt.
|
||
- Echte Stuhlbenutzung mit `SOCIAL_SEATED` bestätigt, unter anderem
|
||
GameObject-Entries 22812 und 177498. Trinken auf dem nativen Stuhl ebenfalls
|
||
serverseitig ausgeführt. Keine künstliche Sitzposition gesetzt.
|
||
- Gemeinsamer Lagerfeuerzauber 818 bei Arthoran als gelernt gespeichert.
|
||
- Außenversuch: `SOCIAL_FIRE_CAST` und `SOCIAL_FIRE_CONFIRMED`, natives
|
||
GameObject-Entry 29784. Kein direkter GameObject-Spawn durch die Botsteuerung,
|
||
keine Kochkunstprüfung und keine Umgehung des normalen Cooldowns.
|
||
- Der temporäre Außen-Testpunkt ist kein Graphnode und wird nach dem Test
|
||
entfernt; Arthoran kehrt zur Goldhainer Taverne zurück.
|
||
|
||
Die visuelle Abnahme der neuen Szenen erfolgt durch den Nutzer. Ein tatsächlicher
|
||
Dialog zwischen mehreren AdventureBots wurde mit dem einzelnen Testbot noch
|
||
nicht im Spiel geprüft; die Auswahl und einseitige Ansprache sind implementiert.
|
||
|
||
Abschließender Teststand: Rasten am bereits vorhandenen Feuer während des
|
||
normalen Zaubercooldowns bestätigt (`social_fire`, Rast-Cue 14). Arthoran ist
|
||
über normale Navigation zur Goldhainer Taverne zurückgekehrt. Der temporäre
|
||
Außenpunkt wurde entfernt und die Ortsdaten erneut abgeglichen. Der Tagesplan
|
||
bleibt deaktiviert; der neue Geselligkeitskatalog läuft zur Sichtprüfung.
|
||
|
||
## Gesprächsposition und Gehmodus
|
||
|
||
Gesprächsplätze liegen vor der tatsächlichen Orientierung des Gegenübers.
|
||
Bevorzugt werden 2,2 Yards Abstand, bei Hindernissen auch 3,2 Yards und
|
||
leicht schräge Positionen (etwa ±16 beziehungsweise ±32 Grad). Ein naher Platz
|
||
seitlich oder hinter dem NPC gilt nicht als fertiger Gesprächsanlauf. Dreht sich
|
||
der NPC, wird die Position vor den nächsten Gesten erneut geprüft und bei Bedarf
|
||
begrenzt nachgeführt. Ist kein frontaler Platz erreichbar, wird die Szene beendet,
|
||
statt von hinten weiterzureden. NPCs werden dabei nicht künstlich gedreht.
|
||
|
||
Lokale Bewegungen während eines Geselligkeits-Intents verwenden den nativen
|
||
Gehmodus. Er bleibt bei Neuplanung und mehreren lokalen Splineabschnitten erhalten;
|
||
für diese Bewegungen wird kein Bodenmount verwendet. Andere Reiseaufträge behalten
|
||
ihre bisherige Fortbewegungswahl. Das Navigationslog zeigt `walk=1`, das Soziallog
|
||
mit `SOCIAL_FRONT` den Winkel und Abstand zum Gegenüber.
|
||
|
||
```bash
|
||
python3 tests/clientless/test_adventure_walk.py
|
||
python3 tests/clientless/test_adventure_social.py
|
||
```
|
||
|
||
Servertest der Korrektur: Ein NPC-Gespräch wurde mit frontalem Winkelversatz
|
||
0,000 und 2,20 Yards Abstand ausgeführt. Sowohl der Weg zum Stuhl als auch der
|
||
Gesprächsanlauf wurden als `walk=1` über die native Spline ausgeführt. Build mit
|
||
`-j10` und die zugehörigen Regressionen bestanden. Visuelle Bestätigung erfolgt
|
||
anschließend durch den Nutzer.
|
||
|
||
## Sitzposition für beobachtende Spieler
|
||
|
||
Ein clientloser Spieler sendet keine normalen Client-Bewegungspakete. Dadurch
|
||
konnte seine `MovementInfo.guid` leer bleiben. Die native Nahteleport-Bestätigung
|
||
benutzte diese Struktur für die Nachricht an Beobachter: Die Sitzpose konnte
|
||
sichtbar werden, während die kleine Versetzung auf den Stuhl beim Beobachter
|
||
fehlte. `CompleteNearTeleport` setzt deshalb die tatsächliche Mover-GUID vor
|
||
dem Senden ausdrücklich; clientlose Sessions erhalten einen frischen Zeitstempel.
|
||
Normale Clients behalten ihren Bewegungszeitstempel.
|
||
|
||
`SOCIAL_SEATED` erfordert nun den tatsächlichen Stuhl- beziehungsweise Bankslot
|
||
(maximal 0,15 Yards horizontaler Fehler), passende Höhe, Ausrichtung und die
|
||
zur Stuhlhöhe gehörende native Sitzanimation. Bodensitzen oder eine Sitzpose
|
||
neben dem Stuhl gelten nicht als Erfolg. Die Prüfung bleibt während der
|
||
Stuhlszene aktiv. Das Log enthält Sitzposition, Slotfehler, Sitzstatus und
|
||
Bewegungs-GUID.
|
||
|
||
```bash
|
||
python3 tests/clientless/test_clientless_near_teleport_observer.py
|
||
python3 tests/clientless/test_adventure_social.py
|
||
```
|
||
|
||
Erneuter Servertest: Stuhl-Entry 22812, Sitzposition
|
||
`(-9475.510, 29.792, 56.343)`, Slotabweichung `0.000`, native Sitzhaltung `5`,
|
||
Bewegungs-GUID `26`. Die Beobachternachricht und die genaue Sitzprüfung sind
|
||
installiert; die visuelle Bestätigung erfolgt durch den Nutzer.
|